/**
* Copyright (c) 2014 Redpine Signals Inc.
*
* Permission to use, copy, modify, and/or distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <linux/firmware.h>
#include <net/bluetooth/bluetooth.h>
#include "rsi_mgmt.h"
#include "rsi_hal.h"
#include "rsi_sdio.h"
#include "rsi_common.h"
/* FLASH Firmware */
static struct ta_metadata metadata_flash_content[] = {
{"flash_content", 0x00010000},
{"rsi/rs9113_wlan_qspi.rps", 0x00010000},
{"rsi/rs9113_wlan_bt_dual_mode.rps", 0x00010000},
{"flash_content", 0x00010000},
{"rsi/rs9113_ap_bt_dual_mode.rps", 0x00010000},
};
static struct ta_metadata metadata[] = {{"pmemdata_dummy", 0x00000000},
{"rsi/rs9116_wlan.rps", 0x00000000},
{"rsi/rs9116_wlan_bt_classic.rps", 0x00000000},
{"rsi/pmemdata_dummy", 0x00000000},
{"rsi/rs9116_wlan_bt_classic.rps", 0x00000000}
};
int rsi_send_pkt_to_bus(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
int status;
if (common->coex_mode > 1)
mutex_lock(&common->tx_bus_mutex);
status = adapter->host_intf_ops->write_pkt(common->priv,
skb->data, skb->len);
if (common->coex_mode > 1)
mutex_unlock(&common->tx_bus_mutex);
return status;
}
int rsi_prepare_mgmt_desc(struct rsi_common *common, struct sk_buff *skb)
{
struct rsi_hw *adapter = common->priv;
struct ieee80211_hdr *wh = NULL;
struct ieee80211_tx_info *info;
struct ieee80211_conf *conf = &adapter->hw->conf;
struct ieee80211_vif *vif;
struct rsi_mgmt_desc *mgmt_desc;
struct skb_info *tx_params;
struct rsi_xtended_desc *xtend_desc = NULL;
u8 header_size;
u32 dword_align_bytes = 0;
if (skb->len > MAX_MGMT_PKT_SIZE) {
rsi_dbg(INFO_ZONE, "%s: Dropping mgmt pkt > 512\n", __func__);
return -EINVAL;
}
info = IEEE80211_SKB_CB(skb);
tx_params = (struct skb_info *)info->driver_data;
vif = tx_params->vif;
/* Update header size */
header_size = FRAME_DESC_SZ + sizeof(struct rsi_xtended_desc);
if (header_size > skb_headroom(skb)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to add extended descriptor\n",
__func__);
return -ENOSPC;
}
skb_push(skb, header_size);
dword_align_bytes = ((unsigned long)skb->data & 0x3f);
if (dword_align_bytes > skb_headroom(skb)) {
rsi_dbg(ERR_ZONE,
"%s: Failed to add dword align\n", __func__);
return -ENOSPC;
}
skb_push(skb, dword_align_bytes);
header_size += dword_align_bytes;
tx_params->internal_hdr_size = header_size;
memset(&skb->data[0],