diff options
Diffstat (limited to 'drivers/net/wireless/mwifiex')
48 files changed, 0 insertions, 42453 deletions
diff --git a/drivers/net/wireless/mwifiex/11ac.c b/drivers/net/wireless/mwifiex/11ac.c deleted file mode 100644 index 59d23fb2365f..000000000000 --- a/drivers/net/wireless/mwifiex/11ac.c +++ /dev/null @@ -1,382 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11ac - * - * Copyright (C) 2013-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "fw.h" -#include "main.h" -#include "11ac.h" - -/* Tables of the MCS map to the highest data rate (in Mbps) supported - * for long GI. - */ -static const u16 max_rate_lgi_80MHZ[8][3] = { - {0x124, 0x15F, 0x186}, /* NSS = 1 */ - {0x249, 0x2BE, 0x30C}, /* NSS = 2 */ - {0x36D, 0x41D, 0x492}, /* NSS = 3 */ - {0x492, 0x57C, 0x618}, /* NSS = 4 */ - {0x5B6, 0x6DB, 0x79E}, /* NSS = 5 */ - {0x6DB, 0x83A, 0x0}, /* NSS = 6 */ - {0x7FF, 0x999, 0xAAA}, /* NSS = 7 */ - {0x924, 0xAF8, 0xC30} /* NSS = 8 */ -}; - -static const u16 max_rate_lgi_160MHZ[8][3] = { - {0x249, 0x2BE, 0x30C}, /* NSS = 1 */ - {0x492, 0x57C, 0x618}, /* NSS = 2 */ - {0x6DB, 0x83A, 0x0}, /* NSS = 3 */ - {0x924, 0xAF8, 0xC30}, /* NSS = 4 */ - {0xB6D, 0xDB6, 0xF3C}, /* NSS = 5 */ - {0xDB6, 0x1074, 0x1248}, /* NSS = 6 */ - {0xFFF, 0x1332, 0x1554}, /* NSS = 7 */ - {0x1248, 0x15F0, 0x1860} /* NSS = 8 */ -}; - -/* This function converts the 2-bit MCS map to the highest long GI - * VHT data rate. - */ -static u16 -mwifiex_convert_mcsmap_to_maxrate(struct mwifiex_private *priv, - u8 bands, u16 mcs_map) -{ - u8 i, nss, mcs; - u16 max_rate = 0; - u32 usr_vht_cap_info = 0; - struct mwifiex_adapter *adapter = priv->adapter; - - if (bands & BAND_AAC) - usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; - else - usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; - - /* find the max NSS supported */ - nss = 1; - for (i = 1; i <= 8; i++) { - mcs = GET_VHTNSSMCS(mcs_map, i); - if (mcs < IEEE80211_VHT_MCS_NOT_SUPPORTED) - nss = i; - } - mcs = GET_VHTNSSMCS(mcs_map, nss); - - /* if mcs is 3, nss must be 1 (NSS = 1). Default mcs to MCS 0~9 */ - if (mcs == IEEE80211_VHT_MCS_NOT_SUPPORTED) - mcs = IEEE80211_VHT_MCS_SUPPORT_0_9; - - if (GET_VHTCAP_CHWDSET(usr_vht_cap_info)) { - /* support 160 MHz */ - max_rate = max_rate_lgi_160MHZ[nss - 1][mcs]; - if (!max_rate) - /* MCS9 is not supported in NSS6 */ - max_rate = max_rate_lgi_160MHZ[nss - 1][mcs - 1]; - } else { - max_rate = max_rate_lgi_80MHZ[nss - 1][mcs]; - if (!max_rate) - /* MCS9 is not supported in NSS3 */ - max_rate = max_rate_lgi_80MHZ[nss - 1][mcs - 1]; - } - - return max_rate; -} - -static void -mwifiex_fill_vht_cap_info(struct mwifiex_private *priv, - struct ieee80211_vht_cap *vht_cap, u8 bands) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - if (bands & BAND_A) - vht_cap->vht_cap_info = - cpu_to_le32(adapter->usr_dot_11ac_dev_cap_a); - else - vht_cap->vht_cap_info = - cpu_to_le32(adapter->usr_dot_11ac_dev_cap_bg); -} - -void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, - struct ieee80211_vht_cap *vht_cap, u8 bands) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u16 mcs_map_user, mcs_map_resp, mcs_map_result; - u16 mcs_user, mcs_resp, nss, tmp; - - /* Fill VHT cap info */ - mwifiex_fill_vht_cap_info(priv, vht_cap, bands); - - /* rx MCS Set: find the minimum of the user rx mcs and ap rx mcs */ - mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support); - mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map); - mcs_map_result = 0; - - for (nss = 1; nss <= 8; nss++) { - mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); - mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); - - if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) || - (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED)) - SET_VHTNSSMCS(mcs_map_result, nss, - IEEE80211_VHT_MCS_NOT_SUPPORTED); - else - SET_VHTNSSMCS(mcs_map_result, nss, - min(mcs_user, mcs_resp)); - } - - vht_cap->supp_mcs.rx_mcs_map = cpu_to_le16(mcs_map_result); - - tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); - vht_cap->supp_mcs.rx_highest = cpu_to_le16(tmp); - - /* tx MCS Set: find the minimum of the user tx mcs and ap tx mcs */ - mcs_map_user = GET_DEVTXMCSMAP(adapter->usr_dot_11ac_mcs_support); - mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.tx_mcs_map); - mcs_map_result = 0; - - for (nss = 1; nss <= 8; nss++) { - mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); - mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); - if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) || - (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED)) - SET_VHTNSSMCS(mcs_map_result, nss, - IEEE80211_VHT_MCS_NOT_SUPPORTED); - else - SET_VHTNSSMCS(mcs_map_result, nss, - min(mcs_user, mcs_resp)); - } - - vht_cap->supp_mcs.tx_mcs_map = cpu_to_le16(mcs_map_result); - - tmp = mwifiex_convert_mcsmap_to_maxrate(priv, bands, mcs_map_result); - vht_cap->supp_mcs.tx_highest = cpu_to_le16(tmp); - - return; -} - -int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 **buffer) -{ - struct mwifiex_ie_types_vhtcap *vht_cap; - struct mwifiex_ie_types_oper_mode_ntf *oper_ntf; - struct ieee_types_oper_mode_ntf *ieee_oper_ntf; - struct mwifiex_ie_types_vht_oper *vht_op; - struct mwifiex_adapter *adapter = priv->adapter; - u8 supp_chwd_set; - u32 usr_vht_cap_info; - int ret_len = 0; - - if (bss_desc->bss_band & BAND_A) - usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; - else - usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; - - /* VHT Capabilities IE */ - if (bss_desc->bcn_vht_cap) { - vht_cap = (struct mwifiex_ie_types_vhtcap *)*buffer; - memset(vht_cap, 0, sizeof(*vht_cap)); - vht_cap->header.type = cpu_to_le16(WLAN_EID_VHT_CAPABILITY); - vht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_vht_cap)); - memcpy((u8 *)vht_cap + sizeof(struct mwifiex_ie_types_header), - (u8 *)bss_desc->bcn_vht_cap, - le16_to_cpu(vht_cap->header.len)); - - mwifiex_fill_vht_cap_tlv(priv, &vht_cap->vht_cap, - bss_desc->bss_band); - *buffer += sizeof(*vht_cap); - ret_len += sizeof(*vht_cap); - } - - /* VHT Operation IE */ - if (bss_desc->bcn_vht_oper) { - if (priv->bss_mode == NL80211_IFTYPE_STATION) { - vht_op = (struct mwifiex_ie_types_vht_oper *)*buffer; - memset(vht_op, 0, sizeof(*vht_op)); - vht_op->header.type = - cpu_to_le16(WLAN_EID_VHT_OPERATION); - vht_op->header.len = cpu_to_le16(sizeof(*vht_op) - - sizeof(struct mwifiex_ie_types_header)); - memcpy((u8 *)vht_op + - sizeof(struct mwifiex_ie_types_header), - (u8 *)bss_desc->bcn_vht_oper, - le16_to_cpu(vht_op->header.len)); - - /* negotiate the channel width and central freq - * and keep the central freq as the peer suggests - */ - supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info); - - switch (supp_chwd_set) { - case 0: - vht_op->chan_width = - min_t(u8, IEEE80211_VHT_CHANWIDTH_80MHZ, - bss_desc->bcn_vht_oper->chan_width); - break; - case 1: - vht_op->chan_width = - min_t(u8, IEEE80211_VHT_CHANWIDTH_160MHZ, - bss_desc->bcn_vht_oper->chan_width); - break; - case 2: - vht_op->chan_width = - min_t(u8, IEEE80211_VHT_CHANWIDTH_80P80MHZ, - bss_desc->bcn_vht_oper->chan_width); - break; - default: - vht_op->chan_width = - IEEE80211_VHT_CHANWIDTH_USE_HT; - break; - } - - *buffer += sizeof(*vht_op); - ret_len += sizeof(*vht_op); - } - } - - /* Operating Mode Notification IE */ - if (bss_desc->oper_mode) { - ieee_oper_ntf = bss_desc->oper_mode; - oper_ntf = (void *)*buffer; - memset(oper_ntf, 0, sizeof(*oper_ntf)); - oper_ntf->header.type = cpu_to_le16(WLAN_EID_OPMODE_NOTIF); - oper_ntf->header.len = cpu_to_le16(sizeof(u8)); - oper_ntf->oper_mode = ieee_oper_ntf->oper_mode; - *buffer += sizeof(*oper_ntf); - ret_len += sizeof(*oper_ntf); - } - - return ret_len; -} - -int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 cmd_action, - struct mwifiex_11ac_vht_cfg *cfg) -{ - struct host_cmd_11ac_vht_cfg *vhtcfg = &cmd->params.vht_cfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_11AC_CFG); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_11ac_vht_cfg) + - S_DS_GEN); - vhtcfg->action = cpu_to_le16(cmd_action); - vhtcfg->band_config = cfg->band_config; - vhtcfg->misc_config = cfg->misc_config; - vhtcfg->cap_info = cpu_to_le32(cfg->cap_info); - vhtcfg->mcs_tx_set = cpu_to_le32(cfg->mcs_tx_set); - vhtcfg->mcs_rx_set = cpu_to_le32(cfg->mcs_rx_set); - - return 0; -} - -/* This function initializes the BlockACK setup information for given - * mwifiex_private structure for 11ac enabled networks. - */ -void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv) -{ - priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - priv->add_ba_param.tx_win_size = - MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE; - priv->add_ba_param.rx_win_size = - MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE; - } else { - priv->add_ba_param.tx_win_size = - MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; - priv->add_ba_param.rx_win_size = - MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE; - } - - return; -} - -bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv) -{ - struct mwifiex_bssdescriptor *bss_desc; - struct ieee80211_vht_operation *vht_oper; - - bss_desc = &priv->curr_bss_params.bss_descriptor; - vht_oper = bss_desc->bcn_vht_oper; - - if (!bss_desc->bcn_vht_cap || !vht_oper) - return false; - - if (vht_oper->chan_width == IEEE80211_VHT_CHANWIDTH_USE_HT) - return false; - - return true; -} - -u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, - u32 pri_chan, u8 chan_bw) -{ - u8 center_freq_idx = 0; - - if (band & BAND_AAC) { - switch (pri_chan) { - case 36: - case 40: - case 44: - case 48: - if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) - center_freq_idx = 42; - break; - case 52: - case 56: - case 60: - case 64: - if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) - center_freq_idx = 58; - else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ) - center_freq_idx = 50; - break; - case 100: - case 104: - case 108: - case 112: - if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) - center_freq_idx = 106; - break; - case 116: - case 120: - case 124: - case 128: - if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) - center_freq_idx = 122; - else if (chan_bw == IEEE80211_VHT_CHANWIDTH_160MHZ) - center_freq_idx = 114; - break; - case 132: - case 136: - case 140: - case 144: - if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) - center_freq_idx = 138; - break; - case 149: - case 153: - case 157: - case 161: - if (chan_bw == IEEE80211_VHT_CHANWIDTH_80MHZ) - center_freq_idx = 155; - break; - default: - center_freq_idx = 42; - } - } - - return center_freq_idx; -} diff --git a/drivers/net/wireless/mwifiex/11ac.h b/drivers/net/wireless/mwifiex/11ac.h deleted file mode 100644 index 1ca92c7a8a4a..000000000000 --- a/drivers/net/wireless/mwifiex/11ac.h +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11ac - * - * Copyright (C) 2013-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11AC_H_ -#define _MWIFIEX_11AC_H_ - -#define VHT_CFG_2GHZ BIT(0) -#define VHT_CFG_5GHZ BIT(1) - -enum vht_cfg_misc_config { - VHT_CAP_TX_OPERATION = 1, - VHT_CAP_ASSOCIATION, - VHT_CAP_UAP_ONLY -}; - -#define DEFAULT_VHT_MCS_SET 0xfffa -#define DISABLE_VHT_MCS_SET 0xffff - -#define VHT_BW_80_160_80P80 BIT(2) - -int mwifiex_cmd_append_11ac_tlv(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 **buffer); -int mwifiex_cmd_11ac_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 cmd_action, - struct mwifiex_11ac_vht_cfg *cfg); -void mwifiex_fill_vht_cap_tlv(struct mwifiex_private *priv, - struct ieee80211_vht_cap *vht_cap, u8 bands); -#endif /* _MWIFIEX_11AC_H_ */ diff --git a/drivers/net/wireless/mwifiex/11h.c b/drivers/net/wireless/mwifiex/11h.c deleted file mode 100644 index 71a1b580796f..000000000000 --- a/drivers/net/wireless/mwifiex/11h.c +++ /dev/null @@ -1,319 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11h - * - * Copyright (C) 2013-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" -#include "fw.h" - - -void mwifiex_init_11h_params(struct mwifiex_private *priv) -{ - priv->state_11h.is_11h_enabled = true; - priv->state_11h.is_11h_active = false; -} - -inline int mwifiex_is_11h_active(struct mwifiex_private *priv) -{ - return priv->state_11h.is_11h_active; -} -/* This function appends 11h info to a buffer while joining an - * infrastructure BSS - */ -static void -mwifiex_11h_process_infra_join(struct mwifiex_private *priv, u8 **buffer, - struct mwifiex_bssdescriptor *bss_desc) -{ - struct mwifiex_ie_types_header *ie_header; - struct mwifiex_ie_types_pwr_capability *cap; - struct mwifiex_ie_types_local_pwr_constraint *constraint; - struct ieee80211_supported_band *sband; - u8 radio_type; - int i; - - if (!buffer || !(*buffer)) - return; - - radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - sband = priv->wdev.wiphy->bands[radio_type]; - - cap = (struct mwifiex_ie_types_pwr_capability *)*buffer; - cap->header.type = cpu_to_le16(WLAN_EID_PWR_CAPABILITY); - cap->header.len = cpu_to_le16(2); - cap->min_pwr = 0; - cap->max_pwr = 0; - *buffer += sizeof(*cap); - - constraint = (struct mwifiex_ie_types_local_pwr_constraint *)*buffer; - constraint->header.type = cpu_to_le16(WLAN_EID_PWR_CONSTRAINT); - constraint->header.len = cpu_to_le16(2); - constraint->chan = bss_desc->channel; - constraint->constraint = bss_desc->local_constraint; - *buffer += sizeof(*constraint); - - ie_header = (struct mwifiex_ie_types_header *)*buffer; - ie_header->type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); - ie_header->len = cpu_to_le16(2 * sband->n_channels + 2); - *buffer += sizeof(*ie_header); - *(*buffer)++ = WLAN_EID_SUPPORTED_CHANNELS; - *(*buffer)++ = 2 * sband->n_channels; - for (i = 0; i < sband->n_channels; i++) { - *(*buffer)++ = ieee80211_frequency_to_channel( - sband->channels[i].center_freq); - *(*buffer)++ = 1; /* one channel in the subband */ - } -} - -/* Enable or disable the 11h extensions in the firmware */ -int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag) -{ - u32 enable = flag; - - /* enable master mode radar detection on AP interface */ - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && enable) - enable |= MWIFIEX_MASTER_RADAR_DET_MASK; - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11H_I, &enable, true); -} - -/* This functions processes TLV buffer for a pending BSS Join command. - * - * Activate 11h functionality in the firmware if the spectrum management - * capability bit is found in the network we are joining. Also, necessary - * TLVs are set based on requested network's 11h capability. - */ -void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (bss_desc->sensed_11h) { - /* Activate 11h functions in firmware, turns on capability - * bit - */ - mwifiex_11h_activate(priv, true); - priv->state_11h.is_11h_active = true; - bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_SPECTRUM_MGMT; - mwifiex_11h_process_infra_join(priv, buffer, bss_desc); - } else { - /* Deactivate 11h functions in the firmware */ - mwifiex_11h_activate(priv, false); - priv->state_11h.is_11h_active = false; - bss_desc->cap_info_bitmap &= ~WLAN_CAPABILITY_SPECTRUM_MGMT; - } -} - -/* This is DFS CAC work queue function. - * This delayed work emits CAC finished event for cfg80211 if - * CAC was started earlier. - */ -void mwifiex_dfs_cac_work_queue(struct work_struct *work) -{ - struct cfg80211_chan_def chandef; - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); - struct mwifiex_private *priv = - container_of(delayed_work, struct mwifiex_private, - dfs_cac_work); - - if (WARN_ON(!priv)) - return; - - chandef = priv->dfs_chandef; - if (priv->wdev.cac_started) { - mwifiex_dbg(priv->adapter, MSG, - "CAC timer finished; No radar detected\n"); - cfg80211_cac_event(priv->netdev, &chandef, - NL80211_RADAR_CAC_FINISHED, - GFP_KERNEL); - } -} - -/* This function prepares channel report request command to FW for - * starting radar detection. - */ -int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) -{ - struct host_cmd_ds_chan_rpt_req *cr_req = &cmd->params.chan_rpt_req; - struct mwifiex_radar_params *radar_params = (void *)data_buf; - - cmd->command = cpu_to_le16(HostCmd_CMD_CHAN_REPORT_REQUEST); - cmd->size = cpu_to_le16(S_DS_GEN); - le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_chan_rpt_req)); - - cr_req->chan_desc.start_freq = cpu_to_le16(MWIFIEX_A_BAND_START_FREQ); - cr_req->chan_desc.chan_num = radar_params->chandef->chan->hw_value; - cr_req->chan_desc.chan_width = radar_params->chandef->width; - cr_req->msec_dwell_time = cpu_to_le32(radar_params->cac_time_ms); - - if (radar_params->cac_time_ms) - mwifiex_dbg(priv->adapter, MSG, - "11h: issuing DFS Radar check for channel=%d\n", - radar_params->chandef->chan->hw_value); - else - mwifiex_dbg(priv->adapter, MSG, "cancelling CAC\n"); - - return 0; -} - -int mwifiex_stop_radar_detection(struct mwifiex_private *priv, - struct cfg80211_chan_def *chandef) -{ - struct mwifiex_radar_params radar_params; - - memset(&radar_params, 0, sizeof(struct mwifiex_radar_params)); - radar_params.chandef = chandef; - radar_params.cac_time_ms = 0; - - return mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST, - HostCmd_ACT_GEN_SET, 0, &radar_params, true); -} - -/* This function is to abort ongoing CAC upon stopping AP operations - * or during unload. - */ -void mwifiex_abort_cac(struct mwifiex_private *priv) -{ - if (priv->wdev.cac_started) { - if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef)) - mwifiex_dbg(priv->adapter, ERROR, - "failed to stop CAC in FW\n"); - mwifiex_dbg(priv->adapter, MSG, - "Aborting delayed work for CAC.\n"); - cancel_delayed_work_sync(&priv->dfs_cac_work); - cfg80211_cac_event(priv->netdev, &priv->dfs_chandef, - NL80211_RADAR_CAC_ABORTED, GFP_KERNEL); - } -} - -/* This function handles channel report event from FW during CAC period. - * If radar is detected during CAC, driver indicates the same to cfg80211 - * and also cancels ongoing delayed work. - */ -int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct host_cmd_ds_chan_rpt_event *rpt_event; - struct mwifiex_ie_types_chan_rpt_data *rpt; - u8 *evt_buf; - u16 event_len, tlv_len; - - rpt_event = (void *)(skb->data + sizeof(u32)); - event_len = skb->len - (sizeof(struct host_cmd_ds_chan_rpt_event)+ - sizeof(u32)); - - if (le32_to_cpu(rpt_event->result) != HostCmd_RESULT_OK) { - mwifiex_dbg(priv->adapter, ERROR, - "Error in channel report event\n"); - return -1; - } - - evt_buf = (void *)&rpt_event->tlvbuf; - - while (event_len >= sizeof(struct mwifiex_ie_types_header)) { - rpt = (void *)&rpt_event->tlvbuf; - tlv_len = le16_to_cpu(rpt->header.len); - - switch (le16_to_cpu(rpt->header.type)) { - case TLV_TYPE_CHANRPT_11H_BASIC: - if (rpt->map.radar) { - mwifiex_dbg(priv->adapter, MSG, - "RADAR Detected on channel %d!\n", - priv->dfs_chandef.chan->hw_value); - cancel_delayed_work_sync(&priv->dfs_cac_work); - cfg80211_cac_event(priv->netdev, - &priv->dfs_chandef, - NL80211_RADAR_DETECTED, - GFP_KERNEL); - } - break; - default: - break; - } - - evt_buf += (tlv_len + sizeof(rpt->header)); - event_len -= (tlv_len + sizeof(rpt->header)); - } - - return 0; -} - -/* Handler for radar detected event from FW.*/ -int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_radar_det_event *rdr_event; - - rdr_event = (void *)(skb->data + sizeof(u32)); - - if (le32_to_cpu(rdr_event->passed)) { - mwifiex_dbg(priv->adapter, MSG, - "radar detected; indicating kernel\n"); - if (mwifiex_stop_radar_detection(priv, &priv->dfs_chandef)) - mwifiex_dbg(priv->adapter, ERROR, - "Failed to stop CAC in FW\n"); - cfg80211_radar_event(priv->adapter->wiphy, &priv->dfs_chandef, - GFP_KERNEL); - mwifiex_dbg(priv->adapter, MSG, "regdomain: %d\n", - rdr_event->reg_domain); - mwifiex_dbg(priv->adapter, MSG, "radar detection type: %d\n", - rdr_event->det_type); - } else { - mwifiex_dbg(priv->adapter, MSG, - "false radar detection event!\n"); - } - - return 0; -} - -/* This is work queue function for channel switch handling. - * This function takes care of updating new channel definitin to - * bss config structure, restart AP and indicate channel switch success - * to cfg80211. - */ -void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work) -{ - struct mwifiex_uap_bss_param *bss_cfg; - struct delayed_work *delayed_work = - container_of(work, struct delayed_work, work); - struct mwifiex_private *priv = - container_of(delayed_work, struct mwifiex_private, - dfs_chan_sw_work); - - if (WARN_ON(!priv)) - return; - - bss_cfg = &priv->bss_cfg; - if (!bss_cfg->beacon_period) { - mwifiex_dbg(priv->adapter, ERROR, - "channel switch: AP already stopped\n"); - return; - } - - mwifiex_uap_set_channel(priv, bss_cfg, priv->dfs_chandef); - - if (mwifiex_config_start_uap(priv, bss_cfg)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to start AP after channel switch\n"); - return; - } - - mwifiex_dbg(priv->adapter, MSG, - "indicating channel switch completion to kernel\n"); - cfg80211_ch_switch_notify(priv->netdev, &priv->dfs_chandef); -} diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c deleted file mode 100644 index c174e79e6df2..000000000000 --- a/drivers/net/wireless/mwifiex/11n.c +++ /dev/null @@ -1,914 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * Fills HT capability information field, AMPDU Parameters field, HT extended - * capability field, and supported MCS set fields. - * - * HT capability information field, AMPDU Parameters field, supported MCS set - * fields are retrieved from cfg80211 stack - * - * RD responder bit to set to clear in the extended capability header. - */ -int mwifiex_fill_cap_info(struct mwifiex_private *priv, u8 radio_type, - struct ieee80211_ht_cap *ht_cap) -{ - uint16_t ht_ext_cap = le16_to_cpu(ht_cap->extended_ht_cap_info); - struct ieee80211_supported_band *sband = - priv->wdev.wiphy->bands[radio_type]; - - if (WARN_ON_ONCE(!sband)) { - mwifiex_dbg(priv->adapter, ERROR, "Invalid radio type!\n"); - return -EINVAL; - } - - ht_cap->ampdu_params_info = - (sband->ht_cap.ampdu_factor & - IEEE80211_HT_AMPDU_PARM_FACTOR) | - ((sband->ht_cap.ampdu_density << - IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT) & - IEEE80211_HT_AMPDU_PARM_DENSITY); - - memcpy((u8 *)&ht_cap->mcs, &sband->ht_cap.mcs, - sizeof(sband->ht_cap.mcs)); - - if (priv->bss_mode == NL80211_IFTYPE_STATION || - (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && - (priv->adapter->sec_chan_offset != - IEEE80211_HT_PARAM_CHA_SEC_NONE))) - /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ - SETHT_MCS32(ht_cap->mcs.rx_mask); - - /* Clear RD responder bit */ - ht_ext_cap &= ~IEEE80211_HT_EXT_CAP_RD_RESPONDER; - - ht_cap->cap_info = cpu_to_le16(sband->ht_cap.cap); - ht_cap->extended_ht_cap_info = cpu_to_le16(ht_ext_cap); - - if (ISSUPP_BEAMFORMING(priv->adapter->hw_dot_11n_dev_cap)) - ht_cap->tx_BF_cap_info = cpu_to_le32(MWIFIEX_DEF_11N_TX_BF_CAP); - - return 0; -} - -/* - * This function returns the pointer to an entry in BA Stream - * table which matches the requested BA status. - */ -static struct mwifiex_tx_ba_stream_tbl * -mwifiex_get_ba_status(struct mwifiex_private *priv, - enum mwifiex_ba_status ba_status) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (tx_ba_tsr_tbl->ba_status == ba_status) { - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, - flags); - return tx_ba_tsr_tbl; - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - return NULL; -} - -/* - * This function handles the command response of delete a block - * ack request. - * - * The function checks the response success status and takes action - * accordingly (send an add BA request in case of success, or recreate - * the deleted stream in case of failure, if the add BA was also - * initiated by us). - */ -int mwifiex_ret_11n_delba(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int tid; - struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; - struct host_cmd_ds_11n_delba *del_ba = &resp->params.del_ba; - uint16_t del_ba_param_set = le16_to_cpu(del_ba->del_ba_param_set); - - tid = del_ba_param_set >> DELBA_TID_POS; - if (del_ba->del_result == BA_RESULT_SUCCESS) { - mwifiex_del_ba_tbl(priv, tid, del_ba->peer_mac_addr, - TYPE_DELBA_SENT, - INITIATOR_BIT(del_ba_param_set)); - - tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS); - if (tx_ba_tbl) - mwifiex_send_addba(priv, tx_ba_tbl->tid, - tx_ba_tbl->ra); - } else { /* - * In case of failure, recreate the deleted stream in case - * we initiated the ADDBA - */ - if (!INITIATOR_BIT(del_ba_param_set)) - return 0; - - mwifiex_create_ba_tbl(priv, del_ba->peer_mac_addr, tid, - BA_SETUP_INPROGRESS); - - tx_ba_tbl = mwifiex_get_ba_status(priv, BA_SETUP_INPROGRESS); - - if (tx_ba_tbl) - mwifiex_del_ba_tbl(priv, tx_ba_tbl->tid, tx_ba_tbl->ra, - TYPE_DELBA_SENT, true); - } - - return 0; -} - -/* - * This function handles the command response of add a block - * ack request. - * - * Handling includes changing the header fields to CPU formats, checking - * the response success status and taking actions accordingly (delete the - * BA stream table in case of failure). - */ -int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int tid, tid_down; - struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; - struct mwifiex_tx_ba_stream_tbl *tx_ba_tbl; - struct mwifiex_ra_list_tbl *ra_list; - u16 block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); - - add_ba_rsp->ssn = cpu_to_le16((le16_to_cpu(add_ba_rsp->ssn)) - & SSN_MASK); - - tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - - tid_down = mwifiex_wmm_downgrade_tid(priv, tid); - ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, add_ba_rsp-> - peer_mac_addr); - if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { - if (ra_list) { - ra_list->ba_status = BA_SETUP_NONE; - ra_list->amsdu_in_ampdu = false; - } - mwifiex_del_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr, - TYPE_DELBA_SENT, true); - if (add_ba_rsp->add_rsp_result != BA_RESULT_TIMEOUT) - priv->aggr_prio_tbl[tid].ampdu_ap = - BA_STREAM_NOT_ALLOWED; - return 0; - } - - tx_ba_tbl = mwifiex_get_ba_tbl(priv, tid, add_ba_rsp->peer_mac_addr); - if (tx_ba_tbl) { - mwifiex_dbg(priv->adapter, EVENT, "info: BA stream complete\n"); - tx_ba_tbl->ba_status = BA_SETUP_COMPLETE; - if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && - priv->add_ba_param.tx_amsdu && - (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) - tx_ba_tbl->amsdu = true; - else - tx_ba_tbl->amsdu = false; - if (ra_list) { - ra_list->amsdu_in_ampdu = tx_ba_tbl->amsdu; - ra_list->ba_status = BA_SETUP_COMPLETE; - } - } else { - mwifiex_dbg(priv->adapter, ERROR, "BA stream not created\n"); - } - - return 0; -} - -/* - * This function prepares command of reconfigure Tx buffer. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting Tx buffer size (for SET only) - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, int cmd_action, - u16 *buf_size) -{ - struct host_cmd_ds_txbuf_cfg *tx_buf = &cmd->params.tx_buf; - u16 action = (u16) cmd_action; - - cmd->command = cpu_to_le16(HostCmd_CMD_RECONFIGURE_TX_BUFF); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_ds_txbuf_cfg) + S_DS_GEN); - tx_buf->action = cpu_to_le16(action); - switch (action) { - case HostCmd_ACT_GEN_SET: - mwifiex_dbg(priv->adapter, CMD, - "cmd: set tx_buf=%d\n", *buf_size); - tx_buf->buff_size = cpu_to_le16(*buf_size); - break; - case HostCmd_ACT_GEN_GET: - default: - tx_buf->buff_size = 0; - break; - } - return 0; -} - -/* - * This function prepares command of AMSDU aggregation control. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting AMSDU control parameters (for SET only) - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, - int cmd_action, - struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl) -{ - struct host_cmd_ds_amsdu_aggr_ctrl *amsdu_ctrl = - &cmd->params.amsdu_aggr_ctrl; - u16 action = (u16) cmd_action; - - cmd->command = cpu_to_le16(HostCmd_CMD_AMSDU_AGGR_CTRL); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_amsdu_aggr_ctrl) - + S_DS_GEN); - amsdu_ctrl->action = cpu_to_le16(action); - switch (action) { - case HostCmd_ACT_GEN_SET: - amsdu_ctrl->enable = cpu_to_le16(aa_ctrl->enable); - amsdu_ctrl->curr_buf_size = 0; - break; - case HostCmd_ACT_GEN_GET: - default: - amsdu_ctrl->curr_buf_size = 0; - break; - } - return 0; -} - -/* - * This function prepares 11n configuration command. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting HT Tx capability and HT Tx information fields - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 cmd_action, - struct mwifiex_ds_11n_tx_cfg *txcfg) -{ - struct host_cmd_ds_11n_cfg *htcfg = &cmd->params.htcfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_CFG); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_11n_cfg) + S_DS_GEN); - htcfg->action = cpu_to_le16(cmd_action); - htcfg->ht_tx_cap = cpu_to_le16(txcfg->tx_htcap); - htcfg->ht_tx_info = cpu_to_le16(txcfg->tx_htinfo); - - if (priv->adapter->is_hw_11ac_capable) - htcfg->misc_config = cpu_to_le16(txcfg->misc_config); - - return 0; -} - -/* - * This function appends an 11n TLV to a buffer. - * - * Buffer allocation is responsibility of the calling - * function. No size validation is made here. - * - * The function fills up the following sections, if applicable - - * - HT capability IE - * - HT information IE (with channel list) - * - 20/40 BSS Coexistence IE - * - HT Extended Capabilities IE - */ -int -mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 **buffer) -{ - struct mwifiex_ie_types_htcap *ht_cap; - struct mwifiex_ie_types_htinfo *ht_info; - struct mwifiex_ie_types_chan_list_param_set *chan_list; - struct mwifiex_ie_types_2040bssco *bss_co_2040; - struct mwifiex_ie_types_extcap *ext_cap; - int ret_len = 0; - struct ieee80211_supported_band *sband; - struct ieee_types_header *hdr; - u8 radio_type; - - if (!buffer || !*buffer) - return ret_len; - - radio_type = mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - sband = priv->wdev.wiphy->bands[radio_type]; - - if (bss_desc->bcn_ht_cap) { - ht_cap = (struct mwifiex_ie_types_htcap *) *buffer; - memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); - ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - memcpy((u8 *) ht_cap + sizeof(struct mwifiex_ie_types_header), - (u8 *)bss_desc->bcn_ht_cap, - le16_to_cpu(ht_cap->header.len)); - - mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); - - *buffer += sizeof(struct mwifiex_ie_types_htcap); - ret_len += sizeof(struct mwifiex_ie_types_htcap); - } - - if (bss_desc->bcn_ht_oper) { - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - ht_info = (struct mwifiex_ie_types_htinfo *) *buffer; - memset(ht_info, 0, - sizeof(struct mwifiex_ie_types_htinfo)); - ht_info->header.type = - cpu_to_le16(WLAN_EID_HT_OPERATION); - ht_info->header.len = - cpu_to_le16( - sizeof(struct ieee80211_ht_operation)); - - memcpy((u8 *) ht_info + - sizeof(struct mwifiex_ie_types_header), - (u8 *)bss_desc->bcn_ht_oper, - le16_to_cpu(ht_info->header.len)); - - if (!(sband->ht_cap.cap & - IEEE80211_HT_CAP_SUP_WIDTH_20_40)) - ht_info->ht_oper.ht_param &= - ~(IEEE80211_HT_PARAM_CHAN_WIDTH_ANY | - IEEE80211_HT_PARAM_CHA_SEC_OFFSET); - - *buffer += sizeof(struct mwifiex_ie_types_htinfo); - ret_len += sizeof(struct mwifiex_ie_types_htinfo); - } - - chan_list = - (struct mwifiex_ie_types_chan_list_param_set *) *buffer; - memset(chan_list, 0, - sizeof(struct mwifiex_ie_types_chan_list_param_set)); - chan_list->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_list->header.len = cpu_to_le16( - sizeof(struct mwifiex_ie_types_chan_list_param_set) - - sizeof(struct mwifiex_ie_types_header)); - chan_list->chan_scan_param[0].chan_number = - bss_desc->bcn_ht_oper->primary_chan; - chan_list->chan_scan_param[0].radio_type = - mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - - if (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40 && - bss_desc->bcn_ht_oper->ht_param & - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY) - SET_SECONDARYCHAN(chan_list->chan_scan_param[0]. - radio_type, - (bss_desc->bcn_ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET)); - - *buffer += sizeof(struct mwifiex_ie_types_chan_list_param_set); - ret_len += sizeof(struct mwifiex_ie_types_chan_list_param_set); - } - - if (bss_desc->bcn_bss_co_2040) { - bss_co_2040 = (struct mwifiex_ie_types_2040bssco *) *buffer; - memset(bss_co_2040, 0, - sizeof(struct mwifiex_ie_types_2040bssco)); - bss_co_2040->header.type = cpu_to_le16(WLAN_EID_BSS_COEX_2040); - bss_co_2040->header.len = - cpu_to_le16(sizeof(bss_co_2040->bss_co_2040)); - - memcpy((u8 *) bss_co_2040 + - sizeof(struct mwifiex_ie_types_header), - bss_desc->bcn_bss_co_2040 + - sizeof(struct ieee_types_header), - le16_to_cpu(bss_co_2040->header.len)); - - *buffer += sizeof(struct mwifiex_ie_types_2040bssco); - ret_len += sizeof(struct mwifiex_ie_types_2040bssco); - } - - if (bss_desc->bcn_ext_cap) { - hdr = (void *)bss_desc->bcn_ext_cap; - ext_cap = (struct mwifiex_ie_types_extcap *) *buffer; - memset(ext_cap, 0, sizeof(struct mwifiex_ie_types_extcap)); - ext_cap->header.type = cpu_to_le16(WLAN_EID_EXT_CAPABILITY); - ext_cap->header.len = cpu_to_le16(hdr->len); - - memcpy((u8 *)ext_cap->ext_capab, - bss_desc->bcn_ext_cap + sizeof(struct ieee_types_header), - le16_to_cpu(ext_cap->header.len)); - - if (hdr->len > 3 && - ext_cap->ext_capab[3] & WLAN_EXT_CAPA4_INTERWORKING_ENABLED) - priv->hs2_enabled = true; - else - priv->hs2_enabled = false; - - *buffer += sizeof(struct mwifiex_ie_types_extcap) + hdr->len; - ret_len += sizeof(struct mwifiex_ie_types_extcap) + hdr->len; - } - - return ret_len; -} - -/* - * This function checks if the given pointer is valid entry of - * Tx BA Stream table. - */ -static int mwifiex_is_tx_ba_stream_ptr_valid(struct mwifiex_private *priv, - struct mwifiex_tx_ba_stream_tbl *tx_tbl_ptr) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (tx_ba_tsr_tbl == tx_tbl_ptr) - return true; - } - - return false; -} - -/* - * This function deletes the given entry in Tx BA Stream table. - * - * The function also performs a validity check on the supplied - * pointer before trying to delete. - */ -void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl) -{ - if (!tx_ba_tsr_tbl && - mwifiex_is_tx_ba_stream_ptr_valid(priv, tx_ba_tsr_tbl)) - return; - - mwifiex_dbg(priv->adapter, INFO, - "info: tx_ba_tsr_tbl %p\n", tx_ba_tsr_tbl); - - list_del(&tx_ba_tsr_tbl->list); - - kfree(tx_ba_tsr_tbl); -} - -/* - * This function deletes all the entries in Tx BA Stream table. - */ -void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv) -{ - int i; - struct mwifiex_tx_ba_stream_tbl *del_tbl_ptr, *tmp_node; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry_safe(del_tbl_ptr, tmp_node, - &priv->tx_ba_stream_tbl_ptr, list) - mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, del_tbl_ptr); - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); - - for (i = 0; i < MAX_NUM_TID; ++i) - priv->aggr_prio_tbl[i].ampdu_ap = - priv->aggr_prio_tbl[i].ampdu_user; -} - -/* - * This function returns the pointer to an entry in BA Stream - * table which matches the given RA/TID pair. - */ -struct mwifiex_tx_ba_stream_tbl * -mwifiex_get_ba_tbl(struct mwifiex_private *priv, int tid, u8 *ra) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (ether_addr_equal_unaligned(tx_ba_tsr_tbl->ra, ra) && - tx_ba_tsr_tbl->tid == tid) { - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, - flags); - return tx_ba_tsr_tbl; - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - return NULL; -} - -/* - * This function creates an entry in Tx BA stream table for the - * given RA/TID pair. - */ -void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, - enum mwifiex_ba_status ba_status) -{ - struct mwifiex_tx_ba_stream_tbl *new_node; - struct mwifiex_ra_list_tbl *ra_list; - unsigned long flags; - int tid_down; - - if (!mwifiex_get_ba_tbl(priv, tid, ra)) { - new_node = kzalloc(sizeof(struct mwifiex_tx_ba_stream_tbl), - GFP_ATOMIC); - if (!new_node) - return; - - tid_down = mwifiex_wmm_downgrade_tid(priv, tid); - ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, ra); - if (ra_list) { - ra_list->ba_status = ba_status; - ra_list->amsdu_in_ampdu = false; - } - INIT_LIST_HEAD(&new_node->list); - - new_node->tid = tid; - new_node->ba_status = ba_status; - memcpy(new_node->ra, ra, ETH_ALEN); - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_add_tail(&new_node->list, &priv->tx_ba_stream_tbl_ptr); - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - } -} - -/* - * This function sends an add BA request to the given TID/RA pair. - */ -int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac) -{ - struct host_cmd_ds_11n_addba_req add_ba_req; - u32 tx_win_size = priv->add_ba_param.tx_win_size; - static u8 dialog_tok; - int ret; - unsigned long flags; - u16 block_ack_param_set; - - mwifiex_dbg(priv->adapter, CMD, "cmd: %s: tid %d\n", __func__, tid); - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - priv->adapter->is_hw_11ac_capable && - memcmp(priv->cfg_bssid, peer_mac, ETH_ALEN)) { - struct mwifiex_sta_node *sta_ptr; - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_ptr = mwifiex_get_sta_entry(priv, peer_mac); - if (!sta_ptr) { - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - mwifiex_dbg(priv->adapter, ERROR, - "BA setup with unknown TDLS peer %pM!\n", - peer_mac); - return -1; - } - if (sta_ptr->is_11ac_enabled) - tx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE; - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - } - - block_ack_param_set = (u16)((tid << BLOCKACKPARAM_TID_POS) | - tx_win_size << BLOCKACKPARAM_WINSIZE_POS | - IMMEDIATE_BLOCK_ACK); - - /* enable AMSDU inside AMPDU */ - if (priv->add_ba_param.tx_amsdu && - (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) - block_ack_param_set |= BLOCKACKPARAM_AMSDU_SUPP_MASK; - - add_ba_req.block_ack_param_set = cpu_to_le16(block_ack_param_set); - add_ba_req.block_ack_tmo = cpu_to_le16((u16)priv->add_ba_param.timeout); - - ++dialog_tok; - - if (dialog_tok == 0) - dialog_tok = 1; - - add_ba_req.dialog_token = dialog_tok; - memcpy(&add_ba_req.peer_mac_addr, peer_mac, ETH_ALEN); - - /* We don't wait for the response of this command */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_REQ, - 0, 0, &add_ba_req, false); - - return ret; -} - -/* - * This function sends a delete BA request to the given TID/RA pair. - */ -int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, - int initiator) -{ - struct host_cmd_ds_11n_delba delba; - int ret; - uint16_t del_ba_param_set; - - memset(&delba, 0, sizeof(delba)); - delba.del_ba_param_set = cpu_to_le16(tid << DELBA_TID_POS); - - del_ba_param_set = le16_to_cpu(delba.del_ba_param_set); - if (initiator) - del_ba_param_set |= IEEE80211_DELBA_PARAM_INITIATOR_MASK; - else - del_ba_param_set &= ~IEEE80211_DELBA_PARAM_INITIATOR_MASK; - - memcpy(&delba.peer_mac_addr, peer_mac, ETH_ALEN); - - /* We don't wait for the response of this command */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, - HostCmd_ACT_GEN_SET, 0, &delba, false); - - return ret; -} - -/* - * This function sends delba to specific tid - */ -void mwifiex_11n_delba(struct mwifiex_private *priv, int tid) -{ - struct mwifiex_rx_reorder_tbl *rx_reor_tbl_ptr; - - if (list_empty(&priv->rx_reorder_tbl_ptr)) { - dev_dbg(priv->adapter->dev, - "mwifiex_11n_delba: rx_reorder_tbl_ptr empty\n"); - return; - } - - list_for_each_entry(rx_reor_tbl_ptr, &priv->rx_reorder_tbl_ptr, list) { - if (rx_reor_tbl_ptr->tid == tid) { - dev_dbg(priv->adapter->dev, - "Send delba to tid=%d, %pM\n", - tid, rx_reor_tbl_ptr->ta); - mwifiex_send_delba(priv, tid, rx_reor_tbl_ptr->ta, 0); - return; - } - } -} - -/* - * This function handles the command response of a delete BA request. - */ -void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba) -{ - struct host_cmd_ds_11n_delba *cmd_del_ba = - (struct host_cmd_ds_11n_delba *) del_ba; - uint16_t del_ba_param_set = le16_to_cpu(cmd_del_ba->del_ba_param_set); - int tid; - - tid = del_ba_param_set >> DELBA_TID_POS; - - mwifiex_del_ba_tbl(priv, tid, cmd_del_ba->peer_mac_addr, - TYPE_DELBA_RECEIVE, INITIATOR_BIT(del_ba_param_set)); -} - -/* - * This function retrieves the Rx reordering table. - */ -int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_rx_reorder_tbl *buf) -{ - int i; - struct mwifiex_ds_rx_reorder_tbl *rx_reo_tbl = buf; - struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr; - int count = 0; - unsigned long flags; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry(rx_reorder_tbl_ptr, &priv->rx_reorder_tbl_ptr, - list) { - rx_reo_tbl->tid = (u16) rx_reorder_tbl_ptr->tid; - memcpy(rx_reo_tbl->ta, rx_reorder_tbl_ptr->ta, ETH_ALEN); - rx_reo_tbl->start_win = rx_reorder_tbl_ptr->start_win; - rx_reo_tbl->win_size = rx_reorder_tbl_ptr->win_size; - for (i = 0; i < rx_reorder_tbl_ptr->win_size; ++i) { - if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) - rx_reo_tbl->buffer[i] = true; - else - rx_reo_tbl->buffer[i] = false; - } - rx_reo_tbl++; - count++; - - if (count >= MWIFIEX_MAX_RX_BASTREAM_SUPPORTED) - break; - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return count; -} - -/* - * This function retrieves the Tx BA stream table. - */ -int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_tx_ba_stream_tbl *buf) -{ - struct mwifiex_tx_ba_stream_tbl *tx_ba_tsr_tbl; - struct mwifiex_ds_tx_ba_stream_tbl *rx_reo_tbl = buf; - int count = 0; - unsigned long flags; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_ba_tsr_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - rx_reo_tbl->tid = (u16) tx_ba_tsr_tbl->tid; - mwifiex_dbg(priv->adapter, DATA, "data: %s tid=%d\n", - __func__, rx_reo_tbl->tid); - memcpy(rx_reo_tbl->ra, tx_ba_tsr_tbl->ra, ETH_ALEN); - rx_reo_tbl->amsdu = tx_ba_tsr_tbl->amsdu; - rx_reo_tbl++; - count++; - if (count >= MWIFIEX_MAX_TX_BASTREAM_SUPPORTED) - break; - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - return count; -} - -/* - * This function retrieves the entry for specific tx BA stream table by RA and - * deletes it. - */ -void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra) -{ - struct mwifiex_tx_ba_stream_tbl *tbl, *tmp; - unsigned long flags; - - if (!ra) - return; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry_safe(tbl, tmp, &priv->tx_ba_stream_tbl_ptr, list) { - if (!memcmp(tbl->ra, ra, ETH_ALEN)) { - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, - flags); - mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, tbl); - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - return; -} - -/* This function initializes the BlockACK setup information for given - * mwifiex_private structure. - */ -void mwifiex_set_ba_params(struct mwifiex_private *priv) -{ - priv->add_ba_param.timeout = MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - priv->add_ba_param.tx_win_size = - MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE; - priv->add_ba_param.rx_win_size = - MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE; - } else { - priv->add_ba_param.tx_win_size = - MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; - priv->add_ba_param.rx_win_size = - MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; - } - - priv->add_ba_param.tx_amsdu = true; - priv->add_ba_param.rx_amsdu = true; - - return; -} - -u8 mwifiex_get_sec_chan_offset(int chan) -{ - u8 sec_offset; - - switch (chan) { - case 36: - case 44: - case 52: - case 60: - case 100: - case 108: - case 116: - case 124: - case 132: - case 140: - case 149: - case 157: - sec_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - break; - case 40: - case 48: - case 56: - case 64: - case 104: - case 112: - case 120: - case 128: - case 136: - case 144: - case 153: - case 161: - sec_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; - break; - case 165: - default: - sec_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; - break; - } - - return sec_offset; -} - -/* This function will send DELBA to entries in the priv's - * Tx BA stream table - */ -static void -mwifiex_send_delba_txbastream_tbl(struct mwifiex_private *priv, u8 tid) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_tx_ba_stream_tbl *tx_ba_stream_tbl_ptr; - - if (list_empty(&priv->tx_ba_stream_tbl_ptr)) - return; - - list_for_each_entry(tx_ba_stream_tbl_ptr, - &priv->tx_ba_stream_tbl_ptr, list) { - if (tx_ba_stream_tbl_ptr->ba_status == BA_SETUP_COMPLETE) { - if (tid == tx_ba_stream_tbl_ptr->tid) { - dev_dbg(adapter->dev, - "Tx:Send delba to tid=%d, %pM\n", tid, - tx_ba_stream_tbl_ptr->ra); - mwifiex_send_delba(priv, - tx_ba_stream_tbl_ptr->tid, - tx_ba_stream_tbl_ptr->ra, 1); - return; - } - } - } -} - -/* This function updates all the tx_win_size - */ -void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *adapter) -{ - u8 i; - u32 tx_win_size; - struct mwifiex_private *priv; - - for (i = 0; i < adapter->priv_num; i++) { - if (!adapter->priv[i]) - continue; - priv = adapter->priv[i]; - tx_win_size = priv->add_ba_param.tx_win_size; - - if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) - priv->add_ba_param.tx_win_size = - MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; - - if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) - priv->add_ba_param.tx_win_size = - MWIFIEX_STA_AMPDU_DEF_TXWINSIZE; - - if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) - priv->add_ba_param.tx_win_size = - MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE; - - if (adapter->coex_win_size) { - if (adapter->coex_tx_win_size) - priv->add_ba_param.tx_win_size = - adapter->coex_tx_win_size; - } - - if (tx_win_size != priv->add_ba_param.tx_win_size) { - if (!priv->media_connected) - continue; - for (i = 0; i < MAX_NUM_TID; i++) - mwifiex_send_delba_txbastream_tbl(priv, i); - } - } -} diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h deleted file mode 100644 index afdd58aa90de..000000000000 --- a/drivers/net/wireless/mwifiex/11n.h +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11N_H_ -#define _MWIFIEX_11N_H_ - -#include "11n_aggr.h" -#include "11n_rxreorder.h" -#include "wmm.h" - -int mwifiex_ret_11n_delba(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_ret_11n_addba_req(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_cmd_11n_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 cmd_action, - struct mwifiex_ds_11n_tx_cfg *txcfg); -int mwifiex_cmd_append_11n_tlv(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 **buffer); -int mwifiex_fill_cap_info(struct mwifiex_private *, u8 radio_type, - struct ieee80211_ht_cap *); -int mwifiex_set_get_11n_htcap_cfg(struct mwifiex_private *priv, - u16 action, int *htcap_cfg); -void mwifiex_11n_delete_tx_ba_stream_tbl_entry(struct mwifiex_private *priv, - struct mwifiex_tx_ba_stream_tbl - *tx_tbl); -void mwifiex_11n_delete_all_tx_ba_stream_tbl(struct mwifiex_private *priv); -struct mwifiex_tx_ba_stream_tbl *mwifiex_get_ba_tbl(struct - mwifiex_private - *priv, int tid, - u8 *ra); -void mwifiex_create_ba_tbl(struct mwifiex_private *priv, u8 *ra, int tid, - enum mwifiex_ba_status ba_status); -int mwifiex_send_addba(struct mwifiex_private *priv, int tid, u8 *peer_mac); -int mwifiex_send_delba(struct mwifiex_private *priv, int tid, u8 *peer_mac, - int initiator); -void mwifiex_11n_delete_ba_stream(struct mwifiex_private *priv, u8 *del_ba); -int mwifiex_get_rx_reorder_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_rx_reorder_tbl *buf); -int mwifiex_get_tx_ba_stream_tbl(struct mwifiex_private *priv, - struct mwifiex_ds_tx_ba_stream_tbl *buf); -int mwifiex_cmd_recfg_tx_buf(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - int cmd_action, u16 *buf_size); -int mwifiex_cmd_amsdu_aggr_ctrl(struct host_cmd_ds_command *cmd, - int cmd_action, - struct mwifiex_ds_11n_amsdu_aggr_ctrl *aa_ctrl); -void mwifiex_del_tx_ba_stream_tbl_by_ra(struct mwifiex_private *priv, u8 *ra); -u8 mwifiex_get_sec_chan_offset(int chan); - -static inline u8 -mwifiex_is_station_ampdu_allowed(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int tid) -{ - struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ptr->ra); - - if (unlikely(!node)) - return false; - - return (node->ampdu_sta[tid] != BA_STREAM_NOT_ALLOWED) ? true : false; -} - -/* This function checks whether AMPDU is allowed or not for a particular TID. */ -static inline u8 -mwifiex_is_ampdu_allowed(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int tid) -{ - if (is_broadcast_ether_addr(ptr->ra)) - return false; - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); - } else { - if (ptr->tdls_link) - return mwifiex_is_station_ampdu_allowed(priv, ptr, tid); - - return (priv->aggr_prio_tbl[tid].ampdu_ap != - BA_STREAM_NOT_ALLOWED) ? true : false; - } -} - -/* - * This function checks whether AMSDU is allowed or not for a particular TID. - */ -static inline u8 -mwifiex_is_amsdu_allowed(struct mwifiex_private *priv, int tid) -{ - return (((priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED) && - (priv->is_data_rate_auto || !(priv->bitmap_rates[2] & 0x03))) - ? true : false); -} - -/* - * This function checks whether a space is available for new BA stream or not. - */ -static inline u8 mwifiex_space_avail_for_new_ba_stream( - struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - u8 i; - u32 ba_stream_num = 0, ba_stream_max; - - ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) - ba_stream_num += mwifiex_wmm_list_len( - &priv->tx_ba_stream_tbl_ptr); - } - - if (adapter->fw_api_ver == MWIFIEX_FW_V15) { - ba_stream_max = - GETSUPP_TXBASTREAMS(adapter->hw_dot_11n_dev_cap); - if (!ba_stream_max) - ba_stream_max = MWIFIEX_MAX_TX_BASTREAM_SUPPORTED; - } - - return ((ba_stream_num < ba_stream_max) ? true : false); -} - -/* - * This function finds the correct Tx BA stream to delete. - * - * Upon successfully locating, both the TID and the RA are returned. - */ -static inline u8 -mwifiex_find_stream_to_delete(struct mwifiex_private *priv, int ptr_tid, - int *ptid, u8 *ra) -{ - int tid; - u8 ret = false; - struct mwifiex_tx_ba_stream_tbl *tx_tbl; - unsigned long flags; - - tid = priv->aggr_prio_tbl[ptr_tid].ampdu_user; - - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - list_for_each_entry(tx_tbl, &priv->tx_ba_stream_tbl_ptr, list) { - if (tid > priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user) { - tid = priv->aggr_prio_tbl[tx_tbl->tid].ampdu_user; - *ptid = tx_tbl->tid; - memcpy(ra, tx_tbl->ra, ETH_ALEN); - ret = true; - } - } - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - - return ret; -} - -/* - * This function checks whether associated station is 11n enabled - */ -static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv, - struct mwifiex_sta_node *node) -{ - - if (!node || (priv->bss_role != MWIFIEX_BSS_ROLE_UAP) || - !priv->ap_11n_enabled) - return 0; - - return node->is_11n_enabled; -} - -static inline u8 -mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, const u8 *ra) -{ - struct mwifiex_sta_node *node = mwifiex_get_sta_entry(priv, ra); - if (node) - return node->is_11n_enabled; - - return false; -} -#endif /* !_MWIFIEX_11N_H_ */ diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c deleted file mode 100644 index aa498e0d2204..000000000000 --- a/drivers/net/wireless/mwifiex/11n_aggr.c +++ /dev/null @@ -1,318 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n Aggregation - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11n_aggr.h" - -/* - * Creates an AMSDU subframe for aggregation into one AMSDU packet. - * - * The resultant AMSDU subframe format is - - * - * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ - * | DA | SA | Length | SNAP header | MSDU | - * | data[0..5] | data[6..11] | | | data[14..] | - * +---- ~ -----+---- ~ ------+---- ~ -----+----- ~ -----+---- ~ -----+ - * <--6-bytes--> <--6-bytes--> <--2-bytes--><--8-bytes--> <--n-bytes--> - * - * This function also computes the amount of padding required to make the - * buffer length multiple of 4 bytes. - * - * Data => |DA|SA|SNAP-TYPE|........ .| - * MSDU => |DA|SA|Length|SNAP|...... ..| - */ -static int -mwifiex_11n_form_amsdu_pkt(struct sk_buff *skb_aggr, - struct sk_buff *skb_src, int *pad) - -{ - int dt_offset; - struct rfc_1042_hdr snap = { - 0xaa, /* LLC DSAP */ - 0xaa, /* LLC SSAP */ - 0x03, /* LLC CTRL */ - {0x00, 0x00, 0x00}, /* SNAP OUI */ - 0x0000 /* SNAP type */ - /* - * This field will be overwritten - * later with ethertype - */ - }; - struct tx_packet_hdr *tx_header; - - tx_header = (void *)skb_put(skb_aggr, sizeof(*tx_header)); - - /* Copy DA and SA */ - dt_offset = 2 * ETH_ALEN; - memcpy(&tx_header->eth803_hdr, skb_src->data, dt_offset); - - /* Copy SNAP header */ - snap.snap_type = ((struct ethhdr *)skb_src->data)->h_proto; - - dt_offset += sizeof(__be16); - - memcpy(&tx_header->rfc1042_hdr, &snap, sizeof(struct rfc_1042_hdr)); - - skb_pull(skb_src, dt_offset); - - /* Update Length field */ - tx_header->eth803_hdr.h_proto = htons(skb_src->len + LLC_SNAP_LEN); - - /* Add payload */ - memcpy(skb_put(skb_aggr, skb_src->len), skb_src->data, skb_src->len); - - /* Add padding for new MSDU to start from 4 byte boundary */ - *pad = (4 - ((unsigned long)skb_aggr->tail & 0x3)) % 4; - - return skb_aggr->len + *pad; -} - -/* - * Adds TxPD to AMSDU header. - * - * Each AMSDU packet will contain one TxPD at the beginning, - * followed by multiple AMSDU subframes. - */ -static void -mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct txpd *local_tx_pd; - struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - unsigned int pad; - int headroom = (priv->adapter->iface_type == - MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; - - pad = ((void *)skb->data - sizeof(*local_tx_pd) - - headroom - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1); - skb_push(skb, pad); - - skb_push(skb, sizeof(*local_tx_pd)); - - local_tx_pd = (struct txpd *) skb->data; - memset(local_tx_pd, 0, sizeof(struct txpd)); - - /* Original priority has been overwritten */ - local_tx_pd->priority = (u8) skb->priority; - local_tx_pd->pkt_delay_2ms = - mwifiex_wmm_compute_drv_pkt_delay(priv, skb); - local_tx_pd->bss_num = priv->bss_num; - local_tx_pd->bss_type = priv->bss_type; - /* Always zero as the data is followed by struct txpd */ - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd) + - pad); - local_tx_pd->tx_pkt_type = cpu_to_le16(PKT_TYPE_AMSDU); - local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len - - sizeof(*local_tx_pd) - - pad); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) - local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; - - if (local_tx_pd->tx_control == 0) - /* TxCtrl set by user or default */ - local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && - priv->adapter->pps_uapsd_mode) { - if (true == mwifiex_check_last_packet_indication(priv)) { - priv->adapter->tx_lock_flag = true; - local_tx_pd->flags = - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; - } - } -} - -/* - * Create aggregated packet. - * - * This function creates an aggregated MSDU packet, by combining buffers - * from the RA list. Each individual buffer is encapsulated as an AMSDU - * subframe and all such subframes are concatenated together to form the - * AMSDU packet. - * - * A TxPD is also added to the front of the resultant AMSDU packets for - * transmission. The resultant packets format is - - * - * +---- ~ ----+------ ~ ------+------ ~ ------+-..-+------ ~ ------+ - * | TxPD |AMSDU sub-frame|AMSDU sub-frame| .. |AMSDU sub-frame| - * | | 1 | 2 | .. | n | - * +---- ~ ----+------ ~ ------+------ ~ ------+ .. +------ ~ ------+ - */ -int -mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *pra_list, - int ptrindex, unsigned long ra_list_flags) - __releases(&priv->wmm.ra_list_spinlock) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct sk_buff *skb_aggr, *skb_src; - struct mwifiex_txinfo *tx_info_aggr, *tx_info_src; - int pad = 0, aggr_num = 0, ret; - struct mwifiex_tx_param tx_param; - struct txpd *ptx_pd = NULL; - int headroom = adapter->iface_type == MWIFIEX_USB ? 0 : INTF_HEADER_LEN; - - skb_src = skb_peek(&pra_list->skb_head); - if (!skb_src) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return 0; - } - - tx_info_src = MWIFIEX_SKB_TXCB(skb_src); - skb_aggr = mwifiex_alloc_dma_align_buf(adapter->tx_buf_size, - GFP_ATOMIC | GFP_DMA); - if (!skb_aggr) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return -1; - } - skb_reserve(skb_aggr, MWIFIEX_MIN_DATA_HEADER_LEN); - tx_info_aggr = MWIFIEX_SKB_TXCB(skb_aggr); - - memset(tx_info_aggr, 0, sizeof(*tx_info_aggr)); - tx_info_aggr->bss_type = tx_info_src->bss_type; - tx_info_aggr->bss_num = tx_info_src->bss_num; - - if (tx_info_src->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) - tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; - tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_AGGR_PKT; - skb_aggr->priority = skb_src->priority; - skb_aggr->tstamp = skb_src->tstamp; - - skb_aggr->tstamp = ktime_get_real(); - - do { - /* Check if AMSDU can accommodate this MSDU */ - if (skb_tailroom(skb_aggr) < (skb_src->len + LLC_SNAP_LEN)) - break; - - skb_src = skb_dequeue(&pra_list->skb_head); - pra_list->total_pkt_count--; - atomic_dec(&priv->wmm.tx_pkts_queued); - aggr_num++; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_11n_form_amsdu_pkt(skb_aggr, skb_src, &pad); - - mwifiex_write_data_complete(adapter, skb_src, 0, 0); - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return -1; - } - - if (skb_tailroom(skb_aggr) < pad) { - pad = 0; - break; - } - skb_put(skb_aggr, pad); - - skb_src = skb_peek(&pra_list->skb_head); - - } while (skb_src); - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - - /* Last AMSDU packet does not need padding */ - skb_trim(skb_aggr, skb_aggr->len - pad); - - /* Form AMSDU */ - mwifiex_11n_form_amsdu_txpd(priv, skb_aggr); - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - ptx_pd = (struct txpd *)skb_aggr->data; - - skb_push(skb_aggr, headroom); - tx_info_aggr->aggr_num = aggr_num * 2; - if (adapter->data_sent || adapter->tx_lock_flag) { - atomic_add(aggr_num * 2, &adapter->tx_queued); - skb_queue_tail(&adapter->tx_data_q, skb_aggr); - return 0; - } - - if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, - skb_aggr, NULL); - } else { - if (skb_src) - tx_param.next_pkt_len = - skb_src->len + sizeof(struct txpd); - else - tx_param.next_pkt_len = 0; - - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb_aggr, &tx_param); - } - switch (ret) { - case -EBUSY: - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - if (!mwifiex_is_ralist_valid(priv, pra_list, ptrindex)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_write_data_complete(adapter, skb_aggr, 1, -1); - return -1; - } - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && - adapter->pps_uapsd_mode && adapter->tx_lock_flag) { - priv->adapter->tx_lock_flag = false; - if (ptx_pd) - ptx_pd->flags = 0; - } - - skb_queue_tail(&pra_list->skb_head, skb_aggr); - - pra_list->total_pkt_count++; - - atomic_inc(&priv->wmm.tx_pkts_queued); - - tx_info_aggr->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); - break; - case -1: - mwifiex_dbg(adapter, ERROR, "%s: host_to_card failed: %#x\n", - __func__, ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); - return 0; - case -EINPROGRESS: - break; - case 0: - mwifiex_write_data_complete(adapter, skb_aggr, 1, ret); - break; - default: - break; - } - if (ret != -EBUSY) { - mwifiex_rotate_priolists(priv, pra_list, ptrindex); - } - - return 0; -} diff --git a/drivers/net/wireless/mwifiex/11n_aggr.h b/drivers/net/wireless/mwifiex/11n_aggr.h deleted file mode 100644 index 0cd2a3eb6c17..000000000000 --- a/drivers/net/wireless/mwifiex/11n_aggr.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n Aggregation - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11N_AGGR_H_ -#define _MWIFIEX_11N_AGGR_H_ - -#define PKT_TYPE_AMSDU 0xE6 -#define MIN_NUM_AMSDU 2 - -int mwifiex_11n_deaggregate_pkt(struct mwifiex_private *priv, - struct sk_buff *skb); -int mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, - int ptr_index, unsigned long flags) - __releases(&priv->wmm.ra_list_spinlock); - -#endif /* !_MWIFIEX_11N_AGGR_H_ */ diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.c b/drivers/net/wireless/mwifiex/11n_rxreorder.c deleted file mode 100644 index b3970a8c9e48..000000000000 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.c +++ /dev/null @@ -1,910 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11n_rxreorder.h" - -/* This function will dispatch amsdu packet and forward it to kernel/upper - * layer. - */ -static int mwifiex_11n_dispatch_amsdu_pkt(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct rxpd *local_rx_pd = (struct rxpd *)(skb->data); - int ret; - - if (le16_to_cpu(local_rx_pd->rx_pkt_type) == PKT_TYPE_AMSDU) { - struct sk_buff_head list; - struct sk_buff *rx_skb; - - __skb_queue_head_init(&list); - - skb_pull(skb, le16_to_cpu(local_rx_pd->rx_pkt_offset)); - skb_trim(skb, le16_to_cpu(local_rx_pd->rx_pkt_length)); - - ieee80211_amsdu_to_8023s(skb, &list, priv->curr_addr, - priv->wdev.iftype, 0, false); - - while (!skb_queue_empty(&list)) { - rx_skb = __skb_dequeue(&list); - ret = mwifiex_recv_packet(priv, rx_skb); - if (ret == -1) - mwifiex_dbg(priv->adapter, ERROR, - "Rx of A-MSDU failed"); - } - return 0; - } - - return -1; -} - -/* This function will process the rx packet and forward it to kernel/upper - * layer. - */ -static int mwifiex_11n_dispatch_pkt(struct mwifiex_private *priv, void *payload) -{ - int ret = mwifiex_11n_dispatch_amsdu_pkt(priv, payload); - - if (!ret) - return 0; - - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - return mwifiex_handle_uap_rx_forward(priv, payload); - - return mwifiex_process_rx_packet(priv, payload); -} - -/* - * This function dispatches all packets in the Rx reorder table until the - * start window. - * - * There could be holes in the buffer, which are skipped by the function. - * Since the buffer is linear, the function uses rotation to simulate - * circular buffer. - */ -static void -mwifiex_11n_dispatch_pkt_until_start_win(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl *tbl, - int start_win) -{ - int pkt_to_send, i; - void *rx_tmp_ptr; - unsigned long flags; - - pkt_to_send = (start_win > tbl->start_win) ? - min((start_win - tbl->start_win), tbl->win_size) : - tbl->win_size; - - for (i = 0; i < pkt_to_send; ++i) { - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - rx_tmp_ptr = NULL; - if (tbl->rx_reorder_ptr[i]) { - rx_tmp_ptr = tbl->rx_reorder_ptr[i]; - tbl->rx_reorder_ptr[i] = NULL; - } - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - if (rx_tmp_ptr) - mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); - } - - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - /* - * We don't have a circular buffer, hence use rotation to simulate - * circular buffer - */ - for (i = 0; i < tbl->win_size - pkt_to_send; ++i) { - tbl->rx_reorder_ptr[i] = tbl->rx_reorder_ptr[pkt_to_send + i]; - tbl->rx_reorder_ptr[pkt_to_send + i] = NULL; - } - - tbl->start_win = start_win; - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -} - -/* - * This function dispatches all packets in the Rx reorder table until - * a hole is found. - * - * The start window is adjusted automatically when a hole is located. - * Since the buffer is linear, the function uses rotation to simulate - * circular buffer. - */ -static void -mwifiex_11n_scan_and_dispatch(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl *tbl) -{ - int i, j, xchg; - void *rx_tmp_ptr; - unsigned long flags; - - for (i = 0; i < tbl->win_size; ++i) { - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - if (!tbl->rx_reorder_ptr[i]) { - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - break; - } - rx_tmp_ptr = tbl->rx_reorder_ptr[i]; - tbl->rx_reorder_ptr[i] = NULL; - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); - mwifiex_11n_dispatch_pkt(priv, rx_tmp_ptr); - } - - spin_lock_irqsave(&priv->rx_pkt_lock, flags); - /* - * We don't have a circular buffer, hence use rotation to simulate - * circular buffer - */ - if (i > 0) { - xchg = tbl->win_size - i; - for (j = 0; j < xchg; ++j) { - tbl->rx_reorder_ptr[j] = tbl->rx_reorder_ptr[i + j]; - tbl->rx_reorder_ptr[i + j] = NULL; - } - } - tbl->start_win = (tbl->start_win + i) & (MAX_TID_VALUE - 1); - spin_unlock_irqrestore(&priv->rx_pkt_lock, flags); -} - -/* - * This function deletes the Rx reorder table and frees the memory. - * - * The function stops the associated timer and dispatches all the - * pending packets in the Rx reorder table before deletion. - */ -static void -mwifiex_del_rx_reorder_entry(struct mwifiex_private *priv, - struct mwifiex_rx_reorder_tbl *tbl) -{ - unsigned long flags; - int start_win; - - if (!tbl) - return; - - spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags); - priv->adapter->rx_locked = true; - if (priv->adapter->rx_processing) { - spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags); - flush_workqueue(priv->adapter->rx_workqueue); - } else { - spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags); - } - - start_win = (tbl->start_win + tbl->win_size) & (MAX_TID_VALUE - 1); - mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); - - del_timer_sync(&tbl->timer_context.timer); - tbl->timer_context.timer_is_set = false; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_del(&tbl->list); - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - kfree(tbl->rx_reorder_ptr); - kfree(tbl); - - spin_lock_irqsave(&priv->adapter->rx_proc_lock, flags); - priv->adapter->rx_locked = false; - spin_unlock_irqrestore(&priv->adapter->rx_proc_lock, flags); - -} - -/* - * This function returns the pointer to an entry in Rx reordering - * table which matches the given TA/TID pair. - */ -struct mwifiex_rx_reorder_tbl * -mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta) -{ - struct mwifiex_rx_reorder_tbl *tbl; - unsigned long flags; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) { - if (!memcmp(tbl->ta, ta, ETH_ALEN) && tbl->tid == tid) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, - flags); - return tbl; - } - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return NULL; -} - -/* This function retrieves the pointer to an entry in Rx reordering - * table which matches the given TA and deletes it. - */ -void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta) -{ - struct mwifiex_rx_reorder_tbl *tbl, *tmp; - unsigned long flags; - - if (!ta) - return; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry_safe(tbl, tmp, &priv->rx_reorder_tbl_ptr, list) { - if (!memcmp(tbl->ta, ta, ETH_ALEN)) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, - flags); - mwifiex_del_rx_reorder_entry(priv, tbl); - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - } - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return; -} - -/* - * This function finds the last sequence number used in the packets - * buffered in Rx reordering table. - */ -static int -mwifiex_11n_find_last_seq_num(struct reorder_tmr_cnxt *ctx) -{ - struct mwifiex_rx_reorder_tbl *rx_reorder_tbl_ptr = ctx->ptr; - struct mwifiex_private *priv = ctx->priv; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - for (i = rx_reorder_tbl_ptr->win_size - 1; i >= 0; --i) { - if (rx_reorder_tbl_ptr->rx_reorder_ptr[i]) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, - flags); - return i; - } - } - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - return -1; -} - -/* - * This function flushes all the packets in Rx reordering table. - * - * The function checks if any packets are currently buffered in the - * table or not. In case there are packets available, it dispatches - * them and then dumps the Rx reordering table. - */ -static void -mwifiex_flush_data(unsigned long context) -{ - struct reorder_tmr_cnxt *ctx = - (struct reorder_tmr_cnxt *) context; - int start_win, seq_num; - - ctx->timer_is_set = false; - seq_num = mwifiex_11n_find_last_seq_num(ctx); - - if (seq_num < 0) - return; - - mwifiex_dbg(ctx->priv->adapter, INFO, "info: flush data %d\n", seq_num); - start_win = (ctx->ptr->start_win + seq_num + 1) & (MAX_TID_VALUE - 1); - mwifiex_11n_dispatch_pkt_until_start_win(ctx->priv, ctx->ptr, - start_win); -} - -/* - * This function creates an entry in Rx reordering table for the - * given TA/TID. - * - * The function also initializes the entry with sequence number, window - * size as well as initializes the timer. - * - * If the received TA/TID pair is already present, all the packets are - * dispatched and the window size is moved until the SSN. - */ -static void -mwifiex_11n_create_rx_reorder_tbl(struct mwifiex_private *priv, u8 *ta, - int tid, int win_size, int seq_num) -{ - int i; - struct mwifiex_rx_reorder_tbl *tbl, *new_node; - u16 last_seq = 0; - unsigned long flags; - struct mwifiex_sta_node *node; - - /* - * If we get a TID, ta pair which is already present dispatch all the - * the packets and move the window size until the ssn - */ - tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); - if (tbl) { - mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, seq_num); - return; - } - /* if !tbl then create one */ - new_node = kzalloc(sizeof(struct mwifiex_rx_reorder_tbl), GFP_KERNEL); - if (!new_node) - return; - - INIT_LIST_HEAD(&new_node->list); - new_node->tid = tid; - memcpy(new_node->ta, ta, ETH_ALEN); - new_node->start_win = seq_num; - new_node->init_win = seq_num; - new_node->flags = 0; - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - if (mwifiex_queuing_ra_based(priv)) { - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { - node = mwifiex_get_sta_entry(priv, ta); - if (node) - last_seq = node->rx_seq[tid]; - } - } else { - node = mwifiex_get_sta_entry(priv, ta); - if (node) - last_seq = node->rx_seq[tid]; - else - last_seq = priv->rx_seq[tid]; - } - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - mwifiex_dbg(priv->adapter, INFO, - "info: last_seq=%d start_win=%d\n", - last_seq, new_node->start_win); - - if (last_seq != MWIFIEX_DEF_11N_RX_SEQ_NUM && - last_seq >= new_node->start_win) { - new_node->start_win = last_seq + 1; - new_node->flags |= RXREOR_INIT_WINDOW_SHIFT; - } - - new_node->win_size = win_size; - - new_node->rx_reorder_ptr = kzalloc(sizeof(void *) * win_size, - GFP_KERNEL); - if (!new_node->rx_reorder_ptr) { - kfree((u8 *) new_node); - mwifiex_dbg(priv->adapter, ERROR, - "%s: failed to alloc reorder_ptr\n", __func__); - return; - } - - new_node->timer_context.ptr = new_node; - new_node->timer_context.priv = priv; - new_node->timer_context.timer_is_set = false; - - setup_timer(&new_node->timer_context.timer, mwifiex_flush_data, - (unsigned long)&new_node->timer_context); - - for (i = 0; i < win_size; ++i) - new_node->rx_reorder_ptr[i] = NULL; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_add_tail(&new_node->list, &priv->rx_reorder_tbl_ptr); - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); -} - -static void -mwifiex_11n_rxreorder_timer_restart(struct mwifiex_rx_reorder_tbl *tbl) -{ - u32 min_flush_time; - - if (tbl->win_size >= MWIFIEX_BA_WIN_SIZE_32) - min_flush_time = MIN_FLUSH_TIMER_15_MS; - else - min_flush_time = MIN_FLUSH_TIMER_MS; - - mod_timer(&tbl->timer_context.timer, - jiffies + msecs_to_jiffies(min_flush_time * tbl->win_size)); - - tbl->timer_context.timer_is_set = true; -} - -/* - * This function prepares command for adding a BA request. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting add BA request buffer - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct host_cmd_ds_11n_addba_req *add_ba_req = &cmd->params.add_ba_req; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_REQ); - cmd->size = cpu_to_le16(sizeof(*add_ba_req) + S_DS_GEN); - memcpy(add_ba_req, data_buf, sizeof(*add_ba_req)); - - return 0; -} - -/* - * This function prepares command for adding a BA response. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting add BA response buffer - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct host_cmd_ds_11n_addba_req - *cmd_addba_req) -{ - struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &cmd->params.add_ba_rsp; - struct mwifiex_sta_node *sta_ptr; - u32 rx_win_size = priv->add_ba_param.rx_win_size; - u8 tid; - int win_size; - unsigned long flags; - uint16_t block_ack_param_set; - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - priv->adapter->is_hw_11ac_capable && - memcmp(priv->cfg_bssid, cmd_addba_req->peer_mac_addr, ETH_ALEN)) { - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_ptr = mwifiex_get_sta_entry(priv, - cmd_addba_req->peer_mac_addr); - if (!sta_ptr) { - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - mwifiex_dbg(priv->adapter, ERROR, - "BA setup with unknown TDLS peer %pM!\n", - cmd_addba_req->peer_mac_addr); - return -1; - } - if (sta_ptr->is_11ac_enabled) - rx_win_size = MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE; - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - } - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_ADDBA_RSP); - cmd->size = cpu_to_le16(sizeof(*add_ba_rsp) + S_DS_GEN); - - memcpy(add_ba_rsp->peer_mac_addr, cmd_addba_req->peer_mac_addr, - ETH_ALEN); - add_ba_rsp->dialog_token = cmd_addba_req->dialog_token; - add_ba_rsp->block_ack_tmo = cmd_addba_req->block_ack_tmo; - add_ba_rsp->ssn = cmd_addba_req->ssn; - - block_ack_param_set = le16_to_cpu(cmd_addba_req->block_ack_param_set); - tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - add_ba_rsp->status_code = cpu_to_le16(ADDBA_RSP_STATUS_ACCEPT); - block_ack_param_set &= ~IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK; - - /* If we don't support AMSDU inside AMPDU, reset the bit */ - if (!priv->add_ba_param.rx_amsdu || - (priv->aggr_prio_tbl[tid].amsdu == BA_STREAM_NOT_ALLOWED)) - block_ack_param_set &= ~BLOCKACKPARAM_AMSDU_SUPP_MASK; - block_ack_param_set |= rx_win_size << BLOCKACKPARAM_WINSIZE_POS; - add_ba_rsp->block_ack_param_set = cpu_to_le16(block_ack_param_set); - win_size = (le16_to_cpu(add_ba_rsp->block_ack_param_set) - & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) - >> BLOCKACKPARAM_WINSIZE_POS; - cmd_addba_req->block_ack_param_set = cpu_to_le16(block_ack_param_set); - - mwifiex_11n_create_rx_reorder_tbl(priv, cmd_addba_req->peer_mac_addr, - tid, win_size, - le16_to_cpu(cmd_addba_req->ssn)); - return 0; -} - -/* - * This function prepares command for deleting a BA request. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting del BA request buffer - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct host_cmd_ds_11n_delba *del_ba = &cmd->params.del_ba; - - cmd->command = cpu_to_le16(HostCmd_CMD_11N_DELBA); - cmd->size = cpu_to_le16(sizeof(*del_ba) + S_DS_GEN); - memcpy(del_ba, data_buf, sizeof(*del_ba)); - - return 0; -} - -/* - * This function identifies if Rx reordering is needed for a received packet. - * - * In case reordering is required, the function will do the reordering - * before sending it to kernel. - * - * The Rx reorder table is checked first with the received TID/TA pair. If - * not found, the received packet is dispatched immediately. But if found, - * the packet is reordered and all the packets in the updated Rx reordering - * table is dispatched until a hole is found. - * - * For sequence number less than the starting window, the packet is dropped. - */ -int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *priv, - u16 seq_num, u16 tid, - u8 *ta, u8 pkt_type, void *payload) -{ - struct mwifiex_rx_reorder_tbl *tbl; - int prev_start_win, start_win, end_win, win_size; - u16 pkt_index; - bool init_window_shift = false; - int ret = 0; - - tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, ta); - if (!tbl) { - if (pkt_type != PKT_TYPE_BAR) - mwifiex_11n_dispatch_pkt(priv, payload); - return ret; - } - - if ((pkt_type == PKT_TYPE_AMSDU) && !tbl->amsdu) { - mwifiex_11n_dispatch_pkt(priv, payload); - return ret; - } - - start_win = tbl->start_win; - prev_start_win = start_win; - win_size = tbl->win_size; - end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); - if (tbl->flags & RXREOR_INIT_WINDOW_SHIFT) { - init_window_shift = true; - tbl->flags &= ~RXREOR_INIT_WINDOW_SHIFT; - } - - if (tbl->flags & RXREOR_FORCE_NO_DROP) { - mwifiex_dbg(priv->adapter, INFO, - "RXREOR_FORCE_NO_DROP when HS is activated\n"); - tbl->flags &= ~RXREOR_FORCE_NO_DROP; - } else if (init_window_shift && seq_num < start_win && - seq_num >= tbl->init_win) { - mwifiex_dbg(priv->adapter, INFO, - "Sender TID sequence number reset %d->%d for SSN %d\n", - start_win, seq_num, tbl->init_win); - tbl->start_win = start_win = seq_num; - end_win = ((start_win + win_size) - 1) & (MAX_TID_VALUE - 1); - } else { - /* - * If seq_num is less then starting win then ignore and drop - * the packet - */ - if ((start_win + TWOPOW11) > (MAX_TID_VALUE - 1)) { - if (seq_num >= ((start_win + TWOPOW11) & - (MAX_TID_VALUE - 1)) && - seq_num < start_win) { - ret = -1; - goto done; - } - } else if ((seq_num < start_win) || - (seq_num >= (start_win + TWOPOW11))) { - ret = -1; - goto done; - } - } - - /* - * If this packet is a BAR we adjust seq_num as - * WinStart = seq_num - */ - if (pkt_type == PKT_TYPE_BAR) - seq_num = ((seq_num + win_size) - 1) & (MAX_TID_VALUE - 1); - - if (((end_win < start_win) && - (seq_num < start_win) && (seq_num > end_win)) || - ((end_win > start_win) && ((seq_num > end_win) || - (seq_num < start_win)))) { - end_win = seq_num; - if (((end_win - win_size) + 1) >= 0) - start_win = (end_win - win_size) + 1; - else - start_win = (MAX_TID_VALUE - (win_size - end_win)) + 1; - mwifiex_11n_dispatch_pkt_until_start_win(priv, tbl, start_win); - } - - if (pkt_type != PKT_TYPE_BAR) { - if (seq_num >= start_win) - pkt_index = seq_num - start_win; - else - pkt_index = (seq_num+MAX_TID_VALUE) - start_win; - - if (tbl->rx_reorder_ptr[pkt_index]) { - ret = -1; - goto done; - } - - tbl->rx_reorder_ptr[pkt_index] = payload; - } - - /* - * Dispatch all packets sequentially from start_win until a - * hole is found and adjust the start_win appropriately - */ - mwifiex_11n_scan_and_dispatch(priv, tbl); - -done: - if (!tbl->timer_context.timer_is_set || - prev_start_win != tbl->start_win) - mwifiex_11n_rxreorder_timer_restart(tbl); - return ret; -} - -/* - * This function deletes an entry for a given TID/TA pair. - * - * The TID/TA are taken from del BA event body. - */ -void -mwifiex_del_ba_tbl(struct mwifiex_private *priv, int tid, u8 *peer_mac, - u8 type, int initiator) -{ - struct mwifiex_rx_reorder_tbl *tbl; - struct mwifiex_tx_ba_stream_tbl *ptx_tbl; - struct mwifiex_ra_list_tbl *ra_list; - u8 cleanup_rx_reorder_tbl; - unsigned long flags; - int tid_down; - - if (type == TYPE_DELBA_RECEIVE) - cleanup_rx_reorder_tbl = (initiator) ? true : false; - else - cleanup_rx_reorder_tbl = (initiator) ? false : true; - - mwifiex_dbg(priv->adapter, EVENT, "event: DELBA: %pM tid=%d initiator=%d\n", - peer_mac, tid, initiator); - - if (cleanup_rx_reorder_tbl) { - tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, - peer_mac); - if (!tbl) { - mwifiex_dbg(priv->adapter, EVENT, - "event: TID, TA not found in table\n"); - return; - } - mwifiex_del_rx_reorder_entry(priv, tbl); - } else { - ptx_tbl = mwifiex_get_ba_tbl(priv, tid, peer_mac); - if (!ptx_tbl) { - mwifiex_dbg(priv->adapter, EVENT, - "event: TID, RA not found in table\n"); - return; - } - - tid_down = mwifiex_wmm_downgrade_tid(priv, tid); - ra_list = mwifiex_wmm_get_ralist_node(priv, tid_down, peer_mac); - if (ra_list) { - ra_list->amsdu_in_ampdu = false; - ra_list->ba_status = BA_SETUP_NONE; - } - spin_lock_irqsave(&priv->tx_ba_stream_tbl_lock, flags); - mwifiex_11n_delete_tx_ba_stream_tbl_entry(priv, ptx_tbl); - spin_unlock_irqrestore(&priv->tx_ba_stream_tbl_lock, flags); - } -} - -/* - * This function handles the command response of an add BA response. - * - * Handling includes changing the header fields into CPU format and - * creating the stream, provided the add BA is accepted. - */ -int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_11n_addba_rsp *add_ba_rsp = &resp->params.add_ba_rsp; - int tid, win_size; - struct mwifiex_rx_reorder_tbl *tbl; - uint16_t block_ack_param_set; - - block_ack_param_set = le16_to_cpu(add_ba_rsp->block_ack_param_set); - - tid = (block_ack_param_set & IEEE80211_ADDBA_PARAM_TID_MASK) - >> BLOCKACKPARAM_TID_POS; - /* - * Check if we had rejected the ADDBA, if yes then do not create - * the stream - */ - if (le16_to_cpu(add_ba_rsp->status_code) != BA_RESULT_SUCCESS) { - mwifiex_dbg(priv->adapter, ERROR, "ADDBA RSP: failed %pM tid=%d)\n", - add_ba_rsp->peer_mac_addr, tid); - - tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, - add_ba_rsp->peer_mac_addr); - if (tbl) - mwifiex_del_rx_reorder_entry(priv, tbl); - - return 0; - } - - win_size = (block_ack_param_set & IEEE80211_ADDBA_PARAM_BUF_SIZE_MASK) - >> BLOCKACKPARAM_WINSIZE_POS; - - tbl = mwifiex_11n_get_rx_reorder_tbl(priv, tid, - add_ba_rsp->peer_mac_addr); - if (tbl) { - if ((block_ack_param_set & BLOCKACKPARAM_AMSDU_SUPP_MASK) && - priv->add_ba_param.rx_amsdu && - (priv->aggr_prio_tbl[tid].amsdu != BA_STREAM_NOT_ALLOWED)) - tbl->amsdu = true; - else - tbl->amsdu = false; - } - - mwifiex_dbg(priv->adapter, CMD, - "cmd: ADDBA RSP: %pM tid=%d ssn=%d win_size=%d\n", - add_ba_rsp->peer_mac_addr, tid, add_ba_rsp->ssn, win_size); - - return 0; -} - -/* - * This function handles BA stream timeout event by preparing and sending - * a command to the firmware. - */ -void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, - struct host_cmd_ds_11n_batimeout *event) -{ - struct host_cmd_ds_11n_delba delba; - - memset(&delba, 0, sizeof(struct host_cmd_ds_11n_delba)); - memcpy(delba.peer_mac_addr, event->peer_mac_addr, ETH_ALEN); - - delba.del_ba_param_set |= - cpu_to_le16((u16) event->tid << DELBA_TID_POS); - delba.del_ba_param_set |= cpu_to_le16( - (u16) event->origninator << DELBA_INITIATOR_POS); - delba.reason_code = cpu_to_le16(WLAN_REASON_QSTA_TIMEOUT); - mwifiex_send_cmd(priv, HostCmd_CMD_11N_DELBA, 0, 0, &delba, false); -} - -/* - * This function cleans up the Rx reorder table by deleting all the entries - * and re-initializing. - */ -void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv) -{ - struct mwifiex_rx_reorder_tbl *del_tbl_ptr, *tmp_node; - unsigned long flags; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - list_for_each_entry_safe(del_tbl_ptr, tmp_node, - &priv->rx_reorder_tbl_ptr, list) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - mwifiex_del_rx_reorder_entry(priv, del_tbl_ptr); - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, flags); - } - INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, flags); - - mwifiex_reset_11n_rx_seq_num(priv); -} - -/* - * This function updates all rx_reorder_tbl's flags. - */ -void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags) -{ - struct mwifiex_private *priv; - struct mwifiex_rx_reorder_tbl *tbl; - unsigned long lock_flags; - int i; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - - spin_lock_irqsave(&priv->rx_reorder_tbl_lock, lock_flags); - if (list_empty(&priv->rx_reorder_tbl_ptr)) { - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, - lock_flags); - continue; - } - - list_for_each_entry(tbl, &priv->rx_reorder_tbl_ptr, list) - tbl->flags = flags; - spin_unlock_irqrestore(&priv->rx_reorder_tbl_lock, lock_flags); - } - - return; -} - -/* This function update all the rx_win_size based on coex flag - */ -static void mwifiex_update_ampdu_rxwinsize(struct mwifiex_adapter *adapter, - bool coex_flag) -{ - u8 i; - u32 rx_win_size; - struct mwifiex_private *priv; - - dev_dbg(adapter->dev, "Update rxwinsize %d\n", coex_flag); - - for (i = 0; i < adapter->priv_num; i++) { - if (!adapter->priv[i]) - continue; - priv = adapter->priv[i]; - rx_win_size = priv->add_ba_param.rx_win_size; - if (coex_flag) { - if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) - priv->add_ba_param.rx_win_size = - MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE; - if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) - priv->add_ba_param.rx_win_size = - MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE; - if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) - priv->add_ba_param.rx_win_size = - MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE; - } else { - if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) - priv->add_ba_param.rx_win_size = - MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; - if (priv->bss_type == MWIFIEX_BSS_TYPE_P2P) - priv->add_ba_param.rx_win_size = - MWIFIEX_STA_AMPDU_DEF_RXWINSIZE; - if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) - priv->add_ba_param.rx_win_size = - MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE; - } - - if (adapter->coex_win_size && adapter->coex_rx_win_size) - priv->add_ba_param.rx_win_size = - adapter->coex_rx_win_size; - - if (rx_win_size != priv->add_ba_param.rx_win_size) { - if (!priv->media_connected) - continue; - for (i = 0; i < MAX_NUM_TID; i++) - mwifiex_11n_delba(priv, i); - } - } -} - -/* This function check coex for RX BA - */ -void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter) -{ - u8 i; - struct mwifiex_private *priv; - u8 count = 0; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { - if (priv->media_connected) - count++; - } - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - if (priv->bss_started) - count++; - } - } - if (count >= MWIFIEX_BSS_COEX_COUNT) - break; - } - if (count >= MWIFIEX_BSS_COEX_COUNT) - mwifiex_update_ampdu_rxwinsize(adapter, true); - else - mwifiex_update_ampdu_rxwinsize(adapter, false); -} diff --git a/drivers/net/wireless/mwifiex/11n_rxreorder.h b/drivers/net/wireless/mwifiex/11n_rxreorder.h deleted file mode 100644 index 63ecea89b4ab..000000000000 --- a/drivers/net/wireless/mwifiex/11n_rxreorder.h +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Marvell Wireless LAN device driver: 802.11n RX Re-ordering - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_11N_RXREORDER_H_ -#define _MWIFIEX_11N_RXREORDER_H_ - -#define MIN_FLUSH_TIMER_MS 50 -#define MIN_FLUSH_TIMER_15_MS 15 -#define MWIFIEX_BA_WIN_SIZE_32 32 - -#define PKT_TYPE_BAR 0xE7 -#define MAX_TID_VALUE (2 << 11) -#define TWOPOW11 (2 << 10) - -#define BLOCKACKPARAM_TID_POS 2 -#define BLOCKACKPARAM_AMSDU_SUPP_MASK 0x1 -#define BLOCKACKPARAM_WINSIZE_POS 6 -#define DELBA_TID_POS 12 -#define DELBA_INITIATOR_POS 11 -#define TYPE_DELBA_SENT 1 -#define TYPE_DELBA_RECEIVE 2 -#define IMMEDIATE_BLOCK_ACK 0x2 - -#define ADDBA_RSP_STATUS_ACCEPT 0 - -#define MWIFIEX_DEF_11N_RX_SEQ_NUM 0xffff -#define BA_SETUP_MAX_PACKET_THRESHOLD 16 -#define BA_SETUP_PACKET_OFFSET 16 - -enum mwifiex_rxreor_flags { - RXREOR_FORCE_NO_DROP = 1<<0, - RXREOR_INIT_WINDOW_SHIFT = 1<<1, -}; - -static inline void mwifiex_reset_11n_rx_seq_num(struct mwifiex_private *priv) -{ - memset(priv->rx_seq, 0xff, sizeof(priv->rx_seq)); -} - -int mwifiex_11n_rx_reorder_pkt(struct mwifiex_private *, - u16 seqNum, - u16 tid, u8 *ta, - u8 pkttype, void *payload); -void mwifiex_del_ba_tbl(struct mwifiex_private *priv, int Tid, - u8 *PeerMACAddr, u8 type, int initiator); -void mwifiex_11n_ba_stream_timeout(struct mwifiex_private *priv, - struct host_cmd_ds_11n_batimeout *event); -int mwifiex_ret_11n_addba_resp(struct mwifiex_private *priv, - struct host_cmd_ds_command - *resp); -int mwifiex_cmd_11n_delba(struct host_cmd_ds_command *cmd, - void *data_buf); -int mwifiex_cmd_11n_addba_rsp_gen(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct host_cmd_ds_11n_addba_req - *cmd_addba_req); -int mwifiex_cmd_11n_addba_req(struct host_cmd_ds_command *cmd, - void *data_buf); -void mwifiex_11n_cleanup_reorder_tbl(struct mwifiex_private *priv); -struct mwifiex_rx_reorder_tbl *mwifiex_11n_get_rxreorder_tbl(struct - mwifiex_private - *priv, int tid, - u8 *ta); -struct mwifiex_rx_reorder_tbl * -mwifiex_11n_get_rx_reorder_tbl(struct mwifiex_private *priv, int tid, u8 *ta); -void mwifiex_11n_del_rx_reorder_tbl_by_ta(struct mwifiex_private *priv, u8 *ta); -void mwifiex_update_rxreor_flags(struct mwifiex_adapter *adapter, u8 flags); - -#endif /* _MWIFIEX_11N_RXREORDER_H_ */ diff --git a/drivers/net/wireless/mwifiex/Kconfig b/drivers/net/wireless/mwifiex/Kconfig deleted file mode 100644 index 279167ddd293..000000000000 --- a/drivers/net/wireless/mwifiex/Kconfig +++ /dev/null @@ -1,44 +0,0 @@ -config MWIFIEX - tristate "Marvell WiFi-Ex Driver" - depends on CFG80211 - ---help--- - This adds support for wireless adapters based on Marvell - 802.11n/ac chipsets. - - If you choose to build it as a module, it will be called - mwifiex. - -config MWIFIEX_SDIO - tristate "Marvell WiFi-Ex Driver for SD8786/SD8787/SD8797/SD8887/SD8897/SD8997" - depends on MWIFIEX && MMC - select FW_LOADER - select WANT_DEV_COREDUMP - ---help--- - This adds support for wireless adapters based on Marvell - 8786/8787/8797/8887/8897/8997 chipsets with SDIO interface. - - If you choose to build it as a module, it will be called - mwifiex_sdio. - -config MWIFIEX_PCIE - tristate "Marvell WiFi-Ex Driver for PCIE 8766/8897/8997" - depends on MWIFIEX && PCI - select FW_LOADER - select WANT_DEV_COREDUMP - ---help--- - This adds support for wireless adapters based on Marvell - 8766/8897/8997 chipsets with PCIe interface. - - If you choose to build it as a module, it will be called - mwifiex_pcie. - -config MWIFIEX_USB - tristate "Marvell WiFi-Ex Driver for USB8766/8797/8997" - depends on MWIFIEX && USB - select FW_LOADER - ---help--- - This adds support for wireless adapters based on Marvell - 8797/8997 chipset with USB interface. - - If you choose to build it as a module, it will be called - mwifiex_usb. diff --git a/drivers/net/wireless/mwifiex/Makefile b/drivers/net/wireless/mwifiex/Makefile deleted file mode 100644 index fdfd9bf15ed4..000000000000 --- a/drivers/net/wireless/mwifiex/Makefile +++ /dev/null @@ -1,57 +0,0 @@ -# -# Copyright (C) 2011-2014, Marvell International Ltd. -# -# This software file (the "File") is distributed by Marvell International -# Ltd. under the terms of the GNU General Public License Version 2, June 1991 -# (the "License"). You may use, redistribute and/or modify this File in -# accordance with the terms and conditions of the License, a copy of which -# is available by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -# -# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -# ARE EXPRESSLY DISCLAIMED. The License provides additional details about -# this warranty disclaimer. - - -mwifiex-y += main.o -mwifiex-y += init.o -mwifiex-y += cfp.o -mwifiex-y += cmdevt.o -mwifiex-y += util.o -mwifiex-y += txrx.o -mwifiex-y += wmm.o -mwifiex-y += 11n.o -mwifiex-y += 11ac.o -mwifiex-y += 11n_aggr.o -mwifiex-y += 11n_rxreorder.o -mwifiex-y += scan.o -mwifiex-y += join.o -mwifiex-y += sta_ioctl.o -mwifiex-y += sta_cmd.o -mwifiex-y += uap_cmd.o -mwifiex-y += ie.o -mwifiex-y += sta_cmdresp.o -mwifiex-y += sta_event.o -mwifiex-y += uap_event.o -mwifiex-y += sta_tx.o -mwifiex-y += sta_rx.o -mwifiex-y += uap_txrx.o -mwifiex-y += cfg80211.o -mwifiex-y += ethtool.o -mwifiex-y += 11h.o -mwifiex-y += tdls.o -mwifiex-$(CONFIG_DEBUG_FS) += debugfs.o -obj-$(CONFIG_MWIFIEX) += mwifiex.o - -mwifiex_sdio-y += sdio.o -obj-$(CONFIG_MWIFIEX_SDIO) += mwifiex_sdio.o - -mwifiex_pcie-y += pcie.o -obj-$(CONFIG_MWIFIEX_PCIE) += mwifiex_pcie.o - -mwifiex_usb-y += usb.o -obj-$(CONFIG_MWIFIEX_USB) += mwifiex_usb.o - -ccflags-y += -D__CHECK_ENDIAN diff --git a/drivers/net/wireless/mwifiex/README b/drivers/net/wireless/mwifiex/README deleted file mode 100644 index 2f0f9b5609d0..000000000000 --- a/drivers/net/wireless/mwifiex/README +++ /dev/null @@ -1,240 +0,0 @@ -# Copyright (C) 2011-2014, Marvell International Ltd. -# -# This software file (the "File") is distributed by Marvell International -# Ltd. under the terms of the GNU General Public License Version 2, June 1991 -# (the "License"). You may use, redistribute and/or modify this File in -# accordance with the terms and conditions of the License, a copy of which -# is available by writing to the Free Software Foundation, Inc., -# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the -# worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. -# -# THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE -# IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE -# ARE EXPRESSLY DISCLAIMED. The License provides additional details about -# this warranty disclaimer. - - -=============================================================================== - U S E R M A N U A L - -1) FOR DRIVER INSTALL - - a) Copy sd8787.bin to /lib/firmware/mrvl/ directory, - create the directory if it doesn't exist. - b) Install WLAN driver, - insmod mwifiex.ko - c) Uninstall WLAN driver, - ifconfig mlanX down - rmmod mwifiex - - -2) FOR DRIVER CONFIGURATION AND INFO - The configurations can be done either using the 'iw' user space - utility or debugfs. - - a) 'iw' utility commands - - Following are some useful iw commands:- - -iw dev mlan0 scan - - This command will trigger a scan. - The command will then display the scan table entries - -iw dev mlan0 connect -w <SSID> [<freq in MHz>] [<bssid>] [key 0:abcde d:1123456789a] - The above command can be used to connect to an AP with a particular SSID. - Ap's operating frequency can be specified or even the bssid. If the AP is using - WEP encryption, wep keys can be specified in the command. - Note: Every time before connecting to an AP scan command (iw dev mlan0 scan) should be used by user. - -iw dev mlan0 disconnect - This command will be used to disconnect from an AP. - - -iw dev mlan0 ibss join <SSID> <freq in MHz> [fixed-freq] [fixed-bssid] [key 0:abcde] - The command will be used to join or create an ibss. Optionally, operating frequency, - bssid and the security related parameters can be specified while joining/creating - and ibss. - -iw dev mlan0 ibss leave - The command will be used to leave an ibss network. - -iw dev mlan0 link - The command will be used to get the connection status. The command will return parameters - such as SSID, operating frequency, rx/tx packets, signal strength, tx bitrate. - - Apart from the iw utility all standard configurations using the 'iwconfig' utility are also supported. - - b) Debugfs interface - - The debugfs interface can be used for configurations and for getting - some useful information from the driver. - The section below explains the configurations that can be - done. - - Mount debugfs to /debugfs mount point: - - mkdir /debugfs - mount -t debugfs debugfs /debugfs - - The information is provided in /debugfs/mwifiex/mlanX/: - -iw reg set <country code> - The command will be used to change the regulatory domain. - -iw reg get - The command will be used to get current regulatory domain. - -info - This command is used to get driver info. - - Usage: - cat info - - driver_name = "mwifiex" - driver_version = <driver_name, driver_version, (firmware_version)> - interface_name = "mlanX" - bss_mode = "Ad-hoc" | "Managed" | "Auto" | "Unknown" - media_state = "Disconnected" | "Connected" - mac_address = <6-byte adapter MAC address> - multicase_count = <multicast address count> - essid = <current SSID> - bssid = <current BSSID> - channel = <current channel> - region_code = <current region code> - multicasr_address[n] = <multicast address> - num_tx_bytes = <number of bytes sent to device> - num_rx_bytes = <number of bytes received from device and sent to kernel> - num_tx_pkts = <number of packets sent to device> - num_rx_pkts = <number of packets received from device and sent to kernel> - num_tx_pkts_dropped = <number of Tx packets dropped by driver> - num_rx_pkts_dropped = <number of Rx packets dropped by driver> - num_tx_pkts_err = <number of Tx packets failed to send to device> - num_rx_pkts_err = <number of Rx packets failed to receive from device> - carrier "on" | "off" - tx queue "stopped" | "started" - - The following debug info are provided in /debugfs/mwifiex/mlanX/debug: - - int_counter = <interrupt count, cleared when interrupt handled> - wmm_ac_vo = <number of packets sent to device from WMM AcVo queue> - wmm_ac_vi = <number of packets sent to device from WMM AcVi queue> - wmm_ac_be = <number of packets sent to device from WMM AcBE queue> - wmm_ac_bk = <number of packets sent to device from WMM AcBK queue> - tx_buf_size = <current Tx buffer size> - curr_tx_buf_size = <current Tx buffer size> - ps_mode = <0/1, CAM mode/PS mode> - ps_state = <0/1/2/3, full power state/awake state/pre-sleep state/sleep state> - is_deep_sleep = <0/1, not deep sleep state/deep sleep state> - wakeup_dev_req = <0/1, wakeup device not required/required> - wakeup_tries = <wakeup device count, cleared when device awake> - hs_configured = <0/1, host sleep not configured/configured> - hs_activated = <0/1, extended host sleep not activated/activated> - num_tx_timeout = <number of Tx timeout> - is_cmd_timedout = <0/1 command timeout not occurred/occurred> - timeout_cmd_id = <command id of the last timeout command> - timeout_cmd_act = <command action of the last timeout command> - last_cmd_id = <command id of the last several commands sent to device> - last_cmd_act = <command action of the last several commands sent to device> - last_cmd_index = <0 based last command index> - last_cmd_resp_id = <command id of the last several command responses received from device> - last_cmd_resp_index = <0 based last command response index> - last_event = <event id of the last several events received from device> - last_event_index = <0 based last event index> - num_cmd_h2c_fail = <number of commands failed to send to device> - num_cmd_sleep_cfm_fail = <number of sleep confirm failed to send to device> - num_tx_h2c_fail = <number of data packets failed to send to device> - num_evt_deauth = <number of deauthenticated events received from device> - num_evt_disassoc = <number of disassociated events received from device> - num_evt_link_lost = <number of link lost events received from device> - num_cmd_deauth = <number of deauthenticate commands sent to device> - num_cmd_assoc_ok = <number of associate commands with success return> - num_cmd_assoc_fail = <number of associate commands with failure return> - cmd_sent = <0/1, send command resources available/sending command to device> - data_sent = <0/1, send data resources available/sending data to device> - mp_rd_bitmap = <SDIO multi-port read bitmap> - mp_wr_bitmap = <SDIO multi-port write bitmap> - cmd_resp_received = <0/1, no cmd response to process/response received and yet to process> - event_received = <0/1, no event to process/event received and yet to process> - cmd_pending = <number of cmd pending> - tx_pending = <number of Tx packet pending> - rx_pending = <number of Rx packet pending> - - -3) FOR DRIVER CONFIGURATION - -regrdwr - This command is used to read/write the adapter register. - - Usage: - echo " <type> <offset> [value]" > regrdwr - cat regrdwr - - where the parameters are, - <type>: 1:MAC/SOC, 2:BBP, 3:RF, 4:PMIC, 5:CAU - <offset>: offset of register - [value]: value to be written - - Examples: - echo "1 0xa060" > regrdwr : Read the MAC register - echo "1 0xa060 0x12" > regrdwr : Write the MAC register - echo "1 0xa794 0x80000000" > regrdwr - : Write 0x80000000 to MAC register -rdeeprom - This command is used to read the EEPROM contents of the card. - - Usage: - echo "<offset> <length>" > rdeeprom - cat rdeeprom - - where the parameters are, - <offset>: multiples of 4 - <length>: 4-20, multiples of 4 - - Example: - echo "0 20" > rdeeprom : Read 20 bytes of EEPROM data from offset 0 - -hscfg - This command is used to debug/simulate host sleep feature using - different configuration parameters. - - Usage: - echo "<condition> [GPIO# [gap]]]" > hscfg - cat hscfg - - where the parameters are, - <condition>: bit 0 = 1 -- broadcast data - bit 1 = 1 -- unicast data - bit 2 = 1 -- mac event - bit 3 = 1 -- multicast data - [GPIO#]: pin number of GPIO used to wakeup the host. - GPIO pin# (e.g. 0-7) or 0xff (interface, e.g. SDIO - will be used instead). - [gap]: the gap in milliseconds between wakeup signal and - wakeup event or 0xff for special setting (host - acknowledge required) when GPIO is used to wakeup host. - - Examples: - echo "-1" > hscfg : Cancel host sleep mode - echo "3" > hscfg : Broadcast and unicast data; - Use GPIO and gap set previously - echo "2 3" > hscfg : Unicast data and GPIO 3; - Use gap set previously - echo "2 1 160" > hscfg : Unicast data, GPIO 1 and gap 160 ms - echo "2 1 0xff" > hscfg : Unicast data, GPIO 1; Wait for host - to ack before sending wakeup event - -getlog - This command is used to get the statistics available in the station. - Usage: - - cat getlog - -device_dump - This command is used to dump driver information and firmware memory - segments. - Usage: - - cat fw_dump - -=============================================================================== diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c deleted file mode 100644 index 4073116e6e9f..000000000000 --- a/drivers/net/wireless/mwifiex/cfg80211.c +++ /dev/null @@ -1,3887 +0,0 @@ -/* - * Marvell Wireless LAN device driver: CFG80211 - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "cfg80211.h" -#include "main.h" -#include "11n.h" - -static char *reg_alpha2; -module_param(reg_alpha2, charp, 0); - -static const struct ieee80211_iface_limit mwifiex_ap_sta_limits[] = { - { - .max = 2, .types = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_P2P_CLIENT), - }, - { - .max = 1, .types = BIT(NL80211_IFTYPE_AP), - }, -}; - -static const struct ieee80211_iface_combination -mwifiex_iface_comb_ap_sta = { - .limits = mwifiex_ap_sta_limits, - .num_different_channels = 1, - .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), - .max_interfaces = MWIFIEX_MAX_BSS_NUM, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40), -}; - -static const struct ieee80211_iface_combination -mwifiex_iface_comb_ap_sta_vht = { - .limits = mwifiex_ap_sta_limits, - .num_different_channels = 1, - .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), - .max_interfaces = MWIFIEX_MAX_BSS_NUM, - .beacon_int_infra_match = true, - .radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) | - BIT(NL80211_CHAN_WIDTH_20) | - BIT(NL80211_CHAN_WIDTH_40) | - BIT(NL80211_CHAN_WIDTH_80), -}; - -static const struct -ieee80211_iface_combination mwifiex_iface_comb_ap_sta_drcs = { - .limits = mwifiex_ap_sta_limits, - .num_different_channels = 2, - .n_limits = ARRAY_SIZE(mwifiex_ap_sta_limits), - .max_interfaces = MWIFIEX_MAX_BSS_NUM, - .beacon_int_infra_match = true, -}; - -/* - * This function maps the nl802.11 channel type into driver channel type. - * - * The mapping is as follows - - * NL80211_CHAN_NO_HT -> IEEE80211_HT_PARAM_CHA_SEC_NONE - * NL80211_CHAN_HT20 -> IEEE80211_HT_PARAM_CHA_SEC_NONE - * NL80211_CHAN_HT40PLUS -> IEEE80211_HT_PARAM_CHA_SEC_ABOVE - * NL80211_CHAN_HT40MINUS -> IEEE80211_HT_PARAM_CHA_SEC_BELOW - * Others -> IEEE80211_HT_PARAM_CHA_SEC_NONE - */ -u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type) -{ - switch (chan_type) { - case NL80211_CHAN_NO_HT: - case NL80211_CHAN_HT20: - return IEEE80211_HT_PARAM_CHA_SEC_NONE; - case NL80211_CHAN_HT40PLUS: - return IEEE80211_HT_PARAM_CHA_SEC_ABOVE; - case NL80211_CHAN_HT40MINUS: - return IEEE80211_HT_PARAM_CHA_SEC_BELOW; - default: - return IEEE80211_HT_PARAM_CHA_SEC_NONE; - } -} - -/* This function maps IEEE HT secondary channel type to NL80211 channel type - */ -u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset) -{ - switch (second_chan_offset) { - case IEEE80211_HT_PARAM_CHA_SEC_NONE: - return NL80211_CHAN_HT20; - case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: - return NL80211_CHAN_HT40PLUS; - case IEEE80211_HT_PARAM_CHA_SEC_BELOW: - return NL80211_CHAN_HT40MINUS; - default: - return NL80211_CHAN_HT20; - } -} - -/* - * This function checks whether WEP is set. - */ -static int -mwifiex_is_alg_wep(u32 cipher) -{ - switch (cipher) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - return 1; - default: - break; - } - - return 0; -} - -/* - * This function retrieves the private structure from kernel wiphy structure. - */ -static void *mwifiex_cfg80211_get_adapter(struct wiphy *wiphy) -{ - return (void *) (*(unsigned long *) wiphy_priv(wiphy)); -} - -/* - * CFG802.11 operation handler to delete a network key. - */ -static int -mwifiex_cfg80211_del_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, bool pairwise, const u8 *mac_addr) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); - const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 *peer_mac = pairwise ? mac_addr : bc_mac; - - if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, peer_mac, 1)) { - mwifiex_dbg(priv->adapter, ERROR, "deleting the crypto keys\n"); - return -EFAULT; - } - - mwifiex_dbg(priv->adapter, INFO, "info: crypto keys deleted\n"); - return 0; -} - -/* - * This function forms an skb for management frame. - */ -static int -mwifiex_form_mgmt_frame(struct sk_buff *skb, const u8 *buf, size_t len) -{ - u8 addr[ETH_ALEN] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - u16 pkt_len; - u32 tx_control = 0, pkt_type = PKT_TYPE_MGMT; - - pkt_len = len + ETH_ALEN; - - skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); - memcpy(skb_push(skb, sizeof(pkt_len)), &pkt_len, sizeof(pkt_len)); - - memcpy(skb_push(skb, sizeof(tx_control)), - &tx_control, sizeof(tx_control)); - - memcpy(skb_push(skb, sizeof(pkt_type)), &pkt_type, sizeof(pkt_type)); - - /* Add packet data and address4 */ - memcpy(skb_put(skb, sizeof(struct ieee80211_hdr_3addr)), buf, - sizeof(struct ieee80211_hdr_3addr)); - memcpy(skb_put(skb, ETH_ALEN), addr, ETH_ALEN); - memcpy(skb_put(skb, len - sizeof(struct ieee80211_hdr_3addr)), - buf + sizeof(struct ieee80211_hdr_3addr), - len - sizeof(struct ieee80211_hdr_3addr)); - - skb->priority = LOW_PRIO_TID; - __net_timestamp(skb); - - return 0; -} - -/* - * CFG802.11 operation handler to transmit a management frame. - */ -static int -mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev, - struct cfg80211_mgmt_tx_params *params, u64 *cookie) -{ - const u8 *buf = params->buf; - size_t len = params->len; - struct sk_buff *skb; - u16 pkt_len; - const struct ieee80211_mgmt *mgmt; - struct mwifiex_txinfo *tx_info; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - - if (!buf || !len) { - mwifiex_dbg(priv->adapter, ERROR, "invalid buffer and length\n"); - return -EFAULT; - } - - mgmt = (const struct ieee80211_mgmt *)buf; - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA && - ieee80211_is_probe_resp(mgmt->frame_control)) { - /* Since we support offload probe resp, we need to skip probe - * resp in AP or GO mode */ - mwifiex_dbg(priv->adapter, INFO, - "info: skip to send probe resp in AP or GO mode\n"); - return 0; - } - - pkt_len = len + ETH_ALEN; - skb = dev_alloc_skb(MWIFIEX_MIN_DATA_HEADER_LEN + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + - pkt_len + sizeof(pkt_len)); - - if (!skb) { - mwifiex_dbg(priv->adapter, ERROR, - "allocate skb failed for management frame\n"); - return -ENOMEM; - } - - tx_info = MWIFIEX_SKB_TXCB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->bss_num = priv->bss_num; - tx_info->bss_type = priv->bss_type; - tx_info->pkt_len = pkt_len; - - mwifiex_form_mgmt_frame(skb, buf, len); - *cookie = prandom_u32() | 1; - - if (ieee80211_is_action(mgmt->frame_control)) - skb = mwifiex_clone_skb_for_tx_status(priv, - skb, - MWIFIEX_BUF_FLAG_ACTION_TX_STATUS, cookie); - else - cfg80211_mgmt_tx_status(wdev, *cookie, buf, len, true, - GFP_ATOMIC); - - mwifiex_queue_tx_pkt(priv, skb); - - mwifiex_dbg(priv->adapter, INFO, "info: management frame transmitted\n"); - return 0; -} - -/* - * CFG802.11 operation handler to register a mgmt frame. - */ -static void -mwifiex_cfg80211_mgmt_frame_register(struct wiphy *wiphy, - struct wireless_dev *wdev, - u16 frame_type, bool reg) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - u32 mask; - - if (reg) - mask = priv->mgmt_frame_mask | BIT(frame_type >> 4); - else - mask = priv->mgmt_frame_mask & ~BIT(frame_type >> 4); - - if (mask != priv->mgmt_frame_mask) { - priv->mgmt_frame_mask = mask; - mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, - HostCmd_ACT_GEN_SET, 0, - &priv->mgmt_frame_mask, false); - mwifiex_dbg(priv->adapter, INFO, "info: mgmt frame registered\n"); - } -} - -/* - * CFG802.11 operation handler to remain on channel. - */ -static int -mwifiex_cfg80211_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - struct ieee80211_channel *chan, - unsigned int duration, u64 *cookie) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - int ret; - - if (!chan || !cookie) { - mwifiex_dbg(priv->adapter, ERROR, "Invalid parameter for ROC\n"); - return -EINVAL; - } - - if (priv->roc_cfg.cookie) { - mwifiex_dbg(priv->adapter, INFO, - "info: ongoing ROC, cookie = 0x%llx\n", - priv->roc_cfg.cookie); - return -EBUSY; - } - - ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_SET, chan, - duration); - - if (!ret) { - *cookie = prandom_u32() | 1; - priv->roc_cfg.cookie = *cookie; - priv->roc_cfg.chan = *chan; - - cfg80211_ready_on_channel(wdev, *cookie, chan, - duration, GFP_ATOMIC); - - mwifiex_dbg(priv->adapter, INFO, - "info: ROC, cookie = 0x%llx\n", *cookie); - } - - return ret; -} - -/* - * CFG802.11 operation handler to cancel remain on channel. - */ -static int -mwifiex_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, u64 cookie) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - int ret; - - if (cookie != priv->roc_cfg.cookie) - return -ENOENT; - - ret = mwifiex_remain_on_chan_cfg(priv, HostCmd_ACT_GEN_REMOVE, - &priv->roc_cfg.chan, 0); - - if (!ret) { - cfg80211_remain_on_channel_expired(wdev, cookie, - &priv->roc_cfg.chan, - GFP_ATOMIC); - - memset(&priv->roc_cfg, 0, sizeof(struct mwifiex_roc_cfg)); - - mwifiex_dbg(priv->adapter, INFO, - "info: cancel ROC, cookie = 0x%llx\n", cookie); - } - - return ret; -} - -/* - * CFG802.11 operation handler to set Tx power. - */ -static int -mwifiex_cfg80211_set_tx_power(struct wiphy *wiphy, - struct wireless_dev *wdev, - enum nl80211_tx_power_setting type, - int mbm) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv; - struct mwifiex_power_cfg power_cfg; - int dbm = MBM_TO_DBM(mbm); - - if (type == NL80211_TX_POWER_FIXED) { - power_cfg.is_power_auto = 0; - power_cfg.power_level = dbm; - } else { - power_cfg.is_power_auto = 1; - } - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - return mwifiex_set_tx_power(priv, &power_cfg); -} - -/* - * CFG802.11 operation handler to set Power Save option. - * - * The timeout value, if provided, is currently ignored. - */ -static int -mwifiex_cfg80211_set_power_mgmt(struct wiphy *wiphy, - struct net_device *dev, - bool enabled, int timeout) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - u32 ps_mode; - - if (timeout) - mwifiex_dbg(priv->adapter, INFO, - "info: ignore timeout value for IEEE Power Save\n"); - - ps_mode = enabled; - - return mwifiex_drv_set_power(priv, &ps_mode); -} - -/* - * CFG802.11 operation handler to set the default network key. - */ -static int -mwifiex_cfg80211_set_default_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, bool unicast, - bool multicast) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); - - /* Return if WEP key not configured */ - if (!priv->sec_info.wep_enabled) - return 0; - - if (priv->bss_type == MWIFIEX_BSS_TYPE_UAP) { - priv->wep_key_curr_index = key_index; - } else if (mwifiex_set_encode(priv, NULL, NULL, 0, key_index, - NULL, 0)) { - mwifiex_dbg(priv->adapter, ERROR, "set default Tx key index\n"); - return -EFAULT; - } - - return 0; -} - -/* - * CFG802.11 operation handler to add a network key. - */ -static int -mwifiex_cfg80211_add_key(struct wiphy *wiphy, struct net_device *netdev, - u8 key_index, bool pairwise, const u8 *mac_addr, - struct key_params *params) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(netdev); - struct mwifiex_wep_key *wep_key; - const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const u8 *peer_mac = pairwise ? mac_addr : bc_mac; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP && - (params->cipher == WLAN_CIPHER_SUITE_WEP40 || - params->cipher == WLAN_CIPHER_SUITE_WEP104)) { - if (params->key && params->key_len) { - wep_key = &priv->wep_key[key_index]; - memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); - memcpy(wep_key->key_material, params->key, - params->key_len); - wep_key->key_index = key_index; - wep_key->key_length = params->key_len; - priv->sec_info.wep_enabled = 1; - } - return 0; - } - - if (mwifiex_set_encode(priv, params, params->key, params->key_len, - key_index, peer_mac, 0)) { - mwifiex_dbg(priv->adapter, ERROR, "crypto keys added\n"); - return -EFAULT; - } - - return 0; -} - -/* - * This function sends domain information to the firmware. - * - * The following information are passed to the firmware - - * - Country codes - * - Sub bands (first channel, number of channels, maximum Tx power) - */ -int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy) -{ - u8 no_of_triplet = 0; - struct ieee80211_country_ie_triplet *t; - u8 no_of_parsed_chan = 0; - u8 first_chan = 0, next_chan = 0, max_pwr = 0; - u8 i, flag = 0; - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv; - struct mwifiex_802_11d_domain_reg *domain_info = &adapter->domain_reg; - - /* Set country code */ - domain_info->country_code[0] = adapter->country_code[0]; - domain_info->country_code[1] = adapter->country_code[1]; - domain_info->country_code[2] = ' '; - - band = mwifiex_band_to_radio_type(adapter->config_bands); - if (!wiphy->bands[band]) { - mwifiex_dbg(adapter, ERROR, - "11D: setting domain info in FW\n"); - return -1; - } - - sband = wiphy->bands[band]; - - for (i = 0; i < sband->n_channels ; i++) { - ch = &sband->channels[i]; - if (ch->flags & IEEE80211_CHAN_DISABLED) - continue; - - if (!flag) { - flag = 1; - first_chan = (u32) ch->hw_value; - next_chan = first_chan; - max_pwr = ch->max_power; - no_of_parsed_chan = 1; - continue; - } - - if (ch->hw_value == next_chan + 1 && - ch->max_power == max_pwr) { - next_chan++; - no_of_parsed_chan++; - } else { - t = &domain_info->triplet[no_of_triplet]; - t->chans.first_channel = first_chan; - t->chans.num_channels = no_of_parsed_chan; - t->chans.max_power = max_pwr; - no_of_triplet++; - first_chan = (u32) ch->hw_value; - next_chan = first_chan; - max_pwr = ch->max_power; - no_of_parsed_chan = 1; - } - } - - if (flag) { - t = &domain_info->triplet[no_of_triplet]; - t->chans.first_channel = first_chan; - t->chans.num_channels = no_of_parsed_chan; - t->chans.max_power = max_pwr; - no_of_triplet++; - } - - domain_info->no_of_triplet = no_of_triplet; - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, - HostCmd_ACT_GEN_SET, 0, NULL, false)) { - mwifiex_dbg(adapter, INFO, - "11D: setting domain info in FW\n"); - return -1; - } - - return 0; -} - -/* - * CFG802.11 regulatory domain callback function. - * - * This function is called when the regulatory domain is changed due to the - * following reasons - - * - Set by driver - * - Set by system core - * - Set by user - * - Set bt Country IE - */ -static void mwifiex_reg_notifier(struct wiphy *wiphy, - struct regulatory_request *request) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv = mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY); - mwifiex_dbg(adapter, INFO, - "info: cfg80211 regulatory domain callback for %c%c\n", - request->alpha2[0], request->alpha2[1]); - - switch (request->initiator) { - case NL80211_REGDOM_SET_BY_DRIVER: - case NL80211_REGDOM_SET_BY_CORE: - case NL80211_REGDOM_SET_BY_USER: - case NL80211_REGDOM_SET_BY_COUNTRY_IE: - break; - default: - mwifiex_dbg(adapter, ERROR, - "unknown regdom initiator: %d\n", - request->initiator); - return; - } - - /* Don't send world or same regdom info to firmware */ - if (strncmp(request->alpha2, "00", 2) && - strncmp(request->alpha2, adapter->country_code, - sizeof(request->alpha2))) { - memcpy(adapter->country_code, request->alpha2, - sizeof(request->alpha2)); - mwifiex_send_domain_info_cmd_fw(wiphy); - mwifiex_dnld_txpwr_table(priv); - } -} - -/* - * This function sets the fragmentation threshold. - * - * The fragmentation threshold value must lie between MWIFIEX_FRAG_MIN_VALUE - * and MWIFIEX_FRAG_MAX_VALUE. - */ -static int -mwifiex_set_frag(struct mwifiex_private *priv, u32 frag_thr) -{ - if (frag_thr < MWIFIEX_FRAG_MIN_VALUE || - frag_thr > MWIFIEX_FRAG_MAX_VALUE) - frag_thr = MWIFIEX_FRAG_MAX_VALUE; - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, FRAG_THRESH_I, - &frag_thr, true); -} - -/* - * This function sets the RTS threshold. - - * The rts value must lie between MWIFIEX_RTS_MIN_VALUE - * and MWIFIEX_RTS_MAX_VALUE. - */ -static int -mwifiex_set_rts(struct mwifiex_private *priv, u32 rts_thr) -{ - if (rts_thr < MWIFIEX_RTS_MIN_VALUE || rts_thr > MWIFIEX_RTS_MAX_VALUE) - rts_thr = MWIFIEX_RTS_MAX_VALUE; - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, RTS_THRESH_I, - &rts_thr, true); -} - -/* - * CFG802.11 operation handler to set wiphy parameters. - * - * This function can be used to set the RTS threshold and the - * Fragmentation threshold of the driver. - */ -static int -mwifiex_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv; - struct mwifiex_uap_bss_param *bss_cfg; - int ret; - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - switch (priv->bss_role) { - case MWIFIEX_BSS_ROLE_UAP: - if (priv->bss_started) { - mwifiex_dbg(adapter, ERROR, - "cannot change wiphy params when bss started"); - return -EINVAL; - } - - bss_cfg = kzalloc(sizeof(*bss_cfg), GFP_KERNEL); - if (!bss_cfg) - return -ENOMEM; - - mwifiex_set_sys_config_invalid_data(bss_cfg); - - if (changed & WIPHY_PARAM_RTS_THRESHOLD) - bss_cfg->rts_threshold = wiphy->rts_threshold; - if (changed & WIPHY_PARAM_FRAG_THRESHOLD) - bss_cfg->frag_threshold = wiphy->frag_threshold; - if (changed & WIPHY_PARAM_RETRY_LONG) - bss_cfg->retry_limit = wiphy->retry_long; - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, - HostCmd_ACT_GEN_SET, - UAP_BSS_PARAMS_I, bss_cfg, - false); - - kfree(bss_cfg); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "Failed to set wiphy phy params\n"); - return ret; - } - break; - - case MWIFIEX_BSS_ROLE_STA: - if (priv->media_connected) { - mwifiex_dbg(adapter, ERROR, - "cannot change wiphy params when connected"); - return -EINVAL; - } - if (changed & WIPHY_PARAM_RTS_THRESHOLD) { - ret = mwifiex_set_rts(priv, - wiphy->rts_threshold); - if (ret) - return ret; - } - if (changed & WIPHY_PARAM_FRAG_THRESHOLD) { - ret = mwifiex_set_frag(priv, - wiphy->frag_threshold); - if (ret) - return ret; - } - break; - } - - return 0; -} - -static int -mwifiex_cfg80211_deinit_p2p(struct mwifiex_private *priv) -{ - u16 mode = P2P_MODE_DISABLE; - - if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode, true)) - return -1; - - return 0; -} - -/* - * This function initializes the functionalities for P2P client. - * The P2P client initialization sequence is: - * disable -> device -> client - */ -static int -mwifiex_cfg80211_init_p2p_client(struct mwifiex_private *priv) -{ - u16 mode; - - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -1; - - mode = P2P_MODE_DEVICE; - if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode, true)) - return -1; - - mode = P2P_MODE_CLIENT; - if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode, true)) - return -1; - - return 0; -} - -/* - * This function initializes the functionalities for P2P GO. - * The P2P GO initialization sequence is: - * disable -> device -> GO - */ -static int -mwifiex_cfg80211_init_p2p_go(struct mwifiex_private *priv) -{ - u16 mode; - - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -1; - - mode = P2P_MODE_DEVICE; - if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode, true)) - return -1; - - mode = P2P_MODE_GO; - if (mwifiex_send_cmd(priv, HostCmd_CMD_P2P_MODE_CFG, - HostCmd_ACT_GEN_SET, 0, &mode, true)) - return -1; - - return 0; -} - -static int mwifiex_deinit_priv_params(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - unsigned long flags; - - priv->mgmt_frame_mask = 0; - if (mwifiex_send_cmd(priv, HostCmd_CMD_MGMT_FRAME_REG, - HostCmd_ACT_GEN_SET, 0, - &priv->mgmt_frame_mask, false)) { - mwifiex_dbg(adapter, ERROR, - "could not unregister mgmt frame rx\n"); - return -1; - } - - mwifiex_deauthenticate(priv, NULL); - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - adapter->main_locked = true; - if (adapter->mwifiex_processing) { - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - flush_workqueue(adapter->workqueue); - } else { - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - } - - spin_lock_irqsave(&adapter->rx_proc_lock, flags); - adapter->rx_locked = true; - if (adapter->rx_processing) { - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - flush_workqueue(adapter->rx_workqueue); - } else { - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - } - - mwifiex_free_priv(priv); - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - - return 0; -} - -static int -mwifiex_init_new_priv_params(struct mwifiex_private *priv, - struct net_device *dev, - enum nl80211_iftype type) -{ - struct mwifiex_adapter *adapter = priv->adapter; - unsigned long flags; - - mwifiex_init_priv(priv); - - priv->bss_mode = type; - priv->wdev.iftype = type; - - mwifiex_init_priv_params(priv, priv->netdev); - priv->bss_started = 0; - - switch (type) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_type = MWIFIEX_BSS_TYPE_STA; - break; - case NL80211_IFTYPE_P2P_CLIENT: - priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_type = MWIFIEX_BSS_TYPE_P2P; - break; - case NL80211_IFTYPE_P2P_GO: - priv->bss_role = MWIFIEX_BSS_ROLE_UAP; - priv->bss_type = MWIFIEX_BSS_TYPE_P2P; - break; - case NL80211_IFTYPE_AP: - priv->bss_type = MWIFIEX_BSS_TYPE_UAP; - priv->bss_role = MWIFIEX_BSS_ROLE_UAP; - break; - default: - mwifiex_dbg(adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; - } - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - adapter->main_locked = false; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - - spin_lock_irqsave(&adapter->rx_proc_lock, flags); - adapter->rx_locked = false; - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - - return 0; -} - -static int -mwifiex_change_vif_to_p2p(struct net_device *dev, - enum nl80211_iftype curr_iftype, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct mwifiex_private *priv; - struct mwifiex_adapter *adapter; - - priv = mwifiex_netdev_get_priv(dev); - - if (!priv) - return -1; - - adapter = priv->adapter; - - if (adapter->curr_iface_comb.p2p_intf == - adapter->iface_limit.p2p_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple P2P ifaces\n"); - return -1; - } - - mwifiex_dbg(adapter, INFO, - "%s: changing role to p2p\n", dev->name); - - if (mwifiex_deinit_priv_params(priv)) - return -1; - if (mwifiex_init_new_priv_params(priv, dev, type)) - return -1; - - switch (type) { - case NL80211_IFTYPE_P2P_CLIENT: - if (mwifiex_cfg80211_init_p2p_client(priv)) - return -EFAULT; - break; - case NL80211_IFTYPE_P2P_GO: - if (mwifiex_cfg80211_init_p2p_go(priv)) - return -EFAULT; - break; - default: - mwifiex_dbg(adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; - } - - if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL, true)) - return -1; - - if (mwifiex_sta_init_cmd(priv, false, false)) - return -1; - - switch (curr_iftype) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf--; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf--; - break; - default: - break; - } - - adapter->curr_iface_comb.p2p_intf++; - dev->ieee80211_ptr->iftype = type; - - return 0; -} - -static int -mwifiex_change_vif_to_sta_adhoc(struct net_device *dev, - enum nl80211_iftype curr_iftype, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct mwifiex_private *priv; - struct mwifiex_adapter *adapter; - - priv = mwifiex_netdev_get_priv(dev); - - if (!priv) - return -1; - - adapter = priv->adapter; - - if ((curr_iftype != NL80211_IFTYPE_P2P_CLIENT && - curr_iftype != NL80211_IFTYPE_P2P_GO) && - (adapter->curr_iface_comb.sta_intf == - adapter->iface_limit.sta_intf)) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple station/adhoc ifaces\n"); - return -1; - } - - if (type == NL80211_IFTYPE_STATION) - mwifiex_dbg(adapter, INFO, - "%s: changing role to station\n", dev->name); - else - mwifiex_dbg(adapter, INFO, - "%s: changing role to adhoc\n", dev->name); - - if (mwifiex_deinit_priv_params(priv)) - return -1; - if (mwifiex_init_new_priv_params(priv, dev, type)) - return -1; - if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL, true)) - return -1; - if (mwifiex_sta_init_cmd(priv, false, false)) - return -1; - - switch (curr_iftype) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf--; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf--; - break; - default: - break; - } - - adapter->curr_iface_comb.sta_intf++; - dev->ieee80211_ptr->iftype = type; - return 0; -} - -static int -mwifiex_change_vif_to_ap(struct net_device *dev, - enum nl80211_iftype curr_iftype, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct mwifiex_private *priv; - struct mwifiex_adapter *adapter; - - priv = mwifiex_netdev_get_priv(dev); - - if (!priv) - return -1; - - adapter = priv->adapter; - - if (adapter->curr_iface_comb.uap_intf == - adapter->iface_limit.uap_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple AP ifaces\n"); - return -1; - } - - mwifiex_dbg(adapter, INFO, - "%s: changing role to AP\n", dev->name); - - if (mwifiex_deinit_priv_params(priv)) - return -1; - if (mwifiex_init_new_priv_params(priv, dev, type)) - return -1; - if (mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL, true)) - return -1; - if (mwifiex_sta_init_cmd(priv, false, false)) - return -1; - - switch (curr_iftype) { - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf--; - break; - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf--; - break; - default: - break; - } - - adapter->curr_iface_comb.uap_intf++; - dev->ieee80211_ptr->iftype = type; - return 0; -} -/* - * CFG802.11 operation handler to change interface type. - */ -static int -mwifiex_cfg80211_change_virtual_intf(struct wiphy *wiphy, - struct net_device *dev, - enum nl80211_iftype type, u32 *flags, - struct vif_params *params) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - enum nl80211_iftype curr_iftype = dev->ieee80211_ptr->iftype; - - switch (curr_iftype) { - case NL80211_IFTYPE_ADHOC: - switch (type) { - case NL80211_IFTYPE_STATION: - priv->bss_mode = type; - priv->sec_info.authentication_mode = - NL80211_AUTHTYPE_OPEN_SYSTEM; - dev->ieee80211_ptr->iftype = type; - mwifiex_deauthenticate(priv, NULL); - return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL, - true); - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return mwifiex_change_vif_to_p2p(dev, curr_iftype, - type, flags, params); - case NL80211_IFTYPE_AP: - return mwifiex_change_vif_to_ap(dev, curr_iftype, type, - flags, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as IBSS\n", dev->name); - case NL80211_IFTYPE_ADHOC: /* This shouldn't happen */ - return 0; - default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; - } - break; - case NL80211_IFTYPE_STATION: - switch (type) { - case NL80211_IFTYPE_ADHOC: - priv->bss_mode = type; - priv->sec_info.authentication_mode = - NL80211_AUTHTYPE_OPEN_SYSTEM; - dev->ieee80211_ptr->iftype = type; - mwifiex_deauthenticate(priv, NULL); - return mwifiex_send_cmd(priv, HostCmd_CMD_SET_BSS_MODE, - HostCmd_ACT_GEN_SET, 0, NULL, - true); - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return mwifiex_change_vif_to_p2p(dev, curr_iftype, - type, flags, params); - case NL80211_IFTYPE_AP: - return mwifiex_change_vif_to_ap(dev, curr_iftype, type, - flags, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as STA\n", dev->name); - case NL80211_IFTYPE_STATION: /* This shouldn't happen */ - return 0; - default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; - } - break; - case NL80211_IFTYPE_AP: - switch (type) { - case NL80211_IFTYPE_ADHOC: - case NL80211_IFTYPE_STATION: - return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, - type, flags, - params); - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return mwifiex_change_vif_to_p2p(dev, curr_iftype, - type, flags, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as AP\n", dev->name); - case NL80211_IFTYPE_AP: /* This shouldn't happen */ - return 0; - default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; - } - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - switch (type) { - case NL80211_IFTYPE_STATION: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; - priv->adapter->curr_iface_comb.p2p_intf--; - priv->adapter->curr_iface_comb.sta_intf++; - dev->ieee80211_ptr->iftype = type; - break; - case NL80211_IFTYPE_ADHOC: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; - return mwifiex_change_vif_to_sta_adhoc(dev, curr_iftype, - type, flags, - params); - break; - case NL80211_IFTYPE_AP: - if (mwifiex_cfg80211_deinit_p2p(priv)) - return -EFAULT; - return mwifiex_change_vif_to_ap(dev, curr_iftype, type, - flags, params); - case NL80211_IFTYPE_UNSPECIFIED: - mwifiex_dbg(priv->adapter, INFO, - "%s: kept type as P2P\n", dev->name); - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - return 0; - default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: changing to %d not supported\n", - dev->name, type); - return -EOPNOTSUPP; - } - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "%s: unknown iftype: %d\n", - dev->name, dev->ieee80211_ptr->iftype); - return -EOPNOTSUPP; - } - - - return 0; -} - -static void -mwifiex_parse_htinfo(struct mwifiex_private *priv, u8 tx_htinfo, - struct rate_info *rate) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - if (adapter->is_hw_11ac_capable) { - /* bit[1-0]: 00=LG 01=HT 10=VHT */ - if (tx_htinfo & BIT(0)) { - /* HT */ - rate->mcs = priv->tx_rate; - rate->flags |= RATE_INFO_FLAGS_MCS; - } - if (tx_htinfo & BIT(1)) { - /* VHT */ - rate->mcs = priv->tx_rate & 0x0F; - rate->flags |= RATE_INFO_FLAGS_VHT_MCS; - } - - if (tx_htinfo & (BIT(1) | BIT(0))) { - /* HT or VHT */ - switch (tx_htinfo & (BIT(3) | BIT(2))) { - case 0: - rate->bw = RATE_INFO_BW_20; - break; - case (BIT(2)): - rate->bw = RATE_INFO_BW_40; - break; - case (BIT(3)): - rate->bw = RATE_INFO_BW_80; - break; - case (BIT(3) | BIT(2)): - rate->bw = RATE_INFO_BW_160; - break; - } - - if (tx_htinfo & BIT(4)) - rate->flags |= RATE_INFO_FLAGS_SHORT_GI; - - if ((priv->tx_rate >> 4) == 1) - rate->nss = 2; - else - rate->nss = 1; - } - } else { - /* - * Bit 0 in tx_htinfo indicates that current Tx rate - * is 11n rate. Valid MCS index values for us are 0 to 15. - */ - if ((tx_htinfo & BIT(0)) && (priv->tx_rate < 16)) { - rate->mcs = priv->tx_rate; - rate->flags |= RATE_INFO_FLAGS_MCS; - rate->bw = RATE_INFO_BW_20; - if (tx_htinfo & BIT(1)) - rate->bw = RATE_INFO_BW_40; - if (tx_htinfo & BIT(2)) - rate->flags |= RATE_INFO_FLAGS_SHORT_GI; - } - } -} - -/* - * This function dumps the station information on a buffer. - * - * The following information are shown - - * - Total bytes transmitted - * - Total bytes received - * - Total packets transmitted - * - Total packets received - * - Signal quality level - * - Transmission rate - */ -static int -mwifiex_dump_station_info(struct mwifiex_private *priv, - struct mwifiex_sta_node *node, - struct station_info *sinfo) -{ - u32 rate; - - sinfo->filled = BIT(NL80211_STA_INFO_RX_BYTES) | BIT(NL80211_STA_INFO_TX_BYTES) | - BIT(NL80211_STA_INFO_RX_PACKETS) | BIT(NL80211_STA_INFO_TX_PACKETS) | - BIT(NL80211_STA_INFO_TX_BITRATE) | - BIT(NL80211_STA_INFO_SIGNAL) | BIT(NL80211_STA_INFO_SIGNAL_AVG); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - if (!node) - return -ENOENT; - - sinfo->filled |= BIT(NL80211_STA_INFO_INACTIVE_TIME) | - BIT(NL80211_STA_INFO_TX_FAILED); - sinfo->inactive_time = - jiffies_to_msecs(jiffies - node->stats.last_rx); - - sinfo->signal = node->stats.rssi; - sinfo->signal_avg = node->stats.rssi; - sinfo->rx_bytes = node->stats.rx_bytes; - sinfo->tx_bytes = node->stats.tx_bytes; - sinfo->rx_packets = node->stats.rx_packets; - sinfo->tx_packets = node->stats.tx_packets; - sinfo->tx_failed = node->stats.tx_failed; - - mwifiex_parse_htinfo(priv, node->stats.last_tx_htinfo, - &sinfo->txrate); - sinfo->txrate.legacy = node->stats.last_tx_rate * 5; - - return 0; - } - - /* Get signal information from the firmware */ - if (mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, - HostCmd_ACT_GEN_GET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, - "failed to get signal information\n"); - return -EFAULT; - } - - if (mwifiex_drv_get_data_rate(priv, &rate)) { - mwifiex_dbg(priv->adapter, ERROR, - "getting data rate error\n"); - return -EFAULT; - } - - /* Get DTIM period information from firmware */ - mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_GET, DTIM_PERIOD_I, - &priv->dtim_period, true); - - mwifiex_parse_htinfo(priv, priv->tx_htinfo, &sinfo->txrate); - - sinfo->signal_avg = priv->bcn_rssi_avg; - sinfo->rx_bytes = priv->stats.rx_bytes; - sinfo->tx_bytes = priv->stats.tx_bytes; - sinfo->rx_packets = priv->stats.rx_packets; - sinfo->tx_packets = priv->stats.tx_packets; - sinfo->signal = priv->bcn_rssi_avg; - /* bit rate is in 500 kb/s units. Convert it to 100kb/s units */ - sinfo->txrate.legacy = rate * 5; - - if (priv->bss_mode == NL80211_IFTYPE_STATION) { - sinfo->filled |= BIT(NL80211_STA_INFO_BSS_PARAM); - sinfo->bss_param.flags = 0; - if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap & - WLAN_CAPABILITY_SHORT_PREAMBLE) - sinfo->bss_param.flags |= - BSS_PARAM_FLAGS_SHORT_PREAMBLE; - if (priv->curr_bss_params.bss_descriptor.cap_info_bitmap & - WLAN_CAPABILITY_SHORT_SLOT_TIME) - sinfo->bss_param.flags |= - BSS_PARAM_FLAGS_SHORT_SLOT_TIME; - sinfo->bss_param.dtim_period = priv->dtim_period; - sinfo->bss_param.beacon_interval = - priv->curr_bss_params.bss_descriptor.beacon_period; - } - - return 0; -} - -/* - * CFG802.11 operation handler to get station information. - * - * This function only works in connected mode, and dumps the - * requested station information, if available. - */ -static int -mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac, struct station_info *sinfo) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (!priv->media_connected) - return -ENOENT; - if (memcmp(mac, priv->cfg_bssid, ETH_ALEN)) - return -ENOENT; - - return mwifiex_dump_station_info(priv, NULL, sinfo); -} - -/* - * CFG802.11 operation handler to dump station information. - */ -static int -mwifiex_cfg80211_dump_station(struct wiphy *wiphy, struct net_device *dev, - int idx, u8 *mac, struct station_info *sinfo) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - static struct mwifiex_sta_node *node; - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - priv->media_connected && idx == 0) { - ether_addr_copy(mac, priv->cfg_bssid); - return mwifiex_dump_station_info(priv, NULL, sinfo); - } else if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - mwifiex_send_cmd(priv, HOST_CMD_APCMD_STA_LIST, - HostCmd_ACT_GEN_GET, 0, NULL, true); - - if (node && (&node->list == &priv->sta_list)) { - node = NULL; - return -ENOENT; - } - - node = list_prepare_entry(node, &priv->sta_list, list); - list_for_each_entry_continue(node, &priv->sta_list, list) { - ether_addr_copy(mac, node->mac_addr); - return mwifiex_dump_station_info(priv, node, sinfo); - } - } - - return -ENOENT; -} - -static int -mwifiex_cfg80211_dump_survey(struct wiphy *wiphy, struct net_device *dev, - int idx, struct survey_info *survey) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_chan_stats *pchan_stats = priv->adapter->chan_stats; - enum ieee80211_band band; - - mwifiex_dbg(priv->adapter, DUMP, "dump_survey idx=%d\n", idx); - - memset(survey, 0, sizeof(struct survey_info)); - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - priv->media_connected && idx == 0) { - u8 curr_bss_band = priv->curr_bss_params.band; - u32 chan = priv->curr_bss_params.bss_descriptor.channel; - - band = mwifiex_band_to_radio_type(curr_bss_band); - survey->channel = ieee80211_get_channel(wiphy, - ieee80211_channel_to_frequency(chan, band)); - - if (priv->bcn_nf_last) { - survey->filled = SURVEY_INFO_NOISE_DBM; - survey->noise = priv->bcn_nf_last; - } - return 0; - } - - if (idx >= priv->adapter->num_in_chan_stats) - return -ENOENT; - - if (!pchan_stats[idx].cca_scan_dur) - return 0; - - band = pchan_stats[idx].bandcfg; - survey->channel = ieee80211_get_channel(wiphy, - ieee80211_channel_to_frequency(pchan_stats[idx].chan_num, band)); - survey->filled = SURVEY_INFO_NOISE_DBM | - SURVEY_INFO_TIME | - SURVEY_INFO_TIME_BUSY; - survey->noise = pchan_stats[idx].noise; - survey->time = pchan_stats[idx].cca_scan_dur; - survey->time_busy = pchan_stats[idx].cca_busy_dur; - - return 0; -} - -/* Supported rates to be advertised to the cfg80211 */ -static struct ieee80211_rate mwifiex_rates[] = { - {.bitrate = 10, .hw_value = 2, }, - {.bitrate = 20, .hw_value = 4, }, - {.bitrate = 55, .hw_value = 11, }, - {.bitrate = 110, .hw_value = 22, }, - {.bitrate = 60, .hw_value = 12, }, - {.bitrate = 90, .hw_value = 18, }, - {.bitrate = 120, .hw_value = 24, }, - {.bitrate = 180, .hw_value = 36, }, - {.bitrate = 240, .hw_value = 48, }, - {.bitrate = 360, .hw_value = 72, }, - {.bitrate = 480, .hw_value = 96, }, - {.bitrate = 540, .hw_value = 108, }, -}; - -/* Channel definitions to be advertised to cfg80211 */ -static struct ieee80211_channel mwifiex_channels_2ghz[] = { - {.center_freq = 2412, .hw_value = 1, }, - {.center_freq = 2417, .hw_value = 2, }, - {.center_freq = 2422, .hw_value = 3, }, - {.center_freq = 2427, .hw_value = 4, }, - {.center_freq = 2432, .hw_value = 5, }, - {.center_freq = 2437, .hw_value = 6, }, - {.center_freq = 2442, .hw_value = 7, }, - {.center_freq = 2447, .hw_value = 8, }, - {.center_freq = 2452, .hw_value = 9, }, - {.center_freq = 2457, .hw_value = 10, }, - {.center_freq = 2462, .hw_value = 11, }, - {.center_freq = 2467, .hw_value = 12, }, - {.center_freq = 2472, .hw_value = 13, }, - {.center_freq = 2484, .hw_value = 14, }, -}; - -static struct ieee80211_supported_band mwifiex_band_2ghz = { - .channels = mwifiex_channels_2ghz, - .n_channels = ARRAY_SIZE(mwifiex_channels_2ghz), - .bitrates = mwifiex_rates, - .n_bitrates = ARRAY_SIZE(mwifiex_rates), -}; - -static struct ieee80211_channel mwifiex_channels_5ghz[] = { - {.center_freq = 5040, .hw_value = 8, }, - {.center_freq = 5060, .hw_value = 12, }, - {.center_freq = 5080, .hw_value = 16, }, - {.center_freq = 5170, .hw_value = 34, }, - {.center_freq = 5190, .hw_value = 38, }, - {.center_freq = 5210, .hw_value = 42, }, - {.center_freq = 5230, .hw_value = 46, }, - {.center_freq = 5180, .hw_value = 36, }, - {.center_freq = 5200, .hw_value = 40, }, - {.center_freq = 5220, .hw_value = 44, }, - {.center_freq = 5240, .hw_value = 48, }, - {.center_freq = 5260, .hw_value = 52, }, - {.center_freq = 5280, .hw_value = 56, }, - {.center_freq = 5300, .hw_value = 60, }, - {.center_freq = 5320, .hw_value = 64, }, - {.center_freq = 5500, .hw_value = 100, }, - {.center_freq = 5520, .hw_value = 104, }, - {.center_freq = 5540, .hw_value = 108, }, - {.center_freq = 5560, .hw_value = 112, }, - {.center_freq = 5580, .hw_value = 116, }, - {.center_freq = 5600, .hw_value = 120, }, - {.center_freq = 5620, .hw_value = 124, }, - {.center_freq = 5640, .hw_value = 128, }, - {.center_freq = 5660, .hw_value = 132, }, - {.center_freq = 5680, .hw_value = 136, }, - {.center_freq = 5700, .hw_value = 140, }, - {.center_freq = 5745, .hw_value = 149, }, - {.center_freq = 5765, .hw_value = 153, }, - {.center_freq = 5785, .hw_value = 157, }, - {.center_freq = 5805, .hw_value = 161, }, - {.center_freq = 5825, .hw_value = 165, }, -}; - -static struct ieee80211_supported_band mwifiex_band_5ghz = { - .channels = mwifiex_channels_5ghz, - .n_channels = ARRAY_SIZE(mwifiex_channels_5ghz), - .bitrates = mwifiex_rates + 4, - .n_bitrates = ARRAY_SIZE(mwifiex_rates) - 4, -}; - - -/* Supported crypto cipher suits to be advertised to cfg80211 */ -static const u32 mwifiex_cipher_suites[] = { - WLAN_CIPHER_SUITE_WEP40, - WLAN_CIPHER_SUITE_WEP104, - WLAN_CIPHER_SUITE_TKIP, - WLAN_CIPHER_SUITE_CCMP, - WLAN_CIPHER_SUITE_AES_CMAC, -}; - -/* Supported mgmt frame types to be advertised to cfg80211 */ -static const struct ieee80211_txrx_stypes -mwifiex_mgmt_stypes[NUM_NL80211_IFTYPES] = { - [NL80211_IFTYPE_STATION] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_AP] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_P2P_CLIENT] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, - [NL80211_IFTYPE_P2P_GO] = { - .tx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_RESP >> 4), - .rx = BIT(IEEE80211_STYPE_ACTION >> 4) | - BIT(IEEE80211_STYPE_PROBE_REQ >> 4), - }, -}; - -/* - * CFG802.11 operation handler for setting bit rates. - * - * Function configures data rates to firmware using bitrate mask - * provided by cfg80211. - */ -static int mwifiex_cfg80211_set_bitrate_mask(struct wiphy *wiphy, - struct net_device *dev, - const u8 *peer, - const struct cfg80211_bitrate_mask *mask) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; - enum ieee80211_band band; - struct mwifiex_adapter *adapter = priv->adapter; - - if (!priv->media_connected) { - mwifiex_dbg(adapter, ERROR, - "Can not set Tx data rate in disconnected state\n"); - return -EINVAL; - } - - band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - - memset(bitmap_rates, 0, sizeof(bitmap_rates)); - - /* Fill HR/DSSS rates. */ - if (band == IEEE80211_BAND_2GHZ) - bitmap_rates[0] = mask->control[band].legacy & 0x000f; - - /* Fill OFDM rates */ - if (band == IEEE80211_BAND_2GHZ) - bitmap_rates[1] = (mask->control[band].legacy & 0x0ff0) >> 4; - else - bitmap_rates[1] = mask->control[band].legacy; - - /* Fill HT MCS rates */ - bitmap_rates[2] = mask->control[band].ht_mcs[0]; - if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) - bitmap_rates[2] |= mask->control[band].ht_mcs[1] << 8; - - /* Fill VHT MCS rates */ - if (adapter->fw_api_ver == MWIFIEX_FW_V15) { - bitmap_rates[10] = mask->control[band].vht_mcs[0]; - if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) - bitmap_rates[11] = mask->control[band].vht_mcs[1]; - } - - return mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_SET, 0, bitmap_rates, true); -} - -/* - * CFG802.11 operation handler for connection quality monitoring. - * - * This function subscribes/unsubscribes HIGH_RSSI and LOW_RSSI - * events to FW. - */ -static int mwifiex_cfg80211_set_cqm_rssi_config(struct wiphy *wiphy, - struct net_device *dev, - s32 rssi_thold, u32 rssi_hyst) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_ds_misc_subsc_evt subsc_evt; - - priv->cqm_rssi_thold = rssi_thold; - priv->cqm_rssi_hyst = rssi_hyst; - - memset(&subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); - subsc_evt.events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; - - /* Subscribe/unsubscribe low and high rssi events */ - if (rssi_thold && rssi_hyst) { - subsc_evt.action = HostCmd_ACT_BITWISE_SET; - subsc_evt.bcn_l_rssi_cfg.abs_value = abs(rssi_thold); - subsc_evt.bcn_h_rssi_cfg.abs_value = abs(rssi_thold); - subsc_evt.bcn_l_rssi_cfg.evt_freq = 1; - subsc_evt.bcn_h_rssi_cfg.evt_freq = 1; - return mwifiex_send_cmd(priv, - HostCmd_CMD_802_11_SUBSCRIBE_EVENT, - 0, 0, &subsc_evt, true); - } else { - subsc_evt.action = HostCmd_ACT_BITWISE_CLR; - return mwifiex_send_cmd(priv, - HostCmd_CMD_802_11_SUBSCRIBE_EVENT, - 0, 0, &subsc_evt, true); - } - - return 0; -} - -/* cfg80211 operation handler for change_beacon. - * Function retrieves and sets modified management IEs to FW. - */ -static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_beacon_data *data) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: bss_type mismatched\n", __func__); - return -EINVAL; - } - - if (!priv->bss_started) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: bss not started\n", __func__); - return -EINVAL; - } - - if (mwifiex_set_mgmt_ies(priv, data)) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: setting mgmt ies failed\n", __func__); - return -EFAULT; - } - - return 0; -} - -/* cfg80211 operation handler for del_station. - * Function deauthenticates station which value is provided in mac parameter. - * If mac is NULL/broadcast, all stations in associated station list are - * deauthenticated. If bss is not started or there are no stations in - * associated stations list, no action is taken. - */ -static int -mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev, - struct station_del_parameters *params) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_sta_node *sta_node; - u8 deauth_mac[ETH_ALEN]; - unsigned long flags; - - if (list_empty(&priv->sta_list) || !priv->bss_started) - return 0; - - if (!params->mac || is_broadcast_ether_addr(params->mac)) - return 0; - - mwifiex_dbg(priv->adapter, INFO, "%s: mac address %pM\n", - __func__, params->mac); - - eth_zero_addr(deauth_mac); - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_node = mwifiex_get_sta_entry(priv, params->mac); - if (sta_node) - ether_addr_copy(deauth_mac, params->mac); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - if (is_valid_ether_addr(deauth_mac)) { - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_STA_DEAUTH, - HostCmd_ACT_GEN_SET, 0, - deauth_mac, true)) - return -1; - } - - return 0; -} - -static int -mwifiex_cfg80211_set_antenna(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv = mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY); - struct mwifiex_ds_ant_cfg ant_cfg; - - if (!tx_ant || !rx_ant) - return -EOPNOTSUPP; - - if (adapter->hw_dev_mcs_support != HT_STREAM_2X2) { - /* Not a MIMO chip. User should provide specific antenna number - * for Tx/Rx path or enable all antennas for diversity - */ - if (tx_ant != rx_ant) - return -EOPNOTSUPP; - - if ((tx_ant & (tx_ant - 1)) && - (tx_ant != BIT(adapter->number_of_antenna) - 1)) - return -EOPNOTSUPP; - - if ((tx_ant == BIT(adapter->number_of_antenna) - 1) && - (priv->adapter->number_of_antenna > 1)) { - tx_ant = RF_ANTENNA_AUTO; - rx_ant = RF_ANTENNA_AUTO; - } - } else { - struct ieee80211_sta_ht_cap *ht_info; - int rx_mcs_supp; - enum ieee80211_band band; - - if ((tx_ant == 0x1 && rx_ant == 0x1)) { - adapter->user_dev_mcs_support = HT_STREAM_1X1; - if (adapter->is_hw_11ac_capable) - adapter->usr_dot_11ac_mcs_support = - MWIFIEX_11AC_MCS_MAP_1X1; - } else { - adapter->user_dev_mcs_support = HT_STREAM_2X2; - if (adapter->is_hw_11ac_capable) - adapter->usr_dot_11ac_mcs_support = - MWIFIEX_11AC_MCS_MAP_2X2; - } - - for (band = 0; band < IEEE80211_NUM_BANDS; band++) { - if (!adapter->wiphy->bands[band]) - continue; - - ht_info = &adapter->wiphy->bands[band]->ht_cap; - rx_mcs_supp = - GET_RXMCSSUPP(adapter->user_dev_mcs_support); - memset(&ht_info->mcs, 0, adapter->number_of_antenna); - memset(&ht_info->mcs, 0xff, rx_mcs_supp); - } - } - - ant_cfg.tx_ant = tx_ant; - ant_cfg.rx_ant = rx_ant; - - return mwifiex_send_cmd(priv, HostCmd_CMD_RF_ANTENNA, - HostCmd_ACT_GEN_SET, 0, &ant_cfg, true); -} - -/* cfg80211 operation handler for stop ap. - * Function stops BSS running at uAP interface. - */ -static int mwifiex_cfg80211_stop_ap(struct wiphy *wiphy, struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - mwifiex_abort_cac(priv); - - if (mwifiex_del_mgmt_ies(priv)) - mwifiex_dbg(priv->adapter, ERROR, - "Failed to delete mgmt IEs!\n"); - - priv->ap_11n_enabled = 0; - memset(&priv->bss_cfg, 0, sizeof(priv->bss_cfg)); - - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to stop the BSS\n"); - return -1; - } - - if (mwifiex_send_cmd(priv, HOST_CMD_APCMD_SYS_RESET, - HostCmd_ACT_GEN_SET, 0, NULL, true)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to reset BSS\n"); - return -1; - } - - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); - - return 0; -} - -/* cfg80211 operation handler for start_ap. - * Function sets beacon period, DTIM period, SSID and security into - * AP config structure. - * AP is configured with these settings and BSS is started. - */ -static int mwifiex_cfg80211_start_ap(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_ap_settings *params) -{ - struct mwifiex_uap_bss_param *bss_cfg; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_UAP) - return -1; - - bss_cfg = kzalloc(sizeof(struct mwifiex_uap_bss_param), GFP_KERNEL); - if (!bss_cfg) - return -ENOMEM; - - mwifiex_set_sys_config_invalid_data(bss_cfg); - - if (params->beacon_interval) - bss_cfg->beacon_period = params->beacon_interval; - if (params->dtim_period) - bss_cfg->dtim_period = params->dtim_period; - - if (params->ssid && params->ssid_len) { - memcpy(bss_cfg->ssid.ssid, params->ssid, params->ssid_len); - bss_cfg->ssid.ssid_len = params->ssid_len; - } - if (params->inactivity_timeout > 0) { - /* sta_ao_timer/ps_sta_ao_timer is in unit of 100ms */ - bss_cfg->sta_ao_timer = 10 * params->inactivity_timeout; - bss_cfg->ps_sta_ao_timer = 10 * params->inactivity_timeout; - } - - switch (params->hidden_ssid) { - case NL80211_HIDDEN_SSID_NOT_IN_USE: - bss_cfg->bcast_ssid_ctl = 1; - break; - case NL80211_HIDDEN_SSID_ZERO_LEN: - bss_cfg->bcast_ssid_ctl = 0; - break; - case NL80211_HIDDEN_SSID_ZERO_CONTENTS: - /* firmware doesn't support this type of hidden SSID */ - default: - kfree(bss_cfg); - return -EINVAL; - } - - mwifiex_uap_set_channel(priv, bss_cfg, params->chandef); - mwifiex_set_uap_rates(bss_cfg, params); - - if (mwifiex_set_secure_params(priv, bss_cfg, params)) { - kfree(bss_cfg); - mwifiex_dbg(priv->adapter, ERROR, - "Failed to parse secuirty parameters!\n"); - return -1; - } - - mwifiex_set_ht_params(priv, bss_cfg, params); - - if (priv->adapter->is_hw_11ac_capable) { - mwifiex_set_vht_params(priv, bss_cfg, params); - mwifiex_set_vht_width(priv, params->chandef.width, - priv->ap_11ac_enabled); - } - - if (priv->ap_11ac_enabled) - mwifiex_set_11ac_ba_params(priv); - else - mwifiex_set_ba_params(priv); - - mwifiex_set_wmm_params(priv, bss_cfg, params); - - if (mwifiex_is_11h_active(priv)) - mwifiex_set_tpc_params(priv, bss_cfg, params); - - if (mwifiex_is_11h_active(priv) && - !cfg80211_chandef_dfs_required(wiphy, ¶ms->chandef, - priv->bss_mode)) { - mwifiex_dbg(priv->adapter, INFO, - "Disable 11h extensions in FW\n"); - if (mwifiex_11h_activate(priv, false)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to disable 11h extensions!!"); - return -1; - } - priv->state_11h.is_11h_active = false; - } - - if (mwifiex_config_start_uap(priv, bss_cfg)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to start AP\n"); - kfree(bss_cfg); - return -1; - } - - if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon)) - return -1; - - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - mwifiex_wake_up_net_dev_queue(priv->netdev, priv->adapter); - - memcpy(&priv->bss_cfg, bss_cfg, sizeof(priv->bss_cfg)); - kfree(bss_cfg); - return 0; -} - -/* - * CFG802.11 operation handler for disconnection request. - * - * This function does not work when there is already a disconnection - * procedure going on. - */ -static int -mwifiex_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, - u16 reason_code) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (mwifiex_deauthenticate(priv, NULL)) - return -EFAULT; - - mwifiex_dbg(priv->adapter, MSG, - "info: successfully disconnected from %pM:\t" - "reason code %d\n", priv->cfg_bssid, reason_code); - - eth_zero_addr(priv->cfg_bssid); - priv->hs2_enabled = false; - - return 0; -} - -/* - * This function informs the CFG802.11 subsystem of a new IBSS. - * - * The following information are sent to the CFG802.11 subsystem - * to register the new IBSS. If we do not register the new IBSS, - * a kernel panic will result. - * - SSID - * - SSID length - * - BSSID - * - Channel - */ -static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv) -{ - struct ieee80211_channel *chan; - struct mwifiex_bss_info bss_info; - struct cfg80211_bss *bss; - int ie_len; - u8 ie_buf[IEEE80211_MAX_SSID_LEN + sizeof(struct ieee_types_header)]; - enum ieee80211_band band; - - if (mwifiex_get_bss_info(priv, &bss_info)) - return -1; - - ie_buf[0] = WLAN_EID_SSID; - ie_buf[1] = bss_info.ssid.ssid_len; - - memcpy(&ie_buf[sizeof(struct ieee_types_header)], - &bss_info.ssid.ssid, bss_info.ssid.ssid_len); - ie_len = ie_buf[1] + sizeof(struct ieee_types_header); - - band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - chan = __ieee80211_get_channel(priv->wdev.wiphy, - ieee80211_channel_to_frequency(bss_info.bss_chan, - band)); - - bss = cfg80211_inform_bss(priv->wdev.wiphy, chan, - CFG80211_BSS_FTYPE_UNKNOWN, - bss_info.bssid, 0, WLAN_CAPABILITY_IBSS, - 0, ie_buf, ie_len, 0, GFP_KERNEL); - if (bss) { - cfg80211_put_bss(priv->wdev.wiphy, bss); - ether_addr_copy(priv->cfg_bssid, bss_info.bssid); - } - - return 0; -} - -/* - * This function connects with a BSS. - * - * This function handles both Infra and Ad-Hoc modes. It also performs - * validity checking on the provided parameters, disconnects from the - * current BSS (if any), sets up the association/scan parameters, - * including security settings, and performs specific SSID scan before - * trying to connect. - * - * For Infra mode, the function returns failure if the specified SSID - * is not found in scan table. However, for Ad-Hoc mode, it can create - * the IBSS if it does not exist. On successful completion in either case, - * the function notifies the CFG802.11 subsystem of the new BSS connection. - */ -static int -mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, - const u8 *ssid, const u8 *bssid, int mode, - struct ieee80211_channel *channel, - struct cfg80211_connect_params *sme, bool privacy) -{ - struct cfg80211_ssid req_ssid; - int ret, auth_type = 0; - struct cfg80211_bss *bss = NULL; - u8 is_scanning_required = 0; - - memset(&req_ssid, 0, sizeof(struct cfg80211_ssid)); - - req_ssid.ssid_len = ssid_len; - if (ssid_len > IEEE80211_MAX_SSID_LEN) { - mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n"); - return -EINVAL; - } - - memcpy(req_ssid.ssid, ssid, ssid_len); - if (!req_ssid.ssid_len || req_ssid.ssid[0] < 0x20) { - mwifiex_dbg(priv->adapter, ERROR, "invalid SSID - aborting\n"); - return -EINVAL; - } - - /* As this is new association, clear locally stored - * keys and security related flags */ - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - priv->wep_key_curr_index = 0; - priv->sec_info.encryption_mode = 0; - priv->sec_info.is_authtype_auto = 0; - ret = mwifiex_set_encode(priv, NULL, NULL, 0, 0, NULL, 1); - - if (mode == NL80211_IFTYPE_ADHOC) { - /* "privacy" is set only for ad-hoc mode */ - if (privacy) { - /* - * Keep WLAN_CIPHER_SUITE_WEP104 for now so that - * the firmware can find a matching network from the - * scan. The cfg80211 does not give us the encryption - * mode at this stage so just setting it to WEP here. - */ - priv->sec_info.encryption_mode = - WLAN_CIPHER_SUITE_WEP104; - priv->sec_info.authentication_mode = - NL80211_AUTHTYPE_OPEN_SYSTEM; - } - - goto done; - } - - /* Now handle infra mode. "sme" is valid for infra mode only */ - if (sme->auth_type == NL80211_AUTHTYPE_AUTOMATIC) { - auth_type = NL80211_AUTHTYPE_OPEN_SYSTEM; - priv->sec_info.is_authtype_auto = 1; - } else { - auth_type = sme->auth_type; - } - - if (sme->crypto.n_ciphers_pairwise) { - priv->sec_info.encryption_mode = - sme->crypto.ciphers_pairwise[0]; - priv->sec_info.authentication_mode = auth_type; - } - - if (sme->crypto.cipher_group) { - priv->sec_info.encryption_mode = sme->crypto.cipher_group; - priv->sec_info.authentication_mode = auth_type; - } - if (sme->ie) - ret = mwifiex_set_gen_ie(priv, sme->ie, sme->ie_len); - - if (sme->key) { - if (mwifiex_is_alg_wep(priv->sec_info.encryption_mode)) { - mwifiex_dbg(priv->adapter, INFO, - "info: setting wep encryption\t" - "with key len %d\n", sme->key_len); - priv->wep_key_curr_index = sme->key_idx; - ret = mwifiex_set_encode(priv, NULL, sme->key, - sme->key_len, sme->key_idx, - NULL, 0); - } - } -done: - /* - * Scan entries are valid for some time (15 sec). So we can save one - * active scan time if we just try cfg80211_get_bss first. If it fails - * then request scan and cfg80211_get_bss() again for final output. - */ - while (1) { - if (is_scanning_required) { - /* Do specific SSID scanning */ - if (mwifiex_request_scan(priv, &req_ssid)) { - mwifiex_dbg(priv->adapter, ERROR, "scan error\n"); - return -EFAULT; - } - } - - /* Find the BSS we want using available scan results */ - if (mode == NL80211_IFTYPE_ADHOC) - bss = cfg80211_get_bss(priv->wdev.wiphy, channel, - bssid, ssid, ssid_len, - IEEE80211_BSS_TYPE_IBSS, - IEEE80211_PRIVACY_ANY); - else - bss = cfg80211_get_bss(priv->wdev.wiphy, channel, - bssid, ssid, ssid_len, - IEEE80211_BSS_TYPE_ESS, - IEEE80211_PRIVACY_ANY); - - if (!bss) { - if (is_scanning_required) { - mwifiex_dbg(priv->adapter, WARN, - "assoc: requested bss not found in scan results\n"); - break; - } - is_scanning_required = 1; - } else { - mwifiex_dbg(priv->adapter, MSG, - "info: trying to associate to '%s' bssid %pM\n", - (char *)req_ssid.ssid, bss->bssid); - memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN); - break; - } - } - - ret = mwifiex_bss_start(priv, bss, &req_ssid); - if (ret) - return ret; - - if (mode == NL80211_IFTYPE_ADHOC) { - /* Inform the BSS information to kernel, otherwise - * kernel will give a panic after successful assoc */ - if (mwifiex_cfg80211_inform_ibss_bss(priv)) - return -EFAULT; - } - - return ret; -} - -/* - * CFG802.11 operation handler for association request. - * - * This function does not work when the current mode is set to Ad-Hoc, or - * when there is already an association procedure going on. The given BSS - * information is used to associate. - */ -static int -mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_connect_params *sme) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_adapter *adapter = priv->adapter; - int ret; - - if (GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) { - mwifiex_dbg(adapter, ERROR, - "%s: reject infra assoc request in non-STA role\n", - dev->name); - return -EINVAL; - } - - if (priv->wdev.current_bss) { - mwifiex_dbg(adapter, ERROR, - "%s: already connected\n", dev->name); - return -EALREADY; - } - - if (adapter->surprise_removed || adapter->is_cmd_timedout) { - mwifiex_dbg(adapter, ERROR, - "%s: Ignore connection.\t" - "Card removed or FW in bad state\n", - dev->name); - return -EFAULT; - } - - mwifiex_dbg(adapter, INFO, - "info: Trying to associate to %s and bssid %pM\n", - (char *)sme->ssid, sme->bssid); - - ret = mwifiex_cfg80211_assoc(priv, sme->ssid_len, sme->ssid, sme->bssid, - priv->bss_mode, sme->channel, sme, 0); - if (!ret) { - cfg80211_connect_result(priv->netdev, priv->cfg_bssid, NULL, 0, - NULL, 0, WLAN_STATUS_SUCCESS, - GFP_KERNEL); - mwifiex_dbg(priv->adapter, MSG, - "info: associated to bssid %pM successfully\n", - priv->cfg_bssid); - if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - priv->adapter->auto_tdls && - priv->bss_type == MWIFIEX_BSS_TYPE_STA) - mwifiex_setup_auto_tdls_timer(priv); - } else { - mwifiex_dbg(priv->adapter, ERROR, - "info: association to bssid %pM failed\n", - priv->cfg_bssid); - eth_zero_addr(priv->cfg_bssid); - - if (ret > 0) - cfg80211_connect_result(priv->netdev, priv->cfg_bssid, - NULL, 0, NULL, 0, ret, - GFP_KERNEL); - else - cfg80211_connect_result(priv->netdev, priv->cfg_bssid, - NULL, 0, NULL, 0, - WLAN_STATUS_UNSPECIFIED_FAILURE, - GFP_KERNEL); - } - - return 0; -} - -/* - * This function sets following parameters for ibss network. - * - channel - * - start band - * - 11n flag - * - secondary channel offset - */ -static int mwifiex_set_ibss_params(struct mwifiex_private *priv, - struct cfg80211_ibss_params *params) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int index = 0, i; - u8 config_bands = 0; - - if (params->chandef.chan->band == IEEE80211_BAND_2GHZ) { - if (!params->basic_rates) { - config_bands = BAND_B | BAND_G; - } else { - for (i = 0; i < mwifiex_band_2ghz.n_bitrates; i++) { - /* - * Rates below 6 Mbps in the table are CCK - * rates; 802.11b and from 6 they are OFDM; - * 802.11G - */ - if (mwifiex_rates[i].bitrate == 60) { - index = 1 << i; - break; - } - } - - if (params->basic_rates < index) { - config_bands = BAND_B; - } else { - config_bands = BAND_G; - if (params->basic_rates % index) - config_bands |= BAND_B; - } - } - - if (cfg80211_get_chandef_type(¶ms->chandef) != - NL80211_CHAN_NO_HT) - config_bands |= BAND_G | BAND_GN; - } else { - if (cfg80211_get_chandef_type(¶ms->chandef) == - NL80211_CHAN_NO_HT) - config_bands = BAND_A; - else - config_bands = BAND_AN | BAND_A; - } - - if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) { - adapter->config_bands = config_bands; - adapter->adhoc_start_band = config_bands; - - if ((config_bands & BAND_GN) || (config_bands & BAND_AN)) - adapter->adhoc_11n_enabled = true; - else - adapter->adhoc_11n_enabled = false; - } - - adapter->sec_chan_offset = - mwifiex_chan_type_to_sec_chan_offset( - cfg80211_get_chandef_type(¶ms->chandef)); - priv->adhoc_channel = ieee80211_frequency_to_channel( - params->chandef.chan->center_freq); - - mwifiex_dbg(adapter, INFO, - "info: set ibss band %d, chan %d, chan offset %d\n", - config_bands, priv->adhoc_channel, - adapter->sec_chan_offset); - - return 0; -} - -/* - * CFG802.11 operation handler to join an IBSS. - * - * This function does not work in any mode other than Ad-Hoc, or if - * a join operation is already in progress. - */ -static int -mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_ibss_params *params) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int ret = 0; - - if (priv->bss_mode != NL80211_IFTYPE_ADHOC) { - mwifiex_dbg(priv->adapter, ERROR, - "request to join ibss received\t" - "when station is not in ibss mode\n"); - goto done; - } - - mwifiex_dbg(priv->adapter, MSG, - "info: trying to join to %s and bssid %pM\n", - (char *)params->ssid, params->bssid); - - mwifiex_set_ibss_params(priv, params); - - ret = mwifiex_cfg80211_assoc(priv, params->ssid_len, params->ssid, - params->bssid, priv->bss_mode, - params->chandef.chan, NULL, - params->privacy); -done: - if (!ret) { - cfg80211_ibss_joined(priv->netdev, priv->cfg_bssid, - params->chandef.chan, GFP_KERNEL); - mwifiex_dbg(priv->adapter, MSG, - "info: joined/created adhoc network with bssid\t" - "%pM successfully\n", priv->cfg_bssid); - } else { - mwifiex_dbg(priv->adapter, ERROR, - "info: failed creating/joining adhoc network\n"); - } - - return ret; -} - -/* - * CFG802.11 operation handler to leave an IBSS. - * - * This function does not work if a leave operation is - * already in progress. - */ -static int -mwifiex_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - mwifiex_dbg(priv->adapter, MSG, "info: disconnecting from essid %pM\n", - priv->cfg_bssid); - if (mwifiex_deauthenticate(priv, NULL)) - return -EFAULT; - - eth_zero_addr(priv->cfg_bssid); - - return 0; -} - -/* - * CFG802.11 operation handler for scan request. - * - * This function issues a scan request to the firmware based upon - * the user specified scan configuration. On successful completion, - * it also informs the results. - */ -static int -mwifiex_cfg80211_scan(struct wiphy *wiphy, - struct cfg80211_scan_request *request) -{ - struct net_device *dev = request->wdev->netdev; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int i, offset, ret; - struct ieee80211_channel *chan; - struct ieee_types_header *ie; - struct mwifiex_user_scan_cfg *user_scan_cfg; - - mwifiex_dbg(priv->adapter, CMD, - "info: received scan request on %s\n", dev->name); - - /* Block scan request if scan operation or scan cleanup when interface - * is disabled is in process - */ - if (priv->scan_request || priv->scan_aborting) { - mwifiex_dbg(priv->adapter, WARN, - "cmd: Scan already in process..\n"); - return -EBUSY; - } - - user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); - if (!user_scan_cfg) - return -ENOMEM; - - priv->scan_request = request; - - user_scan_cfg->num_ssids = request->n_ssids; - user_scan_cfg->ssid_list = request->ssids; - - if (request->ie && request->ie_len) { - offset = 0; - for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { - if (priv->vs_ie[i].mask != MWIFIEX_VSIE_MASK_CLEAR) - continue; - priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_SCAN; - ie = (struct ieee_types_header *)(request->ie + offset); - memcpy(&priv->vs_ie[i].ie, ie, sizeof(*ie) + ie->len); - offset += sizeof(*ie) + ie->len; - - if (offset >= request->ie_len) - break; - } - } - - for (i = 0; i < min_t(u32, request->n_channels, - MWIFIEX_USER_SCAN_CHAN_MAX); i++) { - chan = request->channels[i]; - user_scan_cfg->chan_list[i].chan_number = chan->hw_value; - user_scan_cfg->chan_list[i].radio_type = chan->band; - - if ((chan->flags & IEEE80211_CHAN_NO_IR) || !request->n_ssids) - user_scan_cfg->chan_list[i].scan_type = - MWIFIEX_SCAN_TYPE_PASSIVE; - else - user_scan_cfg->chan_list[i].scan_type = - MWIFIEX_SCAN_TYPE_ACTIVE; - - user_scan_cfg->chan_list[i].scan_time = 0; - } - - if (priv->adapter->scan_chan_gap_enabled && - mwifiex_is_any_intf_active(priv)) - user_scan_cfg->scan_chan_gap = - priv->adapter->scan_chan_gap_time; - - ret = mwifiex_scan_networks(priv, user_scan_cfg); - kfree(user_scan_cfg); - if (ret) { - mwifiex_dbg(priv->adapter, ERROR, - "scan failed: %d\n", ret); - priv->scan_aborting = false; - priv->scan_request = NULL; - return ret; - } - - if (request->ie && request->ie_len) { - for (i = 0; i < MWIFIEX_MAX_VSIE_NUM; i++) { - if (priv->vs_ie[i].mask == MWIFIEX_VSIE_MASK_SCAN) { - priv->vs_ie[i].mask = MWIFIEX_VSIE_MASK_CLEAR; - memset(&priv->vs_ie[i].ie, 0, - MWIFIEX_MAX_VSIE_LEN); - } - } - } - return 0; -} - -static void mwifiex_setup_vht_caps(struct ieee80211_sta_vht_cap *vht_info, - struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - vht_info->vht_supported = true; - - vht_info->cap = adapter->hw_dot_11ac_dev_cap; - /* Update MCS support for VHT */ - vht_info->vht_mcs.rx_mcs_map = cpu_to_le16( - adapter->hw_dot_11ac_mcs_support & 0xFFFF); - vht_info->vht_mcs.rx_highest = 0; - vht_info->vht_mcs.tx_mcs_map = cpu_to_le16( - adapter->hw_dot_11ac_mcs_support >> 16); - vht_info->vht_mcs.tx_highest = 0; -} - -/* - * This function sets up the CFG802.11 specific HT capability fields - * with default values. - * - * The following default values are set - - * - HT Supported = True - * - Maximum AMPDU length factor = IEEE80211_HT_MAX_AMPDU_64K - * - Minimum AMPDU spacing = IEEE80211_HT_MPDU_DENSITY_NONE - * - HT Capabilities supported by firmware - * - MCS information, Rx mask = 0xff - * - MCD information, Tx parameters = IEEE80211_HT_MCS_TX_DEFINED (0x01) - */ -static void -mwifiex_setup_ht_caps(struct ieee80211_sta_ht_cap *ht_info, - struct mwifiex_private *priv) -{ - int rx_mcs_supp; - struct ieee80211_mcs_info mcs_set; - u8 *mcs = (u8 *)&mcs_set; - struct mwifiex_adapter *adapter = priv->adapter; - - ht_info->ht_supported = true; - ht_info->ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - ht_info->ampdu_density = IEEE80211_HT_MPDU_DENSITY_NONE; - - memset(&ht_info->mcs, 0, sizeof(ht_info->mcs)); - - /* Fill HT capability information */ - if (ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40; - else - ht_info->cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - - if (ISSUPP_SHORTGI20(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_SGI_20; - else - ht_info->cap &= ~IEEE80211_HT_CAP_SGI_20; - - if (ISSUPP_SHORTGI40(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_SGI_40; - else - ht_info->cap &= ~IEEE80211_HT_CAP_SGI_40; - - if (adapter->user_dev_mcs_support == HT_STREAM_2X2) - ht_info->cap |= 3 << IEEE80211_HT_CAP_RX_STBC_SHIFT; - else - ht_info->cap |= 1 << IEEE80211_HT_CAP_RX_STBC_SHIFT; - - if (ISSUPP_TXSTBC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_TX_STBC; - else - ht_info->cap &= ~IEEE80211_HT_CAP_TX_STBC; - - if (ISSUPP_GREENFIELD(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_GRN_FLD; - else - ht_info->cap &= ~IEEE80211_HT_CAP_GRN_FLD; - - if (ISENABLED_40MHZ_INTOLERANT(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_40MHZ_INTOLERANT; - else - ht_info->cap &= ~IEEE80211_HT_CAP_40MHZ_INTOLERANT; - - if (ISSUPP_RXLDPC(adapter->hw_dot_11n_dev_cap)) - ht_info->cap |= IEEE80211_HT_CAP_LDPC_CODING; - else - ht_info->cap &= ~IEEE80211_HT_CAP_LDPC_CODING; - - ht_info->cap &= ~IEEE80211_HT_CAP_MAX_AMSDU; - ht_info->cap |= IEEE80211_HT_CAP_SM_PS; - - rx_mcs_supp = GET_RXMCSSUPP(adapter->user_dev_mcs_support); - /* Set MCS for 1x1/2x2 */ - memset(mcs, 0xff, rx_mcs_supp); - /* Clear all the other values */ - memset(&mcs[rx_mcs_supp], 0, - sizeof(struct ieee80211_mcs_info) - rx_mcs_supp); - if (priv->bss_mode == NL80211_IFTYPE_STATION || - ISSUPP_CHANWIDTH40(adapter->hw_dot_11n_dev_cap)) - /* Set MCS32 for infra mode or ad-hoc mode with 40MHz support */ - SETHT_MCS32(mcs_set.rx_mask); - - memcpy((u8 *) &ht_info->mcs, mcs, sizeof(struct ieee80211_mcs_info)); - - ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; -} - -/* - * create a new virtual interface with the given name and name assign type - */ -struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, - const char *name, - unsigned char name_assign_type, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_private *priv; - struct net_device *dev; - void *mdev_priv; - - if (!adapter) - return ERR_PTR(-EFAULT); - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - if (adapter->curr_iface_comb.sta_intf == - adapter->iface_limit.sta_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple sta/adhoc ifaces\n"); - return ERR_PTR(-EINVAL); - } - - priv = mwifiex_get_unused_priv(adapter); - if (!priv) { - mwifiex_dbg(adapter, ERROR, - "could not get free private struct\n"); - return ERR_PTR(-EFAULT); - } - - priv->wdev.wiphy = wiphy; - priv->wdev.iftype = NL80211_IFTYPE_STATION; - - if (type == NL80211_IFTYPE_UNSPECIFIED) - priv->bss_mode = NL80211_IFTYPE_STATION; - else - priv->bss_mode = type; - - priv->bss_type = MWIFIEX_BSS_TYPE_STA; - priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = 0; - priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_num = adapter->curr_iface_comb.sta_intf; - - break; - case NL80211_IFTYPE_AP: - if (adapter->curr_iface_comb.uap_intf == - adapter->iface_limit.uap_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple AP ifaces\n"); - return ERR_PTR(-EINVAL); - } - - priv = mwifiex_get_unused_priv(adapter); - if (!priv) { - mwifiex_dbg(adapter, ERROR, - "could not get free private struct\n"); - return ERR_PTR(-EFAULT); - } - - priv->wdev.wiphy = wiphy; - priv->wdev.iftype = NL80211_IFTYPE_AP; - - priv->bss_type = MWIFIEX_BSS_TYPE_UAP; - priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = 0; - priv->bss_role = MWIFIEX_BSS_ROLE_UAP; - priv->bss_started = 0; - priv->bss_num = adapter->curr_iface_comb.uap_intf; - priv->bss_mode = type; - - break; - case NL80211_IFTYPE_P2P_CLIENT: - if (adapter->curr_iface_comb.p2p_intf == - adapter->iface_limit.p2p_intf) { - mwifiex_dbg(adapter, ERROR, - "cannot create multiple P2P ifaces\n"); - return ERR_PTR(-EINVAL); - } - - priv = mwifiex_get_unused_priv(adapter); - if (!priv) { - mwifiex_dbg(adapter, ERROR, - "could not get free private struct\n"); - return ERR_PTR(-EFAULT); - } - - priv->wdev.wiphy = wiphy; - /* At start-up, wpa_supplicant tries to change the interface - * to NL80211_IFTYPE_STATION if it is not managed mode. - */ - priv->wdev.iftype = NL80211_IFTYPE_P2P_CLIENT; - priv->bss_mode = NL80211_IFTYPE_P2P_CLIENT; - - /* Setting bss_type to P2P tells firmware that this interface - * is receiving P2P peers found during find phase and doing - * action frame handshake. - */ - priv->bss_type = MWIFIEX_BSS_TYPE_P2P; - - priv->frame_type = MWIFIEX_DATA_FRAME_TYPE_ETH_II; - priv->bss_priority = MWIFIEX_BSS_ROLE_STA; - priv->bss_role = MWIFIEX_BSS_ROLE_STA; - priv->bss_started = 0; - priv->bss_num = adapter->curr_iface_comb.p2p_intf; - - if (mwifiex_cfg80211_init_p2p_client(priv)) { - memset(&priv->wdev, 0, sizeof(priv->wdev)); - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-EFAULT); - } - - break; - default: - mwifiex_dbg(adapter, ERROR, "type not supported\n"); - return ERR_PTR(-EINVAL); - } - - dev = alloc_netdev_mqs(sizeof(struct mwifiex_private *), name, - name_assign_type, ether_setup, - IEEE80211_NUM_ACS, 1); - if (!dev) { - mwifiex_dbg(adapter, ERROR, - "no memory available for netdevice\n"); - memset(&priv->wdev, 0, sizeof(priv->wdev)); - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-ENOMEM); - } - - mwifiex_init_priv_params(priv, dev); - priv->netdev = dev; - - mwifiex_setup_ht_caps(&wiphy->bands[IEEE80211_BAND_2GHZ]->ht_cap, priv); - if (adapter->is_hw_11ac_capable) - mwifiex_setup_vht_caps( - &wiphy->bands[IEEE80211_BAND_2GHZ]->vht_cap, priv); - - if (adapter->config_bands & BAND_A) - mwifiex_setup_ht_caps( - &wiphy->bands[IEEE80211_BAND_5GHZ]->ht_cap, priv); - - if ((adapter->config_bands & BAND_A) && adapter->is_hw_11ac_capable) - mwifiex_setup_vht_caps( - &wiphy->bands[IEEE80211_BAND_5GHZ]->vht_cap, priv); - - dev_net_set(dev, wiphy_net(wiphy)); - dev->ieee80211_ptr = &priv->wdev; - dev->ieee80211_ptr->iftype = priv->bss_mode; - memcpy(dev->dev_addr, wiphy->perm_addr, ETH_ALEN); - SET_NETDEV_DEV(dev, wiphy_dev(wiphy)); - - dev->flags |= IFF_BROADCAST | IFF_MULTICAST; - dev->watchdog_timeo = MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT; - dev->hard_header_len += MWIFIEX_MIN_DATA_HEADER_LEN; - dev->ethtool_ops = &mwifiex_ethtool_ops; - - mdev_priv = netdev_priv(dev); - *((unsigned long *) mdev_priv) = (unsigned long) priv; - - SET_NETDEV_DEV(dev, adapter->dev); - - /* Register network device */ - if (register_netdevice(dev)) { - mwifiex_dbg(adapter, ERROR, - "cannot register virtual network device\n"); - free_netdev(dev); - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - priv->netdev = NULL; - memset(&priv->wdev, 0, sizeof(priv->wdev)); - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-EFAULT); - } - - priv->dfs_cac_workqueue = alloc_workqueue("MWIFIEX_DFS_CAC%s", - WQ_HIGHPRI | - WQ_MEM_RECLAIM | - WQ_UNBOUND, 1, name); - if (!priv->dfs_cac_workqueue) { - mwifiex_dbg(adapter, ERROR, - "cannot register virtual network device\n"); - free_netdev(dev); - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - priv->netdev = NULL; - memset(&priv->wdev, 0, sizeof(priv->wdev)); - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-ENOMEM); - } - - INIT_DELAYED_WORK(&priv->dfs_cac_work, mwifiex_dfs_cac_work_queue); - - priv->dfs_chan_sw_workqueue = alloc_workqueue("MWIFIEX_DFS_CHSW%s", - WQ_HIGHPRI | WQ_UNBOUND | - WQ_MEM_RECLAIM, 1, name); - if (!priv->dfs_chan_sw_workqueue) { - mwifiex_dbg(adapter, ERROR, - "cannot register virtual network device\n"); - free_netdev(dev); - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - priv->netdev = NULL; - memset(&priv->wdev, 0, sizeof(priv->wdev)); - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - return ERR_PTR(-ENOMEM); - } - - INIT_DELAYED_WORK(&priv->dfs_chan_sw_work, - mwifiex_dfs_chan_sw_work_queue); - - sema_init(&priv->async_sem, 1); - - mwifiex_dbg(adapter, INFO, - "info: %s: Marvell 802.11 Adapter\n", dev->name); - -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_init(priv); -#endif - - switch (type) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf++; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf++; - break; - case NL80211_IFTYPE_P2P_CLIENT: - adapter->curr_iface_comb.p2p_intf++; - break; - default: - mwifiex_dbg(adapter, ERROR, "type not supported\n"); - return ERR_PTR(-EINVAL); - } - - return &priv->wdev; -} -EXPORT_SYMBOL_GPL(mwifiex_add_virtual_intf); - -/* - * del_virtual_intf: remove the virtual interface determined by dev - */ -int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - struct mwifiex_adapter *adapter = priv->adapter; - struct sk_buff *skb, *tmp; - -#ifdef CONFIG_DEBUG_FS - mwifiex_dev_debugfs_remove(priv); -#endif - - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - - skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) - mwifiex_write_data_complete(priv->adapter, skb, 0, -1); - - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - - if (wdev->netdev->reg_state == NETREG_REGISTERED) - unregister_netdevice(wdev->netdev); - - if (priv->dfs_cac_workqueue) { - flush_workqueue(priv->dfs_cac_workqueue); - destroy_workqueue(priv->dfs_cac_workqueue); - priv->dfs_cac_workqueue = NULL; - } - - if (priv->dfs_chan_sw_workqueue) { - flush_workqueue(priv->dfs_chan_sw_workqueue); - destroy_workqueue(priv->dfs_chan_sw_workqueue); - priv->dfs_chan_sw_workqueue = NULL; - } - /* Clear the priv in adapter */ - priv->netdev->ieee80211_ptr = NULL; - priv->netdev = NULL; - priv->wdev.iftype = NL80211_IFTYPE_UNSPECIFIED; - - priv->media_connected = false; - - switch (priv->bss_mode) { - case NL80211_IFTYPE_UNSPECIFIED: - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - adapter->curr_iface_comb.sta_intf--; - break; - case NL80211_IFTYPE_AP: - adapter->curr_iface_comb.uap_intf--; - break; - case NL80211_IFTYPE_P2P_CLIENT: - case NL80211_IFTYPE_P2P_GO: - adapter->curr_iface_comb.p2p_intf--; - break; - default: - mwifiex_dbg(adapter, ERROR, - "del_virtual_intf: type not supported\n"); - break; - } - - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || - GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) - kfree(priv->hist_data); - - return 0; -} -EXPORT_SYMBOL_GPL(mwifiex_del_virtual_intf); - -static bool -mwifiex_is_pattern_supported(struct cfg80211_pkt_pattern *pat, s8 *byte_seq, - u8 max_byte_seq) -{ - int j, k, valid_byte_cnt = 0; - bool dont_care_byte = false; - - for (j = 0; j < DIV_ROUND_UP(pat->pattern_len, 8); j++) { - for (k = 0; k < 8; k++) { - if (pat->mask[j] & 1 << k) { - memcpy(byte_seq + valid_byte_cnt, - &pat->pattern[j * 8 + k], 1); - valid_byte_cnt++; - if (dont_care_byte) - return false; - } else { - if (valid_byte_cnt) - dont_care_byte = true; - } - - if (valid_byte_cnt > max_byte_seq) - return false; - } - } - - byte_seq[max_byte_seq] = valid_byte_cnt; - - return true; -} - -#ifdef CONFIG_PM -static void mwifiex_set_auto_arp_mef_entry(struct mwifiex_private *priv, - struct mwifiex_mef_entry *mef_entry) -{ - int i, filt_num = 0, num_ipv4 = 0; - struct in_device *in_dev; - struct in_ifaddr *ifa; - __be32 ips[MWIFIEX_MAX_SUPPORTED_IPADDR]; - struct mwifiex_adapter *adapter = priv->adapter; - - mef_entry->mode = MEF_MODE_HOST_SLEEP; - mef_entry->action = MEF_ACTION_AUTO_ARP; - - /* Enable ARP offload feature */ - memset(ips, 0, sizeof(ips)); - for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { - if (adapter->priv[i]->netdev) { - in_dev = __in_dev_get_rtnl(adapter->priv[i]->netdev); - if (!in_dev) - continue; - ifa = in_dev->ifa_list; - if (!ifa || !ifa->ifa_local) - continue; - ips[i] = ifa->ifa_local; - num_ipv4++; - } - } - - for (i = 0; i < num_ipv4; i++) { - if (!ips[i]) - continue; - mef_entry->filter[filt_num].repeat = 1; - memcpy(mef_entry->filter[filt_num].byte_seq, - (u8 *)&ips[i], sizeof(ips[i])); - mef_entry->filter[filt_num]. - byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = - sizeof(ips[i]); - mef_entry->filter[filt_num].offset = 46; - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - if (filt_num) { - mef_entry->filter[filt_num].filt_action = - TYPE_OR; - } - filt_num++; - } - - mef_entry->filter[filt_num].repeat = 1; - mef_entry->filter[filt_num].byte_seq[0] = 0x08; - mef_entry->filter[filt_num].byte_seq[1] = 0x06; - mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = 2; - mef_entry->filter[filt_num].offset = 20; - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - mef_entry->filter[filt_num].filt_action = TYPE_AND; -} - -static int mwifiex_set_wowlan_mef_entry(struct mwifiex_private *priv, - struct mwifiex_ds_mef_cfg *mef_cfg, - struct mwifiex_mef_entry *mef_entry, - struct cfg80211_wowlan *wowlan) -{ - int i, filt_num = 0, ret = 0; - bool first_pat = true; - u8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; - const u8 ipv4_mc_mac[] = {0x33, 0x33}; - const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; - - mef_entry->mode = MEF_MODE_HOST_SLEEP; - mef_entry->action = MEF_ACTION_ALLOW_AND_WAKEUP_HOST; - - for (i = 0; i < wowlan->n_patterns; i++) { - memset(byte_seq, 0, sizeof(byte_seq)); - if (!mwifiex_is_pattern_supported(&wowlan->patterns[i], - byte_seq, - MWIFIEX_MEF_MAX_BYTESEQ)) { - mwifiex_dbg(priv->adapter, ERROR, - "Pattern not supported\n"); - return -EOPNOTSUPP; - } - - if (!wowlan->patterns[i].pkt_offset) { - if (!(byte_seq[0] & 0x01) && - (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 1)) { - mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST; - continue; - } else if (is_broadcast_ether_addr(byte_seq)) { - mef_cfg->criteria |= MWIFIEX_CRITERIA_BROADCAST; - continue; - } else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && - (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 2)) || - (!memcmp(byte_seq, ipv6_mc_mac, 3) && - (byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] == 3))) { - mef_cfg->criteria |= MWIFIEX_CRITERIA_MULTICAST; - continue; - } - } - mef_entry->filter[filt_num].repeat = 1; - mef_entry->filter[filt_num].offset = - wowlan->patterns[i].pkt_offset; - memcpy(mef_entry->filter[filt_num].byte_seq, byte_seq, - sizeof(byte_seq)); - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - - if (first_pat) - first_pat = false; - else - mef_entry->filter[filt_num].filt_action = TYPE_AND; - - filt_num++; - } - - if (wowlan->magic_pkt) { - mef_cfg->criteria |= MWIFIEX_CRITERIA_UNICAST; - mef_entry->filter[filt_num].repeat = 16; - memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, - ETH_ALEN); - mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = - ETH_ALEN; - mef_entry->filter[filt_num].offset = 28; - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - if (filt_num) - mef_entry->filter[filt_num].filt_action = TYPE_OR; - - filt_num++; - mef_entry->filter[filt_num].repeat = 16; - memcpy(mef_entry->filter[filt_num].byte_seq, priv->curr_addr, - ETH_ALEN); - mef_entry->filter[filt_num].byte_seq[MWIFIEX_MEF_MAX_BYTESEQ] = - ETH_ALEN; - mef_entry->filter[filt_num].offset = 56; - mef_entry->filter[filt_num].filt_type = TYPE_EQ; - mef_entry->filter[filt_num].filt_action = TYPE_OR; - } - return ret; -} - -static int mwifiex_set_mef_filter(struct mwifiex_private *priv, - struct cfg80211_wowlan *wowlan) -{ - int ret = 0, num_entries = 1; - struct mwifiex_ds_mef_cfg mef_cfg; - struct mwifiex_mef_entry *mef_entry; - - if (wowlan->n_patterns || wowlan->magic_pkt) - num_entries++; - - mef_entry = kcalloc(num_entries, sizeof(*mef_entry), GFP_KERNEL); - if (!mef_entry) - return -ENOMEM; - - memset(&mef_cfg, 0, sizeof(mef_cfg)); - mef_cfg.criteria |= MWIFIEX_CRITERIA_BROADCAST | - MWIFIEX_CRITERIA_UNICAST; - mef_cfg.num_entries = num_entries; - mef_cfg.mef_entry = mef_entry; - - mwifiex_set_auto_arp_mef_entry(priv, &mef_entry[0]); - - if (wowlan->n_patterns || wowlan->magic_pkt) { - ret = mwifiex_set_wowlan_mef_entry(priv, &mef_cfg, - &mef_entry[1], wowlan); - if (ret) - goto err; - } - - if (!mef_cfg.criteria) - mef_cfg.criteria = MWIFIEX_CRITERIA_BROADCAST | - MWIFIEX_CRITERIA_UNICAST | - MWIFIEX_CRITERIA_MULTICAST; - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_MEF_CFG, - HostCmd_ACT_GEN_SET, 0, - &mef_cfg, true); - -err: - kfree(mef_entry); - return ret; -} - -static int mwifiex_cfg80211_suspend(struct wiphy *wiphy, - struct cfg80211_wowlan *wowlan) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - struct mwifiex_ds_hs_cfg hs_cfg; - int i, ret = 0; - struct mwifiex_private *priv; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - mwifiex_abort_cac(priv); - } - - mwifiex_cancel_all_pending_cmd(adapter); - - if (!wowlan) { - mwifiex_dbg(adapter, ERROR, - "None of the WOWLAN triggers enabled\n"); - return 0; - } - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); - - if (!priv->media_connected) { - mwifiex_dbg(adapter, ERROR, - "Can not configure WOWLAN in disconnected state\n"); - return 0; - } - - ret = mwifiex_set_mef_filter(priv, wowlan); - if (ret) { - mwifiex_dbg(adapter, ERROR, "Failed to set MEF filter\n"); - return ret; - } - - if (wowlan->disconnect) { - memset(&hs_cfg, 0, sizeof(hs_cfg)); - hs_cfg.is_invoke_hostcmd = false; - hs_cfg.conditions = HS_CFG_COND_MAC_EVENT; - hs_cfg.gpio = HS_CFG_GPIO_DEF; - hs_cfg.gap = HS_CFG_GAP_DEF; - ret = mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - MWIFIEX_SYNC_CMD, &hs_cfg); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "Failed to set HS params\n"); - return ret; - } - } - - return ret; -} - -static int mwifiex_cfg80211_resume(struct wiphy *wiphy) -{ - return 0; -} - -static void mwifiex_cfg80211_set_wakeup(struct wiphy *wiphy, - bool enabled) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - - device_set_wakeup_enable(adapter->dev, enabled); -} -#endif - -static int mwifiex_get_coalesce_pkt_type(u8 *byte_seq) -{ - const u8 ipv4_mc_mac[] = {0x33, 0x33}; - const u8 ipv6_mc_mac[] = {0x01, 0x00, 0x5e}; - const u8 bc_mac[] = {0xff, 0xff, 0xff, 0xff}; - - if ((byte_seq[0] & 0x01) && - (byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 1)) - return PACKET_TYPE_UNICAST; - else if (!memcmp(byte_seq, bc_mac, 4)) - return PACKET_TYPE_BROADCAST; - else if ((!memcmp(byte_seq, ipv4_mc_mac, 2) && - byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 2) || - (!memcmp(byte_seq, ipv6_mc_mac, 3) && - byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ] == 3)) - return PACKET_TYPE_MULTICAST; - - return 0; -} - -static int -mwifiex_fill_coalesce_rule_info(struct mwifiex_private *priv, - struct cfg80211_coalesce_rules *crule, - struct mwifiex_coalesce_rule *mrule) -{ - u8 byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ + 1]; - struct filt_field_param *param; - int i; - - mrule->max_coalescing_delay = crule->delay; - - param = mrule->params; - - for (i = 0; i < crule->n_patterns; i++) { - memset(byte_seq, 0, sizeof(byte_seq)); - if (!mwifiex_is_pattern_supported(&crule->patterns[i], - byte_seq, - MWIFIEX_COALESCE_MAX_BYTESEQ)) { - mwifiex_dbg(priv->adapter, ERROR, - "Pattern not supported\n"); - return -EOPNOTSUPP; - } - - if (!crule->patterns[i].pkt_offset) { - u8 pkt_type; - - pkt_type = mwifiex_get_coalesce_pkt_type(byte_seq); - if (pkt_type && mrule->pkt_type) { - mwifiex_dbg(priv->adapter, ERROR, - "Multiple packet types not allowed\n"); - return -EOPNOTSUPP; - } else if (pkt_type) { - mrule->pkt_type = pkt_type; - continue; - } - } - - if (crule->condition == NL80211_COALESCE_CONDITION_MATCH) - param->operation = RECV_FILTER_MATCH_TYPE_EQ; - else - param->operation = RECV_FILTER_MATCH_TYPE_NE; - - param->operand_len = byte_seq[MWIFIEX_COALESCE_MAX_BYTESEQ]; - memcpy(param->operand_byte_stream, byte_seq, - param->operand_len); - param->offset = crule->patterns[i].pkt_offset; - param++; - - mrule->num_of_fields++; - } - - if (!mrule->pkt_type) { - mwifiex_dbg(priv->adapter, ERROR, - "Packet type can not be determined\n"); - return -EOPNOTSUPP; - } - - return 0; -} - -static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy, - struct cfg80211_coalesce *coalesce) -{ - struct mwifiex_adapter *adapter = mwifiex_cfg80211_get_adapter(wiphy); - int i, ret; - struct mwifiex_ds_coalesce_cfg coalesce_cfg; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA); - - memset(&coalesce_cfg, 0, sizeof(coalesce_cfg)); - if (!coalesce) { - mwifiex_dbg(adapter, WARN, - "Disable coalesce and reset all previous rules\n"); - return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG, - HostCmd_ACT_GEN_SET, 0, - &coalesce_cfg, true); - } - - coalesce_cfg.num_of_rules = coalesce->n_rules; - for (i = 0; i < coalesce->n_rules; i++) { - ret = mwifiex_fill_coalesce_rule_info(priv, &coalesce->rules[i], - &coalesce_cfg.rule[i]); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "Recheck the patterns provided for rule %d\n", - i + 1); - return ret; - } - } - - return mwifiex_send_cmd(priv, HostCmd_CMD_COALESCE_CFG, - HostCmd_ACT_GEN_SET, 0, &coalesce_cfg, true); -} - -/* cfg80211 ops handler for tdls_mgmt. - * Function prepares TDLS action frame packets and forwards them to FW - */ -static int -mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, u8 action_code, u8 dialog_token, - u16 status_code, u32 peer_capability, - bool initiator, const u8 *extra_ies, - size_t extra_ies_len) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - int ret; - - if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS)) - return -ENOTSUPP; - - /* make sure we are in station mode and connected */ - if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) - return -ENOTSUPP; - - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - mwifiex_dbg(priv->adapter, MSG, - "Send TDLS Setup Request to %pM status_code=%d\n", - peer, status_code); - mwifiex_add_auto_tdls_peer(priv, peer); - ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, - dialog_token, status_code, - extra_ies, extra_ies_len); - break; - case WLAN_TDLS_SETUP_RESPONSE: - mwifiex_add_auto_tdls_peer(priv, peer); - mwifiex_dbg(priv->adapter, MSG, - "Send TDLS Setup Response to %pM status_code=%d\n", - peer, status_code); - ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, - dialog_token, status_code, - extra_ies, extra_ies_len); - break; - case WLAN_TDLS_SETUP_CONFIRM: - mwifiex_dbg(priv->adapter, MSG, - "Send TDLS Confirm to %pM status_code=%d\n", peer, - status_code); - ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, - dialog_token, status_code, - extra_ies, extra_ies_len); - break; - case WLAN_TDLS_TEARDOWN: - mwifiex_dbg(priv->adapter, MSG, - "Send TDLS Tear down to %pM\n", peer); - ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, - dialog_token, status_code, - extra_ies, extra_ies_len); - break; - case WLAN_TDLS_DISCOVERY_REQUEST: - mwifiex_dbg(priv->adapter, MSG, - "Send TDLS Discovery Request to %pM\n", peer); - ret = mwifiex_send_tdls_data_frame(priv, peer, action_code, - dialog_token, status_code, - extra_ies, extra_ies_len); - break; - case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - mwifiex_dbg(priv->adapter, MSG, - "Send TDLS Discovery Response to %pM\n", peer); - ret = mwifiex_send_tdls_action_frame(priv, peer, action_code, - dialog_token, status_code, - extra_ies, extra_ies_len); - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "Unknown TDLS mgmt/action frame %pM\n", peer); - ret = -EINVAL; - break; - } - - return ret; -} - -static int -mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, - const u8 *peer, enum nl80211_tdls_operation action) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (!(wiphy->flags & WIPHY_FLAG_SUPPORTS_TDLS) || - !(wiphy->flags & WIPHY_FLAG_TDLS_EXTERNAL_SETUP)) - return -ENOTSUPP; - - /* make sure we are in station mode and connected */ - if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) - return -ENOTSUPP; - - mwifiex_dbg(priv->adapter, MSG, - "TDLS peer=%pM, oper=%d\n", peer, action); - - switch (action) { - case NL80211_TDLS_ENABLE_LINK: - action = MWIFIEX_TDLS_ENABLE_LINK; - break; - case NL80211_TDLS_DISABLE_LINK: - action = MWIFIEX_TDLS_DISABLE_LINK; - break; - case NL80211_TDLS_TEARDOWN: - /* shouldn't happen!*/ - mwifiex_dbg(priv->adapter, ERROR, - "tdls_oper: teardown from driver not supported\n"); - return -EINVAL; - case NL80211_TDLS_SETUP: - /* shouldn't happen!*/ - mwifiex_dbg(priv->adapter, ERROR, - "tdls_oper: setup from driver not supported\n"); - return -EINVAL; - case NL80211_TDLS_DISCOVERY_REQ: - /* shouldn't happen!*/ - mwifiex_dbg(priv->adapter, ERROR, - "tdls_oper: discovery from driver not supported\n"); - return -EINVAL; - default: - mwifiex_dbg(priv->adapter, ERROR, - "tdls_oper: operation not supported\n"); - return -ENOTSUPP; - } - - return mwifiex_tdls_oper(priv, peer, action); -} - -static int -mwifiex_cfg80211_tdls_chan_switch(struct wiphy *wiphy, struct net_device *dev, - const u8 *addr, u8 oper_class, - struct cfg80211_chan_def *chandef) -{ - struct mwifiex_sta_node *sta_ptr; - unsigned long flags; - u16 chan; - u8 second_chan_offset, band; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_ptr = mwifiex_get_sta_entry(priv, addr); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - if (!sta_ptr) { - wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n", - __func__, addr); - return -ENOENT; - } - - if (!(sta_ptr->tdls_cap.extcap.ext_capab[3] & - WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH)) { - wiphy_err(wiphy, "%pM do not support tdls cs\n", addr); - return -ENOENT; - } - - if (sta_ptr->tdls_status == TDLS_CHAN_SWITCHING || - sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) { - wiphy_err(wiphy, "channel switch is running, abort request\n"); - return -EALREADY; - } - - chan = chandef->chan->hw_value; - second_chan_offset = mwifiex_get_sec_chan_offset(chan); - band = chandef->chan->band; - mwifiex_start_tdls_cs(priv, addr, chan, second_chan_offset, band); - - return 0; -} - -static void -mwifiex_cfg80211_tdls_cancel_chan_switch(struct wiphy *wiphy, - struct net_device *dev, - const u8 *addr) -{ - struct mwifiex_sta_node *sta_ptr; - unsigned long flags; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_ptr = mwifiex_get_sta_entry(priv, addr); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - if (!sta_ptr) { - wiphy_err(wiphy, "%s: Invalid TDLS peer %pM\n", - __func__, addr); - } else if (!(sta_ptr->tdls_status == TDLS_CHAN_SWITCHING || - sta_ptr->tdls_status == TDLS_IN_BASE_CHAN || - sta_ptr->tdls_status == TDLS_IN_OFF_CHAN)) { - wiphy_err(wiphy, "tdls chan switch not initialize by %pM\n", - addr); - } else - mwifiex_stop_tdls_cs(priv, addr); -} - -static int -mwifiex_cfg80211_add_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac, struct station_parameters *params) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) - return -ENOTSUPP; - - /* make sure we are in station mode and connected */ - if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected) - return -ENOTSUPP; - - return mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CREATE_LINK); -} - -static int -mwifiex_cfg80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, - struct cfg80211_csa_settings *params) -{ - struct ieee_types_header *chsw_ie; - struct ieee80211_channel_sw_ie *channel_sw; - int chsw_msec; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (priv->adapter->scan_processing) { - mwifiex_dbg(priv->adapter, ERROR, - "radar detection: scan in process...\n"); - return -EBUSY; - } - - if (priv->wdev.cac_started) - return -EBUSY; - - if (cfg80211_chandef_identical(¶ms->chandef, - &priv->dfs_chandef)) - return -EINVAL; - - chsw_ie = (void *)cfg80211_find_ie(WLAN_EID_CHANNEL_SWITCH, - params->beacon_csa.tail, - params->beacon_csa.tail_len); - if (!chsw_ie) { - mwifiex_dbg(priv->adapter, ERROR, - "Could not parse channel switch announcement IE\n"); - return -EINVAL; - } - - channel_sw = (void *)(chsw_ie + 1); - if (channel_sw->mode) { - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - mwifiex_stop_net_dev_queue(priv->netdev, priv->adapter); - } - - if (mwifiex_del_mgmt_ies(priv)) - mwifiex_dbg(priv->adapter, ERROR, - "Failed to delete mgmt IEs!\n"); - - if (mwifiex_set_mgmt_ies(priv, ¶ms->beacon_csa)) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: setting mgmt ies failed\n", __func__); - return -EFAULT; - } - - memcpy(&priv->dfs_chandef, ¶ms->chandef, sizeof(priv->dfs_chandef)); - memcpy(&priv->beacon_after, ¶ms->beacon_after, - sizeof(priv->beacon_after)); - - chsw_msec = max(channel_sw->count * priv->bss_cfg.beacon_period, 100); - queue_delayed_work(priv->dfs_chan_sw_workqueue, &priv->dfs_chan_sw_work, - msecs_to_jiffies(chsw_msec)); - return 0; -} - -static int mwifiex_cfg80211_get_channel(struct wiphy *wiphy, - struct wireless_dev *wdev, - struct cfg80211_chan_def *chandef) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(wdev->netdev); - struct mwifiex_bssdescriptor *curr_bss; - struct ieee80211_channel *chan; - u8 second_chan_offset; - enum nl80211_channel_type chan_type; - enum ieee80211_band band; - int freq; - int ret = -ENODATA; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP && - cfg80211_chandef_valid(&priv->bss_chandef)) { - *chandef = priv->bss_chandef; - ret = 0; - } else if (priv->media_connected) { - curr_bss = &priv->curr_bss_params.bss_descriptor; - band = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - freq = ieee80211_channel_to_frequency(curr_bss->channel, band); - chan = ieee80211_get_channel(wiphy, freq); - - if (curr_bss->bcn_ht_oper) { - second_chan_offset = curr_bss->bcn_ht_oper->ht_param & - IEEE80211_HT_PARAM_CHA_SEC_OFFSET; - chan_type = mwifiex_sec_chan_offset_to_chan_type - (second_chan_offset); - cfg80211_chandef_create(chandef, chan, chan_type); - } else { - cfg80211_chandef_create(chandef, chan, - NL80211_CHAN_NO_HT); - } - ret = 0; - } - - return ret; -} - -static int -mwifiex_cfg80211_start_radar_detection(struct wiphy *wiphy, - struct net_device *dev, - struct cfg80211_chan_def *chandef, - u32 cac_time_ms) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_radar_params radar_params; - - if (priv->adapter->scan_processing) { - mwifiex_dbg(priv->adapter, ERROR, - "radar detection: scan already in process...\n"); - return -EBUSY; - } - - if (!mwifiex_is_11h_active(priv)) { - mwifiex_dbg(priv->adapter, INFO, - "Enable 11h extensions in FW\n"); - if (mwifiex_11h_activate(priv, true)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to activate 11h extensions!!"); - return -1; - } - priv->state_11h.is_11h_active = true; - } - - memset(&radar_params, 0, sizeof(struct mwifiex_radar_params)); - radar_params.chandef = chandef; - radar_params.cac_time_ms = cac_time_ms; - - memcpy(&priv->dfs_chandef, chandef, sizeof(priv->dfs_chandef)); - - if (mwifiex_send_cmd(priv, HostCmd_CMD_CHAN_REPORT_REQUEST, - HostCmd_ACT_GEN_SET, 0, &radar_params, true)) - return -1; - - queue_delayed_work(priv->dfs_cac_workqueue, &priv->dfs_cac_work, - msecs_to_jiffies(cac_time_ms)); - return 0; -} - -static int -mwifiex_cfg80211_change_station(struct wiphy *wiphy, struct net_device *dev, - const u8 *mac, - struct station_parameters *params) -{ - int ret; - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - /* we support change_station handler only for TDLS peers*/ - if (!(params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))) - return -ENOTSUPP; - - /* make sure we are in station mode and connected */ - if ((priv->bss_type != MWIFIEX_BSS_TYPE_STA) || !priv->media_connected) - return -ENOTSUPP; - - priv->sta_params = params; - - ret = mwifiex_tdls_oper(priv, mac, MWIFIEX_TDLS_CONFIG_LINK); - priv->sta_params = NULL; - - return ret; -} - -/* station cfg80211 operations */ -static struct cfg80211_ops mwifiex_cfg80211_ops = { - .add_virtual_intf = mwifiex_add_virtual_intf, - .del_virtual_intf = mwifiex_del_virtual_intf, - .change_virtual_intf = mwifiex_cfg80211_change_virtual_intf, - .scan = mwifiex_cfg80211_scan, - .connect = mwifiex_cfg80211_connect, - .disconnect = mwifiex_cfg80211_disconnect, - .get_station = mwifiex_cfg80211_get_station, - .dump_station = mwifiex_cfg80211_dump_station, - .dump_survey = mwifiex_cfg80211_dump_survey, - .set_wiphy_params = mwifiex_cfg80211_set_wiphy_params, - .join_ibss = mwifiex_cfg80211_join_ibss, - .leave_ibss = mwifiex_cfg80211_leave_ibss, - .add_key = mwifiex_cfg80211_add_key, - .del_key = mwifiex_cfg80211_del_key, - .mgmt_tx = mwifiex_cfg80211_mgmt_tx, - .mgmt_frame_register = mwifiex_cfg80211_mgmt_frame_register, - .remain_on_channel = mwifiex_cfg80211_remain_on_channel, - .cancel_remain_on_channel = mwifiex_cfg80211_cancel_remain_on_channel, - .set_default_key = mwifiex_cfg80211_set_default_key, - .set_power_mgmt = mwifiex_cfg80211_set_power_mgmt, - .set_tx_power = mwifiex_cfg80211_set_tx_power, - .set_bitrate_mask = mwifiex_cfg80211_set_bitrate_mask, - .start_ap = mwifiex_cfg80211_start_ap, - .stop_ap = mwifiex_cfg80211_stop_ap, - .change_beacon = mwifiex_cfg80211_change_beacon, - .set_cqm_rssi_config = mwifiex_cfg80211_set_cqm_rssi_config, - .set_antenna = mwifiex_cfg80211_set_antenna, - .del_station = mwifiex_cfg80211_del_station, -#ifdef CONFIG_PM - .suspend = mwifiex_cfg80211_suspend, - .resume = mwifiex_cfg80211_resume, - .set_wakeup = mwifiex_cfg80211_set_wakeup, -#endif - .set_coalesce = mwifiex_cfg80211_set_coalesce, - .tdls_mgmt = mwifiex_cfg80211_tdls_mgmt, - .tdls_oper = mwifiex_cfg80211_tdls_oper, - .tdls_channel_switch = mwifiex_cfg80211_tdls_chan_switch, - .tdls_cancel_channel_switch = mwifiex_cfg80211_tdls_cancel_chan_switch, - .add_station = mwifiex_cfg80211_add_station, - .change_station = mwifiex_cfg80211_change_station, - .get_channel = mwifiex_cfg80211_get_channel, - .start_radar_detection = mwifiex_cfg80211_start_radar_detection, - .channel_switch = mwifiex_cfg80211_channel_switch, -}; - -#ifdef CONFIG_PM -static const struct wiphy_wowlan_support mwifiex_wowlan_support = { - .flags = WIPHY_WOWLAN_MAGIC_PKT | WIPHY_WOWLAN_DISCONNECT, - .n_patterns = MWIFIEX_MEF_MAX_FILTERS, - .pattern_min_len = 1, - .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, - .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, -}; -#endif - -static bool mwifiex_is_valid_alpha2(const char *alpha2) -{ - if (!alpha2 || strlen(alpha2) != 2) - return false; - - if (isalpha(alpha2[0]) && isalpha(alpha2[1])) - return true; - - return false; -} - -static const struct wiphy_coalesce_support mwifiex_coalesce_support = { - .n_rules = MWIFIEX_COALESCE_MAX_RULES, - .max_delay = MWIFIEX_MAX_COALESCING_DELAY, - .n_patterns = MWIFIEX_COALESCE_MAX_FILTERS, - .pattern_min_len = 1, - .pattern_max_len = MWIFIEX_MAX_PATTERN_LEN, - .max_pkt_offset = MWIFIEX_MAX_OFFSET_LEN, -}; - -int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter) -{ - u32 n_channels_bg, n_channels_a = 0; - - n_channels_bg = mwifiex_band_2ghz.n_channels; - - if (adapter->config_bands & BAND_A) - n_channels_a = mwifiex_band_5ghz.n_channels; - - adapter->num_in_chan_stats = max_t(u32, n_channels_bg, n_channels_a); - adapter->chan_stats = vmalloc(sizeof(*adapter->chan_stats) * - adapter->num_in_chan_stats); - - if (!adapter->chan_stats) - return -ENOMEM; - - return 0; -} - -/* - * This function registers the device with CFG802.11 subsystem. - * - * The function creates the wireless device/wiphy, populates it with - * default parameters and handler function pointers, and finally - * registers the device. - */ - -int mwifiex_register_cfg80211(struct mwifiex_adapter *adapter) -{ - int ret; - void *wdev_priv; - struct wiphy *wiphy; - struct mwifiex_private *priv = adapter->priv[MWIFIEX_BSS_TYPE_STA]; - u8 *country_code; - u32 thr, retry; - - /* create a new wiphy for use with cfg80211 */ - wiphy = wiphy_new(&mwifiex_cfg80211_ops, - sizeof(struct mwifiex_adapter *)); - if (!wiphy) { - mwifiex_dbg(adapter, ERROR, - "%s: creating new wiphy\n", __func__); - return -ENOMEM; - } - wiphy->max_scan_ssids = MWIFIEX_MAX_SSID_LIST_LENGTH; - wiphy->max_scan_ie_len = MWIFIEX_MAX_VSIE_LEN; - wiphy->mgmt_stypes = mwifiex_mgmt_stypes; - wiphy->max_remain_on_channel_duration = 5000; - wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | - BIT(NL80211_IFTYPE_ADHOC) | - BIT(NL80211_IFTYPE_P2P_CLIENT) | - BIT(NL80211_IFTYPE_P2P_GO) | - BIT(NL80211_IFTYPE_AP); - - wiphy->bands[IEEE80211_BAND_2GHZ] = &mwifiex_band_2ghz; - if (adapter->config_bands & BAND_A) - wiphy->bands[IEEE80211_BAND_5GHZ] = &mwifiex_band_5ghz; - else - wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - - if (adapter->drcs_enabled && ISSUPP_DRCS_ENABLED(adapter->fw_cap_info)) - wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_drcs; - else if (adapter->is_hw_11ac_capable) - wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta_vht; - else - wiphy->iface_combinations = &mwifiex_iface_comb_ap_sta; - wiphy->n_iface_combinations = 1; - - /* Initialize cipher suits */ - wiphy->cipher_suites = mwifiex_cipher_suites; - wiphy->n_cipher_suites = ARRAY_SIZE(mwifiex_cipher_suites); - - ether_addr_copy(wiphy->perm_addr, adapter->perm_addr); - wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM; - wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME | - WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD | - WIPHY_FLAG_AP_UAPSD | - WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | - WIPHY_FLAG_HAS_CHANNEL_SWITCH | - WIPHY_FLAG_PS_ON_BY_DEFAULT; - - if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) - wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS | - WIPHY_FLAG_TDLS_EXTERNAL_SETUP; - -#ifdef CONFIG_PM - wiphy->wowlan = &mwifiex_wowlan_support; -#endif - - wiphy->coalesce = &mwifiex_coalesce_support; - - wiphy->probe_resp_offload = NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_WPS2 | - NL80211_PROBE_RESP_OFFLOAD_SUPPORT_P2P; - - wiphy->available_antennas_tx = BIT(adapter->number_of_antenna) - 1; - wiphy->available_antennas_rx = BIT(adapter->number_of_antenna) - 1; - - wiphy->features |= NL80211_FEATURE_HT_IBSS | - NL80211_FEATURE_INACTIVITY_TIMER | - NL80211_FEATURE_NEED_OBSS_SCAN; - - if (ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) - wiphy->features |= NL80211_FEATURE_TDLS_CHANNEL_SWITCH; - - if (adapter->fw_api_ver == MWIFIEX_FW_V15) - wiphy->features |= NL80211_FEATURE_SK_TX_STATUS; - - /* Reserve space for mwifiex specific private data for BSS */ - wiphy->bss_priv_size = sizeof(struct mwifiex_bss_priv); - - wiphy->reg_notifier = mwifiex_reg_notifier; - - /* Set struct mwifiex_adapter pointer in wiphy_priv */ - wdev_priv = wiphy_priv(wiphy); - *(unsigned long *)wdev_priv = (unsigned long)adapter; - - set_wiphy_dev(wiphy, priv->adapter->dev); - - ret = wiphy_register(wiphy); - if (ret < 0) { - mwifiex_dbg(adapter, ERROR, - "%s: wiphy_register failed: %d\n", __func__, ret); - wiphy_free(wiphy); - return ret; - } - - if (reg_alpha2 && mwifiex_is_valid_alpha2(reg_alpha2)) { - mwifiex_dbg(adapter, INFO, - "driver hint alpha2: %2.2s\n", reg_alpha2); - regulatory_hint(wiphy, reg_alpha2); - } else { - country_code = mwifiex_11d_code_2_region(adapter->region_code); - if (country_code) - mwifiex_dbg(adapter, WARN, - "ignoring F/W country code %2.2s\n", - country_code); - } - - mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_GET, FRAG_THRESH_I, &thr, true); - wiphy->frag_threshold = thr; - mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_GET, RTS_THRESH_I, &thr, true); - wiphy->rts_threshold = thr; - mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_GET, SHORT_RETRY_LIM_I, &retry, true); - wiphy->retry_short = (u8) retry; - mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_GET, LONG_RETRY_LIM_I, &retry, true); - wiphy->retry_long = (u8) retry; - - adapter->wiphy = wiphy; - return ret; -} diff --git a/drivers/net/wireless/mwifiex/cfg80211.h b/drivers/net/wireless/mwifiex/cfg80211.h deleted file mode 100644 index 908367857d58..000000000000 --- a/drivers/net/wireless/mwifiex/cfg80211.h +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Marvell Wireless LAN device driver: CFG80211 - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef __MWIFIEX_CFG80211__ -#define __MWIFIEX_CFG80211__ - -#include <net/cfg80211.h> - -#include "main.h" - -int mwifiex_register_cfg80211(struct mwifiex_adapter *); - -#endif diff --git a/drivers/net/wireless/mwifiex/cfp.c b/drivers/net/wireless/mwifiex/cfp.c deleted file mode 100644 index 3ddb8ec676ed..000000000000 --- a/drivers/net/wireless/mwifiex/cfp.c +++ /dev/null @@ -1,537 +0,0 @@ -/* - * Marvell Wireless LAN device driver: Channel, Frequence and Power - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "cfg80211.h" - -/* 100mW */ -#define MWIFIEX_TX_PWR_DEFAULT 20 -/* 100mW */ -#define MWIFIEX_TX_PWR_US_DEFAULT 20 -/* 50mW */ -#define MWIFIEX_TX_PWR_JP_DEFAULT 16 -/* 100mW */ -#define MWIFIEX_TX_PWR_FR_100MW 20 -/* 10mW */ -#define MWIFIEX_TX_PWR_FR_10MW 10 -/* 100mW */ -#define MWIFIEX_TX_PWR_EMEA_DEFAULT 20 - -static u8 adhoc_rates_b[B_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, 0 }; - -static u8 adhoc_rates_g[G_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, - 0xb0, 0x48, 0x60, 0x6c, 0 }; - -static u8 adhoc_rates_bg[BG_SUPPORTED_RATES] = { 0x82, 0x84, 0x8b, 0x96, - 0x0c, 0x12, 0x18, 0x24, - 0x30, 0x48, 0x60, 0x6c, 0 }; - -static u8 adhoc_rates_a[A_SUPPORTED_RATES] = { 0x8c, 0x12, 0x98, 0x24, - 0xb0, 0x48, 0x60, 0x6c, 0 }; -static u8 supported_rates_a[A_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, - 0xb0, 0x48, 0x60, 0x6c, 0 }; -static u16 mwifiex_data_rates[MWIFIEX_SUPPORTED_RATES_EXT] = { 0x02, 0x04, - 0x0B, 0x16, 0x00, 0x0C, 0x12, 0x18, - 0x24, 0x30, 0x48, 0x60, 0x6C, 0x90, - 0x0D, 0x1A, 0x27, 0x34, 0x4E, 0x68, - 0x75, 0x82, 0x0C, 0x1B, 0x36, 0x51, - 0x6C, 0xA2, 0xD8, 0xF3, 0x10E, 0x00 }; - -static u8 supported_rates_b[B_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x16, 0 }; - -static u8 supported_rates_g[G_SUPPORTED_RATES] = { 0x0c, 0x12, 0x18, 0x24, - 0x30, 0x48, 0x60, 0x6c, 0 }; - -static u8 supported_rates_bg[BG_SUPPORTED_RATES] = { 0x02, 0x04, 0x0b, 0x0c, - 0x12, 0x16, 0x18, 0x24, 0x30, 0x48, - 0x60, 0x6c, 0 }; - -u16 region_code_index[MWIFIEX_MAX_REGION_CODE] = { 0x10, 0x20, 0x30, - 0x32, 0x40, 0x41, 0xff }; - -static u8 supported_rates_n[N_SUPPORTED_RATES] = { 0x02, 0x04, 0 }; - -/* For every mcs_rate line, the first 8 bytes are for stream 1x1, - * and all 16 bytes are for stream 2x2. - */ -static const u16 mcs_rate[4][16] = { - /* LGI 40M */ - { 0x1b, 0x36, 0x51, 0x6c, 0xa2, 0xd8, 0xf3, 0x10e, - 0x36, 0x6c, 0xa2, 0xd8, 0x144, 0x1b0, 0x1e6, 0x21c }, - - /* SGI 40M */ - { 0x1e, 0x3c, 0x5a, 0x78, 0xb4, 0xf0, 0x10e, 0x12c, - 0x3c, 0x78, 0xb4, 0xf0, 0x168, 0x1e0, 0x21c, 0x258 }, - - /* LGI 20M */ - { 0x0d, 0x1a, 0x27, 0x34, 0x4e, 0x68, 0x75, 0x82, - 0x1a, 0x34, 0x4e, 0x68, 0x9c, 0xd0, 0xea, 0x104 }, - - /* SGI 20M */ - { 0x0e, 0x1c, 0x2b, 0x39, 0x56, 0x73, 0x82, 0x90, - 0x1c, 0x39, 0x56, 0x73, 0xad, 0xe7, 0x104, 0x120 } -}; - -/* AC rates */ -static const u16 ac_mcs_rate_nss1[8][10] = { - /* LG 160M */ - { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, - 0x492, 0x57C, 0x618 }, - - /* SG 160M */ - { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, - 0x514, 0x618, 0x6C6 }, - - /* LG 80M */ - { 0x3B, 0x75, 0xB0, 0xEA, 0x15F, 0x1D4, 0x20F, - 0x249, 0x2BE, 0x30C }, - - /* SG 80M */ - { 0x41, 0x82, 0xC3, 0x104, 0x186, 0x208, 0x249, - 0x28A, 0x30C, 0x363 }, - - /* LG 40M */ - { 0x1B, 0x36, 0x51, 0x6C, 0xA2, 0xD8, 0xF3, - 0x10E, 0x144, 0x168 }, - - /* SG 40M */ - { 0x1E, 0x3C, 0x5A, 0x78, 0xB4, 0xF0, 0x10E, - 0x12C, 0x168, 0x190 }, - - /* LG 20M */ - { 0xD, 0x1A, 0x27, 0x34, 0x4E, 0x68, 0x75, 0x82, 0x9C, 0x00 }, - - /* SG 20M */ - { 0xF, 0x1D, 0x2C, 0x3A, 0x57, 0x74, 0x82, 0x91, 0xAE, 0x00 }, -}; - -/* NSS2 note: the value in the table is 2 multiplier of the actual rate */ -static const u16 ac_mcs_rate_nss2[8][10] = { - /* LG 160M */ - { 0xEA, 0x1D4, 0x2BE, 0x3A8, 0x57C, 0x750, 0x83A, - 0x924, 0xAF8, 0xC30 }, - - /* SG 160M */ - { 0x104, 0x208, 0x30C, 0x410, 0x618, 0x820, 0x924, - 0xA28, 0xC30, 0xD8B }, - - /* LG 80M */ - { 0x75, 0xEA, 0x15F, 0x1D4, 0x2BE, 0x3A8, 0x41D, - 0x492, 0x57C, 0x618 }, - - /* SG 80M */ - { 0x82, 0x104, 0x186, 0x208, 0x30C, 0x410, 0x492, - 0x514, 0x618, 0x6C6 }, - - /* LG 40M */ - { 0x36, 0x6C, 0xA2, 0xD8, 0x144, 0x1B0, 0x1E6, - 0x21C, 0x288, 0x2D0 }, - - /* SG 40M */ - { 0x3C, 0x78, 0xB4, 0xF0, 0x168, 0x1E0, 0x21C, - 0x258, 0x2D0, 0x320 }, - - /* LG 20M */ - { 0x1A, 0x34, 0x4A, 0x68, 0x9C, 0xD0, 0xEA, 0x104, - 0x138, 0x00 }, - - /* SG 20M */ - { 0x1D, 0x3A, 0x57, 0x74, 0xAE, 0xE6, 0x104, 0x121, - 0x15B, 0x00 }, -}; - -struct region_code_mapping { - u8 code; - u8 region[IEEE80211_COUNTRY_STRING_LEN]; -}; - -static struct region_code_mapping region_code_mapping_t[] = { - { 0x10, "US " }, /* US FCC */ - { 0x20, "CA " }, /* IC Canada */ - { 0x30, "EU " }, /* ETSI */ - { 0x31, "ES " }, /* Spain */ - { 0x32, "FR " }, /* France */ - { 0x40, "JP " }, /* Japan */ - { 0x41, "JP " }, /* Japan */ - { 0x50, "CN " }, /* China */ -}; - -/* This function converts integer code to region string */ -u8 *mwifiex_11d_code_2_region(u8 code) -{ - u8 i; - u8 size = sizeof(region_code_mapping_t)/ - sizeof(struct region_code_mapping); - - /* Look for code in mapping table */ - for (i = 0; i < size; i++) - if (region_code_mapping_t[i].code == code) - return region_code_mapping_t[i].region; - - return NULL; -} - -/* - * This function maps an index in supported rates table into - * the corresponding data rate. - */ -u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, - u8 index, u8 ht_info) -{ - u32 rate = 0; - u8 mcs_index = 0; - u8 bw = 0; - u8 gi = 0; - - if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_VHT) { - mcs_index = min(index & 0xF, 9); - - /* 20M: bw=0, 40M: bw=1, 80M: bw=2, 160M: bw=3 */ - bw = (ht_info & 0xC) >> 2; - - /* LGI: gi =0, SGI: gi = 1 */ - gi = (ht_info & 0x10) >> 4; - - if ((index >> 4) == 1) /* NSS = 2 */ - rate = ac_mcs_rate_nss2[2 * (3 - bw) + gi][mcs_index]; - else /* NSS = 1 */ - rate = ac_mcs_rate_nss1[2 * (3 - bw) + gi][mcs_index]; - } else if ((ht_info & 0x3) == MWIFIEX_RATE_FORMAT_HT) { - /* 20M: bw=0, 40M: bw=1 */ - bw = (ht_info & 0xC) >> 2; - - /* LGI: gi =0, SGI: gi = 1 */ - gi = (ht_info & 0x10) >> 4; - - if (index == MWIFIEX_RATE_BITMAP_MCS0) { - if (gi == 1) - rate = 0x0D; /* MCS 32 SGI rate */ - else - rate = 0x0C; /* MCS 32 LGI rate */ - } else if (index < 16) { - if ((bw == 1) || (bw == 0)) - rate = mcs_rate[2 * (1 - bw) + gi][index]; - else - rate = mwifiex_data_rates[0]; - } else { - rate = mwifiex_data_rates[0]; - } - } else { - /* 11n non-HT rates */ - if (index >= MWIFIEX_SUPPORTED_RATES_EXT) - index = 0; - rate = mwifiex_data_rates[index]; - } - - return rate; -} - -/* This function maps an index in supported rates table into - * the corresponding data rate. - */ -u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, - u8 index, u8 ht_info) -{ - u32 mcs_num_supp = - (priv->adapter->user_dev_mcs_support == HT_STREAM_2X2) ? 16 : 8; - u32 rate; - - if (priv->adapter->is_hw_11ac_capable) - return mwifiex_index_to_acs_data_rate(priv, index, ht_info); - - if (ht_info & BIT(0)) { - if (index == MWIFIEX_RATE_BITMAP_MCS0) { - if (ht_info & BIT(2)) - rate = 0x0D; /* MCS 32 SGI rate */ - else - rate = 0x0C; /* MCS 32 LGI rate */ - } else if (index < mcs_num_supp) { - if (ht_info & BIT(1)) { - if (ht_info & BIT(2)) - /* SGI, 40M */ - rate = mcs_rate[1][index]; - else - /* LGI, 40M */ - rate = mcs_rate[0][index]; - } else { - if (ht_info & BIT(2)) - /* SGI, 20M */ - rate = mcs_rate[3][index]; - else - /* LGI, 20M */ - rate = mcs_rate[2][index]; - } - } else - rate = mwifiex_data_rates[0]; - } else { - if (index >= MWIFIEX_SUPPORTED_RATES_EXT) - index = 0; - rate = mwifiex_data_rates[index]; - } - return rate; -} - -/* - * This function returns the current active data rates. - * - * The result may vary depending upon connection status. - */ -u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, u8 *rates) -{ - if (!priv->media_connected) - return mwifiex_get_supported_rates(priv, rates); - else - return mwifiex_copy_rates(rates, 0, - priv->curr_bss_params.data_rates, - priv->curr_bss_params.num_of_rates); -} - -/* - * This function locates the Channel-Frequency-Power triplet based upon - * band and channel/frequency parameters. - */ -struct mwifiex_chan_freq_power * -mwifiex_get_cfp(struct mwifiex_private *priv, u8 band, u16 channel, u32 freq) -{ - struct mwifiex_chan_freq_power *cfp = NULL; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch = NULL; - int i; - - if (!channel && !freq) - return cfp; - - if (mwifiex_band_to_radio_type(band) == HostCmd_SCAN_RADIO_TYPE_BG) - sband = priv->wdev.wiphy->bands[IEEE80211_BAND_2GHZ]; - else - sband = priv->wdev.wiphy->bands[IEEE80211_BAND_5GHZ]; - - if (!sband) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: cannot find cfp by band %d\n", - __func__, band); - return cfp; - } - - for (i = 0; i < sband->n_channels; i++) { - ch = &sband->channels[i]; - - if (ch->flags & IEEE80211_CHAN_DISABLED) - continue; - - if (freq) { - if (ch->center_freq == freq) - break; - } else { - /* find by valid channel*/ - if (ch->hw_value == channel || - channel == FIRST_VALID_CHANNEL) - break; - } - } - if (i == sband->n_channels) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: cannot find cfp by band %d\t" - "& channel=%d freq=%d\n", - __func__, band, channel, freq); - } else { - if (!ch) - return cfp; - - priv->cfp.channel = ch->hw_value; - priv->cfp.freq = ch->center_freq; - priv->cfp.max_tx_power = ch->max_power; - cfp = &priv->cfp; - } - - return cfp; -} - -/* - * This function checks if the data rate is set to auto. - */ -u8 -mwifiex_is_rate_auto(struct mwifiex_private *priv) -{ - u32 i; - int rate_num = 0; - - for (i = 0; i < ARRAY_SIZE(priv->bitmap_rates); i++) - if (priv->bitmap_rates[i]) - rate_num++; - - if (rate_num > 1) - return true; - else - return false; -} - -/* This function gets the supported data rates from bitmask inside - * cfg80211_scan_request. - */ -u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv, - u8 *rates, u8 radio_type) -{ - struct wiphy *wiphy = priv->adapter->wiphy; - struct cfg80211_scan_request *request = priv->scan_request; - u32 num_rates, rate_mask; - struct ieee80211_supported_band *sband; - int i; - - if (radio_type) { - sband = wiphy->bands[IEEE80211_BAND_5GHZ]; - if (WARN_ON_ONCE(!sband)) - return 0; - rate_mask = request->rates[IEEE80211_BAND_5GHZ]; - } else { - sband = wiphy->bands[IEEE80211_BAND_2GHZ]; - if (WARN_ON_ONCE(!sband)) - return 0; - rate_mask = request->rates[IEEE80211_BAND_2GHZ]; - } - - num_rates = 0; - for (i = 0; i < sband->n_bitrates; i++) { - if ((BIT(i) & rate_mask) == 0) - continue; /* skip rate */ - rates[num_rates++] = (u8)(sband->bitrates[i].bitrate / 5); - } - - return num_rates; -} - -/* This function gets the supported data rates. The function works in - * both Ad-Hoc and infra mode by printing the band and returning the - * data rates. - */ -u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates) -{ - u32 k = 0; - struct mwifiex_adapter *adapter = priv->adapter; - - if (priv->bss_mode == NL80211_IFTYPE_STATION || - priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { - switch (adapter->config_bands) { - case BAND_B: - mwifiex_dbg(adapter, INFO, "info: infra band=%d\t" - "supported_rates_b\n", - adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_b, - sizeof(supported_rates_b)); - break; - case BAND_G: - case BAND_G | BAND_GN: - mwifiex_dbg(adapter, INFO, "info: infra band=%d\t" - "supported_rates_g\n", - adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_g, - sizeof(supported_rates_g)); - break; - case BAND_B | BAND_G: - case BAND_A | BAND_B | BAND_G: - case BAND_A | BAND_B: - case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN: - case BAND_A | BAND_B | BAND_G | BAND_GN | BAND_AN | BAND_AAC: - case BAND_B | BAND_G | BAND_GN: - mwifiex_dbg(adapter, INFO, "info: infra band=%d\t" - "supported_rates_bg\n", - adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_bg, - sizeof(supported_rates_bg)); - break; - case BAND_A: - case BAND_A | BAND_G: - mwifiex_dbg(adapter, INFO, "info: infra band=%d\t" - "supported_rates_a\n", - adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_a, - sizeof(supported_rates_a)); - break; - case BAND_AN: - case BAND_A | BAND_AN: - case BAND_A | BAND_AN | BAND_AAC: - case BAND_A | BAND_G | BAND_AN | BAND_GN: - case BAND_A | BAND_G | BAND_AN | BAND_GN | BAND_AAC: - mwifiex_dbg(adapter, INFO, "info: infra band=%d\t" - "supported_rates_a\n", - adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_a, - sizeof(supported_rates_a)); - break; - case BAND_GN: - mwifiex_dbg(adapter, INFO, "info: infra band=%d\t" - "supported_rates_n\n", - adapter->config_bands); - k = mwifiex_copy_rates(rates, k, supported_rates_n, - sizeof(supported_rates_n)); - break; - } - } else { - /* Ad-hoc mode */ - switch (adapter->adhoc_start_band) { - case BAND_B: - mwifiex_dbg(adapter, INFO, "info: adhoc B\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_b, - sizeof(adhoc_rates_b)); - break; - case BAND_G: - case BAND_G | BAND_GN: - mwifiex_dbg(adapter, INFO, "info: adhoc G only\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_g, - sizeof(adhoc_rates_g)); - break; - case BAND_B | BAND_G: - case BAND_B | BAND_G | BAND_GN: - mwifiex_dbg(adapter, INFO, "info: adhoc BG\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_bg, - sizeof(adhoc_rates_bg)); - break; - case BAND_A: - case BAND_A | BAND_AN: - mwifiex_dbg(adapter, INFO, "info: adhoc A\n"); - k = mwifiex_copy_rates(rates, k, adhoc_rates_a, - sizeof(adhoc_rates_a)); - break; - } - } - - return k; -} - -u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, - u8 rx_rate, u8 rate_info) -{ - u8 rate_index = 0; - - /* HT40 */ - if ((rate_info & BIT(0)) && (rate_info & BIT(1))) - rate_index = MWIFIEX_RATE_INDEX_MCS0 + - MWIFIEX_BW20_MCS_NUM + rx_rate; - else if (rate_info & BIT(0)) /* HT20 */ - rate_index = MWIFIEX_RATE_INDEX_MCS0 + rx_rate; - else - rate_index = (rx_rate > MWIFIEX_RATE_INDEX_OFDM0) ? - rx_rate - 1 : rx_rate; - - return rate_index; -} diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c deleted file mode 100644 index 45ae38e32621..000000000000 --- a/drivers/net/wireless/mwifiex/cmdevt.c +++ /dev/null @@ -1,1659 +0,0 @@ -/* - * Marvell Wireless LAN device driver: commands and events - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11ac.h" - -/* - * This function initializes a command node. - * - * The actual allocation of the node is not done by this function. It only - * initiates a node by filling it with default parameters. Similarly, - * allocation of the different buffers used (IOCTL buffer, data buffer) are - * not done by this function either. - */ -static void -mwifiex_init_cmd_node(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node, - u32 cmd_oid, void *data_buf, bool sync) -{ - cmd_node->priv = priv; - cmd_node->cmd_oid = cmd_oid; - if (sync) { - cmd_node->wait_q_enabled = true; - cmd_node->cmd_wait_q_woken = false; - cmd_node->condition = &cmd_node->cmd_wait_q_woken; - } - cmd_node->data_buf = data_buf; - cmd_node->cmd_skb = cmd_node->skb; -} - -/* - * This function returns a command node from the free queue depending upon - * availability. - */ -static struct cmd_ctrl_node * -mwifiex_get_cmd_node(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_node; - unsigned long flags; - - spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); - if (list_empty(&adapter->cmd_free_q)) { - mwifiex_dbg(adapter, ERROR, - "GET_CMD_NODE: cmd node not available\n"); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - return NULL; - } - cmd_node = list_first_entry(&adapter->cmd_free_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); - - return cmd_node; -} - -/* - * This function cleans up a command node. - * - * The function resets the fields including the buffer pointers. - * This function does not try to free the buffers. They must be - * freed before calling this function. - * - * This function will however call the receive completion callback - * in case a response buffer is still available before resetting - * the pointer. - */ -static void -mwifiex_clean_cmd_node(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - cmd_node->cmd_oid = 0; - cmd_node->cmd_flag = 0; - cmd_node->data_buf = NULL; - cmd_node->wait_q_enabled = false; - - if (cmd_node->cmd_skb) - skb_trim(cmd_node->cmd_skb, 0); - - if (cmd_node->resp_skb) { - adapter->if_ops.cmdrsp_complete(adapter, cmd_node->resp_skb); - cmd_node->resp_skb = NULL; - } -} - -/* - * This function sends a host command to the firmware. - * - * The function copies the host command into the driver command - * buffer, which will be transferred to the firmware later by the - * main thread. - */ -static int mwifiex_cmd_host_cmd(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_ds_misc_cmd *pcmd_ptr) -{ - /* Copy the HOST command to command buffer */ - memcpy(cmd, pcmd_ptr->cmd, pcmd_ptr->len); - mwifiex_dbg(priv->adapter, CMD, - "cmd: host cmd size = %d\n", pcmd_ptr->len); - return 0; -} - -/* - * This function downloads a command to the firmware. - * - * The function performs sanity tests, sets the command sequence - * number and size, converts the header fields to CPU format before - * sending. Afterwards, it logs the command ID and action for debugging - * and sets up the command timeout timer. - */ -static int mwifiex_dnld_cmd_to_fw(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node) -{ - - struct mwifiex_adapter *adapter = priv->adapter; - int ret; - struct host_cmd_ds_command *host_cmd; - uint16_t cmd_code; - uint16_t cmd_size; - unsigned long flags; - __le32 tmp; - - if (!adapter || !cmd_node) - return -1; - - host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - - /* Sanity test */ - if (host_cmd == NULL || host_cmd->size == 0) { - mwifiex_dbg(adapter, ERROR, - "DNLD_CMD: host_cmd is null\t" - "or cmd size is 0, not sending\n"); - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - mwifiex_recycle_cmd_node(adapter, cmd_node); - return -1; - } - - cmd_code = le16_to_cpu(host_cmd->command); - cmd_size = le16_to_cpu(host_cmd->size); - - if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET && - cmd_code != HostCmd_CMD_FUNC_SHUTDOWN && - cmd_code != HostCmd_CMD_FUNC_INIT) { - mwifiex_dbg(adapter, ERROR, - "DNLD_CMD: FW in reset state, ignore cmd %#x\n", - cmd_code); - mwifiex_recycle_cmd_node(adapter, cmd_node); - queue_work(adapter->workqueue, &adapter->main_work); - return -1; - } - - /* Set command sequence number */ - adapter->seq_num++; - host_cmd->seq_num = cpu_to_le16(HostCmd_SET_SEQ_NO_BSS_INFO - (adapter->seq_num, - cmd_node->priv->bss_num, - cmd_node->priv->bss_type)); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = cmd_node; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - /* Adjust skb length */ - if (cmd_node->cmd_skb->len > cmd_size) - /* - * cmd_size is less than sizeof(struct host_cmd_ds_command). - * Trim off the unused portion. - */ - skb_trim(cmd_node->cmd_skb, cmd_size); - else if (cmd_node->cmd_skb->len < cmd_size) - /* - * cmd_size is larger than sizeof(struct host_cmd_ds_command) - * because we have appended custom IE TLV. Increase skb length - * accordingly. - */ - skb_put(cmd_node->cmd_skb, cmd_size - cmd_node->cmd_skb->len); - - mwifiex_dbg(adapter, CMD, - "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", - cmd_code, - le16_to_cpu(*(__le16 *)((u8 *)host_cmd + S_DS_GEN)), - cmd_size, le16_to_cpu(host_cmd->seq_num)); - mwifiex_dbg_dump(adapter, CMD_D, "cmd buffer:", host_cmd, cmd_size); - - if (adapter->iface_type == MWIFIEX_USB) { - tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD); - skb_push(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN); - memcpy(cmd_node->cmd_skb->data, &tmp, MWIFIEX_TYPE_LEN); - adapter->cmd_sent = true; - ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_CMD_EVENT, - cmd_node->cmd_skb, NULL); - skb_pull(cmd_node->cmd_skb, MWIFIEX_TYPE_LEN); - if (ret == -EBUSY) - cmd_node->cmd_skb = NULL; - } else { - skb_push(cmd_node->cmd_skb, INTF_HEADER_LEN); - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, - cmd_node->cmd_skb, NULL); - skb_pull(cmd_node->cmd_skb, INTF_HEADER_LEN); - } - - if (ret == -1) { - mwifiex_dbg(adapter, ERROR, - "DNLD_CMD: host to card failed\n"); - if (adapter->iface_type == MWIFIEX_USB) - adapter->cmd_sent = false; - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - adapter->dbg.num_cmd_host_to_card_failure++; - return -1; - } - - /* Save the last command id and action to debug log */ - adapter->dbg.last_cmd_index = - (adapter->dbg.last_cmd_index + 1) % DBG_CMD_NUM; - adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index] = cmd_code; - adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index] = - le16_to_cpu(*(__le16 *) ((u8 *) host_cmd + S_DS_GEN)); - - /* Clear BSS_NO_BITS from HostCmd */ - cmd_code &= HostCmd_CMD_ID_MASK; - - /* Setup the timer after transmit command */ - mod_timer(&adapter->cmd_timer, - jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); - - return 0; -} - -/* - * This function downloads a sleep confirm command to the firmware. - * - * The function performs sanity tests, sets the command sequence - * number and size, converts the header fields to CPU format before - * sending. - * - * No responses are needed for sleep confirm command. - */ -static int mwifiex_dnld_sleep_confirm_cmd(struct mwifiex_adapter *adapter) -{ - int ret; - struct mwifiex_private *priv; - struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = - (struct mwifiex_opt_sleep_confirm *) - adapter->sleep_cfm->data; - struct sk_buff *sleep_cfm_tmp; - __le32 tmp; - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - adapter->seq_num++; - sleep_cfm_buf->seq_num = - cpu_to_le16((HostCmd_SET_SEQ_NO_BSS_INFO - (adapter->seq_num, priv->bss_num, - priv->bss_type))); - - mwifiex_dbg(adapter, CMD, - "cmd: DNLD_CMD: %#x, act %#x, len %d, seqno %#x\n", - le16_to_cpu(sleep_cfm_buf->command), - le16_to_cpu(sleep_cfm_buf->action), - le16_to_cpu(sleep_cfm_buf->size), - le16_to_cpu(sleep_cfm_buf->seq_num)); - mwifiex_dbg_dump(adapter, CMD_D, "SLEEP_CFM buffer: ", sleep_cfm_buf, - le16_to_cpu(sleep_cfm_buf->size)); - - if (adapter->iface_type == MWIFIEX_USB) { - sleep_cfm_tmp = - dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) - + MWIFIEX_TYPE_LEN); - skb_put(sleep_cfm_tmp, sizeof(struct mwifiex_opt_sleep_confirm) - + MWIFIEX_TYPE_LEN); - tmp = cpu_to_le32(MWIFIEX_USB_TYPE_CMD); - memcpy(sleep_cfm_tmp->data, &tmp, MWIFIEX_TYPE_LEN); - memcpy(sleep_cfm_tmp->data + MWIFIEX_TYPE_LEN, - adapter->sleep_cfm->data, - sizeof(struct mwifiex_opt_sleep_confirm)); - ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_USB_EP_CMD_EVENT, - sleep_cfm_tmp, NULL); - if (ret != -EBUSY) - dev_kfree_skb_any(sleep_cfm_tmp); - } else { - skb_push(adapter->sleep_cfm, INTF_HEADER_LEN); - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_CMD, - adapter->sleep_cfm, NULL); - skb_pull(adapter->sleep_cfm, INTF_HEADER_LEN); - } - - if (ret == -1) { - mwifiex_dbg(adapter, ERROR, "SLEEP_CFM: failed\n"); - adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure++; - return -1; - } - - if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl)) - /* Response is not needed for sleep confirm command */ - adapter->ps_state = PS_STATE_SLEEP; - else - adapter->ps_state = PS_STATE_SLEEP_CFM; - - if (!le16_to_cpu(sleep_cfm_buf->resp_ctrl) && - (adapter->is_hs_configured && - !adapter->sleep_period.period)) { - adapter->pm_wakeup_card_req = true; - mwifiex_hs_activated_event(mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), true); - } - - return ret; -} - -/* - * This function allocates the command buffers and links them to - * the command free queue. - * - * The driver uses a pre allocated number of command buffers, which - * are created at driver initializations and freed at driver cleanup. - * Every command needs to obtain a command buffer from this pool before - * it can be issued. The command free queue lists the command buffers - * currently free to use, while the command pending queue lists the - * command buffers already in use and awaiting handling. Command buffers - * are returned to the free queue after use. - */ -int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_array; - u32 i; - - /* Allocate and initialize struct cmd_ctrl_node */ - cmd_array = kcalloc(MWIFIEX_NUM_OF_CMD_BUFFER, - sizeof(struct cmd_ctrl_node), GFP_KERNEL); - if (!cmd_array) - return -ENOMEM; - - adapter->cmd_pool = cmd_array; - - /* Allocate and initialize command buffers */ - for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { - cmd_array[i].skb = dev_alloc_skb(MWIFIEX_SIZE_OF_CMD_BUFFER); - if (!cmd_array[i].skb) { - mwifiex_dbg(adapter, ERROR, - "unable to allocate command buffer\n"); - return -ENOMEM; - } - } - - for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) - mwifiex_insert_cmd_to_free_q(adapter, &cmd_array[i]); - - return 0; -} - -/* - * This function frees the command buffers. - * - * The function calls the completion callback for all the command - * buffers that still have response buffers associated with them. - */ -int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_array; - u32 i; - - /* Need to check if cmd pool is allocated or not */ - if (!adapter->cmd_pool) { - mwifiex_dbg(adapter, FATAL, - "info: FREE_CMD_BUF: cmd_pool is null\n"); - return 0; - } - - cmd_array = adapter->cmd_pool; - - /* Release shared memory buffers */ - for (i = 0; i < MWIFIEX_NUM_OF_CMD_BUFFER; i++) { - if (cmd_array[i].skb) { - mwifiex_dbg(adapter, CMD, - "cmd: free cmd buffer %d\n", i); - dev_kfree_skb_any(cmd_array[i].skb); - } - if (!cmd_array[i].resp_skb) - continue; - - if (adapter->iface_type == MWIFIEX_USB) - adapter->if_ops.cmdrsp_complete(adapter, - cmd_array[i].resp_skb); - else - dev_kfree_skb_any(cmd_array[i].resp_skb); - } - /* Release struct cmd_ctrl_node */ - if (adapter->cmd_pool) { - mwifiex_dbg(adapter, CMD, - "cmd: free cmd pool\n"); - kfree(adapter->cmd_pool); - adapter->cmd_pool = NULL; - } - - return 0; -} - -/* - * This function handles events generated by firmware. - * - * Event body of events received from firmware are not used (though they are - * saved), only the event ID is used. Some events are re-invoked by - * the driver, with a new event body. - * - * After processing, the function calls the completion callback - * for cleanup. - */ -int mwifiex_process_event(struct mwifiex_adapter *adapter) -{ - int ret; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - struct sk_buff *skb = adapter->event_skb; - u32 eventcause = adapter->event_cause; - struct mwifiex_rxinfo *rx_info; - - /* Save the last event to debug log */ - adapter->dbg.last_event_index = - (adapter->dbg.last_event_index + 1) % DBG_CMD_NUM; - adapter->dbg.last_event[adapter->dbg.last_event_index] = - (u16) eventcause; - - /* Get BSS number and corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, EVENT_GET_BSS_NUM(eventcause), - EVENT_GET_BSS_TYPE(eventcause)); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - /* Clear BSS_NO_BITS from event */ - eventcause &= EVENT_ID_MASK; - adapter->event_cause = eventcause; - - if (skb) { - rx_info = MWIFIEX_SKB_RXCB(skb); - memset(rx_info, 0, sizeof(*rx_info)); - rx_info->bss_num = priv->bss_num; - rx_info->bss_type = priv->bss_type; - mwifiex_dbg_dump(adapter, EVT_D, "Event Buf:", - skb->data, skb->len); - } - - mwifiex_dbg(adapter, EVENT, "EVENT: cause: %#x\n", eventcause); - - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - ret = mwifiex_process_uap_event(priv); - else - ret = mwifiex_process_sta_event(priv); - - adapter->event_cause = 0; - adapter->event_skb = NULL; - adapter->if_ops.event_complete(adapter, skb); - - return ret; -} - -/* - * This function prepares a command and send it to the firmware. - * - * Preparation includes - - * - Sanity tests to make sure the card is still present or the FW - * is not reset - * - Getting a new command node from the command free queue - * - Initializing the command node for default parameters - * - Fill up the non-default parameters and buffer pointers - * - Add the command to pending queue - */ -int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, - u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync) -{ - int ret; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node; - struct host_cmd_ds_command *cmd_ptr; - - if (!adapter) { - pr_err("PREP_CMD: adapter is NULL\n"); - return -1; - } - - if (adapter->is_suspended) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: device in suspended state\n"); - return -1; - } - - if (adapter->hs_enabling && cmd_no != HostCmd_CMD_802_11_HS_CFG_ENH) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: host entering sleep state\n"); - return -1; - } - - if (adapter->surprise_removed) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: card is removed\n"); - return -1; - } - - if (adapter->is_cmd_timedout) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: FW is in bad state\n"); - return -1; - } - - if (adapter->hw_status == MWIFIEX_HW_STATUS_RESET) { - if (cmd_no != HostCmd_CMD_FUNC_INIT) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: FW in reset state\n"); - return -1; - } - } - - /* Get a new command node */ - cmd_node = mwifiex_get_cmd_node(adapter); - - if (!cmd_node) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: no free cmd node\n"); - return -1; - } - - /* Initialize the command node */ - mwifiex_init_cmd_node(priv, cmd_node, cmd_oid, data_buf, sync); - - if (!cmd_node->cmd_skb) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: no free cmd buf\n"); - return -1; - } - - memset(skb_put(cmd_node->cmd_skb, sizeof(struct host_cmd_ds_command)), - 0, sizeof(struct host_cmd_ds_command)); - - cmd_ptr = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->result = 0; - - /* Prepare command */ - if (cmd_no) { - switch (cmd_no) { - case HostCmd_CMD_UAP_SYS_CONFIG: - case HostCmd_CMD_UAP_BSS_START: - case HostCmd_CMD_UAP_BSS_STOP: - case HostCmd_CMD_UAP_STA_DEAUTH: - case HOST_CMD_APCMD_SYS_RESET: - case HOST_CMD_APCMD_STA_LIST: - ret = mwifiex_uap_prepare_cmd(priv, cmd_no, cmd_action, - cmd_oid, data_buf, - cmd_ptr); - break; - default: - ret = mwifiex_sta_prepare_cmd(priv, cmd_no, cmd_action, - cmd_oid, data_buf, - cmd_ptr); - break; - } - } else { - ret = mwifiex_cmd_host_cmd(priv, cmd_ptr, data_buf); - cmd_node->cmd_flag |= CMD_F_HOSTCMD; - } - - /* Return error, since the command preparation failed */ - if (ret) { - mwifiex_dbg(adapter, ERROR, - "PREP_CMD: cmd %#x preparation failed\n", - cmd_no); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - return -1; - } - - /* Send command */ - if (cmd_no == HostCmd_CMD_802_11_SCAN || - cmd_no == HostCmd_CMD_802_11_SCAN_EXT) { - mwifiex_queue_scan_cmd(priv, cmd_node); - } else { - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); - queue_work(adapter->workqueue, &adapter->main_work); - if (cmd_node->wait_q_enabled) - ret = mwifiex_wait_queue_complete(adapter, cmd_node); - } - - return ret; -} - -/* - * This function returns a command to the command free queue. - * - * The function also calls the completion callback if required, before - * cleaning the command node and re-inserting it into the free queue. - */ -void -mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - unsigned long flags; - - if (!cmd_node) - return; - - if (cmd_node->wait_q_enabled) - mwifiex_complete_cmd(adapter, cmd_node); - /* Clean the node */ - mwifiex_clean_cmd_node(adapter, cmd_node); - - /* Insert node into cmd_free_q */ - spin_lock_irqsave(&adapter->cmd_free_q_lock, flags); - list_add_tail(&cmd_node->list, &adapter->cmd_free_q); - spin_unlock_irqrestore(&adapter->cmd_free_q_lock, flags); -} - -/* This function reuses a command node. */ -void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - struct host_cmd_ds_command *host_cmd = (void *)cmd_node->cmd_skb->data; - - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - - atomic_dec(&adapter->cmd_pending); - mwifiex_dbg(adapter, CMD, - "cmd: FREE_CMD: cmd=%#x, cmd_pending=%d\n", - le16_to_cpu(host_cmd->command), - atomic_read(&adapter->cmd_pending)); -} - -/* - * This function queues a command to the command pending queue. - * - * This in effect adds the command to the command list to be executed. - * Exit PS command is handled specially, by placing it always to the - * front of the command queue. - */ -void -mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node, u32 add_tail) -{ - struct host_cmd_ds_command *host_cmd = NULL; - u16 command; - unsigned long flags; - - host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - if (!host_cmd) { - mwifiex_dbg(adapter, ERROR, "QUEUE_CMD: host_cmd is NULL\n"); - return; - } - - command = le16_to_cpu(host_cmd->command); - - /* Exit_PS command needs to be queued in the header always. */ - if (command == HostCmd_CMD_802_11_PS_MODE_ENH) { - struct host_cmd_ds_802_11_ps_mode_enh *pm = - &host_cmd->params.psmode_enh; - if ((le16_to_cpu(pm->action) == DIS_PS) || - (le16_to_cpu(pm->action) == DIS_AUTO_PS)) { - if (adapter->ps_state != PS_STATE_AWAKE) - add_tail = false; - } - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - if (add_tail) - list_add_tail(&cmd_node->list, &adapter->cmd_pending_q); - else - list_add(&cmd_node->list, &adapter->cmd_pending_q); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - atomic_inc(&adapter->cmd_pending); - mwifiex_dbg(adapter, CMD, - "cmd: QUEUE_CMD: cmd=%#x, cmd_pending=%d\n", - command, atomic_read(&adapter->cmd_pending)); -} - -/* - * This function executes the next command in command pending queue. - * - * This function will fail if a command is already in processing stage, - * otherwise it will dequeue the first command from the command pending - * queue and send to the firmware. - * - * If the device is currently in host sleep mode, any commands, except the - * host sleep configuration command will de-activate the host sleep. For PS - * mode, the function will put the firmware back to sleep if applicable. - */ -int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - struct cmd_ctrl_node *cmd_node; - int ret = 0; - struct host_cmd_ds_command *host_cmd; - unsigned long cmd_flags; - unsigned long cmd_pending_q_flags; - - /* Check if already in processing */ - if (adapter->curr_cmd) { - mwifiex_dbg(adapter, FATAL, - "EXEC_NEXT_CMD: cmd in processing\n"); - return -1; - } - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - /* Check if any command is pending */ - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); - if (list_empty(&adapter->cmd_pending_q)) { - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - return 0; - } - cmd_node = list_first_entry(&adapter->cmd_pending_q, - struct cmd_ctrl_node, list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - - host_cmd = (struct host_cmd_ds_command *) (cmd_node->cmd_skb->data); - priv = cmd_node->priv; - - if (adapter->ps_state != PS_STATE_AWAKE) { - mwifiex_dbg(adapter, ERROR, - "%s: cannot send cmd in sleep state,\t" - "this should not happen\n", __func__); - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - return ret; - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_pending_q_flags); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, - cmd_pending_q_flags); - - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - ret = mwifiex_dnld_cmd_to_fw(priv, cmd_node); - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - /* Any command sent to the firmware when host is in sleep - * mode should de-configure host sleep. We should skip the - * host sleep configuration command itself though - */ - if (priv && (host_cmd->command != - cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH))) { - if (adapter->hs_activated) { - adapter->is_hs_configured = false; - mwifiex_hs_activated_event(priv, false); - } - } - - return ret; -} - -/* - * This function handles the command response. - * - * After processing, the function cleans the command node and puts - * it back to the command free queue. - */ -int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter) -{ - struct host_cmd_ds_command *resp; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - int ret = 0; - uint16_t orig_cmdresp_no; - uint16_t cmdresp_no; - uint16_t cmdresp_result; - unsigned long flags; - - /* Now we got response from FW, cancel the command timer */ - del_timer_sync(&adapter->cmd_timer); - - if (!adapter->curr_cmd || !adapter->curr_cmd->resp_skb) { - resp = (struct host_cmd_ds_command *) adapter->upld_buf; - mwifiex_dbg(adapter, ERROR, - "CMD_RESP: NULL curr_cmd, %#x\n", - le16_to_cpu(resp->command)); - return -1; - } - - adapter->is_cmd_timedout = 0; - - resp = (struct host_cmd_ds_command *) adapter->curr_cmd->resp_skb->data; - if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { - /* Copy original response back to response buffer */ - struct mwifiex_ds_misc_cmd *hostcmd; - uint16_t size = le16_to_cpu(resp->size); - mwifiex_dbg(adapter, INFO, - "info: host cmd resp size = %d\n", size); - size = min_t(u16, size, MWIFIEX_SIZE_OF_CMD_BUFFER); - if (adapter->curr_cmd->data_buf) { - hostcmd = adapter->curr_cmd->data_buf; - hostcmd->len = size; - memcpy(hostcmd->cmd, resp, size); - } - } - orig_cmdresp_no = le16_to_cpu(resp->command); - - /* Get BSS number and corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, - HostCmd_GET_BSS_NO(le16_to_cpu(resp->seq_num)), - HostCmd_GET_BSS_TYPE(le16_to_cpu(resp->seq_num))); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - /* Clear RET_BIT from HostCmd */ - resp->command = cpu_to_le16(orig_cmdresp_no & HostCmd_CMD_ID_MASK); - - cmdresp_no = le16_to_cpu(resp->command); - cmdresp_result = le16_to_cpu(resp->result); - - /* Save the last command response to debug log */ - adapter->dbg.last_cmd_resp_index = - (adapter->dbg.last_cmd_resp_index + 1) % DBG_CMD_NUM; - adapter->dbg.last_cmd_resp_id[adapter->dbg.last_cmd_resp_index] = - orig_cmdresp_no; - - mwifiex_dbg(adapter, CMD, - "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", - orig_cmdresp_no, cmdresp_result, - le16_to_cpu(resp->size), le16_to_cpu(resp->seq_num)); - mwifiex_dbg_dump(adapter, CMD_D, "CMD_RESP buffer:", resp, - le16_to_cpu(resp->size)); - - if (!(orig_cmdresp_no & HostCmd_RET_BIT)) { - mwifiex_dbg(adapter, ERROR, "CMD_RESP: invalid cmd resp\n"); - if (adapter->curr_cmd->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - - mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - return -1; - } - - if (adapter->curr_cmd->cmd_flag & CMD_F_HOSTCMD) { - adapter->curr_cmd->cmd_flag &= ~CMD_F_HOSTCMD; - if ((cmdresp_result == HostCmd_RESULT_OK) && - (cmdresp_no == HostCmd_CMD_802_11_HS_CFG_ENH)) - ret = mwifiex_ret_802_11_hs_cfg(priv, resp); - } else { - /* handle response */ - ret = mwifiex_process_sta_cmdresp(priv, cmdresp_no, resp); - } - - /* Check init command response */ - if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { - if (ret) { - mwifiex_dbg(adapter, ERROR, - "%s: cmd %#x failed during\t" - "initialization\n", __func__, cmdresp_no); - mwifiex_init_fw_complete(adapter); - return -1; - } else if (adapter->last_init_cmd == cmdresp_no) - adapter->hw_status = MWIFIEX_HW_STATUS_INIT_DONE; - } - - if (adapter->curr_cmd) { - if (adapter->curr_cmd->wait_q_enabled) - adapter->cmd_wait_q.status = ret; - - mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - } - - return ret; -} - -/* - * This function handles the timeout of command sending. - * - * It will re-send the same command again. - */ -void -mwifiex_cmd_timeout_func(unsigned long function_context) -{ - struct mwifiex_adapter *adapter = - (struct mwifiex_adapter *) function_context; - struct cmd_ctrl_node *cmd_node; - - adapter->is_cmd_timedout = 1; - if (!adapter->curr_cmd) { - mwifiex_dbg(adapter, ERROR, - "cmd: empty curr_cmd\n"); - return; - } - cmd_node = adapter->curr_cmd; - if (cmd_node) { - adapter->dbg.timeout_cmd_id = - adapter->dbg.last_cmd_id[adapter->dbg.last_cmd_index]; - adapter->dbg.timeout_cmd_act = - adapter->dbg.last_cmd_act[adapter->dbg.last_cmd_index]; - mwifiex_dbg(adapter, MSG, - "%s: Timeout cmd id = %#x, act = %#x\n", __func__, - adapter->dbg.timeout_cmd_id, - adapter->dbg.timeout_cmd_act); - - mwifiex_dbg(adapter, MSG, - "num_data_h2c_failure = %d\n", - adapter->dbg.num_tx_host_to_card_failure); - mwifiex_dbg(adapter, MSG, - "num_cmd_h2c_failure = %d\n", - adapter->dbg.num_cmd_host_to_card_failure); - - mwifiex_dbg(adapter, MSG, - "is_cmd_timedout = %d\n", - adapter->is_cmd_timedout); - mwifiex_dbg(adapter, MSG, - "num_tx_timeout = %d\n", - adapter->dbg.num_tx_timeout); - - mwifiex_dbg(adapter, MSG, - "last_cmd_index = %d\n", - adapter->dbg.last_cmd_index); - mwifiex_dbg(adapter, MSG, - "last_cmd_id: %*ph\n", - (int)sizeof(adapter->dbg.last_cmd_id), - adapter->dbg.last_cmd_id); - mwifiex_dbg(adapter, MSG, - "last_cmd_act: %*ph\n", - (int)sizeof(adapter->dbg.last_cmd_act), - adapter->dbg.last_cmd_act); - - mwifiex_dbg(adapter, MSG, - "last_cmd_resp_index = %d\n", - adapter->dbg.last_cmd_resp_index); - mwifiex_dbg(adapter, MSG, - "last_cmd_resp_id: %*ph\n", - (int)sizeof(adapter->dbg.last_cmd_resp_id), - adapter->dbg.last_cmd_resp_id); - - mwifiex_dbg(adapter, MSG, - "last_event_index = %d\n", - adapter->dbg.last_event_index); - mwifiex_dbg(adapter, MSG, - "last_event: %*ph\n", - (int)sizeof(adapter->dbg.last_event), - adapter->dbg.last_event); - - mwifiex_dbg(adapter, MSG, - "data_sent=%d cmd_sent=%d\n", - adapter->data_sent, adapter->cmd_sent); - - mwifiex_dbg(adapter, MSG, - "ps_mode=%d ps_state=%d\n", - adapter->ps_mode, adapter->ps_state); - - if (cmd_node->wait_q_enabled) { - adapter->cmd_wait_q.status = -ETIMEDOUT; - mwifiex_cancel_pending_ioctl(adapter); - } - } - if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) { - mwifiex_init_fw_complete(adapter); - return; - } - - if (adapter->if_ops.device_dump) - adapter->if_ops.device_dump(adapter); - - if (adapter->if_ops.card_reset) - adapter->if_ops.card_reset(adapter); -} - -/* - * This function cancels all the pending commands. - * - * The current command, all commands in command pending queue and all scan - * commands in scan pending queue are cancelled. All the completion callbacks - * are called with failure status to ensure cleanup. - */ -void -mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; - unsigned long flags, cmd_flags; - struct mwifiex_private *priv; - int i; - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - /* Cancel current cmd */ - if ((adapter->curr_cmd) && (adapter->curr_cmd->wait_q_enabled)) { - adapter->curr_cmd->wait_q_enabled = false; - adapter->cmd_wait_q.status = -1; - mwifiex_complete_cmd(adapter, adapter->curr_cmd); - /* no recycle probably wait for response */ - } - /* Cancel all pending command */ - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->cmd_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - if (cmd_node->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - mwifiex_recycle_cmd_node(adapter, cmd_node); - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - if (adapter->scan_processing) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - if (priv->scan_request) { - mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } - } - } -} - -/* - * This function cancels all pending commands that matches with - * the given IOCTL request. - * - * Both the current command buffer and the pending command queue are - * searched for matching IOCTL request. The completion callback of - * the matched command is called with failure status to ensure cleanup. - * In case of scan commands, all pending commands in scan pending queue - * are cancelled. - */ -void -mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter) -{ - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node = NULL; - unsigned long cmd_flags; - unsigned long scan_pending_q_flags; - struct mwifiex_private *priv; - int i; - - if ((adapter->curr_cmd) && - (adapter->curr_cmd->wait_q_enabled)) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - cmd_node = adapter->curr_cmd; - /* setting curr_cmd to NULL is quite dangerous, because - * mwifiex_process_cmdresp checks curr_cmd to be != NULL - * at the beginning then relies on it and dereferences - * it at will - * this probably works since mwifiex_cmd_timeout_func - * is the only caller of this function and responses - * at that point - */ - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - - mwifiex_recycle_cmd_node(adapter, cmd_node); - } - - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - scan_pending_q_flags); - - if (adapter->scan_processing) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, cmd_flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, cmd_flags); - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - if (priv->scan_request) { - mwifiex_dbg(adapter, WARN, "info: aborting scan\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } - } - } -} - -/* - * This function sends the sleep confirm command to firmware, if - * possible. - * - * The sleep confirm command cannot be issued if command response, - * data response or event response is awaiting handling, or if we - * are in the middle of sending a command, or expecting a command - * response. - */ -void -mwifiex_check_ps_cond(struct mwifiex_adapter *adapter) -{ - if (!adapter->cmd_sent && - !adapter->curr_cmd && !IS_CARD_RX_RCVD(adapter)) - mwifiex_dnld_sleep_confirm_cmd(adapter); - else - mwifiex_dbg(adapter, CMD, - "cmd: Delay Sleep Confirm (%s%s%s)\n", - (adapter->cmd_sent) ? "D" : "", - (adapter->curr_cmd) ? "C" : "", - (IS_CARD_RX_RCVD(adapter)) ? "R" : ""); -} - -/* - * This function sends a Host Sleep activated event to applications. - * - * This event is generated by the driver, with a blank event body. - */ -void -mwifiex_hs_activated_event(struct mwifiex_private *priv, u8 activated) -{ - if (activated) { - if (priv->adapter->is_hs_configured) { - priv->adapter->hs_activated = true; - mwifiex_update_rxreor_flags(priv->adapter, - RXREOR_FORCE_NO_DROP); - mwifiex_dbg(priv->adapter, EVENT, - "event: hs_activated\n"); - priv->adapter->hs_activate_wait_q_woken = true; - wake_up_interruptible( - &priv->adapter->hs_activate_wait_q); - } else { - mwifiex_dbg(priv->adapter, EVENT, - "event: HS not configured\n"); - } - } else { - mwifiex_dbg(priv->adapter, EVENT, - "event: hs_deactivated\n"); - priv->adapter->hs_activated = false; - } -} - -/* - * This function handles the command response of a Host Sleep configuration - * command. - * - * Handling includes changing the header fields into CPU format - * and setting the current host sleep activation status in driver. - * - * In case host sleep status change, the function generates an event to - * notify the applications. - */ -int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_hs_cfg_enh *phs_cfg = - &resp->params.opt_hs_cfg; - uint32_t conditions = le32_to_cpu(phs_cfg->params.hs_config.conditions); - - if (phs_cfg->action == cpu_to_le16(HS_ACTIVATE) && - adapter->iface_type != MWIFIEX_USB) { - mwifiex_hs_activated_event(priv, true); - return 0; - } else { - mwifiex_dbg(adapter, CMD, - "cmd: CMD_RESP: HS_CFG cmd reply\t" - " result=%#x, conditions=0x%x gpio=0x%x gap=0x%x\n", - resp->result, conditions, - phs_cfg->params.hs_config.gpio, - phs_cfg->params.hs_config.gap); - } - if (conditions != HS_CFG_CANCEL) { - adapter->is_hs_configured = true; - if (adapter->iface_type == MWIFIEX_USB) - mwifiex_hs_activated_event(priv, true); - } else { - adapter->is_hs_configured = false; - if (adapter->hs_activated) - mwifiex_hs_activated_event(priv, false); - } - - return 0; -} - -/* - * This function wakes up the adapter and generates a Host Sleep - * cancel event on receiving the power up interrupt. - */ -void -mwifiex_process_hs_config(struct mwifiex_adapter *adapter) -{ - mwifiex_dbg(adapter, INFO, - "info: %s: auto cancelling host sleep\t" - "since there is interrupt from the firmware\n", - __func__); - - adapter->if_ops.wakeup(adapter); - adapter->hs_activated = false; - adapter->is_hs_configured = false; - adapter->is_suspended = false; - mwifiex_hs_activated_event(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY), - false); -} -EXPORT_SYMBOL_GPL(mwifiex_process_hs_config); - -/* - * This function handles the command response of a sleep confirm command. - * - * The function sets the card state to SLEEP if the response indicates success. - */ -void -mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *adapter, - u8 *pbuf, u32 upld_len) -{ - struct host_cmd_ds_command *cmd = (struct host_cmd_ds_command *) pbuf; - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - uint16_t result = le16_to_cpu(cmd->result); - uint16_t command = le16_to_cpu(cmd->command); - uint16_t seq_num = le16_to_cpu(cmd->seq_num); - - if (!upld_len) { - mwifiex_dbg(adapter, ERROR, - "%s: cmd size is 0\n", __func__); - return; - } - - mwifiex_dbg(adapter, CMD, - "cmd: CMD_RESP: 0x%x, result %d, len %d, seqno 0x%x\n", - command, result, le16_to_cpu(cmd->size), seq_num); - - /* Get BSS number and corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, HostCmd_GET_BSS_NO(seq_num), - HostCmd_GET_BSS_TYPE(seq_num)); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - /* Update sequence number */ - seq_num = HostCmd_GET_SEQ_NO(seq_num); - /* Clear RET_BIT from HostCmd */ - command &= HostCmd_CMD_ID_MASK; - - if (command != HostCmd_CMD_802_11_PS_MODE_ENH) { - mwifiex_dbg(adapter, ERROR, - "%s: rcvd unexpected resp for cmd %#x, result = %x\n", - __func__, command, result); - return; - } - - if (result) { - mwifiex_dbg(adapter, ERROR, - "%s: sleep confirm cmd failed\n", - __func__); - adapter->pm_wakeup_card_req = false; - adapter->ps_state = PS_STATE_AWAKE; - return; - } - adapter->pm_wakeup_card_req = true; - if (adapter->is_hs_configured) - mwifiex_hs_activated_event(mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), - true); - adapter->ps_state = PS_STATE_SLEEP; - cmd->command = cpu_to_le16(command); - cmd->seq_num = cpu_to_le16(seq_num); -} -EXPORT_SYMBOL_GPL(mwifiex_process_sleep_confirm_resp); - -/* - * This function prepares an enhanced power mode command. - * - * This function can be used to disable power save or to configure - * power save with auto PS or STA PS or auto deep sleep. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting Power Save bitmap, PS parameters TLV, PS mode TLV, - * auto deep sleep TLV (as required) - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, uint16_t ps_bitmap, - struct mwifiex_ds_auto_ds *auto_ds) -{ - struct host_cmd_ds_802_11_ps_mode_enh *psmode_enh = - &cmd->params.psmode_enh; - u8 *tlv; - u16 cmd_size = 0; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); - if (cmd_action == DIS_AUTO_PS) { - psmode_enh->action = cpu_to_le16(DIS_AUTO_PS); - psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + - sizeof(psmode_enh->params.ps_bitmap)); - } else if (cmd_action == GET_PS) { - psmode_enh->action = cpu_to_le16(GET_PS); - psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(psmode_enh->action) + - sizeof(psmode_enh->params.ps_bitmap)); - } else if (cmd_action == EN_AUTO_PS) { - psmode_enh->action = cpu_to_le16(EN_AUTO_PS); - psmode_enh->params.ps_bitmap = cpu_to_le16(ps_bitmap); - cmd_size = S_DS_GEN + sizeof(psmode_enh->action) + - sizeof(psmode_enh->params.ps_bitmap); - tlv = (u8 *) cmd + cmd_size; - if (ps_bitmap & BITMAP_STA_PS) { - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_ps_param *ps_tlv = - (struct mwifiex_ie_types_ps_param *) tlv; - struct mwifiex_ps_param *ps_mode = &ps_tlv->param; - ps_tlv->header.type = cpu_to_le16(TLV_TYPE_PS_PARAM); - ps_tlv->header.len = cpu_to_le16(sizeof(*ps_tlv) - - sizeof(struct mwifiex_ie_types_header)); - cmd_size += sizeof(*ps_tlv); - tlv += sizeof(*ps_tlv); - mwifiex_dbg(priv->adapter, CMD, - "cmd: PS Command: Enter PS\n"); - ps_mode->null_pkt_interval = - cpu_to_le16(adapter->null_pkt_interval); - ps_mode->multiple_dtims = - cpu_to_le16(adapter->multiple_dtim); - ps_mode->bcn_miss_timeout = - cpu_to_le16(adapter->bcn_miss_time_out); - ps_mode->local_listen_interval = - cpu_to_le16(adapter->local_listen_interval); - ps_mode->adhoc_wake_period = - cpu_to_le16(adapter->adhoc_awake_period); - ps_mode->delay_to_ps = - cpu_to_le16(adapter->delay_to_ps); - ps_mode->mode = cpu_to_le16(adapter->enhanced_ps_mode); - - } - if (ps_bitmap & BITMAP_AUTO_DS) { - struct mwifiex_ie_types_auto_ds_param *auto_ds_tlv = - (struct mwifiex_ie_types_auto_ds_param *) tlv; - u16 idletime = 0; - - auto_ds_tlv->header.type = - cpu_to_le16(TLV_TYPE_AUTO_DS_PARAM); - auto_ds_tlv->header.len = - cpu_to_le16(sizeof(*auto_ds_tlv) - - sizeof(struct mwifiex_ie_types_header)); - cmd_size += sizeof(*auto_ds_tlv); - tlv += sizeof(*auto_ds_tlv); - if (auto_ds) - idletime = auto_ds->idle_time; - mwifiex_dbg(priv->adapter, CMD, - "cmd: PS Command: Enter Auto Deep Sleep\n"); - auto_ds_tlv->deep_sleep_timeout = cpu_to_le16(idletime); - } - cmd->size = cpu_to_le16(cmd_size); - } - return 0; -} - -/* - * This function handles the command response of an enhanced power mode - * command. - * - * Handling includes changing the header fields into CPU format - * and setting the current enhanced power mode in driver. - */ -int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct mwifiex_ds_pm_cfg *pm_cfg) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ps_mode_enh *ps_mode = - &resp->params.psmode_enh; - uint16_t action = le16_to_cpu(ps_mode->action); - uint16_t ps_bitmap = le16_to_cpu(ps_mode->params.ps_bitmap); - uint16_t auto_ps_bitmap = - le16_to_cpu(ps_mode->params.ps_bitmap); - - mwifiex_dbg(adapter, INFO, - "info: %s: PS_MODE cmd reply result=%#x action=%#X\n", - __func__, resp->result, action); - if (action == EN_AUTO_PS) { - if (auto_ps_bitmap & BITMAP_AUTO_DS) { - mwifiex_dbg(adapter, CMD, - "cmd: Enabled auto deep sleep\n"); - priv->adapter->is_deep_sleep = true; - } - if (auto_ps_bitmap & BITMAP_STA_PS) { - mwifiex_dbg(adapter, CMD, - "cmd: Enabled STA power save\n"); - if (adapter->sleep_period.period) - mwifiex_dbg(adapter, CMD, - "cmd: set to uapsd/pps mode\n"); - } - } else if (action == DIS_AUTO_PS) { - if (ps_bitmap & BITMAP_AUTO_DS) { - priv->adapter->is_deep_sleep = false; - mwifiex_dbg(adapter, CMD, - "cmd: Disabled auto deep sleep\n"); - } - if (ps_bitmap & BITMAP_STA_PS) { - mwifiex_dbg(adapter, CMD, - "cmd: Disabled STA power save\n"); - if (adapter->sleep_period.period) { - adapter->delay_null_pkt = false; - adapter->tx_lock_flag = false; - adapter->pps_uapsd_mode = false; - } - } - } else if (action == GET_PS) { - if (ps_bitmap & BITMAP_STA_PS) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - else - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - - mwifiex_dbg(adapter, CMD, - "cmd: ps_bitmap=%#x\n", ps_bitmap); - - if (pm_cfg) { - /* This section is for get power save mode */ - if (ps_bitmap & BITMAP_STA_PS) - pm_cfg->param.ps_mode = 1; - else - pm_cfg->param.ps_mode = 0; - } - } - return 0; -} - -/* - * This function prepares command to get hardware specifications. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting permanent address parameter - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd) -{ - struct host_cmd_ds_get_hw_spec *hw_spec = &cmd->params.hw_spec; - - cmd->command = cpu_to_le16(HostCmd_CMD_GET_HW_SPEC); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_ds_get_hw_spec) + S_DS_GEN); - memcpy(hw_spec->permanent_addr, priv->curr_addr, ETH_ALEN); - - return 0; -} - -/* - * This function handles the command response of get hardware - * specifications. - * - * Handling includes changing the header fields into CPU format - * and saving/updating the following parameters in driver - - * - Firmware capability information - * - Firmware band settings - * - Ad-hoc start band and channel - * - Ad-hoc 11n activation status - * - Firmware release number - * - Number of antennas - * - Hardware address - * - Hardware interface version - * - Firmware version - * - Region code - * - 11n capabilities - * - MCS support fields - * - MP end port - */ -int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_get_hw_spec *hw_spec = &resp->params.hw_spec; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_header *tlv; - struct hw_spec_api_rev *api_rev; - u16 resp_size, api_id; - int i, left_len, parsed_len = 0; - - adapter->fw_cap_info = le32_to_cpu(hw_spec->fw_cap_info); - - if (IS_SUPPORT_MULTI_BANDS(adapter)) - adapter->fw_bands = (u8) GET_FW_DEFAULT_BANDS(adapter); - else - adapter->fw_bands = BAND_B; - - adapter->config_bands = adapter->fw_bands; - - if (adapter->fw_bands & BAND_A) { - if (adapter->fw_bands & BAND_GN) { - adapter->config_bands |= BAND_AN; - adapter->fw_bands |= BAND_AN; - } - if (adapter->fw_bands & BAND_AN) { - adapter->adhoc_start_band = BAND_A | BAND_AN; - adapter->adhoc_11n_enabled = true; - } else { - adapter->adhoc_start_band = BAND_A; - } - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL_A; - } else if (adapter->fw_bands & BAND_GN) { - adapter->adhoc_start_band = BAND_G | BAND_B | BAND_GN; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - adapter->adhoc_11n_enabled = true; - } else if (adapter->fw_bands & BAND_G) { - adapter->adhoc_start_band = BAND_G | BAND_B; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - } else if (adapter->fw_bands & BAND_B) { - adapter->adhoc_start_band = BAND_B; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - } - - adapter->fw_release_number = le32_to_cpu(hw_spec->fw_release_number); - adapter->fw_api_ver = (adapter->fw_release_number >> 16) & 0xff; - adapter->number_of_antenna = le16_to_cpu(hw_spec->number_of_antenna); - - if (le32_to_cpu(hw_spec->dot_11ac_dev_cap)) { - adapter->is_hw_11ac_capable = true; - - /* Copy 11AC cap */ - adapter->hw_dot_11ac_dev_cap = - le32_to_cpu(hw_spec->dot_11ac_dev_cap); - adapter->usr_dot_11ac_dev_cap_bg = adapter->hw_dot_11ac_dev_cap - & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; - adapter->usr_dot_11ac_dev_cap_a = adapter->hw_dot_11ac_dev_cap - & ~MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK; - - /* Copy 11AC mcs */ - adapter->hw_dot_11ac_mcs_support = - le32_to_cpu(hw_spec->dot_11ac_mcs_support); - adapter->usr_dot_11ac_mcs_support = - adapter->hw_dot_11ac_mcs_support; - } else { - adapter->is_hw_11ac_capable = false; - } - - resp_size = le16_to_cpu(resp->size) - S_DS_GEN; - if (resp_size > sizeof(struct host_cmd_ds_get_hw_spec)) { - /* we have variable HW SPEC information */ - left_len = resp_size - sizeof(struct host_cmd_ds_get_hw_spec); - while (left_len > sizeof(struct mwifiex_ie_types_header)) { - tlv = (void *)&hw_spec->tlvs + parsed_len; - switch (le16_to_cpu(tlv->type)) { - case TLV_TYPE_API_REV: - api_rev = (struct hw_spec_api_rev *)tlv; - api_id = le16_to_cpu(api_rev->api_id); - switch (api_id) { - case KEY_API_VER_ID: - adapter->key_api_major_ver = - api_rev->major_ver; - adapter->key_api_minor_ver = - api_rev->minor_ver; - mwifiex_dbg(adapter, INFO, - "key_api v%d.%d\n", - adapter->key_api_major_ver, - adapter->key_api_minor_ver); - break; - case FW_API_VER_ID: - adapter->fw_api_ver = - api_rev->major_ver; - mwifiex_dbg(adapter, INFO, - "Firmware api version %d\n", - adapter->fw_api_ver); - break; - default: - mwifiex_dbg(adapter, FATAL, - "Unknown api_id: %d\n", - api_id); - break; - } - break; - default: - mwifiex_dbg(adapter, FATAL, - "Unknown GET_HW_SPEC TLV type: %#x\n", - le16_to_cpu(tlv->type)); - break; - } - parsed_len += le16_to_cpu(tlv->len) + - sizeof(struct mwifiex_ie_types_header); - left_len -= le16_to_cpu(tlv->len) + - sizeof(struct mwifiex_ie_types_header); - } - } - - mwifiex_dbg(adapter, INFO, - "info: GET_HW_SPEC: fw_release_number- %#x\n", - adapter->fw_release_number); - mwifiex_dbg(adapter, INFO, - "info: GET_HW_SPEC: permanent addr: %pM\n", - hw_spec->permanent_addr); - mwifiex_dbg(adapter, INFO, - "info: GET_HW_SPEC: hw_if_version=%#x version=%#x\n", - le16_to_cpu(hw_spec->hw_if_version), - le16_to_cpu(hw_spec->version)); - - ether_addr_copy(priv->adapter->perm_addr, hw_spec->permanent_addr); - adapter->region_code = le16_to_cpu(hw_spec->region_code); - - for (i = 0; i < MWIFIEX_MAX_REGION_CODE; i++) - /* Use the region code to search for the index */ - if (adapter->region_code == region_code_index[i]) - break; - - /* If it's unidentified region code, use the default (USA) */ - if (i >= MWIFIEX_MAX_REGION_CODE) { - adapter->region_code = 0x10; - mwifiex_dbg(adapter, WARN, - "cmd: unknown region code, use default (USA)\n"); - } - - adapter->hw_dot_11n_dev_cap = le32_to_cpu(hw_spec->dot_11n_dev_cap); - adapter->hw_dev_mcs_support = hw_spec->dev_mcs_support; - adapter->user_dev_mcs_support = adapter->hw_dev_mcs_support; - - if (adapter->if_ops.update_mp_end_port) - adapter->if_ops.update_mp_end_port(adapter, - le16_to_cpu(hw_spec->mp_end_port)); - - if (adapter->fw_api_ver == MWIFIEX_FW_V15) - adapter->scan_chan_gap_enabled = true; - - return 0; -} diff --git a/drivers/net/wireless/mwifiex/debugfs.c b/drivers/net/wireless/mwifiex/debugfs.c deleted file mode 100644 index 9824d8dd2b44..000000000000 --- a/drivers/net/wireless/mwifiex/debugfs.c +++ /dev/null @@ -1,1005 +0,0 @@ -/* - * Marvell Wireless LAN device driver: debugfs - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include <linux/debugfs.h> - -#include "main.h" -#include "11n.h" - - -static struct dentry *mwifiex_dfs_dir; - -static char *bss_modes[] = { - "UNSPECIFIED", - "ADHOC", - "STATION", - "AP", - "AP_VLAN", - "WDS", - "MONITOR", - "MESH_POINT", - "P2P_CLIENT", - "P2P_GO", - "P2P_DEVICE", -}; - -/* - * Proc info file read handler. - * - * This function is called when the 'info' file is opened for reading. - * It prints the following driver related information - - * - Driver name - * - Driver version - * - Driver extended version - * - Interface name - * - BSS mode - * - Media state (connected or disconnected) - * - MAC address - * - Total number of Tx bytes - * - Total number of Rx bytes - * - Total number of Tx packets - * - Total number of Rx packets - * - Total number of dropped Tx packets - * - Total number of dropped Rx packets - * - Total number of corrupted Tx packets - * - Total number of corrupted Rx packets - * - Carrier status (on or off) - * - Tx queue status (started or stopped) - * - * For STA mode drivers, it also prints the following extra - - * - ESSID - * - BSSID - * - Channel - * - Region code - * - Multicast count - * - Multicast addresses - */ -static ssize_t -mwifiex_info_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - struct net_device *netdev = priv->netdev; - struct netdev_hw_addr *ha; - struct netdev_queue *txq; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *) page, fmt[64]; - struct mwifiex_bss_info info; - ssize_t ret; - int i = 0; - - if (!p) - return -ENOMEM; - - memset(&info, 0, sizeof(info)); - ret = mwifiex_get_bss_info(priv, &info); - if (ret) - goto free_and_exit; - - mwifiex_drv_get_driver_version(priv->adapter, fmt, sizeof(fmt) - 1); - - if (!priv->version_str[0]) - mwifiex_get_ver_ext(priv); - - p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); - p += sprintf(p, "driver_version = %s", fmt); - p += sprintf(p, "\nverext = %s", priv->version_str); - p += sprintf(p, "\ninterface_name=\"%s\"\n", netdev->name); - - if (info.bss_mode >= ARRAY_SIZE(bss_modes)) - p += sprintf(p, "bss_mode=\"%d\"\n", info.bss_mode); - else - p += sprintf(p, "bss_mode=\"%s\"\n", bss_modes[info.bss_mode]); - - p += sprintf(p, "media_state=\"%s\"\n", - (!priv->media_connected ? "Disconnected" : "Connected")); - p += sprintf(p, "mac_address=\"%pM\"\n", netdev->dev_addr); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { - p += sprintf(p, "multicast_count=\"%d\"\n", - netdev_mc_count(netdev)); - p += sprintf(p, "essid=\"%s\"\n", info.ssid.ssid); - p += sprintf(p, "bssid=\"%pM\"\n", info.bssid); - p += sprintf(p, "channel=\"%d\"\n", (int) info.bss_chan); - p += sprintf(p, "country_code = \"%s\"\n", info.country_code); - - netdev_for_each_mc_addr(ha, netdev) - p += sprintf(p, "multicast_address[%d]=\"%pM\"\n", - i++, ha->addr); - } - - p += sprintf(p, "num_tx_bytes = %lu\n", priv->stats.tx_bytes); - p += sprintf(p, "num_rx_bytes = %lu\n", priv->stats.rx_bytes); - p += sprintf(p, "num_tx_pkts = %lu\n", priv->stats.tx_packets); - p += sprintf(p, "num_rx_pkts = %lu\n", priv->stats.rx_packets); - p += sprintf(p, "num_tx_pkts_dropped = %lu\n", priv->stats.tx_dropped); - p += sprintf(p, "num_rx_pkts_dropped = %lu\n", priv->stats.rx_dropped); - p += sprintf(p, "num_tx_pkts_err = %lu\n", priv->stats.tx_errors); - p += sprintf(p, "num_rx_pkts_err = %lu\n", priv->stats.rx_errors); - p += sprintf(p, "carrier %s\n", ((netif_carrier_ok(priv->netdev)) - ? "on" : "off")); - p += sprintf(p, "tx queue"); - for (i = 0; i < netdev->num_tx_queues; i++) { - txq = netdev_get_tx_queue(netdev, i); - p += sprintf(p, " %d:%s", i, netif_tx_queue_stopped(txq) ? - "stopped" : "started"); - } - p += sprintf(p, "\n"); - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, - (unsigned long) p - page); - -free_and_exit: - free_page(page); - return ret; -} - -/* - * Proc device dump read handler. - * - * This function is called when the 'device_dump' file is opened for - * reading. - * This function dumps driver information and firmware memory segments - * (ex. DTCM, ITCM, SQRAM etc.) for - * debugging. - */ -static ssize_t -mwifiex_device_dump_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = file->private_data; - - if (!priv->adapter->if_ops.device_dump) - return -EIO; - - priv->adapter->if_ops.device_dump(priv->adapter); - - return 0; -} - -/* - * Proc getlog file read handler. - * - * This function is called when the 'getlog' file is opened for reading - * It prints the following log information - - * - Number of multicast Tx frames - * - Number of failed packets - * - Number of Tx retries - * - Number of multicast Tx retries - * - Number of duplicate frames - * - Number of RTS successes - * - Number of RTS failures - * - Number of ACK failures - * - Number of fragmented Rx frames - * - Number of multicast Rx frames - * - Number of FCS errors - * - Number of Tx frames - * - WEP ICV error counts - * - Number of received beacons - * - Number of missed beacons - */ -static ssize_t -mwifiex_getlog_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *) page; - ssize_t ret; - struct mwifiex_ds_get_stats stats; - - if (!p) - return -ENOMEM; - - memset(&stats, 0, sizeof(stats)); - ret = mwifiex_get_stats_info(priv, &stats); - if (ret) - goto free_and_exit; - - p += sprintf(p, "\n" - "mcasttxframe %u\n" - "failed %u\n" - "retry %u\n" - "multiretry %u\n" - "framedup %u\n" - "rtssuccess %u\n" - "rtsfailure %u\n" - "ackfailure %u\n" - "rxfrag %u\n" - "mcastrxframe %u\n" - "fcserror %u\n" - "txframe %u\n" - "wepicverrcnt-1 %u\n" - "wepicverrcnt-2 %u\n" - "wepicverrcnt-3 %u\n" - "wepicverrcnt-4 %u\n" - "bcn_rcv_cnt %u\n" - "bcn_miss_cnt %u\n", - stats.mcast_tx_frame, - stats.failed, - stats.retry, - stats.multi_retry, - stats.frame_dup, - stats.rts_success, - stats.rts_failure, - stats.ack_failure, - stats.rx_frag, - stats.mcast_rx_frame, - stats.fcs_error, - stats.tx_frame, - stats.wep_icv_error[0], - stats.wep_icv_error[1], - stats.wep_icv_error[2], - stats.wep_icv_error[3], - stats.bcn_rcv_cnt, - stats.bcn_miss_cnt); - - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, - (unsigned long) p - page); - -free_and_exit: - free_page(page); - return ret; -} - -/* Sysfs histogram file read handler. - * - * This function is called when the 'histogram' file is opened for reading - * It prints the following histogram information - - * - Number of histogram samples - * - Receive packet number of each rx_rate - * - Receive packet number of each snr - * - Receive packet number of each nosie_flr - * - Receive packet number of each signal streath - */ -static ssize_t -mwifiex_histogram_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *)file->private_data; - ssize_t ret; - struct mwifiex_histogram_data *phist_data; - int i, value; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *)page; - - if (!p) - return -ENOMEM; - - if (!priv || !priv->hist_data) - return -EFAULT; - phist_data = priv->hist_data; - - p += sprintf(p, "\n" - "total samples = %d\n", - atomic_read(&phist_data->num_samples)); - - p += sprintf(p, "rx rates (in Mbps): 0=1M 1=2M"); - p += sprintf(p, "2=5.5M 3=11M 4=6M 5=9M 6=12M\n"); - p += sprintf(p, "7=18M 8=24M 9=36M 10=48M 11=54M"); - p += sprintf(p, "12-27=MCS0-15(BW20) 28-43=MCS0-15(BW40)\n"); - - if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) { - p += sprintf(p, "44-53=MCS0-9(VHT:BW20)"); - p += sprintf(p, "54-63=MCS0-9(VHT:BW40)"); - p += sprintf(p, "64-73=MCS0-9(VHT:BW80)\n\n"); - } else { - p += sprintf(p, "\n"); - } - - for (i = 0; i < MWIFIEX_MAX_RX_RATES; i++) { - value = atomic_read(&phist_data->rx_rate[i]); - if (value) - p += sprintf(p, "rx_rate[%02d] = %d\n", i, value); - } - - if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info)) { - for (i = MWIFIEX_MAX_RX_RATES; i < MWIFIEX_MAX_AC_RX_RATES; - i++) { - value = atomic_read(&phist_data->rx_rate[i]); - if (value) - p += sprintf(p, "rx_rate[%02d] = %d\n", - i, value); - } - } - - for (i = 0; i < MWIFIEX_MAX_SNR; i++) { - value = atomic_read(&phist_data->snr[i]); - if (value) - p += sprintf(p, "snr[%02ddB] = %d\n", i, value); - } - for (i = 0; i < MWIFIEX_MAX_NOISE_FLR; i++) { - value = atomic_read(&phist_data->noise_flr[i]); - if (value) - p += sprintf(p, "noise_flr[-%02ddBm] = %d\n", - (int)(i-128), value); - } - for (i = 0; i < MWIFIEX_MAX_SIG_STRENGTH; i++) { - value = atomic_read(&phist_data->sig_str[i]); - if (value) - p += sprintf(p, "sig_strength[-%02ddBm] = %d\n", - i, value); - } - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *)page, - (unsigned long)p - page); - - return ret; -} - -static ssize_t -mwifiex_histogram_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = (void *)file->private_data; - - if (priv && priv->hist_data) - mwifiex_hist_data_reset(priv); - return 0; -} - -static struct mwifiex_debug_info info; - -/* - * Proc debug file read handler. - * - * This function is called when the 'debug' file is opened for reading - * It prints the following log information - - * - Interrupt count - * - WMM AC VO packets count - * - WMM AC VI packets count - * - WMM AC BE packets count - * - WMM AC BK packets count - * - Maximum Tx buffer size - * - Tx buffer size - * - Current Tx buffer size - * - Power Save mode - * - Power Save state - * - Deep Sleep status - * - Device wakeup required status - * - Number of wakeup tries - * - Host Sleep configured status - * - Host Sleep activated status - * - Number of Tx timeouts - * - Number of command timeouts - * - Last timed out command ID - * - Last timed out command action - * - Last command ID - * - Last command action - * - Last command index - * - Last command response ID - * - Last command response index - * - Last event - * - Last event index - * - Number of host to card command failures - * - Number of sleep confirm command failures - * - Number of host to card data failure - * - Number of deauthentication events - * - Number of disassociation events - * - Number of link lost events - * - Number of deauthentication commands - * - Number of association success commands - * - Number of association failure commands - * - Number of commands sent - * - Number of data packets sent - * - Number of command responses received - * - Number of events received - * - Tx BA stream table (TID, RA) - * - Rx reorder table (TID, TA, Start window, Window size, Buffer) - */ -static ssize_t -mwifiex_debug_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *p = (char *) page; - ssize_t ret; - - if (!p) - return -ENOMEM; - - ret = mwifiex_get_debug_info(priv, &info); - if (ret) - goto free_and_exit; - - p += mwifiex_debug_info_to_buffer(priv, p, &info); - - ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page, - (unsigned long) p - page); - -free_and_exit: - free_page(page); - return ret; -} - -static u32 saved_reg_type, saved_reg_offset, saved_reg_value; - -/* - * Proc regrdwr file write handler. - * - * This function is called when the 'regrdwr' file is opened for writing - * - * This function can be used to write to a register. - */ -static ssize_t -mwifiex_regrdwr_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1); - int ret; - u32 reg_type = 0, reg_offset = 0, reg_value = UINT_MAX; - - if (!buf) - return -ENOMEM; - - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - sscanf(buf, "%u %x %x", ®_type, ®_offset, ®_value); - - if (reg_type == 0 || reg_offset == 0) { - ret = -EINVAL; - goto done; - } else { - saved_reg_type = reg_type; - saved_reg_offset = reg_offset; - saved_reg_value = reg_value; - ret = count; - } -done: - free_page(addr); - return ret; -} - -/* - * Proc regrdwr file read handler. - * - * This function is called when the 'regrdwr' file is opened for reading - * - * This function can be used to read from a register. - */ -static ssize_t -mwifiex_regrdwr_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - int pos = 0, ret = 0; - u32 reg_value; - - if (!buf) - return -ENOMEM; - - if (!saved_reg_type) { - /* No command has been given */ - pos += snprintf(buf, PAGE_SIZE, "0"); - goto done; - } - /* Set command has been given */ - if (saved_reg_value != UINT_MAX) { - ret = mwifiex_reg_write(priv, saved_reg_type, saved_reg_offset, - saved_reg_value); - - pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", - saved_reg_type, saved_reg_offset, - saved_reg_value); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - - goto done; - } - /* Get command has been given */ - ret = mwifiex_reg_read(priv, saved_reg_type, - saved_reg_offset, ®_value); - if (ret) { - ret = -EINVAL; - goto done; - } - - pos += snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", saved_reg_type, - saved_reg_offset, reg_value); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - -done: - free_page(addr); - return ret; -} - -/* Proc debug_mask file read handler. - * This function is called when the 'debug_mask' file is opened for reading - * This function can be used read driver debugging mask value. - */ -static ssize_t -mwifiex_debug_mask_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *)file->private_data; - unsigned long page = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)page; - size_t ret = 0; - int pos = 0; - - if (!buf) - return -ENOMEM; - - pos += snprintf(buf, PAGE_SIZE, "debug mask=0x%08x\n", - priv->adapter->debug_mask); - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - - free_page(page); - return ret; -} - -/* Proc debug_mask file read handler. - * This function is called when the 'debug_mask' file is opened for reading - * This function can be used read driver debugging mask value. - */ -static ssize_t -mwifiex_debug_mask_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - int ret; - unsigned long debug_mask; - struct mwifiex_private *priv = (void *)file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (void *)addr; - size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1)); - - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - if (kstrtoul(buf, 0, &debug_mask)) { - ret = -EINVAL; - goto done; - } - - priv->adapter->debug_mask = debug_mask; - ret = count; -done: - free_page(addr); - return ret; -} - -/* Proc memrw file write handler. - * This function is called when the 'memrw' file is opened for writing - * This function can be used to write to a memory location. - */ -static ssize_t -mwifiex_memrw_write(struct file *file, const char __user *ubuf, size_t count, - loff_t *ppos) -{ - int ret; - char cmd; - struct mwifiex_ds_mem_rw mem_rw; - u16 cmd_action; - struct mwifiex_private *priv = (void *)file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (void *)addr; - size_t buf_size = min(count, (size_t)(PAGE_SIZE - 1)); - - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - ret = sscanf(buf, "%c %x %x", &cmd, &mem_rw.addr, &mem_rw.value); - if (ret != 3) { - ret = -EINVAL; - goto done; - } - - if ((cmd == 'r') || (cmd == 'R')) { - cmd_action = HostCmd_ACT_GEN_GET; - mem_rw.value = 0; - } else if ((cmd == 'w') || (cmd == 'W')) { - cmd_action = HostCmd_ACT_GEN_SET; - } else { - ret = -EINVAL; - goto done; - } - - memcpy(&priv->mem_rw, &mem_rw, sizeof(mem_rw)); - if (mwifiex_send_cmd(priv, HostCmd_CMD_MEM_ACCESS, cmd_action, 0, - &mem_rw, true)) - ret = -1; - else - ret = count; - -done: - free_page(addr); - return ret; -} - -/* Proc memrw file read handler. - * This function is called when the 'memrw' file is opened for reading - * This function can be used to read from a memory location. - */ -static ssize_t -mwifiex_memrw_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = (void *)file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - int ret, pos = 0; - - if (!buf) - return -ENOMEM; - - pos += snprintf(buf, PAGE_SIZE, "0x%x 0x%x\n", priv->mem_rw.addr, - priv->mem_rw.value); - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - - free_page(addr); - return ret; -} - -static u32 saved_offset = -1, saved_bytes = -1; - -/* - * Proc rdeeprom file write handler. - * - * This function is called when the 'rdeeprom' file is opened for writing - * - * This function can be used to write to a RDEEPROM location. - */ -static ssize_t -mwifiex_rdeeprom_write(struct file *file, - const char __user *ubuf, size_t count, loff_t *ppos) -{ - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1); - int ret = 0; - int offset = -1, bytes = -1; - - if (!buf) - return -ENOMEM; - - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - sscanf(buf, "%d %d", &offset, &bytes); - - if (offset == -1 || bytes == -1) { - ret = -EINVAL; - goto done; - } else { - saved_offset = offset; - saved_bytes = bytes; - ret = count; - } -done: - free_page(addr); - return ret; -} - -/* - * Proc rdeeprom read write handler. - * - * This function is called when the 'rdeeprom' file is opened for reading - * - * This function can be used to read from a RDEEPROM location. - */ -static ssize_t -mwifiex_rdeeprom_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = - (struct mwifiex_private *) file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *) addr; - int pos, ret, i; - u8 value[MAX_EEPROM_DATA]; - - if (!buf) - return -ENOMEM; - - if (saved_offset == -1) { - /* No command has been given */ - pos = snprintf(buf, PAGE_SIZE, "0"); - goto done; - } - - /* Get command has been given */ - ret = mwifiex_eeprom_read(priv, (u16) saved_offset, - (u16) saved_bytes, value); - if (ret) { - ret = -EINVAL; - goto out_free; - } - - pos = snprintf(buf, PAGE_SIZE, "%d %d ", saved_offset, saved_bytes); - - for (i = 0; i < saved_bytes; i++) - pos += scnprintf(buf + pos, PAGE_SIZE - pos, "%d ", value[i]); - -done: - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); -out_free: - free_page(addr); - return ret; -} - -/* Proc hscfg file write handler - * This function can be used to configure the host sleep parameters. - */ -static ssize_t -mwifiex_hscfg_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = (void *)file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - size_t buf_size = min_t(size_t, count, PAGE_SIZE - 1); - int ret, arg_num; - struct mwifiex_ds_hs_cfg hscfg; - int conditions = HS_CFG_COND_DEF; - u32 gpio = HS_CFG_GPIO_DEF, gap = HS_CFG_GAP_DEF; - - if (!buf) - return -ENOMEM; - - if (copy_from_user(buf, ubuf, buf_size)) { - ret = -EFAULT; - goto done; - } - - arg_num = sscanf(buf, "%d %x %x", &conditions, &gpio, &gap); - - memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); - - if (arg_num > 3) { - mwifiex_dbg(priv->adapter, ERROR, - "Too many arguments\n"); - ret = -EINVAL; - goto done; - } - - if (arg_num >= 1 && arg_num < 3) - mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, - MWIFIEX_SYNC_CMD, &hscfg); - - if (arg_num) { - if (conditions == HS_CFG_CANCEL) { - mwifiex_cancel_hs(priv, MWIFIEX_ASYNC_CMD); - ret = count; - goto done; - } - hscfg.conditions = conditions; - } - if (arg_num >= 2) - hscfg.gpio = gpio; - if (arg_num == 3) - hscfg.gap = gap; - - hscfg.is_invoke_hostcmd = false; - mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - MWIFIEX_SYNC_CMD, &hscfg); - - mwifiex_enable_hs(priv->adapter); - priv->adapter->hs_enabling = false; - ret = count; -done: - free_page(addr); - return ret; -} - -/* Proc hscfg file read handler - * This function can be used to read host sleep configuration - * parameters from driver. - */ -static ssize_t -mwifiex_hscfg_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = (void *)file->private_data; - unsigned long addr = get_zeroed_page(GFP_KERNEL); - char *buf = (char *)addr; - int pos, ret; - struct mwifiex_ds_hs_cfg hscfg; - - if (!buf) - return -ENOMEM; - - mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_GET, - MWIFIEX_SYNC_CMD, &hscfg); - - pos = snprintf(buf, PAGE_SIZE, "%u 0x%x 0x%x\n", hscfg.conditions, - hscfg.gpio, hscfg.gap); - - ret = simple_read_from_buffer(ubuf, count, ppos, buf, pos); - - free_page(addr); - return ret; -} - -static ssize_t -mwifiex_timeshare_coex_read(struct file *file, char __user *ubuf, - size_t count, loff_t *ppos) -{ - struct mwifiex_private *priv = file->private_data; - char buf[3]; - bool timeshare_coex; - int ret; - unsigned int len; - - if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) - return -EOPNOTSUPP; - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, - HostCmd_ACT_GEN_GET, 0, ×hare_coex, true); - if (ret) - return ret; - - len = sprintf(buf, "%d\n", timeshare_coex); - return simple_read_from_buffer(ubuf, count, ppos, buf, len); -} - -static ssize_t -mwifiex_timeshare_coex_write(struct file *file, const char __user *ubuf, - size_t count, loff_t *ppos) -{ - bool timeshare_coex; - struct mwifiex_private *priv = file->private_data; - char kbuf[16]; - int ret; - - if (priv->adapter->fw_api_ver != MWIFIEX_FW_V15) - return -EOPNOTSUPP; - - memset(kbuf, 0, sizeof(kbuf)); - - if (copy_from_user(&kbuf, ubuf, min_t(size_t, sizeof(kbuf) - 1, count))) - return -EFAULT; - - if (strtobool(kbuf, ×hare_coex)) - return -EINVAL; - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_ROBUST_COEX, - HostCmd_ACT_GEN_SET, 0, ×hare_coex, true); - if (ret) - return ret; - else - return count; -} - -#define MWIFIEX_DFS_ADD_FILE(name) do { \ - if (!debugfs_create_file(#name, 0644, priv->dfs_dev_dir, \ - priv, &mwifiex_dfs_##name##_fops)) \ - return; \ -} while (0); - -#define MWIFIEX_DFS_FILE_OPS(name) \ -static const struct file_operations mwifiex_dfs_##name##_fops = { \ - .read = mwifiex_##name##_read, \ - .write = mwifiex_##name##_write, \ - .open = simple_open, \ -}; - -#define MWIFIEX_DFS_FILE_READ_OPS(name) \ -static const struct file_operations mwifiex_dfs_##name##_fops = { \ - .read = mwifiex_##name##_read, \ - .open = simple_open, \ -}; - -#define MWIFIEX_DFS_FILE_WRITE_OPS(name) \ -static const struct file_operations mwifiex_dfs_##name##_fops = { \ - .write = mwifiex_##name##_write, \ - .open = simple_open, \ -}; - - -MWIFIEX_DFS_FILE_READ_OPS(info); -MWIFIEX_DFS_FILE_READ_OPS(debug); -MWIFIEX_DFS_FILE_READ_OPS(getlog); -MWIFIEX_DFS_FILE_READ_OPS(device_dump); -MWIFIEX_DFS_FILE_OPS(regrdwr); -MWIFIEX_DFS_FILE_OPS(rdeeprom); -MWIFIEX_DFS_FILE_OPS(memrw); -MWIFIEX_DFS_FILE_OPS(hscfg); -MWIFIEX_DFS_FILE_OPS(histogram); -MWIFIEX_DFS_FILE_OPS(debug_mask); -MWIFIEX_DFS_FILE_OPS(timeshare_coex); - -/* - * This function creates the debug FS directory structure and the files. - */ -void -mwifiex_dev_debugfs_init(struct mwifiex_private *priv) -{ - if (!mwifiex_dfs_dir || !priv) - return; - - priv->dfs_dev_dir = debugfs_create_dir(priv->netdev->name, - mwifiex_dfs_dir); - - if (!priv->dfs_dev_dir) - return; - - MWIFIEX_DFS_ADD_FILE(info); - MWIFIEX_DFS_ADD_FILE(debug); - MWIFIEX_DFS_ADD_FILE(getlog); - MWIFIEX_DFS_ADD_FILE(regrdwr); - MWIFIEX_DFS_ADD_FILE(rdeeprom); - MWIFIEX_DFS_ADD_FILE(device_dump); - MWIFIEX_DFS_ADD_FILE(memrw); - MWIFIEX_DFS_ADD_FILE(hscfg); - MWIFIEX_DFS_ADD_FILE(histogram); - MWIFIEX_DFS_ADD_FILE(debug_mask); - MWIFIEX_DFS_ADD_FILE(timeshare_coex); -} - -/* - * This function removes the debug FS directory structure and the files. - */ -void -mwifiex_dev_debugfs_remove(struct mwifiex_private *priv) -{ - if (!priv) - return; - - debugfs_remove_recursive(priv->dfs_dev_dir); -} - -/* - * This function creates the top level proc directory. - */ -void -mwifiex_debugfs_init(void) -{ - if (!mwifiex_dfs_dir) - mwifiex_dfs_dir = debugfs_create_dir("mwifiex", NULL); -} - -/* - * This function removes the top level proc directory. - */ -void -mwifiex_debugfs_remove(void) -{ - if (mwifiex_dfs_dir) - debugfs_remove(mwifiex_dfs_dir); -} diff --git a/drivers/net/wireless/mwifiex/decl.h b/drivers/net/wireless/mwifiex/decl.h deleted file mode 100644 index 098e1f14dc9a..000000000000 --- a/drivers/net/wireless/mwifiex/decl.h +++ /dev/null @@ -1,273 +0,0 @@ -/* - * Marvell Wireless LAN device driver: generic data structures and APIs - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_DECL_H_ -#define _MWIFIEX_DECL_H_ - -#undef pr_fmt -#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt - -#include <linux/wait.h> -#include <linux/timer.h> -#include <linux/ieee80211.h> -#include <uapi/linux/if_arp.h> -#include <net/mac80211.h> - -#define MWIFIEX_BSS_COEX_COUNT 2 -#define MWIFIEX_MAX_BSS_NUM (3) - -#define MWIFIEX_DMA_ALIGN_SZ 64 -#define MWIFIEX_RX_HEADROOM 64 -#define MAX_TXPD_SZ 32 -#define INTF_HDR_ALIGN 4 - -#define MWIFIEX_MIN_DATA_HEADER_LEN (MWIFIEX_DMA_ALIGN_SZ + INTF_HDR_ALIGN + \ - MAX_TXPD_SZ) -#define MWIFIEX_MGMT_FRAME_HEADER_SIZE 8 /* sizeof(pkt_type) - * + sizeof(tx_control) - */ - -#define MWIFIEX_MAX_TX_BASTREAM_SUPPORTED 2 -#define MWIFIEX_MAX_RX_BASTREAM_SUPPORTED 16 -#define MWIFIEX_MAX_TDLS_PEER_SUPPORTED 8 - -#define MWIFIEX_STA_AMPDU_DEF_TXWINSIZE 64 -#define MWIFIEX_STA_AMPDU_DEF_RXWINSIZE 64 -#define MWIFIEX_STA_COEX_AMPDU_DEF_RXWINSIZE 16 - -#define MWIFIEX_UAP_AMPDU_DEF_TXWINSIZE 32 - -#define MWIFIEX_UAP_COEX_AMPDU_DEF_RXWINSIZE 16 - -#define MWIFIEX_UAP_AMPDU_DEF_RXWINSIZE 16 -#define MWIFIEX_11AC_STA_AMPDU_DEF_TXWINSIZE 64 -#define MWIFIEX_11AC_STA_AMPDU_DEF_RXWINSIZE 64 -#define MWIFIEX_11AC_UAP_AMPDU_DEF_TXWINSIZE 64 -#define MWIFIEX_11AC_UAP_AMPDU_DEF_RXWINSIZE 64 - -#define MWIFIEX_DEFAULT_BLOCK_ACK_TIMEOUT 0xffff - -#define MWIFIEX_RATE_BITMAP_MCS0 32 - -#define MWIFIEX_RX_DATA_BUF_SIZE (4 * 1024) -#define MWIFIEX_RX_CMD_BUF_SIZE (2 * 1024) - -#define MAX_BEACON_PERIOD (4000) -#define MIN_BEACON_PERIOD (50) -#define MAX_DTIM_PERIOD (100) -#define MIN_DTIM_PERIOD (1) - -#define MWIFIEX_RTS_MIN_VALUE (0) -#define MWIFIEX_RTS_MAX_VALUE (2347) -#define MWIFIEX_FRAG_MIN_VALUE (256) -#define MWIFIEX_FRAG_MAX_VALUE (2346) -#define MWIFIEX_WMM_VERSION 0x01 -#define MWIFIEX_WMM_SUBTYPE 0x01 - -#define MWIFIEX_RETRY_LIMIT 14 -#define MWIFIEX_SDIO_BLOCK_SIZE 256 - -#define MWIFIEX_BUF_FLAG_REQUEUED_PKT BIT(0) -#define MWIFIEX_BUF_FLAG_BRIDGED_PKT BIT(1) -#define MWIFIEX_BUF_FLAG_TDLS_PKT BIT(2) -#define MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS BIT(3) -#define MWIFIEX_BUF_FLAG_ACTION_TX_STATUS BIT(4) -#define MWIFIEX_BUF_FLAG_AGGR_PKT BIT(5) - -#define MWIFIEX_BRIDGED_PKTS_THR_HIGH 1024 -#define MWIFIEX_BRIDGED_PKTS_THR_LOW 128 - -#define MWIFIEX_TDLS_DISABLE_LINK 0x00 -#define MWIFIEX_TDLS_ENABLE_LINK 0x01 -#define MWIFIEX_TDLS_CREATE_LINK 0x02 -#define MWIFIEX_TDLS_CONFIG_LINK 0x03 - -#define MWIFIEX_TDLS_RSSI_HIGH 50 -#define MWIFIEX_TDLS_RSSI_LOW 55 -#define MWIFIEX_TDLS_MAX_FAIL_COUNT 4 -#define MWIFIEX_AUTO_TDLS_IDLE_TIME 10 - -/* 54M rates, index from 0 to 11 */ -#define MWIFIEX_RATE_INDEX_MCS0 12 -/* 12-27=MCS0-15(BW20) */ -#define MWIFIEX_BW20_MCS_NUM 15 - -/* Rate index for OFDM 0 */ -#define MWIFIEX_RATE_INDEX_OFDM0 4 - -#define MWIFIEX_MAX_STA_NUM 1 -#define MWIFIEX_MAX_UAP_NUM 1 -#define MWIFIEX_MAX_P2P_NUM 1 - -#define MWIFIEX_A_BAND_START_FREQ 5000 - -/* SDIO Aggr data packet special info */ -#define SDIO_MAX_AGGR_BUF_SIZE (256 * 255) -#define BLOCK_NUMBER_OFFSET 15 -#define SDIO_HEADER_OFFSET 28 - -enum mwifiex_bss_type { - MWIFIEX_BSS_TYPE_STA = 0, - MWIFIEX_BSS_TYPE_UAP = 1, - MWIFIEX_BSS_TYPE_P2P = 2, - MWIFIEX_BSS_TYPE_ANY = 0xff, -}; - -enum mwifiex_bss_role { - MWIFIEX_BSS_ROLE_STA = 0, - MWIFIEX_BSS_ROLE_UAP = 1, - MWIFIEX_BSS_ROLE_ANY = 0xff, -}; - -enum mwifiex_tdls_status { - TDLS_NOT_SETUP = 0, - TDLS_SETUP_INPROGRESS, - TDLS_SETUP_COMPLETE, - TDLS_SETUP_FAILURE, - TDLS_LINK_TEARDOWN, - TDLS_CHAN_SWITCHING, - TDLS_IN_BASE_CHAN, - TDLS_IN_OFF_CHAN, -}; - -enum mwifiex_tdls_error_code { - TDLS_ERR_NO_ERROR = 0, - TDLS_ERR_INTERNAL_ERROR, - TDLS_ERR_MAX_LINKS_EST, - TDLS_ERR_LINK_EXISTS, - TDLS_ERR_LINK_NONEXISTENT, - TDLS_ERR_PEER_STA_UNREACHABLE = 25, -}; - -#define BSS_ROLE_BIT_MASK BIT(0) - -#define GET_BSS_ROLE(priv) ((priv)->bss_role & BSS_ROLE_BIT_MASK) - -enum mwifiex_data_frame_type { - MWIFIEX_DATA_FRAME_TYPE_ETH_II = 0, - MWIFIEX_DATA_FRAME_TYPE_802_11, -}; - -struct mwifiex_fw_image { - u8 *helper_buf; - u32 helper_len; - u8 *fw_buf; - u32 fw_len; -}; - -struct mwifiex_802_11_ssid { - u32 ssid_len; - u8 ssid[IEEE80211_MAX_SSID_LEN]; -}; - -struct mwifiex_wait_queue { - wait_queue_head_t wait; - int status; -}; - -struct mwifiex_rxinfo { - struct sk_buff *parent; - u8 bss_num; - u8 bss_type; - u8 use_count; - u8 buf_type; -}; - -struct mwifiex_txinfo { - u32 status_code; - u8 flags; - u8 bss_num; - u8 bss_type; - u8 aggr_num; - u32 pkt_len; - u8 ack_frame_id; - u64 cookie; -}; - -enum mwifiex_wmm_ac_e { - WMM_AC_BK, - WMM_AC_BE, - WMM_AC_VI, - WMM_AC_VO -} __packed; - -struct ieee_types_wmm_ac_parameters { - u8 aci_aifsn_bitmap; - u8 ecw_bitmap; - __le16 tx_op_limit; -} __packed; - -struct mwifiex_types_wmm_info { - u8 oui[4]; - u8 subtype; - u8 version; - u8 qos_info; - u8 reserved; - struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; -} __packed; - -struct mwifiex_arp_eth_header { - struct arphdr hdr; - u8 ar_sha[ETH_ALEN]; - u8 ar_sip[4]; - u8 ar_tha[ETH_ALEN]; - u8 ar_tip[4]; -} __packed; - -struct mwifiex_chan_stats { - u8 chan_num; - u8 bandcfg; - u8 flags; - s8 noise; - u16 total_bss; - u16 cca_scan_dur; - u16 cca_busy_dur; -} __packed; - -#define MWIFIEX_HIST_MAX_SAMPLES 1048576 -#define MWIFIEX_MAX_RX_RATES 44 -#define MWIFIEX_MAX_AC_RX_RATES 74 -#define MWIFIEX_MAX_SNR 256 -#define MWIFIEX_MAX_NOISE_FLR 256 -#define MWIFIEX_MAX_SIG_STRENGTH 256 - -struct mwifiex_histogram_data { - atomic_t rx_rate[MWIFIEX_MAX_AC_RX_RATES]; - atomic_t snr[MWIFIEX_MAX_SNR]; - atomic_t noise_flr[MWIFIEX_MAX_NOISE_FLR]; - atomic_t sig_str[MWIFIEX_MAX_SIG_STRENGTH]; - atomic_t num_samples; -}; - -struct mwifiex_iface_comb { - u8 sta_intf; - u8 uap_intf; - u8 p2p_intf; -}; - -struct mwifiex_radar_params { - struct cfg80211_chan_def *chandef; - u32 cac_time_ms; -} __packed; - -struct mwifiex_11h_intf_state { - bool is_11h_enabled; - bool is_11h_active; -} __packed; -#endif /* !_MWIFIEX_DECL_H_ */ diff --git a/drivers/net/wireless/mwifiex/ethtool.c b/drivers/net/wireless/mwifiex/ethtool.c deleted file mode 100644 index 58400c69ab26..000000000000 --- a/drivers/net/wireless/mwifiex/ethtool.c +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Marvell Wireless LAN device driver: ethtool - * - * Copyright (C) 2013-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" - -static void mwifiex_ethtool_get_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - u32 conditions = le32_to_cpu(priv->adapter->hs_cfg.conditions); - - wol->supported = WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY; - - if (conditions == HS_CFG_COND_DEF) - return; - - if (conditions & HS_CFG_COND_UNICAST_DATA) - wol->wolopts |= WAKE_UCAST; - if (conditions & HS_CFG_COND_MULTICAST_DATA) - wol->wolopts |= WAKE_MCAST; - if (conditions & HS_CFG_COND_BROADCAST_DATA) - wol->wolopts |= WAKE_BCAST; - if (conditions & HS_CFG_COND_MAC_EVENT) - wol->wolopts |= WAKE_PHY; -} - -static int mwifiex_ethtool_set_wol(struct net_device *dev, - struct ethtool_wolinfo *wol) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - u32 conditions = 0; - - if (wol->wolopts & ~(WAKE_UCAST|WAKE_MCAST|WAKE_BCAST|WAKE_PHY)) - return -EOPNOTSUPP; - - if (wol->wolopts & WAKE_UCAST) - conditions |= HS_CFG_COND_UNICAST_DATA; - if (wol->wolopts & WAKE_MCAST) - conditions |= HS_CFG_COND_MULTICAST_DATA; - if (wol->wolopts & WAKE_BCAST) - conditions |= HS_CFG_COND_BROADCAST_DATA; - if (wol->wolopts & WAKE_PHY) - conditions |= HS_CFG_COND_MAC_EVENT; - if (wol->wolopts == 0) - conditions |= HS_CFG_COND_DEF; - priv->adapter->hs_cfg.conditions = cpu_to_le32(conditions); - - return 0; -} - -const struct ethtool_ops mwifiex_ethtool_ops = { - .get_wol = mwifiex_ethtool_get_wol, - .set_wol = mwifiex_ethtool_set_wol, -}; diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h deleted file mode 100644 index 1e1e81a0a8d4..000000000000 --- a/drivers/net/wireless/mwifiex/fw.h +++ /dev/null @@ -1,2177 +0,0 @@ -/* - * Marvell Wireless LAN device driver: Firmware specific macros & structures - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_FW_H_ -#define _MWIFIEX_FW_H_ - -#include <linux/if_ether.h> - - -#define INTF_HEADER_LEN 4 - -struct rfc_1042_hdr { - u8 llc_dsap; - u8 llc_ssap; - u8 llc_ctrl; - u8 snap_oui[3]; - __be16 snap_type; -}; - -struct rx_packet_hdr { - struct ethhdr eth803_hdr; - struct rfc_1042_hdr rfc1042_hdr; -}; - -struct tx_packet_hdr { - struct ethhdr eth803_hdr; - struct rfc_1042_hdr rfc1042_hdr; -}; - -#define B_SUPPORTED_RATES 5 -#define G_SUPPORTED_RATES 9 -#define BG_SUPPORTED_RATES 13 -#define A_SUPPORTED_RATES 9 -#define HOSTCMD_SUPPORTED_RATES 14 -#define N_SUPPORTED_RATES 3 -#define ALL_802_11_BANDS (BAND_A | BAND_B | BAND_G | BAND_GN | \ - BAND_AN | BAND_AAC) - -#define FW_MULTI_BANDS_SUPPORT (BIT(8) | BIT(9) | BIT(10) | BIT(11) | \ - BIT(13)) -#define IS_SUPPORT_MULTI_BANDS(adapter) \ - (adapter->fw_cap_info & FW_MULTI_BANDS_SUPPORT) - -/* bit 13: 11ac BAND_AAC - * bit 12: reserved for lab testing, will be reused for BAND_AN - * bit 11: 11n BAND_GN - * bit 10: 11a BAND_A - * bit 9: 11g BAND_G - * bit 8: 11b BAND_B - * Map these bits to band capability by right shifting 8 bits. - */ -#define GET_FW_DEFAULT_BANDS(adapter) \ - (((adapter->fw_cap_info & 0x2f00) >> 8) & \ - ALL_802_11_BANDS) - -#define HostCmd_WEP_KEY_INDEX_MASK 0x3fff - -#define KEY_INFO_ENABLED 0x01 -enum KEY_TYPE_ID { - KEY_TYPE_ID_WEP = 0, - KEY_TYPE_ID_TKIP, - KEY_TYPE_ID_AES, - KEY_TYPE_ID_WAPI, - KEY_TYPE_ID_AES_CMAC, -}; - -#define WPA_PN_SIZE 8 -#define KEY_PARAMS_FIXED_LEN 10 -#define KEY_INDEX_MASK 0xf -#define KEY_API_VER_MAJOR_V2 2 - -#define KEY_MCAST BIT(0) -#define KEY_UNICAST BIT(1) -#define KEY_ENABLED BIT(2) -#define KEY_DEFAULT BIT(3) -#define KEY_TX_KEY BIT(4) -#define KEY_RX_KEY BIT(5) -#define KEY_IGTK BIT(10) - -#define WAPI_KEY_LEN (WLAN_KEY_LEN_SMS4 + PN_LEN + 2) - -#define MAX_POLL_TRIES 100 -#define MAX_FIRMWARE_POLL_TRIES 100 - -#define FIRMWARE_READY_SDIO 0xfedc -#define FIRMWARE_READY_PCIE 0xfedcba00 - -#define MWIFIEX_COEX_MODE_TIMESHARE 0x01 -#define MWIFIEX_COEX_MODE_SPATIAL 0x82 - -enum mwifiex_usb_ep { - MWIFIEX_USB_EP_CMD_EVENT = 1, - MWIFIEX_USB_EP_DATA = 2, - MWIFIEX_USB_EP_DATA_CH2 = 3, -}; - -enum MWIFIEX_802_11_PRIVACY_FILTER { - MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL, - MWIFIEX_802_11_PRIV_FILTER_8021X_WEP -}; - -#define CAL_SNR(RSSI, NF) ((s16)((s16)(RSSI)-(s16)(NF))) -#define CAL_RSSI(SNR, NF) ((s16)((s16)(SNR)+(s16)(NF))) - -#define UAP_BSS_PARAMS_I 0 -#define UAP_CUSTOM_IE_I 1 -#define MWIFIEX_AUTO_IDX_MASK 0xffff -#define MWIFIEX_DELETE_MASK 0x0000 -#define MGMT_MASK_ASSOC_REQ 0x01 -#define MGMT_MASK_REASSOC_REQ 0x04 -#define MGMT_MASK_ASSOC_RESP 0x02 -#define MGMT_MASK_REASSOC_RESP 0x08 -#define MGMT_MASK_PROBE_REQ 0x10 -#define MGMT_MASK_PROBE_RESP 0x20 -#define MGMT_MASK_BEACON 0x100 - -#define TLV_TYPE_UAP_SSID 0x0000 -#define TLV_TYPE_UAP_RATES 0x0001 -#define TLV_TYPE_PWR_CONSTRAINT 0x0020 - -#define PROPRIETARY_TLV_BASE_ID 0x0100 -#define TLV_TYPE_KEY_MATERIAL (PROPRIETARY_TLV_BASE_ID + 0) -#define TLV_TYPE_CHANLIST (PROPRIETARY_TLV_BASE_ID + 1) -#define TLV_TYPE_NUMPROBES (PROPRIETARY_TLV_BASE_ID + 2) -#define TLV_TYPE_RSSI_LOW (PROPRIETARY_TLV_BASE_ID + 4) -#define TLV_TYPE_PASSTHROUGH (PROPRIETARY_TLV_BASE_ID + 10) -#define TLV_TYPE_WMMQSTATUS (PROPRIETARY_TLV_BASE_ID + 16) -#define TLV_TYPE_WILDCARDSSID (PROPRIETARY_TLV_BASE_ID + 18) -#define TLV_TYPE_TSFTIMESTAMP (PROPRIETARY_TLV_BASE_ID + 19) -#define TLV_TYPE_RSSI_HIGH (PROPRIETARY_TLV_BASE_ID + 22) -#define TLV_TYPE_AUTH_TYPE (PROPRIETARY_TLV_BASE_ID + 31) -#define TLV_TYPE_STA_MAC_ADDR (PROPRIETARY_TLV_BASE_ID + 32) -#define TLV_TYPE_BSSID (PROPRIETARY_TLV_BASE_ID + 35) -#define TLV_TYPE_CHANNELBANDLIST (PROPRIETARY_TLV_BASE_ID + 42) -#define TLV_TYPE_UAP_BEACON_PERIOD (PROPRIETARY_TLV_BASE_ID + 44) -#define TLV_TYPE_UAP_DTIM_PERIOD (PROPRIETARY_TLV_BASE_ID + 45) -#define TLV_TYPE_UAP_BCAST_SSID (PROPRIETARY_TLV_BASE_ID + 48) -#define TLV_TYPE_UAP_RTS_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 51) -#define TLV_TYPE_UAP_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 57) -#define TLV_TYPE_UAP_WEP_KEY (PROPRIETARY_TLV_BASE_ID + 59) -#define TLV_TYPE_UAP_WPA_PASSPHRASE (PROPRIETARY_TLV_BASE_ID + 60) -#define TLV_TYPE_UAP_ENCRY_PROTOCOL (PROPRIETARY_TLV_BASE_ID + 64) -#define TLV_TYPE_UAP_AKMP (PROPRIETARY_TLV_BASE_ID + 65) -#define TLV_TYPE_UAP_FRAG_THRESHOLD (PROPRIETARY_TLV_BASE_ID + 70) -#define TLV_TYPE_RATE_DROP_CONTROL (PROPRIETARY_TLV_BASE_ID + 82) -#define TLV_TYPE_RATE_SCOPE (PROPRIETARY_TLV_BASE_ID + 83) -#define TLV_TYPE_POWER_GROUP (PROPRIETARY_TLV_BASE_ID + 84) -#define TLV_TYPE_BSS_SCAN_RSP (PROPRIETARY_TLV_BASE_ID + 86) -#define TLV_TYPE_BSS_SCAN_INFO (PROPRIETARY_TLV_BASE_ID + 87) -#define TLV_TYPE_CHANRPT_11H_BASIC (PROPRIETARY_TLV_BASE_ID + 91) -#define TLV_TYPE_UAP_RETRY_LIMIT (PROPRIETARY_TLV_BASE_ID + 93) -#define TLV_TYPE_WAPI_IE (PROPRIETARY_TLV_BASE_ID + 94) -#define TLV_TYPE_ROBUST_COEX (PROPRIETARY_TLV_BASE_ID + 96) -#define TLV_TYPE_UAP_MGMT_FRAME (PROPRIETARY_TLV_BASE_ID + 104) -#define TLV_TYPE_MGMT_IE (PROPRIETARY_TLV_BASE_ID + 105) -#define TLV_TYPE_AUTO_DS_PARAM (PROPRIETARY_TLV_BASE_ID + 113) -#define TLV_TYPE_PS_PARAM (PROPRIETARY_TLV_BASE_ID + 114) -#define TLV_TYPE_UAP_PS_AO_TIMER (PROPRIETARY_TLV_BASE_ID + 123) -#define TLV_TYPE_PWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 145) -#define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146) -#define TLV_TYPE_TX_PAUSE (PROPRIETARY_TLV_BASE_ID + 148) -#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154) -#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156) -#define TLV_TYPE_MULTI_CHAN_INFO (PROPRIETARY_TLV_BASE_ID + 183) -#define TLV_TYPE_MC_GROUP_INFO (PROPRIETARY_TLV_BASE_ID + 184) -#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194) -#define TLV_TYPE_SCAN_CHANNEL_GAP (PROPRIETARY_TLV_BASE_ID + 197) -#define TLV_TYPE_API_REV (PROPRIETARY_TLV_BASE_ID + 199) -#define TLV_TYPE_CHANNEL_STATS (PROPRIETARY_TLV_BASE_ID + 198) -#define TLV_BTCOEX_WL_AGGR_WINSIZE (PROPRIETARY_TLV_BASE_ID + 202) -#define TLV_BTCOEX_WL_SCANTIME (PROPRIETARY_TLV_BASE_ID + 203) -#define TLV_TYPE_BSS_MODE (PROPRIETARY_TLV_BASE_ID + 206) - -#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048 - -#define SSN_MASK 0xfff0 - -#define BA_RESULT_SUCCESS 0x0 -#define BA_RESULT_TIMEOUT 0x2 - -#define IS_BASTREAM_SETUP(ptr) (ptr->ba_status) - -#define BA_STREAM_NOT_ALLOWED 0xff - -#define IS_11N_ENABLED(priv) ((priv->adapter->config_bands & BAND_GN || \ - priv->adapter->config_bands & BAND_AN) && \ - priv->curr_bss_params.bss_descriptor.bcn_ht_cap) -#define INITIATOR_BIT(DelBAParamSet) (((DelBAParamSet) &\ - BIT(DELBA_INITIATOR_POS)) >> DELBA_INITIATOR_POS) - -#define MWIFIEX_TX_DATA_BUF_SIZE_4K 4096 -#define MWIFIEX_TX_DATA_BUF_SIZE_8K 8192 - -#define ISSUPP_11NENABLED(FwCapInfo) (FwCapInfo & BIT(11)) -#define ISSUPP_TDLS_ENABLED(FwCapInfo) (FwCapInfo & BIT(14)) -#define ISSUPP_DRCS_ENABLED(FwCapInfo) (FwCapInfo & BIT(15)) -#define ISSUPP_SDIO_SPA_ENABLED(FwCapInfo) (FwCapInfo & BIT(16)) - -#define MWIFIEX_DEF_HT_CAP (IEEE80211_HT_CAP_DSSSCCK40 | \ - (1 << IEEE80211_HT_CAP_RX_STBC_SHIFT) | \ - IEEE80211_HT_CAP_SM_PS) - -#define MWIFIEX_DEF_11N_TX_BF_CAP 0x09E1E008 - -#define MWIFIEX_DEF_AMPDU IEEE80211_HT_AMPDU_PARM_FACTOR - -#define GET_RXSTBC(x) (x & IEEE80211_HT_CAP_RX_STBC) -#define MWIFIEX_RX_STBC1 0x0100 -#define MWIFIEX_RX_STBC12 0x0200 -#define MWIFIEX_RX_STBC123 0x0300 - -/* dev_cap bitmap - * BIT - * 0-16 reserved - * 17 IEEE80211_HT_CAP_SUP_WIDTH_20_40 - * 18-22 reserved - * 23 IEEE80211_HT_CAP_SGI_20 - * 24 IEEE80211_HT_CAP_SGI_40 - * 25 IEEE80211_HT_CAP_TX_STBC - * 26 IEEE80211_HT_CAP_RX_STBC - * 27-28 reserved - * 29 IEEE80211_HT_CAP_GRN_FLD - * 30-31 reserved - */ -#define ISSUPP_CHANWIDTH40(Dot11nDevCap) (Dot11nDevCap & BIT(17)) -#define ISSUPP_SHORTGI20(Dot11nDevCap) (Dot11nDevCap & BIT(23)) -#define ISSUPP_SHORTGI40(Dot11nDevCap) (Dot11nDevCap & BIT(24)) -#define ISSUPP_TXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(25)) -#define ISSUPP_RXSTBC(Dot11nDevCap) (Dot11nDevCap & BIT(26)) -#define ISSUPP_GREENFIELD(Dot11nDevCap) (Dot11nDevCap & BIT(29)) -#define ISENABLED_40MHZ_INTOLERANT(Dot11nDevCap) (Dot11nDevCap & BIT(8)) -#define ISSUPP_RXLDPC(Dot11nDevCap) (Dot11nDevCap & BIT(22)) -#define ISSUPP_BEAMFORMING(Dot11nDevCap) (Dot11nDevCap & BIT(30)) -#define ISALLOWED_CHANWIDTH40(ht_param) (ht_param & BIT(2)) -#define GETSUPP_TXBASTREAMS(Dot11nDevCap) ((Dot11nDevCap >> 18) & 0xF) - -/* httxcfg bitmap - * 0 reserved - * 1 20/40 Mhz enable(1)/disable(0) - * 2-3 reserved - * 4 green field enable(1)/disable(0) - * 5 short GI in 20 Mhz enable(1)/disable(0) - * 6 short GI in 40 Mhz enable(1)/disable(0) - * 7-15 reserved - */ -#define MWIFIEX_FW_DEF_HTTXCFG (BIT(1) | BIT(4) | BIT(5) | BIT(6)) - -/* 11AC Tx and Rx MCS map for 1x1 mode: - * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 - * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 7 streams - */ -#define MWIFIEX_11AC_MCS_MAP_1X1 0xfffefffe - -/* 11AC Tx and Rx MCS map for 2x2 mode: - * IEEE80211_VHT_MCS_SUPPORT_0_9 for stream 1 and 2 - * IEEE80211_VHT_MCS_NOT_SUPPORTED for remaining 6 streams - */ -#define MWIFIEX_11AC_MCS_MAP_2X2 0xfffafffa - -#define GET_RXMCSSUPP(DevMCSSupported) (DevMCSSupported & 0x0f) -#define SETHT_MCS32(x) (x[4] |= 1) -#define HT_STREAM_1X1 0x11 -#define HT_STREAM_2X2 0x22 - -#define SET_SECONDARYCHAN(RadioType, SECCHAN) (RadioType |= (SECCHAN << 4)) - -#define LLC_SNAP_LEN 8 - -/* HW_SPEC fw_cap_info */ - -#define ISSUPP_11ACENABLED(fw_cap_info) (fw_cap_info & BIT(13)) - -#define GET_VHTCAP_CHWDSET(vht_cap_info) ((vht_cap_info >> 2) & 0x3) -#define GET_VHTNSSMCS(mcs_mapset, nss) ((mcs_mapset >> (2 * (nss - 1))) & 0x3) -#define SET_VHTNSSMCS(mcs_mapset, nss, value) (mcs_mapset |= (value & 0x3) << \ - (2 * (nss - 1))) -#define GET_DEVTXMCSMAP(dev_mcs_map) (dev_mcs_map >> 16) -#define GET_DEVRXMCSMAP(dev_mcs_map) (dev_mcs_map & 0xFFFF) - -/* Clear SU Beanformer, MU beanformer, MU beanformee and - * sounding dimensions bits - */ -#define MWIFIEX_DEF_11AC_CAP_BF_RESET_MASK \ - (IEEE80211_VHT_CAP_SU_BEAMFORMER_CAPABLE | \ - IEEE80211_VHT_CAP_MU_BEAMFORMER_CAPABLE | \ - IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE | \ - IEEE80211_VHT_CAP_SOUNDING_DIMENSIONS_MASK) - -#define MOD_CLASS_HR_DSSS 0x03 -#define MOD_CLASS_OFDM 0x07 -#define MOD_CLASS_HT 0x08 -#define HT_BW_20 0 -#define HT_BW_40 1 - -#define DFS_CHAN_MOVE_TIME 10000 - -#define HostCmd_CMD_GET_HW_SPEC 0x0003 -#define HostCmd_CMD_802_11_SCAN 0x0006 -#define HostCmd_CMD_802_11_GET_LOG 0x000b -#define HostCmd_CMD_MAC_MULTICAST_ADR 0x0010 -#define HostCmd_CMD_802_11_EEPROM_ACCESS 0x0059 -#define HostCmd_CMD_802_11_ASSOCIATE 0x0012 -#define HostCmd_CMD_802_11_SNMP_MIB 0x0016 -#define HostCmd_CMD_MAC_REG_ACCESS 0x0019 -#define HostCmd_CMD_BBP_REG_ACCESS 0x001a -#define HostCmd_CMD_RF_REG_ACCESS 0x001b -#define HostCmd_CMD_PMIC_REG_ACCESS 0x00ad -#define HostCmd_CMD_RF_TX_PWR 0x001e -#define HostCmd_CMD_RF_ANTENNA 0x0020 -#define HostCmd_CMD_802_11_DEAUTHENTICATE 0x0024 -#define HostCmd_CMD_MAC_CONTROL 0x0028 -#define HostCmd_CMD_802_11_AD_HOC_START 0x002b -#define HostCmd_CMD_802_11_AD_HOC_JOIN 0x002c -#define HostCmd_CMD_802_11_AD_HOC_STOP 0x0040 -#define HostCmd_CMD_802_11_MAC_ADDRESS 0x004D -#define HostCmd_CMD_802_11D_DOMAIN_INFO 0x005b -#define HostCmd_CMD_802_11_KEY_MATERIAL 0x005e -#define HostCmd_CMD_802_11_BG_SCAN_QUERY 0x006c -#define HostCmd_CMD_WMM_GET_STATUS 0x0071 -#define HostCmd_CMD_802_11_SUBSCRIBE_EVENT 0x0075 -#define HostCmd_CMD_802_11_TX_RATE_QUERY 0x007f -#define HostCmd_CMD_802_11_IBSS_COALESCING_STATUS 0x0083 -#define HostCmd_CMD_MEM_ACCESS 0x0086 -#define HostCmd_CMD_CFG_DATA 0x008f -#define HostCmd_CMD_VERSION_EXT 0x0097 -#define HostCmd_CMD_MEF_CFG 0x009a -#define HostCmd_CMD_RSSI_INFO 0x00a4 -#define HostCmd_CMD_FUNC_INIT 0x00a9 -#define HostCmd_CMD_FUNC_SHUTDOWN 0x00aa -#define HOST_CMD_APCMD_SYS_RESET 0x00af -#define HostCmd_CMD_UAP_SYS_CONFIG 0x00b0 -#define HostCmd_CMD_UAP_BSS_START 0x00b1 -#define HostCmd_CMD_UAP_BSS_STOP 0x00b2 -#define HOST_CMD_APCMD_STA_LIST 0x00b3 -#define HostCmd_CMD_UAP_STA_DEAUTH 0x00b5 -#define HostCmd_CMD_11N_CFG 0x00cd -#define HostCmd_CMD_11N_ADDBA_REQ 0x00ce -#define HostCmd_CMD_11N_ADDBA_RSP 0x00cf -#define HostCmd_CMD_11N_DELBA 0x00d0 -#define HostCmd_CMD_RECONFIGURE_TX_BUFF 0x00d9 -#define HostCmd_CMD_CHAN_REPORT_REQUEST 0x00dd -#define HostCmd_CMD_AMSDU_AGGR_CTRL 0x00df -#define HostCmd_CMD_TXPWR_CFG 0x00d1 -#define HostCmd_CMD_TX_RATE_CFG 0x00d6 -#define HostCmd_CMD_ROBUST_COEX 0x00e0 -#define HostCmd_CMD_802_11_PS_MODE_ENH 0x00e4 -#define HostCmd_CMD_802_11_HS_CFG_ENH 0x00e5 -#define HostCmd_CMD_P2P_MODE_CFG 0x00eb -#define HostCmd_CMD_CAU_REG_ACCESS 0x00ed -#define HostCmd_CMD_SET_BSS_MODE 0x00f7 -#define HostCmd_CMD_PCIE_DESC_DETAILS 0x00fa -#define HostCmd_CMD_802_11_SCAN_EXT 0x0107 -#define HostCmd_CMD_COALESCE_CFG 0x010a -#define HostCmd_CMD_MGMT_FRAME_REG 0x010c -#define HostCmd_CMD_REMAIN_ON_CHAN 0x010d -#define HostCmd_CMD_11AC_CFG 0x0112 -#define HostCmd_CMD_TDLS_CONFIG 0x0100 -#define HostCmd_CMD_MC_POLICY 0x0121 -#define HostCmd_CMD_TDLS_OPER 0x0122 -#define HostCmd_CMD_SDIO_SP_RX_AGGR_CFG 0x0223 - -#define PROTOCOL_NO_SECURITY 0x01 -#define PROTOCOL_STATIC_WEP 0x02 -#define PROTOCOL_WPA 0x08 -#define PROTOCOL_WPA2 0x20 -#define PROTOCOL_WPA2_MIXED 0x28 -#define PROTOCOL_EAP 0x40 -#define KEY_MGMT_NONE 0x04 -#define KEY_MGMT_PSK 0x02 -#define KEY_MGMT_EAP 0x01 -#define CIPHER_TKIP 0x04 -#define CIPHER_AES_CCMP 0x08 -#define VALID_CIPHER_BITMAP 0x0c - -enum ENH_PS_MODES { - EN_PS = 1, - DIS_PS = 2, - EN_AUTO_DS = 3, - DIS_AUTO_DS = 4, - SLEEP_CONFIRM = 5, - GET_PS = 0, - EN_AUTO_PS = 0xff, - DIS_AUTO_PS = 0xfe, -}; - -enum P2P_MODES { - P2P_MODE_DISABLE = 0, - P2P_MODE_DEVICE = 1, - P2P_MODE_GO = 2, - P2P_MODE_CLIENT = 3, -}; - -#define HostCmd_RET_BIT 0x8000 -#define HostCmd_ACT_GEN_GET 0x0000 -#define HostCmd_ACT_GEN_SET 0x0001 -#define HostCmd_ACT_GEN_REMOVE 0x0004 -#define HostCmd_ACT_BITWISE_SET 0x0002 -#define HostCmd_ACT_BITWISE_CLR 0x0003 -#define HostCmd_RESULT_OK 0x0000 - -#define HostCmd_ACT_MAC_RX_ON 0x0001 -#define HostCmd_ACT_MAC_TX_ON 0x0002 -#define HostCmd_ACT_MAC_WEP_ENABLE 0x0008 -#define HostCmd_ACT_MAC_ETHERNETII_ENABLE 0x0010 -#define HostCmd_ACT_MAC_PROMISCUOUS_ENABLE 0x0080 -#define HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE 0x0100 -#define HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON 0x2000 - -#define HostCmd_BSS_MODE_IBSS 0x0002 -#define HostCmd_BSS_MODE_ANY 0x0003 - -#define HostCmd_SCAN_RADIO_TYPE_BG 0 -#define HostCmd_SCAN_RADIO_TYPE_A 1 - -#define HS_CFG_CANCEL 0xffffffff -#define HS_CFG_COND_DEF 0x00000000 -#define HS_CFG_GPIO_DEF 0xff -#define HS_CFG_GAP_DEF 0xff -#define HS_CFG_COND_BROADCAST_DATA 0x00000001 -#define HS_CFG_COND_UNICAST_DATA 0x00000002 -#define HS_CFG_COND_MAC_EVENT 0x00000004 -#define HS_CFG_COND_MULTICAST_DATA 0x00000008 - -#define CONNECT_ERR_AUTH_ERR_STA_FAILURE 0xFFFB -#define CONNECT_ERR_ASSOC_ERR_TIMEOUT 0xFFFC -#define CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED 0xFFFD -#define CONNECT_ERR_AUTH_MSG_UNHANDLED 0xFFFE -#define CONNECT_ERR_STA_FAILURE 0xFFFF - - -#define CMD_F_HOSTCMD (1 << 0) - -#define HostCmd_CMD_ID_MASK 0x0fff - -#define HostCmd_SEQ_NUM_MASK 0x00ff - -#define HostCmd_BSS_NUM_MASK 0x0f00 - -#define HostCmd_BSS_TYPE_MASK 0xf000 - -#define HostCmd_ACT_SET_RX 0x0001 -#define HostCmd_ACT_SET_TX 0x0002 -#define HostCmd_ACT_SET_BOTH 0x0003 - -#define RF_ANTENNA_AUTO 0xFFFF - -#define HostCmd_SET_SEQ_NO_BSS_INFO(seq, num, type) { \ - (((seq) & 0x00ff) | \ - (((num) & 0x000f) << 8)) | \ - (((type) & 0x000f) << 12); } - -#define HostCmd_GET_SEQ_NO(seq) \ - ((seq) & HostCmd_SEQ_NUM_MASK) - -#define HostCmd_GET_BSS_NO(seq) \ - (((seq) & HostCmd_BSS_NUM_MASK) >> 8) - -#define HostCmd_GET_BSS_TYPE(seq) \ - (((seq) & HostCmd_BSS_TYPE_MASK) >> 12) - -#define EVENT_DUMMY_HOST_WAKEUP_SIGNAL 0x00000001 -#define EVENT_LINK_LOST 0x00000003 -#define EVENT_LINK_SENSED 0x00000004 -#define EVENT_MIB_CHANGED 0x00000006 -#define EVENT_INIT_DONE 0x00000007 -#define EVENT_DEAUTHENTICATED 0x00000008 -#define EVENT_DISASSOCIATED 0x00000009 -#define EVENT_PS_AWAKE 0x0000000a -#define EVENT_PS_SLEEP 0x0000000b -#define EVENT_MIC_ERR_MULTICAST 0x0000000d -#define EVENT_MIC_ERR_UNICAST 0x0000000e -#define EVENT_DEEP_SLEEP_AWAKE 0x00000010 -#define EVENT_ADHOC_BCN_LOST 0x00000011 - -#define EVENT_WMM_STATUS_CHANGE 0x00000017 -#define EVENT_BG_SCAN_REPORT 0x00000018 -#define EVENT_RSSI_LOW 0x00000019 -#define EVENT_SNR_LOW 0x0000001a -#define EVENT_MAX_FAIL 0x0000001b -#define EVENT_RSSI_HIGH 0x0000001c -#define EVENT_SNR_HIGH 0x0000001d -#define EVENT_IBSS_COALESCED 0x0000001e -#define EVENT_DATA_RSSI_LOW 0x00000024 -#define EVENT_DATA_SNR_LOW 0x00000025 -#define EVENT_DATA_RSSI_HIGH 0x00000026 -#define EVENT_DATA_SNR_HIGH 0x00000027 -#define EVENT_LINK_QUALITY 0x00000028 -#define EVENT_PORT_RELEASE 0x0000002b -#define EVENT_UAP_STA_DEAUTH 0x0000002c -#define EVENT_UAP_STA_ASSOC 0x0000002d -#define EVENT_UAP_BSS_START 0x0000002e -#define EVENT_PRE_BEACON_LOST 0x00000031 -#define EVENT_ADDBA 0x00000033 -#define EVENT_DELBA 0x00000034 -#define EVENT_BA_STREAM_TIEMOUT 0x00000037 -#define EVENT_AMSDU_AGGR_CTRL 0x00000042 -#define EVENT_UAP_BSS_IDLE 0x00000043 -#define EVENT_UAP_BSS_ACTIVE 0x00000044 -#define EVENT_WEP_ICV_ERR 0x00000046 -#define EVENT_HS_ACT_REQ 0x00000047 -#define EVENT_BW_CHANGE 0x00000048 -#define EVENT_UAP_MIC_COUNTERMEASURES 0x0000004c -#define EVENT_HOSTWAKE_STAIE 0x0000004d -#define EVENT_CHANNEL_SWITCH_ANN 0x00000050 -#define EVENT_TDLS_GENERIC_EVENT 0x00000052 -#define EVENT_RADAR_DETECTED 0x00000053 -#define EVENT_CHANNEL_REPORT_RDY 0x00000054 -#define EVENT_TX_DATA_PAUSE 0x00000055 -#define EVENT_EXT_SCAN_REPORT 0x00000058 -#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f -#define EVENT_MULTI_CHAN_INFO 0x0000006a -#define EVENT_TX_STATUS_REPORT 0x00000074 -#define EVENT_BT_COEX_WLAN_PARA_CHANGE 0X00000076 - -#define EVENT_ID_MASK 0xffff -#define BSS_NUM_MASK 0xf - -#define EVENT_GET_BSS_NUM(event_cause) \ - (((event_cause) >> 16) & BSS_NUM_MASK) - -#define EVENT_GET_BSS_TYPE(event_cause) \ - (((event_cause) >> 24) & 0x00ff) - -#define MWIFIEX_MAX_PATTERN_LEN 20 -#define MWIFIEX_MAX_OFFSET_LEN 100 -#define STACK_NBYTES 100 -#define TYPE_DNUM 1 -#define TYPE_BYTESEQ 2 -#define MAX_OPERAND 0x40 -#define TYPE_EQ (MAX_OPERAND+1) -#define TYPE_EQ_DNUM (MAX_OPERAND+2) -#define TYPE_EQ_BIT (MAX_OPERAND+3) -#define TYPE_AND (MAX_OPERAND+4) -#define TYPE_OR (MAX_OPERAND+5) -#define MEF_MODE_HOST_SLEEP 1 -#define MEF_ACTION_ALLOW_AND_WAKEUP_HOST 3 -#define MEF_ACTION_AUTO_ARP 0x10 -#define MWIFIEX_CRITERIA_BROADCAST BIT(0) -#define MWIFIEX_CRITERIA_UNICAST BIT(1) -#define MWIFIEX_CRITERIA_MULTICAST BIT(3) -#define MWIFIEX_MAX_SUPPORTED_IPADDR 4 - -#define ACT_TDLS_DELETE 0x00 -#define ACT_TDLS_CREATE 0x01 -#define ACT_TDLS_CONFIG 0x02 - -#define TDLS_EVENT_LINK_TEAR_DOWN 3 -#define TDLS_EVENT_CHAN_SWITCH_RESULT 7 -#define TDLS_EVENT_START_CHAN_SWITCH 8 -#define TDLS_EVENT_CHAN_SWITCH_STOPPED 9 - -#define TDLS_BASE_CHANNEL 0 -#define TDLS_OFF_CHANNEL 1 - -#define ACT_TDLS_CS_ENABLE_CONFIG 0x00 -#define ACT_TDLS_CS_INIT 0x06 -#define ACT_TDLS_CS_STOP 0x07 -#define ACT_TDLS_CS_PARAMS 0x08 - -#define MWIFIEX_DEF_CS_UNIT_TIME 2 -#define MWIFIEX_DEF_CS_THR_OTHERLINK 10 -#define MWIFIEX_DEF_THR_DIRECTLINK 0 -#define MWIFIEX_DEF_CS_TIME 10 -#define MWIFIEX_DEF_CS_TIMEOUT 16 -#define MWIFIEX_DEF_CS_REG_CLASS 12 -#define MWIFIEX_DEF_CS_PERIODICITY 1 - -#define MWIFIEX_FW_V15 15 - -#define MWIFIEX_MASTER_RADAR_DET_MASK BIT(1) - -struct mwifiex_ie_types_header { - __le16 type; - __le16 len; -} __packed; - -struct mwifiex_ie_types_data { - struct mwifiex_ie_types_header header; - u8 data[1]; -} __packed; - -#define MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET 0x01 -#define MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET 0x08 -#define MWIFIEX_TXPD_FLAGS_TDLS_PACKET 0x10 -#define MWIFIEX_RXPD_FLAGS_TDLS_PACKET 0x01 -#define MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS 0x20 - -struct txpd { - u8 bss_type; - u8 bss_num; - __le16 tx_pkt_length; - __le16 tx_pkt_offset; - __le16 tx_pkt_type; - __le32 tx_control; - u8 priority; - u8 flags; - u8 pkt_delay_2ms; - u8 reserved1[2]; - u8 tx_token_id; - u8 reserved[2]; -} __packed; - -struct rxpd { - u8 bss_type; - u8 bss_num; - __le16 rx_pkt_length; - __le16 rx_pkt_offset; - __le16 rx_pkt_type; - __le16 seq_num; - u8 priority; - u8 rx_rate; - s8 snr; - s8 nf; - - /* For: Non-802.11 AC cards - * - * Ht Info [Bit 0] RxRate format: LG=0, HT=1 - * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 - * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 - * - * For: 802.11 AC cards - * [Bit 1] [Bit 0] RxRate format: legacy rate = 00 HT = 01 VHT = 10 - * [Bit 3] [Bit 2] HT/VHT Bandwidth BW20 = 00 BW40 = 01 - * BW80 = 10 BW160 = 11 - * [Bit 4] HT/VHT Guard interval LGI = 0 SGI = 1 - * [Bit 5] STBC support Enabled = 1 - * [Bit 6] LDPC support Enabled = 1 - * [Bit 7] Reserved - */ - u8 ht_info; - u8 reserved[3]; - u8 flags; -} __packed; - -struct uap_txpd { - u8 bss_type; - u8 bss_num; - __le16 tx_pkt_length; - __le16 tx_pkt_offset; - __le16 tx_pkt_type; - __le32 tx_control; - u8 priority; - u8 flags; - u8 pkt_delay_2ms; - u8 reserved1[2]; - u8 tx_token_id; - u8 reserved[2]; -}; - -struct uap_rxpd { - u8 bss_type; - u8 bss_num; - __le16 rx_pkt_length; - __le16 rx_pkt_offset; - __le16 rx_pkt_type; - __le16 seq_num; - u8 priority; - u8 rx_rate; - s8 snr; - s8 nf; - u8 ht_info; - u8 reserved[3]; - u8 flags; -}; - -struct mwifiex_fw_chan_stats { - u8 chan_num; - u8 bandcfg; - u8 flags; - s8 noise; - __le16 total_bss; - __le16 cca_scan_dur; - __le16 cca_busy_dur; -} __packed; - -enum mwifiex_chan_scan_mode_bitmasks { - MWIFIEX_PASSIVE_SCAN = BIT(0), - MWIFIEX_DISABLE_CHAN_FILT = BIT(1), - MWIFIEX_HIDDEN_SSID_REPORT = BIT(4), -}; - -struct mwifiex_chan_scan_param_set { - u8 radio_type; - u8 chan_number; - u8 chan_scan_mode_bitmap; - __le16 min_scan_time; - __le16 max_scan_time; -} __packed; - -struct mwifiex_ie_types_chan_list_param_set { - struct mwifiex_ie_types_header header; - struct mwifiex_chan_scan_param_set chan_scan_param[1]; -} __packed; - -struct chan_band_param_set { - u8 radio_type; - u8 chan_number; -}; - -struct mwifiex_ie_types_chan_band_list_param_set { - struct mwifiex_ie_types_header header; - struct chan_band_param_set chan_band_param[1]; -} __packed; - -struct mwifiex_ie_types_rates_param_set { - struct mwifiex_ie_types_header header; - u8 rates[1]; -} __packed; - -struct mwifiex_ie_types_ssid_param_set { - struct mwifiex_ie_types_header header; - u8 ssid[1]; -} __packed; - -struct mwifiex_ie_types_num_probes { - struct mwifiex_ie_types_header header; - __le16 num_probes; -} __packed; - -struct mwifiex_ie_types_scan_chan_gap { - struct mwifiex_ie_types_header header; - /* time gap in TUs to be used between two consecutive channels scan */ - __le16 chan_gap; -} __packed; - -struct mwifiex_ietypes_chanstats { - struct mwifiex_ie_types_header header; - struct mwifiex_fw_chan_stats chanstats[0]; -} __packed; - -struct mwifiex_ie_types_wildcard_ssid_params { - struct mwifiex_ie_types_header header; - u8 max_ssid_length; - u8 ssid[1]; -} __packed; - -#define TSF_DATA_SIZE 8 -struct mwifiex_ie_types_tsf_timestamp { - struct mwifiex_ie_types_header header; - u8 tsf_data[1]; -} __packed; - -struct mwifiex_cf_param_set { - u8 cfp_cnt; - u8 cfp_period; - __le16 cfp_max_duration; - __le16 cfp_duration_remaining; -} __packed; - -struct mwifiex_ibss_param_set { - __le16 atim_window; -} __packed; - -struct mwifiex_ie_types_ss_param_set { - struct mwifiex_ie_types_header header; - union { - struct mwifiex_cf_param_set cf_param_set[1]; - struct mwifiex_ibss_param_set ibss_param_set[1]; - } cf_ibss; -} __packed; - -struct mwifiex_fh_param_set { - __le16 dwell_time; - u8 hop_set; - u8 hop_pattern; - u8 hop_index; -} __packed; - -struct mwifiex_ds_param_set { - u8 current_chan; -} __packed; - -struct mwifiex_ie_types_phy_param_set { - struct mwifiex_ie_types_header header; - union { - struct mwifiex_fh_param_set fh_param_set[1]; - struct mwifiex_ds_param_set ds_param_set[1]; - } fh_ds; -} __packed; - -struct mwifiex_ie_types_auth_type { - struct mwifiex_ie_types_header header; - __le16 auth_type; -} __packed; - -struct mwifiex_ie_types_vendor_param_set { - struct mwifiex_ie_types_header header; - u8 ie[MWIFIEX_MAX_VSIE_LEN]; -}; - -#define MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC 60 - -struct mwifiex_ie_types_tdls_idle_timeout { - struct mwifiex_ie_types_header header; - __le16 value; -} __packed; - -struct mwifiex_ie_types_rsn_param_set { - struct mwifiex_ie_types_header header; - u8 rsn_ie[1]; -} __packed; - -#define KEYPARAMSET_FIXED_LEN 6 - -struct mwifiex_ie_type_key_param_set { - __le16 type; - __le16 length; - __le16 key_type_id; - __le16 key_info; - __le16 key_len; - u8 key[50]; -} __packed; - -#define IGTK_PN_LEN 8 - -struct mwifiex_cmac_param { - u8 ipn[IGTK_PN_LEN]; - u8 key[WLAN_KEY_LEN_AES_CMAC]; -} __packed; - -struct mwifiex_wep_param { - __le16 key_len; - u8 key[WLAN_KEY_LEN_WEP104]; -} __packed; - -struct mwifiex_tkip_param { - u8 pn[WPA_PN_SIZE]; - __le16 key_len; - u8 key[WLAN_KEY_LEN_TKIP]; -} __packed; - -struct mwifiex_aes_param { - u8 pn[WPA_PN_SIZE]; - __le16 key_len; - u8 key[WLAN_KEY_LEN_CCMP]; -} __packed; - -struct mwifiex_wapi_param { - u8 pn[PN_LEN]; - __le16 key_len; - u8 key[WLAN_KEY_LEN_SMS4]; -} __packed; - -struct mwifiex_cmac_aes_param { - u8 ipn[IGTK_PN_LEN]; - __le16 key_len; - u8 key[WLAN_KEY_LEN_AES_CMAC]; -} __packed; - -struct mwifiex_ie_type_key_param_set_v2 { - __le16 type; - __le16 len; - u8 mac_addr[ETH_ALEN]; - u8 key_idx; - u8 key_type; - __le16 key_info; - union { - struct mwifiex_wep_param wep; - struct mwifiex_tkip_param tkip; - struct mwifiex_aes_param aes; - struct mwifiex_wapi_param wapi; - struct mwifiex_cmac_aes_param cmac_aes; - } key_params; -} __packed; - -struct host_cmd_ds_802_11_key_material_v2 { - __le16 action; - struct mwifiex_ie_type_key_param_set_v2 key_param_set; -} __packed; - -struct host_cmd_ds_802_11_key_material { - __le16 action; - struct mwifiex_ie_type_key_param_set key_param_set; -} __packed; - -struct host_cmd_ds_gen { - __le16 command; - __le16 size; - __le16 seq_num; - __le16 result; -}; - -#define S_DS_GEN sizeof(struct host_cmd_ds_gen) - -enum sleep_resp_ctrl { - RESP_NOT_NEEDED = 0, - RESP_NEEDED, -}; - -struct mwifiex_ps_param { - __le16 null_pkt_interval; - __le16 multiple_dtims; - __le16 bcn_miss_timeout; - __le16 local_listen_interval; - __le16 adhoc_wake_period; - __le16 mode; - __le16 delay_to_ps; -}; - -#define BITMAP_AUTO_DS 0x01 -#define BITMAP_STA_PS 0x10 - -struct mwifiex_ie_types_auto_ds_param { - struct mwifiex_ie_types_header header; - __le16 deep_sleep_timeout; -} __packed; - -struct mwifiex_ie_types_ps_param { - struct mwifiex_ie_types_header header; - struct mwifiex_ps_param param; -} __packed; - -struct host_cmd_ds_802_11_ps_mode_enh { - __le16 action; - - union { - struct mwifiex_ps_param opt_ps; - __le16 ps_bitmap; - } params; -} __packed; - -enum API_VER_ID { - KEY_API_VER_ID = 1, - FW_API_VER_ID = 2, -}; - -struct hw_spec_api_rev { - struct mwifiex_ie_types_header header; - __le16 api_id; - u8 major_ver; - u8 minor_ver; -} __packed; - -struct host_cmd_ds_get_hw_spec { - __le16 hw_if_version; - __le16 version; - __le16 reserved; - __le16 num_of_mcast_adr; - u8 permanent_addr[ETH_ALEN]; - __le16 region_code; - __le16 number_of_antenna; - __le32 fw_release_number; - __le32 reserved_1; - __le32 reserved_2; - __le32 reserved_3; - __le32 fw_cap_info; - __le32 dot_11n_dev_cap; - u8 dev_mcs_support; - __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ - __le16 mgmt_buf_count; /* mgmt IE buffer count */ - __le32 reserved_5; - __le32 reserved_6; - __le32 dot_11ac_dev_cap; - __le32 dot_11ac_mcs_support; - u8 tlvs[0]; -} __packed; - -struct host_cmd_ds_802_11_rssi_info { - __le16 action; - __le16 ndata; - __le16 nbcn; - __le16 reserved[9]; - long long reserved_1; -}; - -struct host_cmd_ds_802_11_rssi_info_rsp { - __le16 action; - __le16 ndata; - __le16 nbcn; - __le16 data_rssi_last; - __le16 data_nf_last; - __le16 data_rssi_avg; - __le16 data_nf_avg; - __le16 bcn_rssi_last; - __le16 bcn_nf_last; - __le16 bcn_rssi_avg; - __le16 bcn_nf_avg; - long long tsf_bcn; -}; - -struct host_cmd_ds_802_11_mac_address { - __le16 action; - u8 mac_addr[ETH_ALEN]; -}; - -struct host_cmd_ds_mac_control { - __le16 action; - __le16 reserved; -}; - -struct host_cmd_ds_mac_multicast_adr { - __le16 action; - __le16 num_of_adrs; - u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; -} __packed; - -struct host_cmd_ds_802_11_deauthenticate { - u8 mac_addr[ETH_ALEN]; - __le16 reason_code; -} __packed; - -struct host_cmd_ds_802_11_associate { - u8 peer_sta_addr[ETH_ALEN]; - __le16 cap_info_bitmap; - __le16 listen_interval; - __le16 beacon_period; - u8 dtim_period; -} __packed; - -struct ieee_types_assoc_rsp { - __le16 cap_info_bitmap; - __le16 status_code; - __le16 a_id; - u8 ie_buffer[1]; -} __packed; - -struct host_cmd_ds_802_11_associate_rsp { - struct ieee_types_assoc_rsp assoc_rsp; -} __packed; - -struct ieee_types_cf_param_set { - u8 element_id; - u8 len; - u8 cfp_cnt; - u8 cfp_period; - __le16 cfp_max_duration; - __le16 cfp_duration_remaining; -} __packed; - -struct ieee_types_ibss_param_set { - u8 element_id; - u8 len; - __le16 atim_window; -} __packed; - -union ieee_types_ss_param_set { - struct ieee_types_cf_param_set cf_param_set; - struct ieee_types_ibss_param_set ibss_param_set; -} __packed; - -struct ieee_types_fh_param_set { - u8 element_id; - u8 len; - __le16 dwell_time; - u8 hop_set; - u8 hop_pattern; - u8 hop_index; -} __packed; - -struct ieee_types_ds_param_set { - u8 element_id; - u8 len; - u8 current_chan; -} __packed; - -union ieee_types_phy_param_set { - struct ieee_types_fh_param_set fh_param_set; - struct ieee_types_ds_param_set ds_param_set; -} __packed; - -struct ieee_types_oper_mode_ntf { - u8 element_id; - u8 len; - u8 oper_mode; -} __packed; - -struct host_cmd_ds_802_11_ad_hoc_start { - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 bss_mode; - __le16 beacon_period; - u8 dtim_period; - union ieee_types_ss_param_set ss_param_set; - union ieee_types_phy_param_set phy_param_set; - u16 reserved1; - __le16 cap_info_bitmap; - u8 data_rate[HOSTCMD_SUPPORTED_RATES]; -} __packed; - -struct host_cmd_ds_802_11_ad_hoc_result { - u8 pad[3]; - u8 bssid[ETH_ALEN]; -} __packed; - -struct adhoc_bss_desc { - u8 bssid[ETH_ALEN]; - u8 ssid[IEEE80211_MAX_SSID_LEN]; - u8 bss_mode; - __le16 beacon_period; - u8 dtim_period; - u8 time_stamp[8]; - u8 local_time[8]; - union ieee_types_phy_param_set phy_param_set; - union ieee_types_ss_param_set ss_param_set; - __le16 cap_info_bitmap; - u8 data_rates[HOSTCMD_SUPPORTED_RATES]; - - /* - * DO NOT ADD ANY FIELDS TO THIS STRUCTURE. - * It is used in the Adhoc join command and will cause a - * binary layout mismatch with the firmware - */ -} __packed; - -struct host_cmd_ds_802_11_ad_hoc_join { - struct adhoc_bss_desc bss_descriptor; - u16 reserved1; - u16 reserved2; -} __packed; - -struct host_cmd_ds_802_11_get_log { - __le32 mcast_tx_frame; - __le32 failed; - __le32 retry; - __le32 multi_retry; - __le32 frame_dup; - __le32 rts_success; - __le32 rts_failure; - __le32 ack_failure; - __le32 rx_frag; - __le32 mcast_rx_frame; - __le32 fcs_error; - __le32 tx_frame; - __le32 reserved; - __le32 wep_icv_err_cnt[4]; - __le32 bcn_rcv_cnt; - __le32 bcn_miss_cnt; -}; - -/* Enumeration for rate format */ -enum _mwifiex_rate_format { - MWIFIEX_RATE_FORMAT_LG = 0, - MWIFIEX_RATE_FORMAT_HT, - MWIFIEX_RATE_FORMAT_VHT, - MWIFIEX_RATE_FORMAT_AUTO = 0xFF, -}; - -struct host_cmd_ds_tx_rate_query { - u8 tx_rate; - /* Tx Rate Info: For 802.11 AC cards - * - * [Bit 0-1] tx rate formate: LG = 0, HT = 1, VHT = 2 - * [Bit 2-3] HT/VHT Bandwidth: BW20 = 0, BW40 = 1, BW80 = 2, BW160 = 3 - * [Bit 4] HT/VHT Guard Interval: LGI = 0, SGI = 1 - * - * For non-802.11 AC cards - * Ht Info [Bit 0] RxRate format: LG=0, HT=1 - * [Bit 1] HT Bandwidth: BW20 = 0, BW40 = 1 - * [Bit 2] HT Guard Interval: LGI = 0, SGI = 1 - */ - u8 ht_info; -} __packed; - -struct mwifiex_tx_pause_tlv { - struct mwifiex_ie_types_header header; - u8 peermac[ETH_ALEN]; - u8 tx_pause; - u8 pkt_cnt; -} __packed; - -enum Host_Sleep_Action { - HS_CONFIGURE = 0x0001, - HS_ACTIVATE = 0x0002, -}; - -struct mwifiex_hs_config_param { - __le32 conditions; - u8 gpio; - u8 gap; -} __packed; - -struct hs_activate_param { - __le16 resp_ctrl; -} __packed; - -struct host_cmd_ds_802_11_hs_cfg_enh { - __le16 action; - - union { - struct mwifiex_hs_config_param hs_config; - struct hs_activate_param hs_activate; - } params; -} __packed; - -enum SNMP_MIB_INDEX { - OP_RATE_SET_I = 1, - DTIM_PERIOD_I = 3, - RTS_THRESH_I = 5, - SHORT_RETRY_LIM_I = 6, - LONG_RETRY_LIM_I = 7, - FRAG_THRESH_I = 8, - DOT11D_I = 9, - DOT11H_I = 10, -}; - -enum mwifiex_assocmd_failurepoint { - MWIFIEX_ASSOC_CMD_SUCCESS = 0, - MWIFIEX_ASSOC_CMD_FAILURE_ASSOC, - MWIFIEX_ASSOC_CMD_FAILURE_AUTH, - MWIFIEX_ASSOC_CMD_FAILURE_JOIN -}; - -#define MAX_SNMP_BUF_SIZE 128 - -struct host_cmd_ds_802_11_snmp_mib { - __le16 query_type; - __le16 oid; - __le16 buf_size; - u8 value[1]; -} __packed; - -struct mwifiex_rate_scope { - __le16 type; - __le16 length; - __le16 hr_dsss_rate_bitmap; - __le16 ofdm_rate_bitmap; - __le16 ht_mcs_rate_bitmap[8]; - __le16 vht_mcs_rate_bitmap[8]; -} __packed; - -struct mwifiex_rate_drop_pattern { - __le16 type; - __le16 length; - __le32 rate_drop_mode; -} __packed; - -struct host_cmd_ds_tx_rate_cfg { - __le16 action; - __le16 cfg_index; -} __packed; - -struct mwifiex_power_group { - u8 modulation_class; - u8 first_rate_code; - u8 last_rate_code; - s8 power_step; - s8 power_min; - s8 power_max; - u8 ht_bandwidth; - u8 reserved; -} __packed; - -struct mwifiex_types_power_group { - __le16 type; - __le16 length; -} __packed; - -struct host_cmd_ds_txpwr_cfg { - __le16 action; - __le16 cfg_index; - __le32 mode; -} __packed; - -struct host_cmd_ds_rf_tx_pwr { - __le16 action; - __le16 cur_level; - u8 max_power; - u8 min_power; -} __packed; - -struct host_cmd_ds_rf_ant_mimo { - __le16 action_tx; - __le16 tx_ant_mode; - __le16 action_rx; - __le16 rx_ant_mode; -}; - -struct host_cmd_ds_rf_ant_siso { - __le16 action; - __le16 ant_mode; -}; - -struct host_cmd_ds_tdls_oper { - __le16 tdls_action; - __le16 reason; - u8 peer_mac[ETH_ALEN]; -} __packed; - -struct mwifiex_tdls_config { - __le16 enable; -}; - -struct mwifiex_tdls_config_cs_params { - u8 unit_time; - u8 thr_otherlink; - u8 thr_directlink; -}; - -struct mwifiex_tdls_init_cs_params { - u8 peer_mac[ETH_ALEN]; - u8 primary_chan; - u8 second_chan_offset; - u8 band; - __le16 switch_time; - __le16 switch_timeout; - u8 reg_class; - u8 periodicity; -} __packed; - -struct mwifiex_tdls_stop_cs_params { - u8 peer_mac[ETH_ALEN]; -}; - -struct host_cmd_ds_tdls_config { - __le16 tdls_action; - u8 tdls_data[1]; -} __packed; - -struct mwifiex_chan_desc { - __le16 start_freq; - u8 chan_width; - u8 chan_num; -} __packed; - -struct host_cmd_ds_chan_rpt_req { - struct mwifiex_chan_desc chan_desc; - __le32 msec_dwell_time; -} __packed; - -struct host_cmd_ds_chan_rpt_event { - __le32 result; - __le64 start_tsf; - __le32 duration; - u8 tlvbuf[0]; -} __packed; - -struct host_cmd_sdio_sp_rx_aggr_cfg { - u8 action; - u8 enable; - __le16 block_size; -} __packed; - -struct mwifiex_fixed_bcn_param { - __le64 timestamp; - __le16 beacon_period; - __le16 cap_info_bitmap; -} __packed; - -struct mwifiex_event_scan_result { - __le16 event_id; - u8 bss_index; - u8 bss_type; - u8 more_event; - u8 reserved[3]; - __le16 buf_size; - u8 num_of_set; -} __packed; - -struct tx_status_event { - u8 packet_type; - u8 tx_token_id; - u8 status; -} __packed; - -#define MWIFIEX_USER_SCAN_CHAN_MAX 50 - -#define MWIFIEX_MAX_SSID_LIST_LENGTH 10 - -struct mwifiex_scan_cmd_config { - /* - * BSS mode to be sent in the firmware command - */ - u8 bss_mode; - - /* Specific BSSID used to filter scan results in the firmware */ - u8 specific_bssid[ETH_ALEN]; - - /* Length of TLVs sent in command starting at tlvBuffer */ - u32 tlv_buf_len; - - /* - * SSID TLV(s) and ChanList TLVs to be sent in the firmware command - * - * TLV_TYPE_CHANLIST, mwifiex_ie_types_chan_list_param_set - * WLAN_EID_SSID, mwifiex_ie_types_ssid_param_set - */ - u8 tlv_buf[1]; /* SSID TLV(s) and ChanList TLVs are stored - here */ -} __packed; - -struct mwifiex_user_scan_chan { - u8 chan_number; - u8 radio_type; - u8 scan_type; - u8 reserved; - u32 scan_time; -} __packed; - -struct mwifiex_user_scan_cfg { - /* - * BSS mode to be sent in the firmware command - */ - u8 bss_mode; - /* Configure the number of probe requests for active chan scans */ - u8 num_probes; - u8 reserved; - /* BSSID filter sent in the firmware command to limit the results */ - u8 specific_bssid[ETH_ALEN]; - /* SSID filter list used in the firmware to limit the scan results */ - struct cfg80211_ssid *ssid_list; - u8 num_ssids; - /* Variable number (fixed maximum) of channels to scan up */ - struct mwifiex_user_scan_chan chan_list[MWIFIEX_USER_SCAN_CHAN_MAX]; - u16 scan_chan_gap; -} __packed; - -struct ie_body { - u8 grp_key_oui[4]; - u8 ptk_cnt[2]; - u8 ptk_body[4]; -} __packed; - -struct host_cmd_ds_802_11_scan { - u8 bss_mode; - u8 bssid[ETH_ALEN]; - u8 tlv_buffer[1]; -} __packed; - -struct host_cmd_ds_802_11_scan_rsp { - __le16 bss_descript_size; - u8 number_of_sets; - u8 bss_desc_and_tlv_buffer[1]; -} __packed; - -struct host_cmd_ds_802_11_scan_ext { - u32 reserved; - u8 tlv_buffer[1]; -} __packed; - -struct mwifiex_ie_types_bss_mode { - struct mwifiex_ie_types_header header; - u8 bss_mode; -} __packed; - -struct mwifiex_ie_types_bss_scan_rsp { - struct mwifiex_ie_types_header header; - u8 bssid[ETH_ALEN]; - u8 frame_body[1]; -} __packed; - -struct mwifiex_ie_types_bss_scan_info { - struct mwifiex_ie_types_header header; - __le16 rssi; - __le16 anpi; - u8 cca_busy_fraction; - u8 radio_type; - u8 channel; - u8 reserved; - __le64 tsf; -} __packed; - -struct host_cmd_ds_802_11_bg_scan_query { - u8 flush; -} __packed; - -struct host_cmd_ds_802_11_bg_scan_query_rsp { - __le32 report_condition; - struct host_cmd_ds_802_11_scan_rsp scan_resp; -} __packed; - -struct mwifiex_ietypes_domain_param_set { - struct mwifiex_ie_types_header header; - u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; - struct ieee80211_country_ie_triplet triplet[1]; -} __packed; - -struct host_cmd_ds_802_11d_domain_info { - __le16 action; - struct mwifiex_ietypes_domain_param_set domain; -} __packed; - -struct host_cmd_ds_802_11d_domain_info_rsp { - __le16 action; - struct mwifiex_ietypes_domain_param_set domain; -} __packed; - -struct host_cmd_ds_11n_addba_req { - u8 add_req_result; - u8 peer_mac_addr[ETH_ALEN]; - u8 dialog_token; - __le16 block_ack_param_set; - __le16 block_ack_tmo; - __le16 ssn; -} __packed; - -struct host_cmd_ds_11n_addba_rsp { - u8 add_rsp_result; - u8 peer_mac_addr[ETH_ALEN]; - u8 dialog_token; - __le16 status_code; - __le16 block_ack_param_set; - __le16 block_ack_tmo; - __le16 ssn; -} __packed; - -struct host_cmd_ds_11n_delba { - u8 del_result; - u8 peer_mac_addr[ETH_ALEN]; - __le16 del_ba_param_set; - __le16 reason_code; - u8 reserved; -} __packed; - -struct host_cmd_ds_11n_batimeout { - u8 tid; - u8 peer_mac_addr[ETH_ALEN]; - u8 origninator; -} __packed; - -struct host_cmd_ds_11n_cfg { - __le16 action; - __le16 ht_tx_cap; - __le16 ht_tx_info; - __le16 misc_config; /* Needed for 802.11AC cards only */ -} __packed; - -struct host_cmd_ds_txbuf_cfg { - __le16 action; - __le16 buff_size; - __le16 mp_end_port; /* SDIO only, reserved for other interfacces */ - __le16 reserved3; -} __packed; - -struct host_cmd_ds_amsdu_aggr_ctrl { - __le16 action; - __le16 enable; - __le16 curr_buf_size; -} __packed; - -struct host_cmd_ds_sta_deauth { - u8 mac[ETH_ALEN]; - __le16 reason; -} __packed; - -struct mwifiex_ie_types_sta_info { - struct mwifiex_ie_types_header header; - u8 mac[ETH_ALEN]; - u8 power_mfg_status; - s8 rssi; -}; - -struct host_cmd_ds_sta_list { - u16 sta_count; - u8 tlv[0]; -} __packed; - -struct mwifiex_ie_types_pwr_capability { - struct mwifiex_ie_types_header header; - s8 min_pwr; - s8 max_pwr; -}; - -struct mwifiex_ie_types_local_pwr_constraint { - struct mwifiex_ie_types_header header; - u8 chan; - u8 constraint; -}; - -struct mwifiex_ie_types_wmm_param_set { - struct mwifiex_ie_types_header header; - u8 wmm_ie[1]; -}; - -struct mwifiex_ie_types_wmm_queue_status { - struct mwifiex_ie_types_header header; - u8 queue_index; - u8 disabled; - __le16 medium_time; - u8 flow_required; - u8 flow_created; - u32 reserved; -}; - -struct ieee_types_vendor_header { - u8 element_id; - u8 len; - u8 oui[4]; /* 0~2: oui, 3: oui_type */ - u8 oui_subtype; - u8 version; -} __packed; - -struct ieee_types_wmm_parameter { - /* - * WMM Parameter IE - Vendor Specific Header: - * element_id [221/0xdd] - * Len [24] - * Oui [00:50:f2] - * OuiType [2] - * OuiSubType [1] - * Version [1] - */ - struct ieee_types_vendor_header vend_hdr; - u8 qos_info_bitmap; - u8 reserved; - struct ieee_types_wmm_ac_parameters ac_params[IEEE80211_NUM_ACS]; -} __packed; - -struct ieee_types_wmm_info { - - /* - * WMM Info IE - Vendor Specific Header: - * element_id [221/0xdd] - * Len [7] - * Oui [00:50:f2] - * OuiType [2] - * OuiSubType [0] - * Version [1] - */ - struct ieee_types_vendor_header vend_hdr; - - u8 qos_info_bitmap; -} __packed; - -struct host_cmd_ds_wmm_get_status { - u8 queue_status_tlv[sizeof(struct mwifiex_ie_types_wmm_queue_status) * - IEEE80211_NUM_ACS]; - u8 wmm_param_tlv[sizeof(struct ieee_types_wmm_parameter) + 2]; -} __packed; - -struct mwifiex_wmm_ac_status { - u8 disabled; - u8 flow_required; - u8 flow_created; -}; - -struct mwifiex_ie_types_htcap { - struct mwifiex_ie_types_header header; - struct ieee80211_ht_cap ht_cap; -} __packed; - -struct mwifiex_ie_types_vhtcap { - struct mwifiex_ie_types_header header; - struct ieee80211_vht_cap vht_cap; -} __packed; - -struct mwifiex_ie_types_aid { - struct mwifiex_ie_types_header header; - __le16 aid; -} __packed; - -struct mwifiex_ie_types_oper_mode_ntf { - struct mwifiex_ie_types_header header; - u8 oper_mode; -} __packed; - -/* VHT Operations IE */ -struct mwifiex_ie_types_vht_oper { - struct mwifiex_ie_types_header header; - u8 chan_width; - u8 chan_center_freq_1; - u8 chan_center_freq_2; - /* Basic MCS set map, each 2 bits stands for a NSS */ - __le16 basic_mcs_map; -} __packed; - -struct mwifiex_ie_types_wmmcap { - struct mwifiex_ie_types_header header; - struct mwifiex_types_wmm_info wmm_info; -} __packed; - -struct mwifiex_ie_types_htinfo { - struct mwifiex_ie_types_header header; - struct ieee80211_ht_operation ht_oper; -} __packed; - -struct mwifiex_ie_types_2040bssco { - struct mwifiex_ie_types_header header; - u8 bss_co_2040; -} __packed; - -struct mwifiex_ie_types_extcap { - struct mwifiex_ie_types_header header; - u8 ext_capab[0]; -} __packed; - -struct host_cmd_ds_mem_access { - __le16 action; - __le16 reserved; - __le32 addr; - __le32 value; -}; - -struct mwifiex_ie_types_qos_info { - struct mwifiex_ie_types_header header; - u8 qos_info; -} __packed; - -struct host_cmd_ds_mac_reg_access { - __le16 action; - __le16 offset; - __le32 value; -} __packed; - -struct host_cmd_ds_bbp_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; - -struct host_cmd_ds_rf_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; - -struct host_cmd_ds_pmic_reg_access { - __le16 action; - __le16 offset; - u8 value; - u8 reserved[3]; -} __packed; - -struct host_cmd_ds_802_11_eeprom_access { - __le16 action; - - __le16 offset; - __le16 byte_count; - u8 value; -} __packed; - -struct mwifiex_assoc_event { - u8 sta_addr[ETH_ALEN]; - __le16 type; - __le16 len; - __le16 frame_control; - __le16 cap_info; - __le16 listen_interval; - u8 data[0]; -} __packed; - -struct host_cmd_ds_sys_config { - __le16 action; - u8 tlv[0]; -}; - -struct host_cmd_11ac_vht_cfg { - __le16 action; - u8 band_config; - u8 misc_config; - __le32 cap_info; - __le32 mcs_tx_set; - __le32 mcs_rx_set; -} __packed; - -struct host_cmd_tlv_akmp { - struct mwifiex_ie_types_header header; - __le16 key_mgmt; - __le16 key_mgmt_operation; -} __packed; - -struct host_cmd_tlv_pwk_cipher { - struct mwifiex_ie_types_header header; - __le16 proto; - u8 cipher; - u8 reserved; -} __packed; - -struct host_cmd_tlv_gwk_cipher { - struct mwifiex_ie_types_header header; - u8 cipher; - u8 reserved; -} __packed; - -struct host_cmd_tlv_passphrase { - struct mwifiex_ie_types_header header; - u8 passphrase[0]; -} __packed; - -struct host_cmd_tlv_wep_key { - struct mwifiex_ie_types_header header; - u8 key_index; - u8 is_default; - u8 key[1]; -}; - -struct host_cmd_tlv_auth_type { - struct mwifiex_ie_types_header header; - u8 auth_type; -} __packed; - -struct host_cmd_tlv_encrypt_protocol { - struct mwifiex_ie_types_header header; - __le16 proto; -} __packed; - -struct host_cmd_tlv_ssid { - struct mwifiex_ie_types_header header; - u8 ssid[0]; -} __packed; - -struct host_cmd_tlv_rates { - struct mwifiex_ie_types_header header; - u8 rates[0]; -} __packed; - -struct mwifiex_ie_types_bssid_list { - struct mwifiex_ie_types_header header; - u8 bssid[ETH_ALEN]; -} __packed; - -struct host_cmd_tlv_bcast_ssid { - struct mwifiex_ie_types_header header; - u8 bcast_ctl; -} __packed; - -struct host_cmd_tlv_beacon_period { - struct mwifiex_ie_types_header header; - __le16 period; -} __packed; - -struct host_cmd_tlv_dtim_period { - struct mwifiex_ie_types_header header; - u8 period; -} __packed; - -struct host_cmd_tlv_frag_threshold { - struct mwifiex_ie_types_header header; - __le16 frag_thr; -} __packed; - -struct host_cmd_tlv_rts_threshold { - struct mwifiex_ie_types_header header; - __le16 rts_thr; -} __packed; - -struct host_cmd_tlv_retry_limit { - struct mwifiex_ie_types_header header; - u8 limit; -} __packed; - -struct host_cmd_tlv_mac_addr { - struct mwifiex_ie_types_header header; - u8 mac_addr[ETH_ALEN]; -} __packed; - -struct host_cmd_tlv_channel_band { - struct mwifiex_ie_types_header header; - u8 band_config; - u8 channel; -} __packed; - -struct host_cmd_tlv_ageout_timer { - struct mwifiex_ie_types_header header; - __le32 sta_ao_timer; -} __packed; - -struct host_cmd_tlv_power_constraint { - struct mwifiex_ie_types_header header; - u8 constraint; -} __packed; - -struct mwifiex_ie_types_btcoex_scan_time { - struct mwifiex_ie_types_header header; - u8 coex_scan; - u8 reserved; - u16 min_scan_time; - u16 max_scan_time; -} __packed; - -struct mwifiex_ie_types_btcoex_aggr_win_size { - struct mwifiex_ie_types_header header; - u8 coex_win_size; - u8 tx_win_size; - u8 rx_win_size; - u8 reserved; -} __packed; - -struct mwifiex_ie_types_robust_coex { - struct mwifiex_ie_types_header header; - __le32 mode; -} __packed; - -struct host_cmd_ds_version_ext { - u8 version_str_sel; - char version_str[128]; -} __packed; - -struct host_cmd_ds_mgmt_frame_reg { - __le16 action; - __le32 mask; -} __packed; - -struct host_cmd_ds_p2p_mode_cfg { - __le16 action; - __le16 mode; -} __packed; - -struct host_cmd_ds_remain_on_chan { - __le16 action; - u8 status; - u8 reserved; - u8 band_cfg; - u8 channel; - __le32 duration; -} __packed; - -struct host_cmd_ds_802_11_ibss_status { - __le16 action; - __le16 enable; - u8 bssid[ETH_ALEN]; - __le16 beacon_interval; - __le16 atim_window; - __le16 use_g_rate_protect; -} __packed; - -struct mwifiex_fw_mef_entry { - u8 mode; - u8 action; - __le16 exprsize; - u8 expr[0]; -} __packed; - -struct host_cmd_ds_mef_cfg { - __le32 criteria; - __le16 num_entries; - struct mwifiex_fw_mef_entry mef_entry[0]; -} __packed; - -#define CONNECTION_TYPE_INFRA 0 -#define CONNECTION_TYPE_ADHOC 1 -#define CONNECTION_TYPE_AP 2 - -struct host_cmd_ds_set_bss_mode { - u8 con_type; -} __packed; - -struct host_cmd_ds_pcie_details { - /* TX buffer descriptor ring address */ - u32 txbd_addr_lo; - u32 txbd_addr_hi; - /* TX buffer descriptor ring count */ - u32 txbd_count; - - /* RX buffer descriptor ring address */ - u32 rxbd_addr_lo; - u32 rxbd_addr_hi; - /* RX buffer descriptor ring count */ - u32 rxbd_count; - - /* Event buffer descriptor ring address */ - u32 evtbd_addr_lo; - u32 evtbd_addr_hi; - /* Event buffer descriptor ring count */ - u32 evtbd_count; - - /* Sleep cookie buffer physical address */ - u32 sleep_cookie_addr_lo; - u32 sleep_cookie_addr_hi; -} __packed; - -struct mwifiex_ie_types_rssi_threshold { - struct mwifiex_ie_types_header header; - u8 abs_value; - u8 evt_freq; -} __packed; - -#define MWIFIEX_DFS_REC_HDR_LEN 8 -#define MWIFIEX_DFS_REC_HDR_NUM 10 -#define MWIFIEX_BIN_COUNTER_LEN 7 - -struct mwifiex_radar_det_event { - __le32 detect_count; - u8 reg_domain; /*1=fcc, 2=etsi, 3=mic*/ - u8 det_type; /*0=none, 1=pw(chirp), 2=pri(radar)*/ - __le16 pw_chirp_type; - u8 pw_chirp_idx; - u8 pw_value; - u8 pri_radar_type; - u8 pri_bincnt; - u8 bin_counter[MWIFIEX_BIN_COUNTER_LEN]; - u8 num_dfs_records; - u8 dfs_record_hdr[MWIFIEX_DFS_REC_HDR_NUM][MWIFIEX_DFS_REC_HDR_LEN]; - __le32 passed; -} __packed; - -struct mwifiex_ie_types_multi_chan_info { - struct mwifiex_ie_types_header header; - __le16 status; - u8 tlv_buffer[0]; -} __packed; - -struct mwifiex_ie_types_mc_group_info { - struct mwifiex_ie_types_header header; - u8 chan_group_id; - u8 chan_buf_weight; - u8 band_config; - u8 chan_num; - u32 chan_time; - u32 reserved; - union { - u8 sdio_func_num; - u8 usb_ep_num; - } hid_num; - u8 intf_num; - u8 bss_type_numlist[0]; -} __packed; - -struct meas_rpt_map { - u8 rssi:3; - u8 unmeasured:1; - u8 radar:1; - u8 unidentified_sig:1; - u8 ofdm_preamble:1; - u8 bss:1; -} __packed; - -struct mwifiex_ie_types_chan_rpt_data { - struct mwifiex_ie_types_header header; - struct meas_rpt_map map; -} __packed; - -struct host_cmd_ds_802_11_subsc_evt { - __le16 action; - __le16 events; -} __packed; - -struct chan_switch_result { - u8 cur_chan; - u8 status; - u8 reason; -} __packed; - -struct mwifiex_tdls_generic_event { - __le16 type; - u8 peer_mac[ETH_ALEN]; - union { - struct chan_switch_result switch_result; - u8 cs_stop_reason; - __le16 reason_code; - __le16 reserved; - } u; -} __packed; - -struct mwifiex_ie { - __le16 ie_index; - __le16 mgmt_subtype_mask; - __le16 ie_length; - u8 ie_buffer[IEEE_MAX_IE_SIZE]; -} __packed; - -#define MAX_MGMT_IE_INDEX 16 -struct mwifiex_ie_list { - __le16 type; - __le16 len; - struct mwifiex_ie ie_list[MAX_MGMT_IE_INDEX]; -} __packed; - -struct coalesce_filt_field_param { - u8 operation; - u8 operand_len; - __le16 offset; - u8 operand_byte_stream[4]; -}; - -struct coalesce_receive_filt_rule { - struct mwifiex_ie_types_header header; - u8 num_of_fields; - u8 pkt_type; - __le16 max_coalescing_delay; - struct coalesce_filt_field_param params[0]; -} __packed; - -struct host_cmd_ds_coalesce_cfg { - __le16 action; - __le16 num_of_rules; - struct coalesce_receive_filt_rule rule[0]; -} __packed; - -struct host_cmd_ds_multi_chan_policy { - __le16 action; - __le16 policy; -} __packed; - -struct host_cmd_ds_robust_coex { - __le16 action; - __le16 reserved; -} __packed; - -struct host_cmd_ds_command { - __le16 command; - __le16 size; - __le16 seq_num; - __le16 result; - union { - struct host_cmd_ds_get_hw_spec hw_spec; - struct host_cmd_ds_mac_control mac_ctrl; - struct host_cmd_ds_802_11_mac_address mac_addr; - struct host_cmd_ds_mac_multicast_adr mc_addr; - struct host_cmd_ds_802_11_get_log get_log; - struct host_cmd_ds_802_11_rssi_info rssi_info; - struct host_cmd_ds_802_11_rssi_info_rsp rssi_info_rsp; - struct host_cmd_ds_802_11_snmp_mib smib; - struct host_cmd_ds_tx_rate_query tx_rate; - struct host_cmd_ds_tx_rate_cfg tx_rate_cfg; - struct host_cmd_ds_txpwr_cfg txp_cfg; - struct host_cmd_ds_rf_tx_pwr txp; - struct host_cmd_ds_rf_ant_mimo ant_mimo; - struct host_cmd_ds_rf_ant_siso ant_siso; - struct host_cmd_ds_802_11_ps_mode_enh psmode_enh; - struct host_cmd_ds_802_11_hs_cfg_enh opt_hs_cfg; - struct host_cmd_ds_802_11_scan scan; - struct host_cmd_ds_802_11_scan_ext ext_scan; - struct host_cmd_ds_802_11_scan_rsp scan_resp; - struct host_cmd_ds_802_11_bg_scan_query bg_scan_query; - struct host_cmd_ds_802_11_bg_scan_query_rsp bg_scan_query_resp; - struct host_cmd_ds_802_11_associate associate; - struct host_cmd_ds_802_11_associate_rsp associate_rsp; - struct host_cmd_ds_802_11_deauthenticate deauth; - struct host_cmd_ds_802_11_ad_hoc_start adhoc_start; - struct host_cmd_ds_802_11_ad_hoc_result adhoc_result; - struct host_cmd_ds_802_11_ad_hoc_join adhoc_join; - struct host_cmd_ds_802_11d_domain_info domain_info; - struct host_cmd_ds_802_11d_domain_info_rsp domain_info_resp; - struct host_cmd_ds_11n_addba_req add_ba_req; - struct host_cmd_ds_11n_addba_rsp add_ba_rsp; - struct host_cmd_ds_11n_delba del_ba; - struct host_cmd_ds_txbuf_cfg tx_buf; - struct host_cmd_ds_amsdu_aggr_ctrl amsdu_aggr_ctrl; - struct host_cmd_ds_11n_cfg htcfg; - struct host_cmd_ds_wmm_get_status get_wmm_status; - struct host_cmd_ds_802_11_key_material key_material; - struct host_cmd_ds_802_11_key_material_v2 key_material_v2; - struct host_cmd_ds_version_ext verext; - struct host_cmd_ds_mgmt_frame_reg reg_mask; - struct host_cmd_ds_remain_on_chan roc_cfg; - struct host_cmd_ds_p2p_mode_cfg mode_cfg; - struct host_cmd_ds_802_11_ibss_status ibss_coalescing; - struct host_cmd_ds_mef_cfg mef_cfg; - struct host_cmd_ds_mem_access mem; - struct host_cmd_ds_mac_reg_access mac_reg; - struct host_cmd_ds_bbp_reg_access bbp_reg; - struct host_cmd_ds_rf_reg_access rf_reg; - struct host_cmd_ds_pmic_reg_access pmic_reg; - struct host_cmd_ds_set_bss_mode bss_mode; - struct host_cmd_ds_pcie_details pcie_host_spec; - struct host_cmd_ds_802_11_eeprom_access eeprom; - struct host_cmd_ds_802_11_subsc_evt subsc_evt; - struct host_cmd_ds_sys_config uap_sys_config; - struct host_cmd_ds_sta_deauth sta_deauth; - struct host_cmd_ds_sta_list sta_list; - struct host_cmd_11ac_vht_cfg vht_cfg; - struct host_cmd_ds_coalesce_cfg coalesce_cfg; - struct host_cmd_ds_tdls_config tdls_config; - struct host_cmd_ds_tdls_oper tdls_oper; - struct host_cmd_ds_chan_rpt_req chan_rpt_req; - struct host_cmd_sdio_sp_rx_aggr_cfg sdio_rx_aggr_cfg; - struct host_cmd_ds_multi_chan_policy mc_policy; - struct host_cmd_ds_robust_coex coex; - } params; -} __packed; - -struct mwifiex_opt_sleep_confirm { - __le16 command; - __le16 size; - __le16 seq_num; - __le16 result; - __le16 action; - __le16 resp_ctrl; -} __packed; -#endif /* !_MWIFIEX_FW_H_ */ diff --git a/drivers/net/wireless/mwifiex/ie.c b/drivers/net/wireless/mwifiex/ie.c deleted file mode 100644 index abf52d25b981..000000000000 --- a/drivers/net/wireless/mwifiex/ie.c +++ /dev/null @@ -1,488 +0,0 @@ -/* - * Marvell Wireless LAN device driver: management IE handling- setting and - * deleting IE. - * - * Copyright (C) 2012-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" - -/* This function checks if current IE index is used by any on other interface. - * Return: -1: yes, current IE index is used by someone else. - * 0: no, current IE index is NOT used by other interface. - */ -static int -mwifiex_ie_index_used_by_other_intf(struct mwifiex_private *priv, u16 idx) -{ - int i; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie *ie; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i] != priv) { - ie = &adapter->priv[i]->mgmt_ie[idx]; - if (ie->mgmt_subtype_mask && ie->ie_length) - return -1; - } - } - - return 0; -} - -/* Get unused IE index. This index will be used for setting new IE */ -static int -mwifiex_ie_get_autoidx(struct mwifiex_private *priv, u16 subtype_mask, - struct mwifiex_ie *ie, u16 *index) -{ - u16 mask, len, i; - - for (i = 0; i < priv->adapter->max_mgmt_ie_index; i++) { - mask = le16_to_cpu(priv->mgmt_ie[i].mgmt_subtype_mask); - len = le16_to_cpu(ie->ie_length); - - if (mask == MWIFIEX_AUTO_IDX_MASK) - continue; - - if (mask == subtype_mask) { - if (len > IEEE_MAX_IE_SIZE) - continue; - - *index = i; - return 0; - } - - if (!priv->mgmt_ie[i].ie_length) { - if (mwifiex_ie_index_used_by_other_intf(priv, i)) - continue; - - *index = i; - return 0; - } - } - - return -1; -} - -/* This function prepares IE data buffer for command to be sent to FW */ -static int -mwifiex_update_autoindex_ies(struct mwifiex_private *priv, - struct mwifiex_ie_list *ie_list) -{ - u16 travel_len, index, mask; - s16 input_len, tlv_len; - struct mwifiex_ie *ie; - u8 *tmp; - - input_len = le16_to_cpu(ie_list->len); - travel_len = sizeof(struct mwifiex_ie_types_header); - - ie_list->len = 0; - - while (input_len >= sizeof(struct mwifiex_ie_types_header)) { - ie = (struct mwifiex_ie *)(((u8 *)ie_list) + travel_len); - tlv_len = le16_to_cpu(ie->ie_length); - travel_len += tlv_len + MWIFIEX_IE_HDR_SIZE; - - if (input_len < tlv_len + MWIFIEX_IE_HDR_SIZE) - return -1; - index = le16_to_cpu(ie->ie_index); - mask = le16_to_cpu(ie->mgmt_subtype_mask); - - if (index == MWIFIEX_AUTO_IDX_MASK) { - /* automatic addition */ - if (mwifiex_ie_get_autoidx(priv, mask, ie, &index)) - return -1; - if (index == MWIFIEX_AUTO_IDX_MASK) - return -1; - - tmp = (u8 *)&priv->mgmt_ie[index].ie_buffer; - memcpy(tmp, &ie->ie_buffer, le16_to_cpu(ie->ie_length)); - priv->mgmt_ie[index].ie_length = ie->ie_length; - priv->mgmt_ie[index].ie_index = cpu_to_le16(index); - priv->mgmt_ie[index].mgmt_subtype_mask = - cpu_to_le16(mask); - - ie->ie_index = cpu_to_le16(index); - } else { - if (mask != MWIFIEX_DELETE_MASK) - return -1; - /* - * Check if this index is being used on any - * other interface. - */ - if (mwifiex_ie_index_used_by_other_intf(priv, index)) - return -1; - - ie->ie_length = 0; - memcpy(&priv->mgmt_ie[index], ie, - sizeof(struct mwifiex_ie)); - } - - le16_add_cpu(&ie_list->len, - le16_to_cpu(priv->mgmt_ie[index].ie_length) + - MWIFIEX_IE_HDR_SIZE); - input_len -= tlv_len + MWIFIEX_IE_HDR_SIZE; - } - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) - return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, - HostCmd_ACT_GEN_SET, - UAP_CUSTOM_IE_I, ie_list, false); - - return 0; -} - -/* Copy individual custom IEs for beacon, probe response and assoc response - * and prepare single structure for IE setting. - * This function also updates allocated IE indices from driver. - */ -static int -mwifiex_update_uap_custom_ie(struct mwifiex_private *priv, - struct mwifiex_ie *beacon_ie, u16 *beacon_idx, - struct mwifiex_ie *pr_ie, u16 *probe_idx, - struct mwifiex_ie *ar_ie, u16 *assoc_idx) -{ - struct mwifiex_ie_list *ap_custom_ie; - u8 *pos; - u16 len; - int ret; - - ap_custom_ie = kzalloc(sizeof(*ap_custom_ie), GFP_KERNEL); - if (!ap_custom_ie) - return -ENOMEM; - - ap_custom_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); - pos = (u8 *)ap_custom_ie->ie_list; - - if (beacon_ie) { - len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + - le16_to_cpu(beacon_ie->ie_length); - memcpy(pos, beacon_ie, len); - pos += len; - le16_add_cpu(&ap_custom_ie->len, len); - } - if (pr_ie) { - len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + - le16_to_cpu(pr_ie->ie_length); - memcpy(pos, pr_ie, len); - pos += len; - le16_add_cpu(&ap_custom_ie->len, len); - } - if (ar_ie) { - len = sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE + - le16_to_cpu(ar_ie->ie_length); - memcpy(pos, ar_ie, len); - pos += len; - le16_add_cpu(&ap_custom_ie->len, len); - } - - ret = mwifiex_update_autoindex_ies(priv, ap_custom_ie); - - pos = (u8 *)(&ap_custom_ie->ie_list[0].ie_index); - if (beacon_ie && *beacon_idx == MWIFIEX_AUTO_IDX_MASK) { - /* save beacon ie index after auto-indexing */ - *beacon_idx = le16_to_cpu(ap_custom_ie->ie_list[0].ie_index); - len = sizeof(*beacon_ie) - IEEE_MAX_IE_SIZE + - le16_to_cpu(beacon_ie->ie_length); - pos += len; - } - if (pr_ie && le16_to_cpu(pr_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) { - /* save probe resp ie index after auto-indexing */ - *probe_idx = *((u16 *)pos); - len = sizeof(*pr_ie) - IEEE_MAX_IE_SIZE + - le16_to_cpu(pr_ie->ie_length); - pos += len; - } - if (ar_ie && le16_to_cpu(ar_ie->ie_index) == MWIFIEX_AUTO_IDX_MASK) - /* save assoc resp ie index after auto-indexing */ - *assoc_idx = *((u16 *)pos); - - kfree(ap_custom_ie); - return ret; -} - -/* This function checks if the vendor specified IE is present in passed buffer - * and copies it to mwifiex_ie structure. - * Function takes pointer to struct mwifiex_ie pointer as argument. - * If the vendor specified IE is present then memory is allocated for - * mwifiex_ie pointer and filled in with IE. Caller should take care of freeing - * this memory. - */ -static int mwifiex_update_vs_ie(const u8 *ies, int ies_len, - struct mwifiex_ie **ie_ptr, u16 mask, - unsigned int oui, u8 oui_type) -{ - struct ieee_types_header *vs_ie; - struct mwifiex_ie *ie = *ie_ptr; - const u8 *vendor_ie; - - vendor_ie = cfg80211_find_vendor_ie(oui, oui_type, ies, ies_len); - if (vendor_ie) { - if (!*ie_ptr) { - *ie_ptr = kzalloc(sizeof(struct mwifiex_ie), - GFP_KERNEL); - if (!*ie_ptr) - return -ENOMEM; - ie = *ie_ptr; - } - - vs_ie = (struct ieee_types_header *)vendor_ie; - memcpy(ie->ie_buffer + le16_to_cpu(ie->ie_length), - vs_ie, vs_ie->len + 2); - le16_add_cpu(&ie->ie_length, vs_ie->len + 2); - ie->mgmt_subtype_mask = cpu_to_le16(mask); - ie->ie_index = cpu_to_le16(MWIFIEX_AUTO_IDX_MASK); - } - - *ie_ptr = ie; - return 0; -} - -/* This function parses beacon IEs, probe response IEs, association response IEs - * from cfg80211_ap_settings->beacon and sets these IE to FW. - */ -static int mwifiex_set_mgmt_beacon_data_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *data) -{ - struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL, *ar_ie = NULL; - u16 beacon_idx = MWIFIEX_AUTO_IDX_MASK, pr_idx = MWIFIEX_AUTO_IDX_MASK; - u16 ar_idx = MWIFIEX_AUTO_IDX_MASK; - int ret = 0; - - if (data->beacon_ies && data->beacon_ies_len) { - mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len, - &beacon_ie, MGMT_MASK_BEACON, - WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS); - mwifiex_update_vs_ie(data->beacon_ies, data->beacon_ies_len, - &beacon_ie, MGMT_MASK_BEACON, - WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); - } - - if (data->proberesp_ies && data->proberesp_ies_len) { - mwifiex_update_vs_ie(data->proberesp_ies, - data->proberesp_ies_len, &pr_ie, - MGMT_MASK_PROBE_RESP, WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS); - mwifiex_update_vs_ie(data->proberesp_ies, - data->proberesp_ies_len, &pr_ie, - MGMT_MASK_PROBE_RESP, - WLAN_OUI_WFA, WLAN_OUI_TYPE_WFA_P2P); - } - - if (data->assocresp_ies && data->assocresp_ies_len) { - mwifiex_update_vs_ie(data->assocresp_ies, - data->assocresp_ies_len, &ar_ie, - MGMT_MASK_ASSOC_RESP | - MGMT_MASK_REASSOC_RESP, - WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPS); - mwifiex_update_vs_ie(data->assocresp_ies, - data->assocresp_ies_len, &ar_ie, - MGMT_MASK_ASSOC_RESP | - MGMT_MASK_REASSOC_RESP, WLAN_OUI_WFA, - WLAN_OUI_TYPE_WFA_P2P); - } - - if (beacon_ie || pr_ie || ar_ie) { - ret = mwifiex_update_uap_custom_ie(priv, beacon_ie, - &beacon_idx, pr_ie, - &pr_idx, ar_ie, &ar_idx); - if (ret) - goto done; - } - - priv->beacon_idx = beacon_idx; - priv->proberesp_idx = pr_idx; - priv->assocresp_idx = ar_idx; - -done: - kfree(beacon_ie); - kfree(pr_ie); - kfree(ar_ie); - - return ret; -} - -/* This function parses head and tail IEs, from cfg80211_beacon_data and sets - * these IE to FW. - */ -static int mwifiex_uap_parse_tail_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *info) -{ - struct mwifiex_ie *gen_ie; - struct ieee_types_header *hdr; - struct ieee80211_vendor_ie *vendorhdr; - u16 gen_idx = MWIFIEX_AUTO_IDX_MASK, ie_len = 0; - int left_len, parsed_len = 0; - - if (!info->tail || !info->tail_len) - return 0; - - gen_ie = kzalloc(sizeof(*gen_ie), GFP_KERNEL); - if (!gen_ie) - return -ENOMEM; - - left_len = info->tail_len; - - /* Many IEs are generated in FW by parsing bss configuration. - * Let's not add them here; else we may end up duplicating these IEs - */ - while (left_len > sizeof(struct ieee_types_header)) { - hdr = (void *)(info->tail + parsed_len); - switch (hdr->element_id) { - case WLAN_EID_SSID: - case WLAN_EID_SUPP_RATES: - case WLAN_EID_COUNTRY: - case WLAN_EID_PWR_CONSTRAINT: - case WLAN_EID_EXT_SUPP_RATES: - case WLAN_EID_HT_CAPABILITY: - case WLAN_EID_HT_OPERATION: - case WLAN_EID_VHT_CAPABILITY: - case WLAN_EID_VHT_OPERATION: - case WLAN_EID_VENDOR_SPECIFIC: - break; - default: - memcpy(gen_ie->ie_buffer + ie_len, hdr, - hdr->len + sizeof(struct ieee_types_header)); - ie_len += hdr->len + sizeof(struct ieee_types_header); - break; - } - left_len -= hdr->len + sizeof(struct ieee_types_header); - parsed_len += hdr->len + sizeof(struct ieee_types_header); - } - - /* parse only WPA vendor IE from tail, WMM IE is configured by - * bss_config command - */ - vendorhdr = (void *)cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WPA, - info->tail, info->tail_len); - if (vendorhdr) { - memcpy(gen_ie->ie_buffer + ie_len, vendorhdr, - vendorhdr->len + sizeof(struct ieee_types_header)); - ie_len += vendorhdr->len + sizeof(struct ieee_types_header); - } - - if (!ie_len) { - kfree(gen_ie); - return 0; - } - - gen_ie->ie_index = cpu_to_le16(gen_idx); - gen_ie->mgmt_subtype_mask = cpu_to_le16(MGMT_MASK_BEACON | - MGMT_MASK_PROBE_RESP | - MGMT_MASK_ASSOC_RESP); - gen_ie->ie_length = cpu_to_le16(ie_len); - - if (mwifiex_update_uap_custom_ie(priv, gen_ie, &gen_idx, NULL, NULL, - NULL, NULL)) { - kfree(gen_ie); - return -1; - } - - priv->gen_idx = gen_idx; - kfree(gen_ie); - return 0; -} - -/* This function parses different IEs-head & tail IEs, beacon IEs, - * probe response IEs, association response IEs from cfg80211_ap_settings - * function and sets these IE to FW. - */ -int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *info) -{ - int ret; - - ret = mwifiex_uap_parse_tail_ies(priv, info); - - if (ret) - return ret; - - return mwifiex_set_mgmt_beacon_data_ies(priv, info); -} - -/* This function removes management IE set */ -int mwifiex_del_mgmt_ies(struct mwifiex_private *priv) -{ - struct mwifiex_ie *beacon_ie = NULL, *pr_ie = NULL; - struct mwifiex_ie *ar_ie = NULL, *gen_ie = NULL; - int ret = 0; - - if (priv->gen_idx != MWIFIEX_AUTO_IDX_MASK) { - gen_ie = kmalloc(sizeof(*gen_ie), GFP_KERNEL); - if (!gen_ie) - return -ENOMEM; - - gen_ie->ie_index = cpu_to_le16(priv->gen_idx); - gen_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); - gen_ie->ie_length = 0; - if (mwifiex_update_uap_custom_ie(priv, gen_ie, &priv->gen_idx, - NULL, &priv->proberesp_idx, - NULL, &priv->assocresp_idx)) { - ret = -1; - goto done; - } - - priv->gen_idx = MWIFIEX_AUTO_IDX_MASK; - } - - if (priv->beacon_idx != MWIFIEX_AUTO_IDX_MASK) { - beacon_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); - if (!beacon_ie) { - ret = -ENOMEM; - goto done; - } - beacon_ie->ie_index = cpu_to_le16(priv->beacon_idx); - beacon_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); - beacon_ie->ie_length = 0; - } - if (priv->proberesp_idx != MWIFIEX_AUTO_IDX_MASK) { - pr_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); - if (!pr_ie) { - ret = -ENOMEM; - goto done; - } - pr_ie->ie_index = cpu_to_le16(priv->proberesp_idx); - pr_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); - pr_ie->ie_length = 0; - } - if (priv->assocresp_idx != MWIFIEX_AUTO_IDX_MASK) { - ar_ie = kmalloc(sizeof(struct mwifiex_ie), GFP_KERNEL); - if (!ar_ie) { - ret = -ENOMEM; - goto done; - } - ar_ie->ie_index = cpu_to_le16(priv->assocresp_idx); - ar_ie->mgmt_subtype_mask = cpu_to_le16(MWIFIEX_DELETE_MASK); - ar_ie->ie_length = 0; - } - - if (beacon_ie || pr_ie || ar_ie) - ret = mwifiex_update_uap_custom_ie(priv, - beacon_ie, &priv->beacon_idx, - pr_ie, &priv->proberesp_idx, - ar_ie, &priv->assocresp_idx); - -done: - kfree(gen_ie); - kfree(beacon_ie); - kfree(pr_ie); - kfree(ar_ie); - - return ret; -} diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c deleted file mode 100644 index de74a7773fb6..000000000000 --- a/drivers/net/wireless/mwifiex/init.c +++ /dev/null @@ -1,782 +0,0 @@ -/* - * Marvell Wireless LAN device driver: HW/FW Initialization - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * This function adds a BSS priority table to the table list. - * - * The function allocates a new BSS priority table node and adds it to - * the end of BSS priority table list, kept in driver memory. - */ -static int mwifiex_add_bss_prio_tbl(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_node *bss_prio; - struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl; - unsigned long flags; - - bss_prio = kzalloc(sizeof(struct mwifiex_bss_prio_node), GFP_KERNEL); - if (!bss_prio) - return -ENOMEM; - - bss_prio->priv = priv; - INIT_LIST_HEAD(&bss_prio->list); - - spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags); - list_add_tail(&bss_prio->list, &tbl[priv->bss_priority].bss_prio_head); - spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags); - - return 0; -} - -static void wakeup_timer_fn(unsigned long data) -{ - struct mwifiex_adapter *adapter = (struct mwifiex_adapter *)data; - - mwifiex_dbg(adapter, ERROR, "Firmware wakeup failed\n"); - adapter->hw_status = MWIFIEX_HW_STATUS_RESET; - mwifiex_cancel_all_pending_cmd(adapter); - - if (adapter->if_ops.card_reset) - adapter->if_ops.card_reset(adapter); -} - -/* - * This function initializes the private structure and sets default - * values to the members. - * - * Additionally, it also initializes all the locks and sets up all the - * lists. - */ -int mwifiex_init_priv(struct mwifiex_private *priv) -{ - u32 i; - - priv->media_connected = false; - eth_broadcast_addr(priv->curr_addr); - priv->port_open = false; - priv->usb_port = MWIFIEX_USB_EP_DATA; - priv->pkt_tx_ctrl = 0; - priv->bss_mode = NL80211_IFTYPE_UNSPECIFIED; - priv->data_rate = 0; /* Initially indicate the rate as auto */ - priv->is_data_rate_auto = true; - priv->bcn_avg_factor = DEFAULT_BCN_AVG_FACTOR; - priv->data_avg_factor = DEFAULT_DATA_AVG_FACTOR; - - priv->sec_info.wep_enabled = 0; - priv->sec_info.authentication_mode = NL80211_AUTHTYPE_OPEN_SYSTEM; - priv->sec_info.encryption_mode = 0; - for (i = 0; i < ARRAY_SIZE(priv->wep_key); i++) - memset(&priv->wep_key[i], 0, sizeof(struct mwifiex_wep_key)); - priv->wep_key_curr_index = 0; - priv->curr_pkt_filter = HostCmd_ACT_MAC_RX_ON | HostCmd_ACT_MAC_TX_ON | - HostCmd_ACT_MAC_ETHERNETII_ENABLE; - - priv->beacon_period = 100; /* beacon interval */ ; - priv->attempted_bss_desc = NULL; - memset(&priv->curr_bss_params, 0, sizeof(priv->curr_bss_params)); - priv->listen_interval = MWIFIEX_DEFAULT_LISTEN_INTERVAL; - - memset(&priv->prev_ssid, 0, sizeof(priv->prev_ssid)); - memset(&priv->prev_bssid, 0, sizeof(priv->prev_bssid)); - memset(&priv->assoc_rsp_buf, 0, sizeof(priv->assoc_rsp_buf)); - priv->assoc_rsp_size = 0; - priv->adhoc_channel = DEFAULT_AD_HOC_CHANNEL; - priv->atim_window = 0; - priv->adhoc_state = ADHOC_IDLE; - priv->tx_power_level = 0; - priv->max_tx_power_level = 0; - priv->min_tx_power_level = 0; - priv->tx_rate = 0; - priv->rxpd_htinfo = 0; - priv->rxpd_rate = 0; - priv->rate_bitmap = 0; - priv->data_rssi_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->data_nf_last = 0; - priv->bcn_rssi_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - priv->bcn_nf_last = 0; - memset(&priv->wpa_ie, 0, sizeof(priv->wpa_ie)); - memset(&priv->aes_key, 0, sizeof(priv->aes_key)); - priv->wpa_ie_len = 0; - priv->wpa_is_gtk_set = false; - - memset(&priv->assoc_tlv_buf, 0, sizeof(priv->assoc_tlv_buf)); - priv->assoc_tlv_buf_len = 0; - memset(&priv->wps, 0, sizeof(priv->wps)); - memset(&priv->gen_ie_buf, 0, sizeof(priv->gen_ie_buf)); - priv->gen_ie_buf_len = 0; - memset(priv->vs_ie, 0, sizeof(priv->vs_ie)); - - priv->wmm_required = true; - priv->wmm_enabled = false; - priv->wmm_qosinfo = 0; - priv->curr_bcn_buf = NULL; - priv->curr_bcn_size = 0; - priv->wps_ie = NULL; - priv->wps_ie_len = 0; - priv->ap_11n_enabled = 0; - memset(&priv->roc_cfg, 0, sizeof(priv->roc_cfg)); - - priv->scan_block = false; - - priv->csa_chan = 0; - priv->csa_expire_time = 0; - priv->del_list_idx = 0; - priv->hs2_enabled = false; - priv->check_tdls_tx = false; - memcpy(priv->tos_to_tid_inv, tos_to_tid_inv, MAX_NUM_TID); - - mwifiex_init_11h_params(priv); - - return mwifiex_add_bss_prio_tbl(priv); -} - -/* - * This function allocates buffers for members of the adapter - * structure. - * - * The memory allocated includes scan table, command buffers, and - * sleep confirm command buffer. In addition, the queues are - * also initialized. - */ -static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) -{ - int ret; - - /* Allocate command buffer */ - ret = mwifiex_alloc_cmd_buffer(adapter); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to alloc cmd buffer\n", - __func__); - return -1; - } - - adapter->sleep_cfm = - dev_alloc_skb(sizeof(struct mwifiex_opt_sleep_confirm) - + INTF_HEADER_LEN); - - if (!adapter->sleep_cfm) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to alloc sleep cfm\t" - " cmd buffer\n", __func__); - return -1; - } - skb_reserve(adapter->sleep_cfm, INTF_HEADER_LEN); - - return 0; -} - -/* - * This function initializes the adapter structure and sets default - * values to the members of adapter. - * - * This also initializes the WMM related parameters in the driver private - * structures. - */ -static void mwifiex_init_adapter(struct mwifiex_adapter *adapter) -{ - struct mwifiex_opt_sleep_confirm *sleep_cfm_buf = NULL; - - skb_put(adapter->sleep_cfm, sizeof(struct mwifiex_opt_sleep_confirm)); - - adapter->cmd_sent = false; - - if (adapter->iface_type == MWIFIEX_SDIO) - adapter->data_sent = true; - else - adapter->data_sent = false; - - adapter->cmd_resp_received = false; - adapter->event_received = false; - adapter->data_received = false; - - adapter->surprise_removed = false; - - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - adapter->ps_state = PS_STATE_AWAKE; - adapter->need_to_wakeup = false; - - adapter->scan_mode = HostCmd_BSS_MODE_ANY; - adapter->specific_scan_time = MWIFIEX_SPECIFIC_SCAN_CHAN_TIME; - adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME; - adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME; - adapter->scan_chan_gap_time = MWIFIEX_DEF_SCAN_CHAN_GAP_TIME; - - adapter->scan_probes = 1; - - adapter->multiple_dtim = 1; - - adapter->local_listen_interval = 0; /* default value in firmware - will be used */ - - adapter->is_deep_sleep = false; - - adapter->delay_null_pkt = false; - adapter->delay_to_ps = 1000; - adapter->enhanced_ps_mode = PS_MODE_AUTO; - - adapter->gen_null_pkt = false; /* Disable NULL Pkg generation by - default */ - adapter->pps_uapsd_mode = false; /* Disable pps/uapsd mode by - default */ - adapter->pm_wakeup_card_req = false; - - adapter->pm_wakeup_fw_try = false; - - adapter->curr_tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - - adapter->is_hs_configured = false; - adapter->hs_cfg.conditions = cpu_to_le32(HS_CFG_COND_DEF); - adapter->hs_cfg.gpio = HS_CFG_GPIO_DEF; - adapter->hs_cfg.gap = HS_CFG_GAP_DEF; - adapter->hs_activated = false; - - memset(adapter->event_body, 0, sizeof(adapter->event_body)); - adapter->hw_dot_11n_dev_cap = 0; - adapter->hw_dev_mcs_support = 0; - adapter->sec_chan_offset = 0; - adapter->adhoc_11n_enabled = false; - - mwifiex_wmm_init(adapter); - - sleep_cfm_buf = (struct mwifiex_opt_sleep_confirm *) - adapter->sleep_cfm->data; - memset(sleep_cfm_buf, 0, adapter->sleep_cfm->len); - sleep_cfm_buf->command = cpu_to_le16(HostCmd_CMD_802_11_PS_MODE_ENH); - sleep_cfm_buf->size = cpu_to_le16(adapter->sleep_cfm->len); - sleep_cfm_buf->result = 0; - sleep_cfm_buf->action = cpu_to_le16(SLEEP_CONFIRM); - sleep_cfm_buf->resp_ctrl = cpu_to_le16(RESP_NEEDED); - - memset(&adapter->sleep_params, 0, sizeof(adapter->sleep_params)); - memset(&adapter->sleep_period, 0, sizeof(adapter->sleep_period)); - adapter->tx_lock_flag = false; - adapter->null_pkt_interval = 0; - adapter->fw_bands = 0; - adapter->config_bands = 0; - adapter->adhoc_start_band = 0; - adapter->scan_channels = NULL; - adapter->fw_release_number = 0; - adapter->fw_cap_info = 0; - memset(&adapter->upld_buf, 0, sizeof(adapter->upld_buf)); - adapter->event_cause = 0; - adapter->region_code = 0; - adapter->bcn_miss_time_out = DEFAULT_BCN_MISS_TIMEOUT; - adapter->adhoc_awake_period = 0; - memset(&adapter->arp_filter, 0, sizeof(adapter->arp_filter)); - adapter->arp_filter_size = 0; - adapter->max_mgmt_ie_index = MAX_MGMT_IE_INDEX; - adapter->key_api_major_ver = 0; - adapter->key_api_minor_ver = 0; - eth_broadcast_addr(adapter->perm_addr); - adapter->iface_limit.sta_intf = MWIFIEX_MAX_STA_NUM; - adapter->iface_limit.uap_intf = MWIFIEX_MAX_UAP_NUM; - adapter->iface_limit.p2p_intf = MWIFIEX_MAX_P2P_NUM; - adapter->active_scan_triggered = false; - setup_timer(&adapter->wakeup_timer, wakeup_timer_fn, - (unsigned long)adapter); -} - -/* - * This function sets trans_start per tx_queue - */ -void mwifiex_set_trans_start(struct net_device *dev) -{ - int i; - - for (i = 0; i < dev->num_tx_queues; i++) - netdev_get_tx_queue(dev, i)->trans_start = jiffies; - - dev->trans_start = jiffies; -} - -/* - * This function wakes up all queues in net_device - */ -void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, - struct mwifiex_adapter *adapter) -{ - unsigned long dev_queue_flags; - unsigned int i; - - spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); - - for (i = 0; i < netdev->num_tx_queues; i++) { - struct netdev_queue *txq = netdev_get_tx_queue(netdev, i); - - if (netif_tx_queue_stopped(txq)) - netif_tx_wake_queue(txq); - } - - spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); -} - -/* - * This function stops all queues in net_device - */ -void mwifiex_stop_net_dev_queue(struct net_device *netdev, - struct mwifiex_adapter *adapter) -{ - unsigned long dev_queue_flags; - unsigned int i; - - spin_lock_irqsave(&adapter->queue_lock, dev_queue_flags); - - for (i = 0; i < netdev->num_tx_queues; i++) { - struct netdev_queue *txq = netdev_get_tx_queue(netdev, i); - - if (!netif_tx_queue_stopped(txq)) - netif_tx_stop_queue(txq); - } - - spin_unlock_irqrestore(&adapter->queue_lock, dev_queue_flags); -} - -/* - * This function releases the lock variables and frees the locks and - * associated locks. - */ -static void mwifiex_free_lock_list(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - s32 i, j; - - /* Free lists */ - list_del(&adapter->cmd_free_q); - list_del(&adapter->cmd_pending_q); - list_del(&adapter->scan_pending_q); - - for (i = 0; i < adapter->priv_num; i++) - list_del(&adapter->bss_prio_tbl[i].bss_prio_head); - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - for (j = 0; j < MAX_NUM_TID; ++j) - list_del(&priv->wmm.tid_tbl_ptr[j].ra_list); - list_del(&priv->tx_ba_stream_tbl_ptr); - list_del(&priv->rx_reorder_tbl_ptr); - list_del(&priv->sta_list); - list_del(&priv->auto_tdls_list); - } - } -} - -/* - * This function performs cleanup for adapter structure. - * - * The cleanup is done recursively, by canceling all pending - * commands, freeing the member buffers previously allocated - * (command buffers, scan table buffer, sleep confirm command - * buffer), stopping the timers and calling the cleanup routines - * for every interface. - */ -static void -mwifiex_adapter_cleanup(struct mwifiex_adapter *adapter) -{ - int idx; - - if (!adapter) { - pr_err("%s: adapter is NULL\n", __func__); - return; - } - - del_timer(&adapter->wakeup_timer); - mwifiex_cancel_all_pending_cmd(adapter); - wake_up_interruptible(&adapter->cmd_wait_q.wait); - wake_up_interruptible(&adapter->hs_activate_wait_q); - - /* Free lock variables */ - mwifiex_free_lock_list(adapter); - - /* Free command buffer */ - mwifiex_dbg(adapter, INFO, "info: free cmd buffer\n"); - mwifiex_free_cmd_buffer(adapter); - - for (idx = 0; idx < adapter->num_mem_types; idx++) { - struct memory_type_mapping *entry = - &adapter->mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - } - - if (adapter->drv_info_dump) { - vfree(adapter->drv_info_dump); - adapter->drv_info_dump = NULL; - adapter->drv_info_size = 0; - } - - if (adapter->sleep_cfm) - dev_kfree_skb_any(adapter->sleep_cfm); -} - -/* - * This function intializes the lock variables and - * the list heads. - */ -int mwifiex_init_lock_list(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - s32 i, j; - - spin_lock_init(&adapter->mwifiex_lock); - spin_lock_init(&adapter->int_lock); - spin_lock_init(&adapter->main_proc_lock); - spin_lock_init(&adapter->mwifiex_cmd_lock); - spin_lock_init(&adapter->queue_lock); - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - spin_lock_init(&priv->rx_pkt_lock); - spin_lock_init(&priv->wmm.ra_list_spinlock); - spin_lock_init(&priv->curr_bcn_buf_lock); - spin_lock_init(&priv->sta_list_spinlock); - spin_lock_init(&priv->auto_tdls_lock); - } - } - - /* Initialize cmd_free_q */ - INIT_LIST_HEAD(&adapter->cmd_free_q); - /* Initialize cmd_pending_q */ - INIT_LIST_HEAD(&adapter->cmd_pending_q); - /* Initialize scan_pending_q */ - INIT_LIST_HEAD(&adapter->scan_pending_q); - - spin_lock_init(&adapter->cmd_free_q_lock); - spin_lock_init(&adapter->cmd_pending_q_lock); - spin_lock_init(&adapter->scan_pending_q_lock); - spin_lock_init(&adapter->rx_proc_lock); - - skb_queue_head_init(&adapter->rx_data_q); - skb_queue_head_init(&adapter->tx_data_q); - - for (i = 0; i < adapter->priv_num; ++i) { - INIT_LIST_HEAD(&adapter->bss_prio_tbl[i].bss_prio_head); - spin_lock_init(&adapter->bss_prio_tbl[i].bss_prio_lock); - } - - for (i = 0; i < adapter->priv_num; i++) { - if (!adapter->priv[i]) - continue; - priv = adapter->priv[i]; - for (j = 0; j < MAX_NUM_TID; ++j) - INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[j].ra_list); - INIT_LIST_HEAD(&priv->tx_ba_stream_tbl_ptr); - INIT_LIST_HEAD(&priv->rx_reorder_tbl_ptr); - INIT_LIST_HEAD(&priv->sta_list); - INIT_LIST_HEAD(&priv->auto_tdls_list); - skb_queue_head_init(&priv->tdls_txq); - skb_queue_head_init(&priv->bypass_txq); - - spin_lock_init(&priv->tx_ba_stream_tbl_lock); - spin_lock_init(&priv->rx_reorder_tbl_lock); - - spin_lock_init(&priv->ack_status_lock); - idr_init(&priv->ack_status_frames); - } - - return 0; -} - -/* - * This function initializes the firmware. - * - * The following operations are performed sequentially - - * - Allocate adapter structure - * - Initialize the adapter structure - * - Initialize the private structure - * - Add BSS priority tables to the adapter structure - * - For each interface, send the init commands to firmware - * - Send the first command in command pending queue, if available - */ -int mwifiex_init_fw(struct mwifiex_adapter *adapter) -{ - int ret; - struct mwifiex_private *priv; - u8 i, first_sta = true; - int is_cmd_pend_q_empty; - unsigned long flags; - - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - - /* Allocate memory for member of adapter structure */ - ret = mwifiex_allocate_adapter(adapter); - if (ret) - return -1; - - /* Initialize adapter structure */ - mwifiex_init_adapter(adapter); - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - - /* Initialize private structure */ - ret = mwifiex_init_priv(priv); - if (ret) - return -1; - } - } - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - ret = mwifiex_sta_init_cmd(adapter->priv[i], first_sta, - true); - if (ret == -1) - return -1; - - first_sta = false; - } - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - if (!is_cmd_pend_q_empty) { - /* Send the first command in queue and return */ - if (mwifiex_main_process(adapter) != -1) - ret = -EINPROGRESS; - } else { - adapter->hw_status = MWIFIEX_HW_STATUS_READY; - } - - return ret; -} - -/* - * This function deletes the BSS priority tables. - * - * The function traverses through all the allocated BSS priority nodes - * in every BSS priority table and frees them. - */ -static void mwifiex_delete_bss_prio_tbl(struct mwifiex_private *priv) -{ - int i; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_node *bssprio_node, *tmp_node; - struct list_head *head; - spinlock_t *lock; /* bss priority lock */ - unsigned long flags; - - for (i = 0; i < adapter->priv_num; ++i) { - head = &adapter->bss_prio_tbl[i].bss_prio_head; - lock = &adapter->bss_prio_tbl[i].bss_prio_lock; - mwifiex_dbg(adapter, INFO, - "info: delete BSS priority table,\t" - "bss_type = %d, bss_num = %d, i = %d,\t" - "head = %p\n", - priv->bss_type, priv->bss_num, i, head); - - { - spin_lock_irqsave(lock, flags); - if (list_empty(head)) { - spin_unlock_irqrestore(lock, flags); - continue; - } - list_for_each_entry_safe(bssprio_node, tmp_node, head, - list) { - if (bssprio_node->priv == priv) { - mwifiex_dbg(adapter, INFO, - "info: Delete\t" - "node %p, next = %p\n", - bssprio_node, tmp_node); - list_del(&bssprio_node->list); - kfree(bssprio_node); - } - } - spin_unlock_irqrestore(lock, flags); - } - } -} - -/* - * This function frees the private structure, including cleans - * up the TX and RX queues and frees the BSS priority tables. - */ -void mwifiex_free_priv(struct mwifiex_private *priv) -{ - mwifiex_clean_txrx(priv); - mwifiex_delete_bss_prio_tbl(priv); - mwifiex_free_curr_bcn(priv); -} - -/* - * This function is used to shutdown the driver. - * - * The following operations are performed sequentially - - * - Check if already shut down - * - Make sure the main process has stopped - * - Clean up the Tx and Rx queues - * - Delete BSS priority tables - * - Free the adapter - * - Notify completion - */ -int -mwifiex_shutdown_drv(struct mwifiex_adapter *adapter) -{ - int ret = -EINPROGRESS; - struct mwifiex_private *priv; - s32 i; - unsigned long flags; - struct sk_buff *skb; - - /* mwifiex already shutdown */ - if (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY) - return 0; - - adapter->hw_status = MWIFIEX_HW_STATUS_CLOSING; - /* wait for mwifiex_process to complete */ - if (adapter->mwifiex_processing) { - mwifiex_dbg(adapter, WARN, - "main process is still running\n"); - return ret; - } - - /* cancel current command */ - if (adapter->curr_cmd) { - mwifiex_dbg(adapter, WARN, - "curr_cmd is still in processing\n"); - del_timer_sync(&adapter->cmd_timer); - mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); - adapter->curr_cmd = NULL; - } - - /* shut down mwifiex */ - mwifiex_dbg(adapter, MSG, - "info: shutdown mwifiex...\n"); - - /* Clean up Tx/Rx queues and delete BSS priority table */ - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - priv = adapter->priv[i]; - - mwifiex_clean_auto_tdls(priv); - mwifiex_abort_cac(priv); - mwifiex_clean_txrx(priv); - mwifiex_delete_bss_prio_tbl(priv); - } - } - - atomic_set(&adapter->tx_queued, 0); - while ((skb = skb_dequeue(&adapter->tx_data_q))) - mwifiex_write_data_complete(adapter, skb, 0, 0); - - spin_lock_irqsave(&adapter->rx_proc_lock, flags); - - while ((skb = skb_dequeue(&adapter->rx_data_q))) { - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - - atomic_dec(&adapter->rx_pending); - priv = adapter->priv[rx_info->bss_num]; - if (priv) - priv->stats.rx_dropped++; - - dev_kfree_skb_any(skb); - } - - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - - spin_lock(&adapter->mwifiex_lock); - - mwifiex_adapter_cleanup(adapter); - - spin_unlock(&adapter->mwifiex_lock); - - /* Notify completion */ - ret = mwifiex_shutdown_fw_complete(adapter); - - return ret; -} - -/* - * This function downloads the firmware to the card. - * - * The actual download is preceded by two sanity checks - - * - Check if firmware is already running - * - Check if the interface is the winner to download the firmware - * - * ...and followed by another - - * - Check if the firmware is downloaded successfully - * - * After download is successfully completed, the host interrupts are enabled. - */ -int mwifiex_dnld_fw(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *pmfw) -{ - int ret; - u32 poll_num = 1; - - if (adapter->if_ops.check_fw_status) { - adapter->winner = 0; - - /* check if firmware is already running */ - ret = adapter->if_ops.check_fw_status(adapter, poll_num); - if (!ret) { - mwifiex_dbg(adapter, MSG, - "WLAN FW already running! Skip FW dnld\n"); - return 0; - } - - poll_num = MAX_FIRMWARE_POLL_TRIES; - - /* check if we are the winner for downloading FW */ - if (!adapter->winner) { - mwifiex_dbg(adapter, MSG, - "FW already running! Skip FW dnld\n"); - goto poll_fw; - } - } - - if (pmfw) { - /* Download firmware with helper */ - ret = adapter->if_ops.prog_fw(adapter, pmfw); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "prog_fw failed ret=%#x\n", ret); - return ret; - } - } - -poll_fw: - /* Check if the firmware is downloaded successfully or not */ - ret = adapter->if_ops.check_fw_status(adapter, poll_num); - if (ret) - mwifiex_dbg(adapter, ERROR, - "FW failed to be active in time\n"); - - return ret; -} diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h deleted file mode 100644 index 4f0174c64946..000000000000 --- a/drivers/net/wireless/mwifiex/ioctl.h +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Marvell Wireless LAN device driver: ioctl data structures & APIs - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_IOCTL_H_ -#define _MWIFIEX_IOCTL_H_ - -#include <net/lib80211.h> - -enum { - MWIFIEX_SCAN_TYPE_UNCHANGED = 0, - MWIFIEX_SCAN_TYPE_ACTIVE, - MWIFIEX_SCAN_TYPE_PASSIVE -}; - -struct mwifiex_user_scan { - u32 scan_cfg_len; - u8 scan_cfg_buf[1]; -}; - -#define MWIFIEX_PROMISC_MODE 1 -#define MWIFIEX_MULTICAST_MODE 2 -#define MWIFIEX_ALL_MULTI_MODE 4 -#define MWIFIEX_MAX_MULTICAST_LIST_SIZE 32 - -struct mwifiex_multicast_list { - u32 mode; - u32 num_multicast_addr; - u8 mac_list[MWIFIEX_MAX_MULTICAST_LIST_SIZE][ETH_ALEN]; -}; - -struct mwifiex_chan_freq { - u32 channel; - u32 freq; -}; - -struct mwifiex_ssid_bssid { - struct cfg80211_ssid ssid; - u8 bssid[ETH_ALEN]; -}; - -enum { - BAND_B = 1, - BAND_G = 2, - BAND_A = 4, - BAND_GN = 8, - BAND_AN = 16, - BAND_AAC = 32, -}; - -#define MWIFIEX_WPA_PASSHPHRASE_LEN 64 -struct wpa_param { - u8 pairwise_cipher_wpa; - u8 pairwise_cipher_wpa2; - u8 group_cipher; - u32 length; - u8 passphrase[MWIFIEX_WPA_PASSHPHRASE_LEN]; -}; - -struct wep_key { - u8 key_index; - u8 is_default; - u16 length; - u8 key[WLAN_KEY_LEN_WEP104]; -}; - -#define KEY_MGMT_ON_HOST 0x03 -#define MWIFIEX_AUTH_MODE_AUTO 0xFF -#define BAND_CONFIG_BG 0x00 -#define BAND_CONFIG_A 0x01 -#define MWIFIEX_SUPPORTED_RATES 14 -#define MWIFIEX_SUPPORTED_RATES_EXT 32 -#define MWIFIEX_TDLS_SUPPORTED_RATES 8 -#define MWIFIEX_TDLS_DEF_QOS_CAPAB 0xf -#define MWIFIEX_PRIO_BK 2 -#define MWIFIEX_PRIO_VI 5 - -struct mwifiex_uap_bss_param { - u8 channel; - u8 band_cfg; - u16 rts_threshold; - u16 frag_threshold; - u8 retry_limit; - struct mwifiex_802_11_ssid ssid; - u8 bcast_ssid_ctl; - u8 radio_ctl; - u8 dtim_period; - u16 beacon_period; - u16 auth_mode; - u16 protocol; - u16 key_mgmt; - u16 key_mgmt_operation; - struct wpa_param wpa_cfg; - struct wep_key wep_cfg[NUM_WEP_KEYS]; - struct ieee80211_ht_cap ht_cap; - struct ieee80211_vht_cap vht_cap; - u8 rates[MWIFIEX_SUPPORTED_RATES]; - u32 sta_ao_timer; - u32 ps_sta_ao_timer; - u8 qos_info; - u8 power_constraint; - struct mwifiex_types_wmm_info wmm_info; -}; - -enum { - ADHOC_IDLE, - ADHOC_STARTED, - ADHOC_JOINED, - ADHOC_COALESCED -}; - -struct mwifiex_ds_get_stats { - u32 mcast_tx_frame; - u32 failed; - u32 retry; - u32 multi_retry; - u32 frame_dup; - u32 rts_success; - u32 rts_failure; - u32 ack_failure; - u32 rx_frag; - u32 mcast_rx_frame; - u32 fcs_error; - u32 tx_frame; - u32 wep_icv_error[4]; - u32 bcn_rcv_cnt; - u32 bcn_miss_cnt; -}; - -#define MWIFIEX_MAX_VER_STR_LEN 128 - -struct mwifiex_ver_ext { - u32 version_str_sel; - char version_str[MWIFIEX_MAX_VER_STR_LEN]; -}; - -struct mwifiex_bss_info { - u32 bss_mode; - struct cfg80211_ssid ssid; - u32 bss_chan; - u8 country_code[3]; - u32 media_connected; - u32 max_power_level; - u32 min_power_level; - u32 adhoc_state; - signed int bcn_nf_last; - u32 wep_status; - u32 is_hs_configured; - u32 is_deep_sleep; - u8 bssid[ETH_ALEN]; -}; - -#define MAX_NUM_TID 8 - -#define MAX_RX_WINSIZE 64 - -struct mwifiex_ds_rx_reorder_tbl { - u16 tid; - u8 ta[ETH_ALEN]; - u32 start_win; - u32 win_size; - u32 buffer[MAX_RX_WINSIZE]; -}; - -struct mwifiex_ds_tx_ba_stream_tbl { - u16 tid; - u8 ra[ETH_ALEN]; - u8 amsdu; -}; - -#define DBG_CMD_NUM 5 - -struct tdls_peer_info { - u8 peer_addr[ETH_ALEN]; -}; - -struct mwifiex_debug_info { - unsigned int debug_mask; - u32 int_counter; - u32 packets_out[MAX_NUM_TID]; - u32 tx_buf_size; - u32 curr_tx_buf_size; - u32 tx_tbl_num; - struct mwifiex_ds_tx_ba_stream_tbl - tx_tbl[MWIFIEX_MAX_TX_BASTREAM_SUPPORTED]; - u32 rx_tbl_num; - struct mwifiex_ds_rx_reorder_tbl rx_tbl - [MWIFIEX_MAX_RX_BASTREAM_SUPPORTED]; - u32 tdls_peer_num; - struct tdls_peer_info tdls_list - [MWIFIEX_MAX_TDLS_PEER_SUPPORTED]; - u16 ps_mode; - u32 ps_state; - u8 is_deep_sleep; - u8 pm_wakeup_card_req; - u32 pm_wakeup_fw_try; - u8 is_hs_configured; - u8 hs_activated; - u32 num_cmd_host_to_card_failure; - u32 num_cmd_sleep_cfm_host_to_card_failure; - u32 num_tx_host_to_card_failure; - u32 num_event_deauth; - u32 num_event_disassoc; - u32 num_event_link_lost; - u32 num_cmd_deauth; - u32 num_cmd_assoc_success; - u32 num_cmd_assoc_failure; - u32 num_tx_timeout; - u8 is_cmd_timedout; - u16 timeout_cmd_id; - u16 timeout_cmd_act; - u16 last_cmd_id[DBG_CMD_NUM]; - u16 last_cmd_act[DBG_CMD_NUM]; - u16 last_cmd_index; - u16 last_cmd_resp_id[DBG_CMD_NUM]; - u16 last_cmd_resp_index; - u16 last_event[DBG_CMD_NUM]; - u16 last_event_index; - u8 data_sent; - u8 cmd_sent; - u8 cmd_resp_received; - u8 event_received; -}; - -#define MWIFIEX_KEY_INDEX_UNICAST 0x40000000 -#define PN_LEN 16 - -struct mwifiex_ds_encrypt_key { - u32 key_disable; - u32 key_index; - u32 key_len; - u8 key_material[WLAN_MAX_KEY_LEN]; - u8 mac_addr[ETH_ALEN]; - u32 is_wapi_key; - u8 pn[PN_LEN]; /* packet number */ - u8 pn_len; - u8 is_igtk_key; - u8 is_current_wep_key; - u8 is_rx_seq_valid; -}; - -struct mwifiex_power_cfg { - u32 is_power_auto; - u32 power_level; -}; - -struct mwifiex_ds_hs_cfg { - u32 is_invoke_hostcmd; - /* Bit0: non-unicast data - * Bit1: unicast data - * Bit2: mac events - * Bit3: magic packet - */ - u32 conditions; - u32 gpio; - u32 gap; -}; - -#define DEEP_SLEEP_ON 1 -#define DEEP_SLEEP_OFF 0 -#define DEEP_SLEEP_IDLE_TIME 100 -#define PS_MODE_AUTO 1 - -struct mwifiex_ds_auto_ds { - u16 auto_ds; - u16 idle_time; -}; - -struct mwifiex_ds_pm_cfg { - union { - u32 ps_mode; - struct mwifiex_ds_hs_cfg hs_cfg; - struct mwifiex_ds_auto_ds auto_deep_sleep; - u32 sleep_period; - } param; -}; - -struct mwifiex_11ac_vht_cfg { - u8 band_config; - u8 misc_config; - u32 cap_info; - u32 mcs_tx_set; - u32 mcs_rx_set; -}; - -struct mwifiex_ds_11n_tx_cfg { - u16 tx_htcap; - u16 tx_htinfo; - u16 misc_config; /* Needed for 802.11AC cards only */ -}; - -struct mwifiex_ds_11n_amsdu_aggr_ctrl { - u16 enable; - u16 curr_buf_size; -}; - -struct mwifiex_ds_ant_cfg { - u32 tx_ant; - u32 rx_ant; -}; - -#define MWIFIEX_NUM_OF_CMD_BUFFER 50 -#define MWIFIEX_SIZE_OF_CMD_BUFFER 2048 - -enum { - MWIFIEX_IE_TYPE_GEN_IE = 0, - MWIFIEX_IE_TYPE_ARP_FILTER, -}; - -enum { - MWIFIEX_REG_MAC = 1, - MWIFIEX_REG_BBP, - MWIFIEX_REG_RF, - MWIFIEX_REG_PMIC, - MWIFIEX_REG_CAU, -}; - -struct mwifiex_ds_reg_rw { - __le32 type; - __le32 offset; - __le32 value; -}; - -#define MAX_EEPROM_DATA 256 - -struct mwifiex_ds_read_eeprom { - __le16 offset; - __le16 byte_count; - u8 value[MAX_EEPROM_DATA]; -}; - -struct mwifiex_ds_mem_rw { - u32 addr; - u32 value; -}; - -#define IEEE_MAX_IE_SIZE 256 - -#define MWIFIEX_IE_HDR_SIZE (sizeof(struct mwifiex_ie) - IEEE_MAX_IE_SIZE) - -struct mwifiex_ds_misc_gen_ie { - u32 type; - u32 len; - u8 ie_data[IEEE_MAX_IE_SIZE]; -}; - -struct mwifiex_ds_misc_cmd { - u32 len; - u8 cmd[MWIFIEX_SIZE_OF_CMD_BUFFER]; -}; - -#define BITMASK_BCN_RSSI_LOW BIT(0) -#define BITMASK_BCN_RSSI_HIGH BIT(4) - -enum subsc_evt_rssi_state { - EVENT_HANDLED, - RSSI_LOW_RECVD, - RSSI_HIGH_RECVD -}; - -struct subsc_evt_cfg { - u8 abs_value; - u8 evt_freq; -}; - -struct mwifiex_ds_misc_subsc_evt { - u16 action; - u16 events; - struct subsc_evt_cfg bcn_l_rssi_cfg; - struct subsc_evt_cfg bcn_h_rssi_cfg; -}; - -#define MWIFIEX_MEF_MAX_BYTESEQ 6 /* non-adjustable */ -#define MWIFIEX_MEF_MAX_FILTERS 10 - -struct mwifiex_mef_filter { - u16 repeat; - u16 offset; - s8 byte_seq[MWIFIEX_MEF_MAX_BYTESEQ + 1]; - u8 filt_type; - u8 filt_action; -}; - -struct mwifiex_mef_entry { - u8 mode; - u8 action; - struct mwifiex_mef_filter filter[MWIFIEX_MEF_MAX_FILTERS]; -}; - -struct mwifiex_ds_mef_cfg { - u32 criteria; - u16 num_entries; - struct mwifiex_mef_entry *mef_entry; -}; - -#define MWIFIEX_MAX_VSIE_LEN (256) -#define MWIFIEX_MAX_VSIE_NUM (8) -#define MWIFIEX_VSIE_MASK_CLEAR 0x00 -#define MWIFIEX_VSIE_MASK_SCAN 0x01 -#define MWIFIEX_VSIE_MASK_ASSOC 0x02 -#define MWIFIEX_VSIE_MASK_ADHOC 0x04 - -enum { - MWIFIEX_FUNC_INIT = 1, - MWIFIEX_FUNC_SHUTDOWN, -}; - -enum COALESCE_OPERATION { - RECV_FILTER_MATCH_TYPE_EQ = 0x80, - RECV_FILTER_MATCH_TYPE_NE, -}; - -enum COALESCE_PACKET_TYPE { - PACKET_TYPE_UNICAST = 1, - PACKET_TYPE_MULTICAST = 2, - PACKET_TYPE_BROADCAST = 3 -}; - -#define MWIFIEX_COALESCE_MAX_RULES 8 -#define MWIFIEX_COALESCE_MAX_BYTESEQ 4 /* non-adjustable */ -#define MWIFIEX_COALESCE_MAX_FILTERS 4 -#define MWIFIEX_MAX_COALESCING_DELAY 100 /* in msecs */ - -struct filt_field_param { - u8 operation; - u8 operand_len; - u16 offset; - u8 operand_byte_stream[MWIFIEX_COALESCE_MAX_BYTESEQ]; -}; - -struct mwifiex_coalesce_rule { - u16 max_coalescing_delay; - u8 num_of_fields; - u8 pkt_type; - struct filt_field_param params[MWIFIEX_COALESCE_MAX_FILTERS]; -}; - -struct mwifiex_ds_coalesce_cfg { - u16 num_of_rules; - struct mwifiex_coalesce_rule rule[MWIFIEX_COALESCE_MAX_RULES]; -}; - -struct mwifiex_ds_tdls_oper { - u16 tdls_action; - u8 peer_mac[ETH_ALEN]; - u16 capability; - u8 qos_info; - u8 *ext_capab; - u8 ext_capab_len; - u8 *supp_rates; - u8 supp_rates_len; - u8 *ht_capab; -}; - -#endif /* !_MWIFIEX_IOCTL_H_ */ diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c deleted file mode 100644 index 3cda1f956f0b..000000000000 --- a/drivers/net/wireless/mwifiex/join.c +++ /dev/null @@ -1,1525 +0,0 @@ -/* - * Marvell Wireless LAN device driver: association and ad-hoc start/join - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11ac.h" - -#define CAPINFO_MASK (~(BIT(15) | BIT(14) | BIT(12) | BIT(11) | BIT(9))) - -/* - * Append a generic IE as a pass through TLV to a TLV buffer. - * - * This function is called from the network join command preparation routine. - * - * If the IE buffer has been setup by the application, this routine appends - * the buffer as a pass through TLV type to the request. - */ -static int -mwifiex_cmd_append_generic_ie(struct mwifiex_private *priv, u8 **buffer) -{ - int ret_len = 0; - struct mwifiex_ie_types_header ie_header; - - /* Null Checks */ - if (!buffer) - return 0; - if (!(*buffer)) - return 0; - - /* - * If there is a generic ie buffer setup, append it to the return - * parameter buffer pointer. - */ - if (priv->gen_ie_buf_len) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: append generic ie len %d to %p\n", - __func__, priv->gen_ie_buf_len, *buffer); - - /* Wrap the generic IE buffer with a pass through TLV type */ - ie_header.type = cpu_to_le16(TLV_TYPE_PASSTHROUGH); - ie_header.len = cpu_to_le16(priv->gen_ie_buf_len); - memcpy(*buffer, &ie_header, sizeof(ie_header)); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += sizeof(ie_header); - ret_len += sizeof(ie_header); - - /* Copy the generic IE buffer to the output buffer, advance - pointer */ - memcpy(*buffer, priv->gen_ie_buf, priv->gen_ie_buf_len); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += priv->gen_ie_buf_len; - ret_len += priv->gen_ie_buf_len; - - /* Reset the generic IE buffer */ - priv->gen_ie_buf_len = 0; - } - - /* return the length appended to the buffer */ - return ret_len; -} - -/* - * Append TSF tracking info from the scan table for the target AP. - * - * This function is called from the network join command preparation routine. - * - * The TSF table TSF sent to the firmware contains two TSF values: - * - The TSF of the target AP from its previous beacon/probe response - * - The TSF timestamp of our local MAC at the time we observed the - * beacon/probe response. - * - * The firmware uses the timestamp values to set an initial TSF value - * in the MAC for the new association after a reassociation attempt. - */ -static int -mwifiex_cmd_append_tsf_tlv(struct mwifiex_private *priv, u8 **buffer, - struct mwifiex_bssdescriptor *bss_desc) -{ - struct mwifiex_ie_types_tsf_timestamp tsf_tlv; - __le64 tsf_val; - - /* Null Checks */ - if (buffer == NULL) - return 0; - if (*buffer == NULL) - return 0; - - memset(&tsf_tlv, 0x00, sizeof(struct mwifiex_ie_types_tsf_timestamp)); - - tsf_tlv.header.type = cpu_to_le16(TLV_TYPE_TSFTIMESTAMP); - tsf_tlv.header.len = cpu_to_le16(2 * sizeof(tsf_val)); - - memcpy(*buffer, &tsf_tlv, sizeof(tsf_tlv.header)); - *buffer += sizeof(tsf_tlv.header); - - /* TSF at the time when beacon/probe_response was received */ - tsf_val = cpu_to_le64(bss_desc->fw_tsf); - memcpy(*buffer, &tsf_val, sizeof(tsf_val)); - *buffer += sizeof(tsf_val); - - tsf_val = cpu_to_le64(bss_desc->timestamp); - - mwifiex_dbg(priv->adapter, INFO, - "info: %s: TSF offset calc: %016llx - %016llx\n", - __func__, bss_desc->timestamp, bss_desc->fw_tsf); - - memcpy(*buffer, &tsf_val, sizeof(tsf_val)); - *buffer += sizeof(tsf_val); - - return sizeof(tsf_tlv.header) + (2 * sizeof(tsf_val)); -} - -/* - * This function finds out the common rates between rate1 and rate2. - * - * It will fill common rates in rate1 as output if found. - * - * NOTE: Setting the MSB of the basic rates needs to be taken - * care of, either before or after calling this function. - */ -static int mwifiex_get_common_rates(struct mwifiex_private *priv, u8 *rate1, - u32 rate1_size, u8 *rate2, u32 rate2_size) -{ - int ret; - u8 *ptr = rate1, *tmp; - u32 i, j; - - tmp = kmemdup(rate1, rate1_size, GFP_KERNEL); - if (!tmp) { - mwifiex_dbg(priv->adapter, ERROR, "failed to alloc tmp buf\n"); - return -ENOMEM; - } - - memset(rate1, 0, rate1_size); - - for (i = 0; i < rate2_size && rate2[i]; i++) { - for (j = 0; j < rate1_size && tmp[j]; j++) { - /* Check common rate, excluding the bit for - basic rate */ - if ((rate2[i] & 0x7F) == (tmp[j] & 0x7F)) { - *rate1++ = tmp[j]; - break; - } - } - } - - mwifiex_dbg(priv->adapter, INFO, "info: Tx data rate set to %#x\n", - priv->data_rate); - - if (!priv->is_data_rate_auto) { - while (*ptr) { - if ((*ptr & 0x7f) == priv->data_rate) { - ret = 0; - goto done; - } - ptr++; - } - mwifiex_dbg(priv->adapter, ERROR, - "previously set fixed data rate %#x\t" - "is not compatible with the network\n", - priv->data_rate); - - ret = -1; - goto done; - } - - ret = 0; -done: - kfree(tmp); - return ret; -} - -/* - * This function creates the intersection of the rates supported by a - * target BSS and our adapter settings for use in an assoc/join command. - */ -static int -mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, - u8 *out_rates, u32 *out_rates_size) -{ - u8 card_rates[MWIFIEX_SUPPORTED_RATES]; - u32 card_rates_size; - - /* Copy AP supported rates */ - memcpy(out_rates, bss_desc->supported_rates, MWIFIEX_SUPPORTED_RATES); - /* Get the STA supported rates */ - card_rates_size = mwifiex_get_active_data_rates(priv, card_rates); - /* Get the common rates between AP and STA supported rates */ - if (mwifiex_get_common_rates(priv, out_rates, MWIFIEX_SUPPORTED_RATES, - card_rates, card_rates_size)) { - *out_rates_size = 0; - mwifiex_dbg(priv->adapter, ERROR, - "%s: cannot get common rates\n", - __func__); - return -1; - } - - *out_rates_size = - min_t(size_t, strlen(out_rates), MWIFIEX_SUPPORTED_RATES); - - return 0; -} - -/* - * This function appends a WPS IE. It is called from the network join command - * preparation routine. - * - * If the IE buffer has been setup by the application, this routine appends - * the buffer as a WPS TLV type to the request. - */ -static int -mwifiex_cmd_append_wps_ie(struct mwifiex_private *priv, u8 **buffer) -{ - int retLen = 0; - struct mwifiex_ie_types_header ie_header; - - if (!buffer || !*buffer) - return 0; - - /* - * If there is a wps ie buffer setup, append it to the return - * parameter buffer pointer. - */ - if (priv->wps_ie_len) { - mwifiex_dbg(priv->adapter, CMD, - "cmd: append wps ie %d to %p\n", - priv->wps_ie_len, *buffer); - - /* Wrap the generic IE buffer with a pass through TLV type */ - ie_header.type = cpu_to_le16(TLV_TYPE_MGMT_IE); - ie_header.len = cpu_to_le16(priv->wps_ie_len); - memcpy(*buffer, &ie_header, sizeof(ie_header)); - *buffer += sizeof(ie_header); - retLen += sizeof(ie_header); - - memcpy(*buffer, priv->wps_ie, priv->wps_ie_len); - *buffer += priv->wps_ie_len; - retLen += priv->wps_ie_len; - - } - - kfree(priv->wps_ie); - priv->wps_ie_len = 0; - return retLen; -} - -/* - * This function appends a WAPI IE. - * - * This function is called from the network join command preparation routine. - * - * If the IE buffer has been setup by the application, this routine appends - * the buffer as a WAPI TLV type to the request. - */ -static int -mwifiex_cmd_append_wapi_ie(struct mwifiex_private *priv, u8 **buffer) -{ - int retLen = 0; - struct mwifiex_ie_types_header ie_header; - - /* Null Checks */ - if (buffer == NULL) - return 0; - if (*buffer == NULL) - return 0; - - /* - * If there is a wapi ie buffer setup, append it to the return - * parameter buffer pointer. - */ - if (priv->wapi_ie_len) { - mwifiex_dbg(priv->adapter, CMD, - "cmd: append wapi ie %d to %p\n", - priv->wapi_ie_len, *buffer); - - /* Wrap the generic IE buffer with a pass through TLV type */ - ie_header.type = cpu_to_le16(TLV_TYPE_WAPI_IE); - ie_header.len = cpu_to_le16(priv->wapi_ie_len); - memcpy(*buffer, &ie_header, sizeof(ie_header)); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += sizeof(ie_header); - retLen += sizeof(ie_header); - - /* Copy the wapi IE buffer to the output buffer, advance - pointer */ - memcpy(*buffer, priv->wapi_ie, priv->wapi_ie_len); - - /* Increment the return size and the return buffer pointer - param */ - *buffer += priv->wapi_ie_len; - retLen += priv->wapi_ie_len; - - } - /* return the length appended to the buffer */ - return retLen; -} - -/* - * This function appends rsn ie tlv for wpa/wpa2 security modes. - * It is called from the network join command preparation routine. - */ -static int mwifiex_append_rsn_ie_wpa_wpa2(struct mwifiex_private *priv, - u8 **buffer) -{ - struct mwifiex_ie_types_rsn_param_set *rsn_ie_tlv; - int rsn_ie_len; - - if (!buffer || !(*buffer)) - return 0; - - rsn_ie_tlv = (struct mwifiex_ie_types_rsn_param_set *) (*buffer); - rsn_ie_tlv->header.type = cpu_to_le16((u16) priv->wpa_ie[0]); - rsn_ie_tlv->header.type = cpu_to_le16( - le16_to_cpu(rsn_ie_tlv->header.type) & 0x00FF); - rsn_ie_tlv->header.len = cpu_to_le16((u16) priv->wpa_ie[1]); - rsn_ie_tlv->header.len = cpu_to_le16(le16_to_cpu(rsn_ie_tlv->header.len) - & 0x00FF); - if (le16_to_cpu(rsn_ie_tlv->header.len) <= (sizeof(priv->wpa_ie) - 2)) - memcpy(rsn_ie_tlv->rsn_ie, &priv->wpa_ie[2], - le16_to_cpu(rsn_ie_tlv->header.len)); - else - return -1; - - rsn_ie_len = sizeof(rsn_ie_tlv->header) + - le16_to_cpu(rsn_ie_tlv->header.len); - *buffer += rsn_ie_len; - - return rsn_ie_len; -} - -/* - * This function prepares command for association. - * - * This sets the following parameters - - * - Peer MAC address - * - Listen interval - * - Beacon interval - * - Capability information - * - * ...and the following TLVs, as required - - * - SSID TLV - * - PHY TLV - * - SS TLV - * - Rates TLV - * - Authentication TLV - * - Channel TLV - * - WPA/WPA2 IE - * - 11n TLV - * - Vendor specific TLV - * - WMM TLV - * - WAPI IE - * - Generic IE - * - TSF TLV - * - * Preparation also includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_bssdescriptor *bss_desc) -{ - struct host_cmd_ds_802_11_associate *assoc = &cmd->params.associate; - struct mwifiex_ie_types_ssid_param_set *ssid_tlv; - struct mwifiex_ie_types_phy_param_set *phy_tlv; - struct mwifiex_ie_types_ss_param_set *ss_tlv; - struct mwifiex_ie_types_rates_param_set *rates_tlv; - struct mwifiex_ie_types_auth_type *auth_tlv; - struct mwifiex_ie_types_chan_list_param_set *chan_tlv; - u8 rates[MWIFIEX_SUPPORTED_RATES]; - u32 rates_size; - u16 tmp_cap; - u8 *pos; - int rsn_ie_len = 0; - - pos = (u8 *) assoc; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_ASSOCIATE); - - /* Save so we know which BSS Desc to use in the response handler */ - priv->attempted_bss_desc = bss_desc; - - memcpy(assoc->peer_sta_addr, - bss_desc->mac_address, sizeof(assoc->peer_sta_addr)); - pos += sizeof(assoc->peer_sta_addr); - - /* Set the listen interval */ - assoc->listen_interval = cpu_to_le16(priv->listen_interval); - /* Set the beacon period */ - assoc->beacon_period = cpu_to_le16(bss_desc->beacon_period); - - pos += sizeof(assoc->cap_info_bitmap); - pos += sizeof(assoc->listen_interval); - pos += sizeof(assoc->beacon_period); - pos += sizeof(assoc->dtim_period); - - ssid_tlv = (struct mwifiex_ie_types_ssid_param_set *) pos; - ssid_tlv->header.type = cpu_to_le16(WLAN_EID_SSID); - ssid_tlv->header.len = cpu_to_le16((u16) bss_desc->ssid.ssid_len); - memcpy(ssid_tlv->ssid, bss_desc->ssid.ssid, - le16_to_cpu(ssid_tlv->header.len)); - pos += sizeof(ssid_tlv->header) + le16_to_cpu(ssid_tlv->header.len); - - phy_tlv = (struct mwifiex_ie_types_phy_param_set *) pos; - phy_tlv->header.type = cpu_to_le16(WLAN_EID_DS_PARAMS); - phy_tlv->header.len = cpu_to_le16(sizeof(phy_tlv->fh_ds.ds_param_set)); - memcpy(&phy_tlv->fh_ds.ds_param_set, - &bss_desc->phy_param_set.ds_param_set.current_chan, - sizeof(phy_tlv->fh_ds.ds_param_set)); - pos += sizeof(phy_tlv->header) + le16_to_cpu(phy_tlv->header.len); - - ss_tlv = (struct mwifiex_ie_types_ss_param_set *) pos; - ss_tlv->header.type = cpu_to_le16(WLAN_EID_CF_PARAMS); - ss_tlv->header.len = cpu_to_le16(sizeof(ss_tlv->cf_ibss.cf_param_set)); - pos += sizeof(ss_tlv->header) + le16_to_cpu(ss_tlv->header.len); - - /* Get the common rates supported between the driver and the BSS Desc */ - if (mwifiex_setup_rates_from_bssdesc - (priv, bss_desc, rates, &rates_size)) - return -1; - - /* Save the data rates into Current BSS state structure */ - priv->curr_bss_params.num_of_rates = rates_size; - memcpy(&priv->curr_bss_params.data_rates, rates, rates_size); - - /* Setup the Rates TLV in the association command */ - rates_tlv = (struct mwifiex_ie_types_rates_param_set *) pos; - rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); - rates_tlv->header.len = cpu_to_le16((u16) rates_size); - memcpy(rates_tlv->rates, rates, rates_size); - pos += sizeof(rates_tlv->header) + rates_size; - mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_CMD: rates size = %d\n", - rates_size); - - /* Add the Authentication type to be used for Auth frames */ - auth_tlv = (struct mwifiex_ie_types_auth_type *) pos; - auth_tlv->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); - auth_tlv->header.len = cpu_to_le16(sizeof(auth_tlv->auth_type)); - if (priv->sec_info.wep_enabled) - auth_tlv->auth_type = cpu_to_le16( - (u16) priv->sec_info.authentication_mode); - else - auth_tlv->auth_type = cpu_to_le16(NL80211_AUTHTYPE_OPEN_SYSTEM); - - pos += sizeof(auth_tlv->header) + le16_to_cpu(auth_tlv->header.len); - - if (IS_SUPPORT_MULTI_BANDS(priv->adapter) && - !(ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && - (!bss_desc->disable_11n) && - (priv->adapter->config_bands & BAND_GN || - priv->adapter->config_bands & BAND_AN) && - (bss_desc->bcn_ht_cap) - ) - ) { - /* Append a channel TLV for the channel the attempted AP was - found on */ - chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); - - memset(chan_tlv->chan_scan_param, 0x00, - sizeof(struct mwifiex_chan_scan_param_set)); - chan_tlv->chan_scan_param[0].chan_number = - (bss_desc->phy_param_set.ds_param_set.current_chan); - mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Chan = %d\n", - chan_tlv->chan_scan_param[0].chan_number); - - chan_tlv->chan_scan_param[0].radio_type = - mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - - mwifiex_dbg(priv->adapter, INFO, "info: Assoc: TLV Band = %d\n", - chan_tlv->chan_scan_param[0].radio_type); - pos += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - } - - if (!priv->wps.session_enable) { - if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) - rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); - - if (rsn_ie_len == -1) - return -1; - } - - if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && - (!bss_desc->disable_11n) && - (priv->adapter->config_bands & BAND_GN || - priv->adapter->config_bands & BAND_AN)) - mwifiex_cmd_append_11n_tlv(priv, bss_desc, &pos); - - if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && - !bss_desc->disable_11n && !bss_desc->disable_11ac && - priv->adapter->config_bands & BAND_AAC) - mwifiex_cmd_append_11ac_tlv(priv, bss_desc, &pos); - - /* Append vendor specific IE TLV */ - mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_ASSOC, &pos); - - mwifiex_wmm_process_association_req(priv, &pos, &bss_desc->wmm_ie, - bss_desc->bcn_ht_cap); - if (priv->sec_info.wapi_enabled && priv->wapi_ie_len) - mwifiex_cmd_append_wapi_ie(priv, &pos); - - if (priv->wps.session_enable && priv->wps_ie_len) - mwifiex_cmd_append_wps_ie(priv, &pos); - - mwifiex_cmd_append_generic_ie(priv, &pos); - - mwifiex_cmd_append_tsf_tlv(priv, &pos, bss_desc); - - mwifiex_11h_process_join(priv, &pos, bss_desc); - - cmd->size = cpu_to_le16((u16) (pos - (u8 *) assoc) + S_DS_GEN); - - /* Set the Capability info at last */ - tmp_cap = bss_desc->cap_info_bitmap; - - if (priv->adapter->config_bands == BAND_B) - tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; - - tmp_cap &= CAPINFO_MASK; - mwifiex_dbg(priv->adapter, INFO, - "info: ASSOC_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", - tmp_cap, CAPINFO_MASK); - assoc->cap_info_bitmap = cpu_to_le16(tmp_cap); - - return 0; -} - -static const char *assoc_failure_reason_to_str(u16 cap_info) -{ - switch (cap_info) { - case CONNECT_ERR_AUTH_ERR_STA_FAILURE: - return "CONNECT_ERR_AUTH_ERR_STA_FAILURE"; - case CONNECT_ERR_AUTH_MSG_UNHANDLED: - return "CONNECT_ERR_AUTH_MSG_UNHANDLED"; - case CONNECT_ERR_ASSOC_ERR_TIMEOUT: - return "CONNECT_ERR_ASSOC_ERR_TIMEOUT"; - case CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED: - return "CONNECT_ERR_ASSOC_ERR_AUTH_REFUSED"; - case CONNECT_ERR_STA_FAILURE: - return "CONNECT_ERR_STA_FAILURE"; - } - - return "Unknown connect failure"; -} -/* - * Association firmware command response handler - * - * The response buffer for the association command has the following - * memory layout. - * - * For cases where an association response was not received (indicated - * by the CapInfo and AId field): - * - * .------------------------------------------------------------. - * | Header(4 * sizeof(t_u16)): Standard command response hdr | - * .------------------------------------------------------------. - * | cap_info/Error Return(t_u16): | - * | 0xFFFF(-1): Internal error | - * | 0xFFFE(-2): Authentication unhandled message | - * | 0xFFFD(-3): Authentication refused | - * | 0xFFFC(-4): Timeout waiting for AP response | - * .------------------------------------------------------------. - * | status_code(t_u16): | - * | If cap_info is -1: | - * | An internal firmware failure prevented the | - * | command from being processed. The status_code | - * | will be set to 1. | - * | | - * | If cap_info is -2: | - * | An authentication frame was received but was | - * | not handled by the firmware. IEEE Status | - * | code for the failure is returned. | - * | | - * | If cap_info is -3: | - * | An authentication frame was received and the | - * | status_code is the IEEE Status reported in the | - * | response. | - * | | - * | If cap_info is -4: | - * | (1) Association response timeout | - * | (2) Authentication response timeout | - * .------------------------------------------------------------. - * | a_id(t_u16): 0xFFFF | - * .------------------------------------------------------------. - * - * - * For cases where an association response was received, the IEEE - * standard association response frame is returned: - * - * .------------------------------------------------------------. - * | Header(4 * sizeof(t_u16)): Standard command response hdr | - * .------------------------------------------------------------. - * | cap_info(t_u16): IEEE Capability | - * .------------------------------------------------------------. - * | status_code(t_u16): IEEE Status Code | - * .------------------------------------------------------------. - * | a_id(t_u16): IEEE Association ID | - * .------------------------------------------------------------. - * | IEEE IEs(variable): Any received IEs comprising the | - * | remaining portion of a received | - * | association response frame. | - * .------------------------------------------------------------. - * - * For simplistic handling, the status_code field can be used to determine - * an association success (0) or failure (non-zero). - */ -int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - struct ieee_types_assoc_rsp *assoc_rsp; - struct mwifiex_bssdescriptor *bss_desc; - bool enable_data = true; - u16 cap_info, status_code, aid; - - assoc_rsp = (struct ieee_types_assoc_rsp *) &resp->params; - - cap_info = le16_to_cpu(assoc_rsp->cap_info_bitmap); - status_code = le16_to_cpu(assoc_rsp->status_code); - aid = le16_to_cpu(assoc_rsp->a_id); - - if ((aid & (BIT(15) | BIT(14))) != (BIT(15) | BIT(14))) - dev_err(priv->adapter->dev, - "invalid AID value 0x%x; bits 15:14 not set\n", - aid); - - aid &= ~(BIT(15) | BIT(14)); - - priv->assoc_rsp_size = min(le16_to_cpu(resp->size) - S_DS_GEN, - sizeof(priv->assoc_rsp_buf)); - - memcpy(priv->assoc_rsp_buf, &resp->params, priv->assoc_rsp_size); - - assoc_rsp->a_id = cpu_to_le16(aid); - - if (status_code) { - priv->adapter->dbg.num_cmd_assoc_failure++; - mwifiex_dbg(priv->adapter, ERROR, - "ASSOC_RESP: failed,\t" - "status code=%d err=%#x a_id=%#x\n", - status_code, cap_info, - le16_to_cpu(assoc_rsp->a_id)); - - mwifiex_dbg(priv->adapter, ERROR, "assoc failure: reason %s\n", - assoc_failure_reason_to_str(cap_info)); - if (cap_info == CONNECT_ERR_ASSOC_ERR_TIMEOUT) { - if (status_code == MWIFIEX_ASSOC_CMD_FAILURE_AUTH) { - ret = WLAN_STATUS_AUTH_TIMEOUT; - mwifiex_dbg(priv->adapter, ERROR, - "ASSOC_RESP: AUTH timeout\n"); - } else { - ret = WLAN_STATUS_UNSPECIFIED_FAILURE; - mwifiex_dbg(priv->adapter, ERROR, - "ASSOC_RESP: UNSPECIFIED failure\n"); - } - } else { - ret = status_code; - } - - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->media_connected = true; - - priv->adapter->ps_state = PS_STATE_AWAKE; - priv->adapter->pps_uapsd_mode = false; - priv->adapter->tx_lock_flag = false; - - /* Set the attempted BSSID Index to current */ - bss_desc = priv->attempted_bss_desc; - - mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: %s\n", - bss_desc->ssid.ssid); - - /* Make a copy of current BSSID descriptor */ - memcpy(&priv->curr_bss_params.bss_descriptor, - bss_desc, sizeof(struct mwifiex_bssdescriptor)); - - /* Update curr_bss_params */ - priv->curr_bss_params.bss_descriptor.channel - = bss_desc->phy_param_set.ds_param_set.current_chan; - - priv->curr_bss_params.band = (u8) bss_desc->bss_band; - - if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) - priv->curr_bss_params.wmm_enabled = true; - else - priv->curr_bss_params.wmm_enabled = false; - - if ((priv->wmm_required || bss_desc->bcn_ht_cap) && - priv->curr_bss_params.wmm_enabled) - priv->wmm_enabled = true; - else - priv->wmm_enabled = false; - - priv->curr_bss_params.wmm_uapsd_enabled = false; - - if (priv->wmm_enabled) - priv->curr_bss_params.wmm_uapsd_enabled - = ((bss_desc->wmm_ie.qos_info_bitmap & - IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) ? 1 : 0); - - mwifiex_dbg(priv->adapter, INFO, - "info: ASSOC_RESP: curr_pkt_filter is %#x\n", - priv->curr_pkt_filter); - if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) - priv->wpa_is_gtk_set = false; - - if (priv->wmm_enabled) { - /* Don't re-enable carrier until we get the WMM_GET_STATUS - event */ - enable_data = false; - } else { - /* Since WMM is not enabled, setup the queues with the - defaults */ - mwifiex_wmm_setup_queue_priorities(priv, NULL); - mwifiex_wmm_setup_ac_downgrade(priv); - } - - if (enable_data) - mwifiex_dbg(priv->adapter, INFO, - "info: post association, re-enabling data flow\n"); - - /* Reset SNR/NF/RSSI values */ - priv->data_rssi_last = 0; - priv->data_nf_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->bcn_rssi_last = 0; - priv->bcn_nf_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - priv->rxpd_rate = 0; - priv->rxpd_htinfo = 0; - - mwifiex_save_curr_bcn(priv); - - priv->adapter->dbg.num_cmd_assoc_success++; - - mwifiex_dbg(priv->adapter, INFO, "info: ASSOC_RESP: associated\n"); - - /* Add the ra_list here for infra mode as there will be only 1 ra - always */ - mwifiex_ralist_add(priv, - priv->curr_bss_params.bss_descriptor.mac_address); - - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); - - if (priv->sec_info.wpa_enabled || priv->sec_info.wpa2_enabled) - priv->scan_block = true; - else - priv->port_open = true; - -done: - /* Need to indicate IOCTL complete */ - if (adapter->curr_cmd->wait_q_enabled) { - if (ret) - adapter->cmd_wait_q.status = -1; - else - adapter->cmd_wait_q.status = 0; - } - - return ret; -} - -/* - * This function prepares command for ad-hoc start. - * - * Driver will fill up SSID, BSS mode, IBSS parameters, physical - * parameters, probe delay, and capability information. Firmware - * will fill up beacon period, basic rates and operational rates. - * - * In addition, the following TLVs are added - - * - Channel TLV - * - Vendor specific IE - * - WPA/WPA2 IE - * - HT Capabilities IE - * - HT Information IE - * - * Preparation also includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -int -mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct cfg80211_ssid *req_ssid) -{ - int rsn_ie_len = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ad_hoc_start *adhoc_start = - &cmd->params.adhoc_start; - struct mwifiex_bssdescriptor *bss_desc; - u32 cmd_append_size = 0; - u32 i; - u16 tmp_cap; - struct mwifiex_ie_types_chan_list_param_set *chan_tlv; - u8 radio_type; - - struct mwifiex_ie_types_htcap *ht_cap; - struct mwifiex_ie_types_htinfo *ht_info; - u8 *pos = (u8 *) adhoc_start + - sizeof(struct host_cmd_ds_802_11_ad_hoc_start); - - if (!adapter) - return -1; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_START); - - bss_desc = &priv->curr_bss_params.bss_descriptor; - priv->attempted_bss_desc = bss_desc; - - /* - * Fill in the parameters for 2 data structures: - * 1. struct host_cmd_ds_802_11_ad_hoc_start command - * 2. bss_desc - * Driver will fill up SSID, bss_mode,IBSS param, Physical Param, - * probe delay, and Cap info. - * Firmware will fill up beacon period, Basic rates - * and operational rates. - */ - - memset(adhoc_start->ssid, 0, IEEE80211_MAX_SSID_LEN); - - memcpy(adhoc_start->ssid, req_ssid->ssid, req_ssid->ssid_len); - - mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: SSID = %s\n", - adhoc_start->ssid); - - memset(bss_desc->ssid.ssid, 0, IEEE80211_MAX_SSID_LEN); - memcpy(bss_desc->ssid.ssid, req_ssid->ssid, req_ssid->ssid_len); - - bss_desc->ssid.ssid_len = req_ssid->ssid_len; - - /* Set the BSS mode */ - adhoc_start->bss_mode = HostCmd_BSS_MODE_IBSS; - bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; - adhoc_start->beacon_period = cpu_to_le16(priv->beacon_period); - bss_desc->beacon_period = priv->beacon_period; - - /* Set Physical param set */ -/* Parameter IE Id */ -#define DS_PARA_IE_ID 3 -/* Parameter IE length */ -#define DS_PARA_IE_LEN 1 - - adhoc_start->phy_param_set.ds_param_set.element_id = DS_PARA_IE_ID; - adhoc_start->phy_param_set.ds_param_set.len = DS_PARA_IE_LEN; - - if (!mwifiex_get_cfp(priv, adapter->adhoc_start_band, - (u16) priv->adhoc_channel, 0)) { - struct mwifiex_chan_freq_power *cfp; - cfp = mwifiex_get_cfp(priv, adapter->adhoc_start_band, - FIRST_VALID_CHANNEL, 0); - if (cfp) - priv->adhoc_channel = (u8) cfp->channel; - } - - if (!priv->adhoc_channel) { - mwifiex_dbg(adapter, ERROR, - "ADHOC_S_CMD: adhoc_channel cannot be 0\n"); - return -1; - } - - mwifiex_dbg(adapter, INFO, - "info: ADHOC_S_CMD: creating ADHOC on channel %d\n", - priv->adhoc_channel); - - priv->curr_bss_params.bss_descriptor.channel = priv->adhoc_channel; - priv->curr_bss_params.band = adapter->adhoc_start_band; - - bss_desc->channel = priv->adhoc_channel; - adhoc_start->phy_param_set.ds_param_set.current_chan = - priv->adhoc_channel; - - memcpy(&bss_desc->phy_param_set, &adhoc_start->phy_param_set, - sizeof(union ieee_types_phy_param_set)); - - /* Set IBSS param set */ -/* IBSS parameter IE Id */ -#define IBSS_PARA_IE_ID 6 -/* IBSS parameter IE length */ -#define IBSS_PARA_IE_LEN 2 - - adhoc_start->ss_param_set.ibss_param_set.element_id = IBSS_PARA_IE_ID; - adhoc_start->ss_param_set.ibss_param_set.len = IBSS_PARA_IE_LEN; - adhoc_start->ss_param_set.ibss_param_set.atim_window - = cpu_to_le16(priv->atim_window); - memcpy(&bss_desc->ss_param_set, &adhoc_start->ss_param_set, - sizeof(union ieee_types_ss_param_set)); - - /* Set Capability info */ - bss_desc->cap_info_bitmap |= WLAN_CAPABILITY_IBSS; - tmp_cap = WLAN_CAPABILITY_IBSS; - - /* Set up privacy in bss_desc */ - if (priv->sec_info.encryption_mode) { - /* Ad-Hoc capability privacy on */ - mwifiex_dbg(adapter, INFO, - "info: ADHOC_S_CMD: wep_status set privacy to WEP\n"); - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; - tmp_cap |= WLAN_CAPABILITY_PRIVACY; - } else { - mwifiex_dbg(adapter, INFO, - "info: ADHOC_S_CMD: wep_status NOT set,\t" - "setting privacy to ACCEPT ALL\n"); - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; - } - - memset(adhoc_start->data_rate, 0, sizeof(adhoc_start->data_rate)); - mwifiex_get_active_data_rates(priv, adhoc_start->data_rate); - if ((adapter->adhoc_start_band & BAND_G) && - (priv->curr_pkt_filter & HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON)) { - if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter, false)) { - mwifiex_dbg(adapter, ERROR, - "ADHOC_S_CMD: G Protection config failed\n"); - return -1; - } - } - /* Find the last non zero */ - for (i = 0; i < sizeof(adhoc_start->data_rate); i++) - if (!adhoc_start->data_rate[i]) - break; - - priv->curr_bss_params.num_of_rates = i; - - /* Copy the ad-hoc creating rates into Current BSS rate structure */ - memcpy(&priv->curr_bss_params.data_rates, - &adhoc_start->data_rate, priv->curr_bss_params.num_of_rates); - - mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: rates=%4ph\n", - adhoc_start->data_rate); - - mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: AD-HOC Start command is ready\n"); - - if (IS_SUPPORT_MULTI_BANDS(adapter)) { - /* Append a channel TLV */ - chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); - - memset(chan_tlv->chan_scan_param, 0x00, - sizeof(struct mwifiex_chan_scan_param_set)); - chan_tlv->chan_scan_param[0].chan_number = - (u8) priv->curr_bss_params.bss_descriptor.channel; - - mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Chan = %d\n", - chan_tlv->chan_scan_param[0].chan_number); - - chan_tlv->chan_scan_param[0].radio_type - = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - if (adapter->adhoc_start_band & BAND_GN || - adapter->adhoc_start_band & BAND_AN) { - if (adapter->sec_chan_offset == - IEEE80211_HT_PARAM_CHA_SEC_ABOVE) - chan_tlv->chan_scan_param[0].radio_type |= - (IEEE80211_HT_PARAM_CHA_SEC_ABOVE << 4); - else if (adapter->sec_chan_offset == - IEEE80211_HT_PARAM_CHA_SEC_BELOW) - chan_tlv->chan_scan_param[0].radio_type |= - (IEEE80211_HT_PARAM_CHA_SEC_BELOW << 4); - } - mwifiex_dbg(adapter, INFO, "info: ADHOC_S_CMD: TLV Band = %d\n", - chan_tlv->chan_scan_param[0].radio_type); - pos += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - cmd_append_size += - sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - } - - /* Append vendor specific IE TLV */ - cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, - MWIFIEX_VSIE_MASK_ADHOC, &pos); - - if (priv->sec_info.wpa_enabled) { - rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); - if (rsn_ie_len == -1) - return -1; - cmd_append_size += rsn_ie_len; - } - - if (adapter->adhoc_11n_enabled) { - /* Fill HT CAPABILITY */ - ht_cap = (struct mwifiex_ie_types_htcap *) pos; - memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); - ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - radio_type = mwifiex_band_to_radio_type( - priv->adapter->config_bands); - mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); - - if (adapter->sec_chan_offset == - IEEE80211_HT_PARAM_CHA_SEC_NONE) { - u16 tmp_ht_cap; - - tmp_ht_cap = le16_to_cpu(ht_cap->ht_cap.cap_info); - tmp_ht_cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; - tmp_ht_cap &= ~IEEE80211_HT_CAP_SGI_40; - ht_cap->ht_cap.cap_info = cpu_to_le16(tmp_ht_cap); - } - - pos += sizeof(struct mwifiex_ie_types_htcap); - cmd_append_size += sizeof(struct mwifiex_ie_types_htcap); - - /* Fill HT INFORMATION */ - ht_info = (struct mwifiex_ie_types_htinfo *) pos; - memset(ht_info, 0, sizeof(struct mwifiex_ie_types_htinfo)); - ht_info->header.type = cpu_to_le16(WLAN_EID_HT_OPERATION); - ht_info->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_operation)); - - ht_info->ht_oper.primary_chan = - (u8) priv->curr_bss_params.bss_descriptor.channel; - if (adapter->sec_chan_offset) { - ht_info->ht_oper.ht_param = adapter->sec_chan_offset; - ht_info->ht_oper.ht_param |= - IEEE80211_HT_PARAM_CHAN_WIDTH_ANY; - } - ht_info->ht_oper.operation_mode = - cpu_to_le16(IEEE80211_HT_OP_MODE_NON_GF_STA_PRSNT); - ht_info->ht_oper.basic_set[0] = 0xff; - pos += sizeof(struct mwifiex_ie_types_htinfo); - cmd_append_size += - sizeof(struct mwifiex_ie_types_htinfo); - } - - cmd->size = - cpu_to_le16((u16)(sizeof(struct host_cmd_ds_802_11_ad_hoc_start) - + S_DS_GEN + cmd_append_size)); - - if (adapter->adhoc_start_band == BAND_B) - tmp_cap &= ~WLAN_CAPABILITY_SHORT_SLOT_TIME; - else - tmp_cap |= WLAN_CAPABILITY_SHORT_SLOT_TIME; - - adhoc_start->cap_info_bitmap = cpu_to_le16(tmp_cap); - - return 0; -} - -/* - * This function prepares command for ad-hoc join. - * - * Most of the parameters are set up by copying from the target BSS descriptor - * from the scan response. - * - * In addition, the following TLVs are added - - * - Channel TLV - * - Vendor specific IE - * - WPA/WPA2 IE - * - 11n IE - * - * Preparation also includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -int -mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_bssdescriptor *bss_desc) -{ - int rsn_ie_len = 0; - struct host_cmd_ds_802_11_ad_hoc_join *adhoc_join = - &cmd->params.adhoc_join; - struct mwifiex_ie_types_chan_list_param_set *chan_tlv; - u32 cmd_append_size = 0; - u16 tmp_cap; - u32 i, rates_size = 0; - u16 curr_pkt_filter; - u8 *pos = - (u8 *) adhoc_join + - sizeof(struct host_cmd_ds_802_11_ad_hoc_join); - -/* Use G protection */ -#define USE_G_PROTECTION 0x02 - if (bss_desc->erp_flags & USE_G_PROTECTION) { - curr_pkt_filter = - priv-> - curr_pkt_filter | HostCmd_ACT_MAC_ADHOC_G_PROTECTION_ON; - - if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &curr_pkt_filter, false)) { - mwifiex_dbg(priv->adapter, ERROR, - "ADHOC_J_CMD: G Protection config failed\n"); - return -1; - } - } - - priv->attempted_bss_desc = bss_desc; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_JOIN); - - adhoc_join->bss_descriptor.bss_mode = HostCmd_BSS_MODE_IBSS; - - adhoc_join->bss_descriptor.beacon_period - = cpu_to_le16(bss_desc->beacon_period); - - memcpy(&adhoc_join->bss_descriptor.bssid, - &bss_desc->mac_address, ETH_ALEN); - - memcpy(&adhoc_join->bss_descriptor.ssid, - &bss_desc->ssid.ssid, bss_desc->ssid.ssid_len); - - memcpy(&adhoc_join->bss_descriptor.phy_param_set, - &bss_desc->phy_param_set, - sizeof(union ieee_types_phy_param_set)); - - memcpy(&adhoc_join->bss_descriptor.ss_param_set, - &bss_desc->ss_param_set, sizeof(union ieee_types_ss_param_set)); - - tmp_cap = bss_desc->cap_info_bitmap; - - tmp_cap &= CAPINFO_MASK; - - mwifiex_dbg(priv->adapter, INFO, - "info: ADHOC_J_CMD: tmp_cap=%4X CAPINFO_MASK=%4lX\n", - tmp_cap, CAPINFO_MASK); - - /* Information on BSSID descriptor passed to FW */ - mwifiex_dbg(priv->adapter, INFO, - "info: ADHOC_J_CMD: BSSID=%pM, SSID='%s'\n", - adhoc_join->bss_descriptor.bssid, - adhoc_join->bss_descriptor.ssid); - - for (i = 0; i < MWIFIEX_SUPPORTED_RATES && - bss_desc->supported_rates[i]; i++) - ; - rates_size = i; - - /* Copy Data Rates from the Rates recorded in scan response */ - memset(adhoc_join->bss_descriptor.data_rates, 0, - sizeof(adhoc_join->bss_descriptor.data_rates)); - memcpy(adhoc_join->bss_descriptor.data_rates, - bss_desc->supported_rates, rates_size); - - /* Copy the adhoc join rates into Current BSS state structure */ - priv->curr_bss_params.num_of_rates = rates_size; - memcpy(&priv->curr_bss_params.data_rates, bss_desc->supported_rates, - rates_size); - - /* Copy the channel information */ - priv->curr_bss_params.bss_descriptor.channel = bss_desc->channel; - priv->curr_bss_params.band = (u8) bss_desc->bss_band; - - if (priv->sec_info.wep_enabled || priv->sec_info.wpa_enabled) - tmp_cap |= WLAN_CAPABILITY_PRIVACY; - - if (IS_SUPPORT_MULTI_BANDS(priv->adapter)) { - /* Append a channel TLV */ - chan_tlv = (struct mwifiex_ie_types_chan_list_param_set *) pos; - chan_tlv->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - chan_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_chan_scan_param_set)); - - memset(chan_tlv->chan_scan_param, 0x00, - sizeof(struct mwifiex_chan_scan_param_set)); - chan_tlv->chan_scan_param[0].chan_number = - (bss_desc->phy_param_set.ds_param_set.current_chan); - mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Chan=%d\n", - chan_tlv->chan_scan_param[0].chan_number); - - chan_tlv->chan_scan_param[0].radio_type = - mwifiex_band_to_radio_type((u8) bss_desc->bss_band); - - mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_J_CMD: TLV Band=%d\n", - chan_tlv->chan_scan_param[0].radio_type); - pos += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - cmd_append_size += sizeof(chan_tlv->header) + - sizeof(struct mwifiex_chan_scan_param_set); - } - - if (priv->sec_info.wpa_enabled) - rsn_ie_len = mwifiex_append_rsn_ie_wpa_wpa2(priv, &pos); - if (rsn_ie_len == -1) - return -1; - cmd_append_size += rsn_ie_len; - - if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) - cmd_append_size += mwifiex_cmd_append_11n_tlv(priv, - bss_desc, &pos); - - /* Append vendor specific IE TLV */ - cmd_append_size += mwifiex_cmd_append_vsie_tlv(priv, - MWIFIEX_VSIE_MASK_ADHOC, &pos); - - cmd->size = cpu_to_le16 - ((u16) (sizeof(struct host_cmd_ds_802_11_ad_hoc_join) - + S_DS_GEN + cmd_append_size)); - - adhoc_join->bss_descriptor.cap_info_bitmap = cpu_to_le16(tmp_cap); - - return 0; -} - -/* - * This function handles the command response of ad-hoc start and - * ad-hoc join. - * - * The function generates a device-connected event to notify - * the applications, in case of successful ad-hoc start/join, and - * saves the beacon buffer. - */ -int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ad_hoc_result *adhoc_result; - struct mwifiex_bssdescriptor *bss_desc; - u16 reason_code; - - adhoc_result = &resp->params.adhoc_result; - - bss_desc = priv->attempted_bss_desc; - - /* Join result code 0 --> SUCCESS */ - reason_code = le16_to_cpu(resp->result); - if (reason_code) { - mwifiex_dbg(priv->adapter, ERROR, "ADHOC_RESP: failed\n"); - if (priv->media_connected) - mwifiex_reset_connect_state(priv, reason_code); - - memset(&priv->curr_bss_params.bss_descriptor, - 0x00, sizeof(struct mwifiex_bssdescriptor)); - - ret = -1; - goto done; - } - - /* Send a Media Connected event, according to the Spec */ - priv->media_connected = true; - - if (le16_to_cpu(resp->command) == HostCmd_CMD_802_11_AD_HOC_START) { - mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_S_RESP %s\n", - bss_desc->ssid.ssid); - - /* Update the created network descriptor with the new BSSID */ - memcpy(bss_desc->mac_address, - adhoc_result->bssid, ETH_ALEN); - - priv->adhoc_state = ADHOC_STARTED; - } else { - /* - * Now the join cmd should be successful. - * If BSSID has changed use SSID to compare instead of BSSID - */ - mwifiex_dbg(priv->adapter, INFO, - "info: ADHOC_J_RESP %s\n", - bss_desc->ssid.ssid); - - /* - * Make a copy of current BSSID descriptor, only needed for - * join since the current descriptor is already being used - * for adhoc start - */ - memcpy(&priv->curr_bss_params.bss_descriptor, - bss_desc, sizeof(struct mwifiex_bssdescriptor)); - - priv->adhoc_state = ADHOC_JOINED; - } - - mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: channel = %d\n", - priv->adhoc_channel); - mwifiex_dbg(priv->adapter, INFO, "info: ADHOC_RESP: BSSID = %pM\n", - priv->curr_bss_params.bss_descriptor.mac_address); - - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); - - mwifiex_save_curr_bcn(priv); - -done: - /* Need to indicate IOCTL complete */ - if (adapter->curr_cmd->wait_q_enabled) { - if (ret) - adapter->cmd_wait_q.status = -1; - else - adapter->cmd_wait_q.status = 0; - - } - - return ret; -} - -/* - * This function associates to a specific BSS discovered in a scan. - * - * It clears any past association response stored for application - * retrieval and calls the command preparation routine to send the - * command to firmware. - */ -int mwifiex_associate(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - /* Return error if the adapter is not STA role or table entry - * is not marked as infra. - */ - if ((GET_BSS_ROLE(priv) != MWIFIEX_BSS_ROLE_STA) || - (bss_desc->bss_mode != NL80211_IFTYPE_STATION)) - return -1; - - if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && - !bss_desc->disable_11n && !bss_desc->disable_11ac && - priv->adapter->config_bands & BAND_AAC) - mwifiex_set_11ac_ba_params(priv); - else - mwifiex_set_ba_params(priv); - - /* Clear any past association response stored for application - retrieval */ - priv->assoc_rsp_size = 0; - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_ASSOCIATE, - HostCmd_ACT_GEN_SET, 0, bss_desc, true); -} - -/* - * This function starts an ad-hoc network. - * - * It calls the command preparation routine to send the command to firmware. - */ -int -mwifiex_adhoc_start(struct mwifiex_private *priv, - struct cfg80211_ssid *adhoc_ssid) -{ - mwifiex_dbg(priv->adapter, INFO, "info: Adhoc Channel = %d\n", - priv->adhoc_channel); - mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.channel = %d\n", - priv->curr_bss_params.bss_descriptor.channel); - mwifiex_dbg(priv->adapter, INFO, "info: curr_bss_params.band = %d\n", - priv->curr_bss_params.band); - - if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && - priv->adapter->config_bands & BAND_AAC) - mwifiex_set_11ac_ba_params(priv); - else - mwifiex_set_ba_params(priv); - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_START, - HostCmd_ACT_GEN_SET, 0, adhoc_ssid, true); -} - -/* - * This function joins an ad-hoc network found in a previous scan. - * - * It calls the command preparation routine to send the command to firmware, - * if already not connected to the requested SSID. - */ -int mwifiex_adhoc_join(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - mwifiex_dbg(priv->adapter, INFO, - "info: adhoc join: curr_bss ssid =%s\n", - priv->curr_bss_params.bss_descriptor.ssid.ssid); - mwifiex_dbg(priv->adapter, INFO, - "info: adhoc join: curr_bss ssid_len =%u\n", - priv->curr_bss_params.bss_descriptor.ssid.ssid_len); - mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid =%s\n", - bss_desc->ssid.ssid); - mwifiex_dbg(priv->adapter, INFO, "info: adhoc join: ssid_len =%u\n", - bss_desc->ssid.ssid_len); - - /* Check if the requested SSID is already joined */ - if (priv->curr_bss_params.bss_descriptor.ssid.ssid_len && - !mwifiex_ssid_cmp(&bss_desc->ssid, - &priv->curr_bss_params.bss_descriptor.ssid) && - (priv->curr_bss_params.bss_descriptor.bss_mode == - NL80211_IFTYPE_ADHOC)) { - mwifiex_dbg(priv->adapter, INFO, - "info: ADHOC_J_CMD: new ad-hoc SSID\t" - "is the same as current; not attempting to re-join\n"); - return -1; - } - - if (ISSUPP_11ACENABLED(priv->adapter->fw_cap_info) && - !bss_desc->disable_11n && !bss_desc->disable_11ac && - priv->adapter->config_bands & BAND_AAC) - mwifiex_set_11ac_ba_params(priv); - else - mwifiex_set_ba_params(priv); - - mwifiex_dbg(priv->adapter, INFO, - "info: curr_bss_params.channel = %d\n", - priv->curr_bss_params.bss_descriptor.channel); - mwifiex_dbg(priv->adapter, INFO, - "info: curr_bss_params.band = %c\n", - priv->curr_bss_params.band); - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_JOIN, - HostCmd_ACT_GEN_SET, 0, bss_desc, true); -} - -/* - * This function deauthenticates/disconnects from infra network by sending - * deauthentication request. - */ -static int mwifiex_deauthenticate_infra(struct mwifiex_private *priv, u8 *mac) -{ - u8 mac_address[ETH_ALEN]; - int ret; - - if (!mac || is_zero_ether_addr(mac)) - memcpy(mac_address, - priv->curr_bss_params.bss_descriptor.mac_address, - ETH_ALEN); - else - memcpy(mac_address, mac, ETH_ALEN); - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, - HostCmd_ACT_GEN_SET, 0, mac_address, true); - - return ret; -} - -/* - * This function deauthenticates/disconnects from a BSS. - * - * In case of infra made, it sends deauthentication request, and - * in case of ad-hoc mode, a stop network request is sent to the firmware. - * In AP mode, a command to stop bss is sent to firmware. - */ -int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac) -{ - int ret = 0; - - if (!priv->media_connected) - return 0; - - switch (priv->bss_mode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_P2P_CLIENT: - ret = mwifiex_deauthenticate_infra(priv, mac); - if (ret) - cfg80211_disconnected(priv->netdev, 0, NULL, 0, - true, GFP_KERNEL); - break; - case NL80211_IFTYPE_ADHOC: - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_AD_HOC_STOP, - HostCmd_ACT_GEN_SET, 0, NULL, true); - case NL80211_IFTYPE_AP: - return mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_STOP, - HostCmd_ACT_GEN_SET, 0, NULL, true); - default: - break; - } - - return ret; -} - -/* This function deauthenticates/disconnects from all BSS. */ -void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - int i; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) - mwifiex_deauthenticate(priv, NULL); - } -} -EXPORT_SYMBOL_GPL(mwifiex_deauthenticate_all); - -/* - * This function converts band to radio type used in channel TLV. - */ -u8 -mwifiex_band_to_radio_type(u8 band) -{ - switch (band) { - case BAND_A: - case BAND_AN: - case BAND_A | BAND_AN: - case BAND_A | BAND_AN | BAND_AAC: - return HostCmd_SCAN_RADIO_TYPE_A; - case BAND_B: - case BAND_G: - case BAND_B | BAND_G: - default: - return HostCmd_SCAN_RADIO_TYPE_BG; - } -} diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c deleted file mode 100644 index 969ca1e1f3e9..000000000000 --- a/drivers/net/wireless/mwifiex/main.c +++ /dev/null @@ -1,1552 +0,0 @@ -/* - * Marvell Wireless LAN device driver: major functions - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" -#include "wmm.h" -#include "cfg80211.h" -#include "11n.h" - -#define VERSION "1.0" - -static unsigned int debug_mask = MWIFIEX_DEFAULT_DEBUG_MASK; -module_param(debug_mask, uint, 0); -MODULE_PARM_DESC(debug_mask, "bitmap for debug flags"); - -const char driver_version[] = "mwifiex " VERSION " (%s) "; -static char *cal_data_cfg; -module_param(cal_data_cfg, charp, 0); - -static unsigned short driver_mode; -module_param(driver_mode, ushort, 0); -MODULE_PARM_DESC(driver_mode, - "station=0x1(default), ap-sta=0x3, station-p2p=0x5, ap-sta-p2p=0x7"); - -/* - * This function registers the device and performs all the necessary - * initializations. - * - * The following initialization operations are performed - - * - Allocate adapter structure - * - Save interface specific operations table in adapter - * - Call interface specific initialization routine - * - Allocate private structures - * - Set default adapter structure parameters - * - Initialize locks - * - * In case of any errors during inittialization, this function also ensures - * proper cleanup before exiting. - */ -static int mwifiex_register(void *card, struct mwifiex_if_ops *if_ops, - void **padapter) -{ - struct mwifiex_adapter *adapter; - int i; - - adapter = kzalloc(sizeof(struct mwifiex_adapter), GFP_KERNEL); - if (!adapter) - return -ENOMEM; - - *padapter = adapter; - adapter->card = card; - - /* Save interface specific operations in adapter */ - memmove(&adapter->if_ops, if_ops, sizeof(struct mwifiex_if_ops)); - adapter->debug_mask = debug_mask; - - /* card specific initialization has been deferred until now .. */ - if (adapter->if_ops.init_if) - if (adapter->if_ops.init_if(adapter)) - goto error; - - adapter->priv_num = 0; - - for (i = 0; i < MWIFIEX_MAX_BSS_NUM; i++) { - /* Allocate memory for private structure */ - adapter->priv[i] = - kzalloc(sizeof(struct mwifiex_private), GFP_KERNEL); - if (!adapter->priv[i]) - goto error; - - adapter->priv[i]->adapter = adapter; - adapter->priv_num++; - } - mwifiex_init_lock_list(adapter); - - setup_timer(&adapter->cmd_timer, mwifiex_cmd_timeout_func, - (unsigned long)adapter); - - return 0; - -error: - mwifiex_dbg(adapter, ERROR, - "info: leave mwifiex_register with error\n"); - - for (i = 0; i < adapter->priv_num; i++) - kfree(adapter->priv[i]); - - kfree(adapter); - - return -1; -} - -/* - * This function unregisters the device and performs all the necessary - * cleanups. - * - * The following cleanup operations are performed - - * - Free the timers - * - Free beacon buffers - * - Free private structures - * - Free adapter structure - */ -static int mwifiex_unregister(struct mwifiex_adapter *adapter) -{ - s32 i; - - if (adapter->if_ops.cleanup_if) - adapter->if_ops.cleanup_if(adapter); - - del_timer_sync(&adapter->cmd_timer); - - /* Free private structures */ - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - mwifiex_free_curr_bcn(adapter->priv[i]); - kfree(adapter->priv[i]); - } - } - - vfree(adapter->chan_stats); - kfree(adapter); - return 0; -} - -void mwifiex_queue_main_work(struct mwifiex_adapter *adapter) -{ - unsigned long flags; - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - if (adapter->mwifiex_processing) { - adapter->more_task_flag = true; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - } else { - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - queue_work(adapter->workqueue, &adapter->main_work); - } -} -EXPORT_SYMBOL_GPL(mwifiex_queue_main_work); - -static void mwifiex_queue_rx_work(struct mwifiex_adapter *adapter) -{ - unsigned long flags; - - spin_lock_irqsave(&adapter->rx_proc_lock, flags); - if (adapter->rx_processing) { - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - } else { - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - queue_work(adapter->rx_workqueue, &adapter->rx_work); - } -} - -static int mwifiex_process_rx(struct mwifiex_adapter *adapter) -{ - unsigned long flags; - struct sk_buff *skb; - struct mwifiex_rxinfo *rx_info; - - spin_lock_irqsave(&adapter->rx_proc_lock, flags); - if (adapter->rx_processing || adapter->rx_locked) { - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - goto exit_rx_proc; - } else { - adapter->rx_processing = true; - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - } - - /* Check for Rx data */ - while ((skb = skb_dequeue(&adapter->rx_data_q))) { - atomic_dec(&adapter->rx_pending); - if ((adapter->delay_main_work || - adapter->iface_type == MWIFIEX_USB) && - (atomic_read(&adapter->rx_pending) < LOW_RX_PENDING)) { - if (adapter->if_ops.submit_rem_rx_urbs) - adapter->if_ops.submit_rem_rx_urbs(adapter); - adapter->delay_main_work = false; - mwifiex_queue_main_work(adapter); - } - rx_info = MWIFIEX_SKB_RXCB(skb); - if (rx_info->buf_type == MWIFIEX_TYPE_AGGR_DATA) { - if (adapter->if_ops.deaggr_pkt) - adapter->if_ops.deaggr_pkt(adapter, skb); - dev_kfree_skb_any(skb); - } else { - mwifiex_handle_rx_packet(adapter, skb); - } - } - spin_lock_irqsave(&adapter->rx_proc_lock, flags); - adapter->rx_processing = false; - spin_unlock_irqrestore(&adapter->rx_proc_lock, flags); - -exit_rx_proc: - return 0; -} - -/* - * The main process. - * - * This function is the main procedure of the driver and handles various driver - * operations. It runs in a loop and provides the core functionalities. - * - * The main responsibilities of this function are - - * - Ensure concurrency control - * - Handle pending interrupts and call interrupt handlers - * - Wake up the card if required - * - Handle command responses and call response handlers - * - Handle events and call event handlers - * - Execute pending commands - * - Transmit pending data packets - */ -int mwifiex_main_process(struct mwifiex_adapter *adapter) -{ - int ret = 0; - unsigned long flags; - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - - /* Check if already processing */ - if (adapter->mwifiex_processing || adapter->main_locked) { - adapter->more_task_flag = true; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - goto exit_main_proc; - } else { - adapter->mwifiex_processing = true; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - } -process_start: - do { - if ((adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) || - (adapter->hw_status == MWIFIEX_HW_STATUS_NOT_READY)) - break; - - /* For non-USB interfaces, If we process interrupts first, it - * would increase RX pending even further. Avoid this by - * checking if rx_pending has crossed high threshold and - * schedule rx work queue and then process interrupts. - * For USB interface, there are no interrupts. We already have - * HIGH_RX_PENDING check in usb.c - */ - if (atomic_read(&adapter->rx_pending) >= HIGH_RX_PENDING && - adapter->iface_type != MWIFIEX_USB) { - adapter->delay_main_work = true; - mwifiex_queue_rx_work(adapter); - break; - } - - /* Handle pending interrupt if any */ - if (adapter->int_status) { - if (adapter->hs_activated) - mwifiex_process_hs_config(adapter); - if (adapter->if_ops.process_int_status) - adapter->if_ops.process_int_status(adapter); - } - - if (adapter->rx_work_enabled && adapter->data_received) - mwifiex_queue_rx_work(adapter); - - /* Need to wake up the card ? */ - if ((adapter->ps_state == PS_STATE_SLEEP) && - (adapter->pm_wakeup_card_req && - !adapter->pm_wakeup_fw_try) && - (is_command_pending(adapter) || - !skb_queue_empty(&adapter->tx_data_q) || - !mwifiex_bypass_txlist_empty(adapter) || - !mwifiex_wmm_lists_empty(adapter))) { - adapter->pm_wakeup_fw_try = true; - mod_timer(&adapter->wakeup_timer, jiffies + (HZ*3)); - adapter->if_ops.wakeup(adapter); - continue; - } - - if (IS_CARD_RX_RCVD(adapter)) { - adapter->data_received = false; - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - if (adapter->ps_state == PS_STATE_SLEEP) - adapter->ps_state = PS_STATE_AWAKE; - } else { - /* We have tried to wakeup the card already */ - if (adapter->pm_wakeup_fw_try) - break; - if (adapter->ps_state != PS_STATE_AWAKE) - break; - if (adapter->tx_lock_flag) { - if (adapter->iface_type == MWIFIEX_USB) { - if (!adapter->usb_mc_setup) - break; - } else - break; - } - - if ((!adapter->scan_chan_gap_enabled && - adapter->scan_processing) || adapter->data_sent || - mwifiex_is_tdls_chan_switching - (mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_STA)) || - (mwifiex_wmm_lists_empty(adapter) && - mwifiex_bypass_txlist_empty(adapter) && - skb_queue_empty(&adapter->tx_data_q))) { - if (adapter->cmd_sent || adapter->curr_cmd || - !mwifiex_is_send_cmd_allowed - (mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_STA)) || - (!is_command_pending(adapter))) - break; - } - } - - /* Check for event */ - if (adapter->event_received) { - adapter->event_received = false; - mwifiex_process_event(adapter); - } - - /* Check for Cmd Resp */ - if (adapter->cmd_resp_received) { - adapter->cmd_resp_received = false; - mwifiex_process_cmdresp(adapter); - - /* call mwifiex back when init_fw is done */ - if (adapter->hw_status == MWIFIEX_HW_STATUS_INIT_DONE) { - adapter->hw_status = MWIFIEX_HW_STATUS_READY; - mwifiex_init_fw_complete(adapter); - } - } - - /* Check if we need to confirm Sleep Request - received previously */ - if (adapter->ps_state == PS_STATE_PRE_SLEEP) { - if (!adapter->cmd_sent && !adapter->curr_cmd) - mwifiex_check_ps_cond(adapter); - } - - /* * The ps_state may have been changed during processing of - * Sleep Request event. - */ - if ((adapter->ps_state == PS_STATE_SLEEP) || - (adapter->ps_state == PS_STATE_PRE_SLEEP) || - (adapter->ps_state == PS_STATE_SLEEP_CFM)) { - continue; - } - - if (adapter->tx_lock_flag) { - if (adapter->iface_type == MWIFIEX_USB) { - if (!adapter->usb_mc_setup) - continue; - } else - continue; - } - - if (!adapter->cmd_sent && !adapter->curr_cmd && - mwifiex_is_send_cmd_allowed - (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { - if (mwifiex_exec_next_cmd(adapter) == -1) { - ret = -1; - break; - } - } - - /** If USB Multi channel setup ongoing, - * wait for ready to tx data. - */ - if (adapter->iface_type == MWIFIEX_USB && - adapter->usb_mc_setup) - continue; - - if ((adapter->scan_chan_gap_enabled || - !adapter->scan_processing) && - !adapter->data_sent && - !skb_queue_empty(&adapter->tx_data_q)) { - mwifiex_process_tx_queue(adapter); - if (adapter->hs_activated) { - adapter->is_hs_configured = false; - mwifiex_hs_activated_event - (mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), - false); - } - } - - if ((adapter->scan_chan_gap_enabled || - !adapter->scan_processing) && - !adapter->data_sent && - !mwifiex_bypass_txlist_empty(adapter) && - !mwifiex_is_tdls_chan_switching - (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { - mwifiex_process_bypass_tx(adapter); - if (adapter->hs_activated) { - adapter->is_hs_configured = false; - mwifiex_hs_activated_event - (mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), - false); - } - } - - if ((adapter->scan_chan_gap_enabled || - !adapter->scan_processing) && - !adapter->data_sent && !mwifiex_wmm_lists_empty(adapter) && - !mwifiex_is_tdls_chan_switching - (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA))) { - mwifiex_wmm_process_tx(adapter); - if (adapter->hs_activated) { - adapter->is_hs_configured = false; - mwifiex_hs_activated_event - (mwifiex_get_priv - (adapter, MWIFIEX_BSS_ROLE_ANY), - false); - } - } - - if (adapter->delay_null_pkt && !adapter->cmd_sent && - !adapter->curr_cmd && !is_command_pending(adapter) && - (mwifiex_wmm_lists_empty(adapter) && - mwifiex_bypass_txlist_empty(adapter) && - skb_queue_empty(&adapter->tx_data_q))) { - if (!mwifiex_send_null_packet - (mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) { - adapter->delay_null_pkt = false; - adapter->ps_state = PS_STATE_SLEEP; - } - break; - } - } while (true); - - spin_lock_irqsave(&adapter->main_proc_lock, flags); - if (adapter->more_task_flag) { - adapter->more_task_flag = false; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - goto process_start; - } - adapter->mwifiex_processing = false; - spin_unlock_irqrestore(&adapter->main_proc_lock, flags); - -exit_main_proc: - if (adapter->hw_status == MWIFIEX_HW_STATUS_CLOSING) - mwifiex_shutdown_drv(adapter); - return ret; -} -EXPORT_SYMBOL_GPL(mwifiex_main_process); - -/* - * This function frees the adapter structure. - * - * Additionally, this closes the netlink socket, frees the timers - * and private structures. - */ -static void mwifiex_free_adapter(struct mwifiex_adapter *adapter) -{ - if (!adapter) { - pr_err("%s: adapter is NULL\n", __func__); - return; - } - - mwifiex_unregister(adapter); - pr_debug("info: %s: free adapter\n", __func__); -} - -/* - * This function cancels all works in the queue and destroys - * the main workqueue. - */ -static void mwifiex_terminate_workqueue(struct mwifiex_adapter *adapter) -{ - flush_workqueue(adapter->workqueue); - destroy_workqueue(adapter->workqueue); - adapter->workqueue = NULL; - - if (adapter->rx_workqueue) { - flush_workqueue(adapter->rx_workqueue); - destroy_workqueue(adapter->rx_workqueue); - adapter->rx_workqueue = NULL; - } -} - -/* - * This function gets firmware and initializes it. - * - * The main initialization steps followed are - - * - Download the correct firmware to card - * - Issue the init commands to firmware - */ -static void mwifiex_fw_dpc(const struct firmware *firmware, void *context) -{ - int ret; - char fmt[64]; - struct mwifiex_private *priv; - struct mwifiex_adapter *adapter = context; - struct mwifiex_fw_image fw; - struct semaphore *sem = adapter->card_sem; - bool init_failed = false; - struct wireless_dev *wdev; - - if (!firmware) { - mwifiex_dbg(adapter, ERROR, - "Failed to get firmware %s\n", adapter->fw_name); - goto err_dnld_fw; - } - - memset(&fw, 0, sizeof(struct mwifiex_fw_image)); - adapter->firmware = firmware; - fw.fw_buf = (u8 *) adapter->firmware->data; - fw.fw_len = adapter->firmware->size; - - if (adapter->if_ops.dnld_fw) - ret = adapter->if_ops.dnld_fw(adapter, &fw); - else - ret = mwifiex_dnld_fw(adapter, &fw); - if (ret == -1) - goto err_dnld_fw; - - mwifiex_dbg(adapter, MSG, "WLAN FW is active\n"); - - if (cal_data_cfg) { - if ((request_firmware(&adapter->cal_data, cal_data_cfg, - adapter->dev)) < 0) - mwifiex_dbg(adapter, ERROR, - "Cal data request_firmware() failed\n"); - } - - /* enable host interrupt after fw dnld is successful */ - if (adapter->if_ops.enable_int) { - if (adapter->if_ops.enable_int(adapter)) - goto err_dnld_fw; - } - - adapter->init_wait_q_woken = false; - ret = mwifiex_init_fw(adapter); - if (ret == -1) { - goto err_init_fw; - } else if (!ret) { - adapter->hw_status = MWIFIEX_HW_STATUS_READY; - goto done; - } - /* Wait for mwifiex_init to complete */ - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - if (adapter->hw_status != MWIFIEX_HW_STATUS_READY) - goto err_init_fw; - - priv = adapter->priv[MWIFIEX_BSS_ROLE_STA]; - if (mwifiex_register_cfg80211(adapter)) { - mwifiex_dbg(adapter, ERROR, - "cannot register with cfg80211\n"); - goto err_init_fw; - } - - if (mwifiex_init_channel_scan_gap(adapter)) { - mwifiex_dbg(adapter, ERROR, - "could not init channel stats table\n"); - goto err_init_fw; - } - - if (driver_mode) { - driver_mode &= MWIFIEX_DRIVER_MODE_BITMASK; - driver_mode |= MWIFIEX_DRIVER_MODE_STA; - } - - rtnl_lock(); - /* Create station interface by default */ - wdev = mwifiex_add_virtual_intf(adapter->wiphy, "mlan%d", NET_NAME_ENUM, - NL80211_IFTYPE_STATION, NULL, NULL); - if (IS_ERR(wdev)) { - mwifiex_dbg(adapter, ERROR, - "cannot create default STA interface\n"); - rtnl_unlock(); - goto err_add_intf; - } - - if (driver_mode & MWIFIEX_DRIVER_MODE_UAP) { - wdev = mwifiex_add_virtual_intf(adapter->wiphy, "uap%d", NET_NAME_ENUM, - NL80211_IFTYPE_AP, NULL, NULL); - if (IS_ERR(wdev)) { - mwifiex_dbg(adapter, ERROR, - "cannot create AP interface\n"); - rtnl_unlock(); - goto err_add_intf; - } - } - - if (driver_mode & MWIFIEX_DRIVER_MODE_P2P) { - wdev = mwifiex_add_virtual_intf(adapter->wiphy, "p2p%d", NET_NAME_ENUM, - NL80211_IFTYPE_P2P_CLIENT, NULL, - NULL); - if (IS_ERR(wdev)) { - mwifiex_dbg(adapter, ERROR, - "cannot create p2p client interface\n"); - rtnl_unlock(); - goto err_add_intf; - } - } - rtnl_unlock(); - - mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1); - mwifiex_dbg(adapter, MSG, "driver_version = %s\n", fmt); - goto done; - -err_add_intf: - wiphy_unregister(adapter->wiphy); - wiphy_free(adapter->wiphy); -err_init_fw: - if (adapter->if_ops.disable_int) - adapter->if_ops.disable_int(adapter); -err_dnld_fw: - mwifiex_dbg(adapter, ERROR, - "info: %s: unregister device\n", __func__); - if (adapter->if_ops.unregister_dev) - adapter->if_ops.unregister_dev(adapter); - - if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { - pr_debug("info: %s: shutdown mwifiex\n", __func__); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - } - adapter->surprise_removed = true; - mwifiex_terminate_workqueue(adapter); - init_failed = true; -done: - if (adapter->cal_data) { - release_firmware(adapter->cal_data); - adapter->cal_data = NULL; - } - if (adapter->firmware) { - release_firmware(adapter->firmware); - adapter->firmware = NULL; - } - if (init_failed) - mwifiex_free_adapter(adapter); - up(sem); - return; -} - -/* - * This function initializes the hardware and gets firmware. - */ -static int mwifiex_init_hw_fw(struct mwifiex_adapter *adapter) -{ - int ret; - - ret = request_firmware_nowait(THIS_MODULE, 1, adapter->fw_name, - adapter->dev, GFP_KERNEL, adapter, - mwifiex_fw_dpc); - if (ret < 0) - mwifiex_dbg(adapter, ERROR, - "request_firmware_nowait error %d\n", ret); - return ret; -} - -/* - * CFG802.11 network device handler for open. - * - * Starts the data queue. - */ -static int -mwifiex_open(struct net_device *dev) -{ - netif_carrier_off(dev); - - return 0; -} - -/* - * CFG802.11 network device handler for close. - */ -static int -mwifiex_close(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - if (priv->scan_request) { - mwifiex_dbg(priv->adapter, INFO, - "aborting scan on ndo_stop\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - priv->scan_aborting = true; - } - - return 0; -} - -static bool -mwifiex_bypass_tx_queue(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct ethhdr *eth_hdr = (struct ethhdr *)skb->data; - - if (ntohs(eth_hdr->h_proto) == ETH_P_PAE || - mwifiex_is_skb_mgmt_frame(skb) || - (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && - ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - (ntohs(eth_hdr->h_proto) == ETH_P_TDLS))) { - mwifiex_dbg(priv->adapter, DATA, - "bypass txqueue; eth type %#x, mgmt %d\n", - ntohs(eth_hdr->h_proto), - mwifiex_is_skb_mgmt_frame(skb)); - return true; - } - - return false; -} -/* - * Add buffer into wmm tx queue and queue work to transmit it. - */ -int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb) -{ - struct netdev_queue *txq; - int index = mwifiex_1d_to_wmm_queue[skb->priority]; - - if (atomic_inc_return(&priv->wmm_tx_pending[index]) >= MAX_TX_PENDING) { - txq = netdev_get_tx_queue(priv->netdev, index); - if (!netif_tx_queue_stopped(txq)) { - netif_tx_stop_queue(txq); - mwifiex_dbg(priv->adapter, DATA, - "stop queue: %d\n", index); - } - } - - if (mwifiex_bypass_tx_queue(priv, skb)) { - atomic_inc(&priv->adapter->tx_pending); - atomic_inc(&priv->adapter->bypass_tx_pending); - mwifiex_wmm_add_buf_bypass_txqueue(priv, skb); - } else { - atomic_inc(&priv->adapter->tx_pending); - mwifiex_wmm_add_buf_txqueue(priv, skb); - } - - mwifiex_queue_main_work(priv->adapter); - - return 0; -} - -struct sk_buff * -mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, - struct sk_buff *skb, u8 flag, u64 *cookie) -{ - struct sk_buff *orig_skb = skb; - struct mwifiex_txinfo *tx_info, *orig_tx_info; - - skb = skb_clone(skb, GFP_ATOMIC); - if (skb) { - unsigned long flags; - int id; - - spin_lock_irqsave(&priv->ack_status_lock, flags); - id = idr_alloc(&priv->ack_status_frames, orig_skb, - 1, 0xff, GFP_ATOMIC); - spin_unlock_irqrestore(&priv->ack_status_lock, flags); - - if (id >= 0) { - tx_info = MWIFIEX_SKB_TXCB(skb); - tx_info->ack_frame_id = id; - tx_info->flags |= flag; - orig_tx_info = MWIFIEX_SKB_TXCB(orig_skb); - orig_tx_info->ack_frame_id = id; - orig_tx_info->flags |= flag; - - if (flag == MWIFIEX_BUF_FLAG_ACTION_TX_STATUS && cookie) - orig_tx_info->cookie = *cookie; - - } else if (skb_shared(skb)) { - kfree_skb(orig_skb); - } else { - kfree_skb(skb); - skb = orig_skb; - } - } else { - /* couldn't clone -- lose tx status ... */ - skb = orig_skb; - } - - return skb; -} - -/* - * CFG802.11 network device handler for data transmission. - */ -static int -mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct sk_buff *new_skb; - struct mwifiex_txinfo *tx_info; - bool multicast; - - mwifiex_dbg(priv->adapter, DATA, - "data: %lu BSS(%d-%d): Data <= kernel\n", - jiffies, priv->bss_type, priv->bss_num); - - if (priv->adapter->surprise_removed) { - kfree_skb(skb); - priv->stats.tx_dropped++; - return 0; - } - if (!skb->len || (skb->len > ETH_FRAME_LEN)) { - mwifiex_dbg(priv->adapter, ERROR, - "Tx: bad skb len %d\n", skb->len); - kfree_skb(skb); - priv->stats.tx_dropped++; - return 0; - } - if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { - mwifiex_dbg(priv->adapter, DATA, - "data: Tx: insufficient skb headroom %d\n", - skb_headroom(skb)); - /* Insufficient skb headroom - allocate a new skb */ - new_skb = - skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); - if (unlikely(!new_skb)) { - mwifiex_dbg(priv->adapter, ERROR, - "Tx: cannot alloca new_skb\n"); - kfree_skb(skb); - priv->stats.tx_dropped++; - return 0; - } - kfree_skb(skb); - skb = new_skb; - mwifiex_dbg(priv->adapter, INFO, - "info: new skb headroomd %d\n", - skb_headroom(skb)); - } - - tx_info = MWIFIEX_SKB_TXCB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->bss_num = priv->bss_num; - tx_info->bss_type = priv->bss_type; - tx_info->pkt_len = skb->len; - - multicast = is_multicast_ether_addr(skb->data); - - if (unlikely(!multicast && skb->sk && - skb_shinfo(skb)->tx_flags & SKBTX_WIFI_STATUS && - priv->adapter->fw_api_ver == MWIFIEX_FW_V15)) - skb = mwifiex_clone_skb_for_tx_status(priv, - skb, - MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS, NULL); - - /* Record the current time the packet was queued; used to - * determine the amount of time the packet was queued in - * the driver before it was sent to the firmware. - * The delay is then sent along with the packet to the - * firmware for aggregate delay calculation for stats and - * MSDU lifetime expiry. - */ - __net_timestamp(skb); - - if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - priv->bss_type == MWIFIEX_BSS_TYPE_STA && - !ether_addr_equal_unaligned(priv->cfg_bssid, skb->data)) { - if (priv->adapter->auto_tdls && priv->check_tdls_tx) - mwifiex_tdls_check_tx(priv, skb); - } - - mwifiex_queue_tx_pkt(priv, skb); - - return 0; -} - -/* - * CFG802.11 network device handler for setting MAC address. - */ -static int -mwifiex_set_mac_address(struct net_device *dev, void *addr) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct sockaddr *hw_addr = addr; - int ret; - - memcpy(priv->curr_addr, hw_addr->sa_data, ETH_ALEN); - - /* Send request to firmware */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_MAC_ADDRESS, - HostCmd_ACT_GEN_SET, 0, NULL, true); - - if (!ret) - memcpy(priv->netdev->dev_addr, priv->curr_addr, ETH_ALEN); - else - mwifiex_dbg(priv->adapter, ERROR, - "set mac address failed: ret=%d\n", ret); - - memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); - - return ret; -} - -/* - * CFG802.11 network device handler for setting multicast list. - */ -static void mwifiex_set_multicast_list(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - struct mwifiex_multicast_list mcast_list; - - if (dev->flags & IFF_PROMISC) { - mcast_list.mode = MWIFIEX_PROMISC_MODE; - } else if (dev->flags & IFF_ALLMULTI || - netdev_mc_count(dev) > MWIFIEX_MAX_MULTICAST_LIST_SIZE) { - mcast_list.mode = MWIFIEX_ALL_MULTI_MODE; - } else { - mcast_list.mode = MWIFIEX_MULTICAST_MODE; - mcast_list.num_multicast_addr = - mwifiex_copy_mcast_addr(&mcast_list, dev); - } - mwifiex_request_set_multicast_list(priv, &mcast_list); -} - -/* - * CFG802.11 network device handler for transmission timeout. - */ -static void -mwifiex_tx_timeout(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - priv->num_tx_timeout++; - priv->tx_timeout_cnt++; - mwifiex_dbg(priv->adapter, ERROR, - "%lu : Tx timeout(#%d), bss_type-num = %d-%d\n", - jiffies, priv->tx_timeout_cnt, priv->bss_type, - priv->bss_num); - mwifiex_set_trans_start(dev); - - if (priv->tx_timeout_cnt > TX_TIMEOUT_THRESHOLD && - priv->adapter->if_ops.card_reset) { - mwifiex_dbg(priv->adapter, ERROR, - "tx_timeout_cnt exceeds threshold.\t" - "Triggering card reset!\n"); - priv->adapter->if_ops.card_reset(priv->adapter); - } -} - -void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = adapter->card; - struct mwifiex_private *priv; - u16 tx_buf_size; - int i, ret; - - card->mc_resync_flag = true; - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { - if (atomic_read(&card->port[i].tx_data_urb_pending)) { - mwifiex_dbg(adapter, WARN, "pending data urb in sys\n"); - return; - } - } - - card->mc_resync_flag = false; - tx_buf_size = 0xffff; - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, &tx_buf_size, false); - if (ret) - mwifiex_dbg(adapter, ERROR, - "send reconfig tx buf size cmd err\n"); -} -EXPORT_SYMBOL_GPL(mwifiex_multi_chan_resync); - -void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter) -{ - void *p; - char drv_version[64]; - struct usb_card_rec *cardp; - struct sdio_mmc_card *sdio_card; - struct mwifiex_private *priv; - int i, idx; - struct netdev_queue *txq; - struct mwifiex_debug_info *debug_info; - - if (adapter->drv_info_dump) { - vfree(adapter->drv_info_dump); - adapter->drv_info_dump = NULL; - adapter->drv_info_size = 0; - } - - mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump start===\n"); - - adapter->drv_info_dump = vzalloc(MWIFIEX_DRV_INFO_SIZE_MAX); - - if (!adapter->drv_info_dump) - return; - - p = (char *)(adapter->drv_info_dump); - p += sprintf(p, "driver_name = " "\"mwifiex\"\n"); - - mwifiex_drv_get_driver_version(adapter, drv_version, - sizeof(drv_version) - 1); - p += sprintf(p, "driver_version = %s\n", drv_version); - - if (adapter->iface_type == MWIFIEX_USB) { - cardp = (struct usb_card_rec *)adapter->card; - p += sprintf(p, "tx_cmd_urb_pending = %d\n", - atomic_read(&cardp->tx_cmd_urb_pending)); - p += sprintf(p, "tx_data_urb_pending_port_0 = %d\n", - atomic_read(&cardp->port[0].tx_data_urb_pending)); - p += sprintf(p, "tx_data_urb_pending_port_1 = %d\n", - atomic_read(&cardp->port[1].tx_data_urb_pending)); - p += sprintf(p, "rx_cmd_urb_pending = %d\n", - atomic_read(&cardp->rx_cmd_urb_pending)); - p += sprintf(p, "rx_data_urb_pending = %d\n", - atomic_read(&cardp->rx_data_urb_pending)); - } - - p += sprintf(p, "tx_pending = %d\n", - atomic_read(&adapter->tx_pending)); - p += sprintf(p, "rx_pending = %d\n", - atomic_read(&adapter->rx_pending)); - - if (adapter->iface_type == MWIFIEX_SDIO) { - sdio_card = (struct sdio_mmc_card *)adapter->card; - p += sprintf(p, "\nmp_rd_bitmap=0x%x curr_rd_port=0x%x\n", - sdio_card->mp_rd_bitmap, sdio_card->curr_rd_port); - p += sprintf(p, "mp_wr_bitmap=0x%x curr_wr_port=0x%x\n", - sdio_card->mp_wr_bitmap, sdio_card->curr_wr_port); - } - - for (i = 0; i < adapter->priv_num; i++) { - if (!adapter->priv[i] || !adapter->priv[i]->netdev) - continue; - priv = adapter->priv[i]; - p += sprintf(p, "\n[interface : \"%s\"]\n", - priv->netdev->name); - p += sprintf(p, "wmm_tx_pending[0] = %d\n", - atomic_read(&priv->wmm_tx_pending[0])); - p += sprintf(p, "wmm_tx_pending[1] = %d\n", - atomic_read(&priv->wmm_tx_pending[1])); - p += sprintf(p, "wmm_tx_pending[2] = %d\n", - atomic_read(&priv->wmm_tx_pending[2])); - p += sprintf(p, "wmm_tx_pending[3] = %d\n", - atomic_read(&priv->wmm_tx_pending[3])); - p += sprintf(p, "media_state=\"%s\"\n", !priv->media_connected ? - "Disconnected" : "Connected"); - p += sprintf(p, "carrier %s\n", (netif_carrier_ok(priv->netdev) - ? "on" : "off")); - for (idx = 0; idx < priv->netdev->num_tx_queues; idx++) { - txq = netdev_get_tx_queue(priv->netdev, idx); - p += sprintf(p, "tx queue %d:%s ", idx, - netif_tx_queue_stopped(txq) ? - "stopped" : "started"); - } - p += sprintf(p, "\n%s: num_tx_timeout = %d\n", - priv->netdev->name, priv->num_tx_timeout); - } - - if (adapter->iface_type == MWIFIEX_SDIO) { - p += sprintf(p, "\n=== SDIO register dump===\n"); - if (adapter->if_ops.reg_dump) - p += adapter->if_ops.reg_dump(adapter, p); - } - - p += sprintf(p, "\n=== more debug information\n"); - debug_info = kzalloc(sizeof(*debug_info), GFP_KERNEL); - if (debug_info) { - for (i = 0; i < adapter->priv_num; i++) { - if (!adapter->priv[i] || !adapter->priv[i]->netdev) - continue; - priv = adapter->priv[i]; - mwifiex_get_debug_info(priv, debug_info); - p += mwifiex_debug_info_to_buffer(priv, p, debug_info); - break; - } - kfree(debug_info); - } - - adapter->drv_info_size = p - adapter->drv_info_dump; - mwifiex_dbg(adapter, MSG, "===mwifiex driverinfo dump end===\n"); -} -EXPORT_SYMBOL_GPL(mwifiex_drv_info_dump); - -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter) -{ - u8 idx, *dump_data, *fw_dump_ptr; - u32 dump_len; - - dump_len = (strlen("========Start dump driverinfo========\n") + - adapter->drv_info_size + - strlen("\n========End dump========\n")); - - for (idx = 0; idx < adapter->num_mem_types; idx++) { - struct memory_type_mapping *entry = - &adapter->mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - dump_len += (strlen("========Start dump ") + - strlen(entry->mem_name) + - strlen("========\n") + - (entry->mem_size + 1) + - strlen("\n========End dump========\n")); - } - } - - dump_data = vzalloc(dump_len + 1); - if (!dump_data) - goto done; - - fw_dump_ptr = dump_data; - - /* Dump all the memory data into single file, a userspace script will - * be used to split all the memory data to multiple files - */ - mwifiex_dbg(adapter, MSG, - "== mwifiex dump information to /sys/class/devcoredump start"); - - strcpy(fw_dump_ptr, "========Start dump driverinfo========\n"); - fw_dump_ptr += strlen("========Start dump driverinfo========\n"); - memcpy(fw_dump_ptr, adapter->drv_info_dump, adapter->drv_info_size); - fw_dump_ptr += adapter->drv_info_size; - strcpy(fw_dump_ptr, "\n========End dump========\n"); - fw_dump_ptr += strlen("\n========End dump========\n"); - - for (idx = 0; idx < adapter->num_mem_types; idx++) { - struct memory_type_mapping *entry = - &adapter->mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - strcpy(fw_dump_ptr, "========Start dump "); - fw_dump_ptr += strlen("========Start dump "); - - strcpy(fw_dump_ptr, entry->mem_name); - fw_dump_ptr += strlen(entry->mem_name); - - strcpy(fw_dump_ptr, "========\n"); - fw_dump_ptr += strlen("========\n"); - - memcpy(fw_dump_ptr, entry->mem_ptr, entry->mem_size); - fw_dump_ptr += entry->mem_size; - - strcpy(fw_dump_ptr, "\n========End dump========\n"); - fw_dump_ptr += strlen("\n========End dump========\n"); - } - } - - /* device dump data will be free in device coredump release function - * after 5 min - */ - dev_coredumpv(adapter->dev, dump_data, dump_len, GFP_KERNEL); - mwifiex_dbg(adapter, MSG, - "== mwifiex dump information to /sys/class/devcoredump end"); - -done: - for (idx = 0; idx < adapter->num_mem_types; idx++) { - struct memory_type_mapping *entry = - &adapter->mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - } - - if (adapter->drv_info_dump) { - vfree(adapter->drv_info_dump); - adapter->drv_info_dump = NULL; - adapter->drv_info_size = 0; - } -} -EXPORT_SYMBOL_GPL(mwifiex_upload_device_dump); - -/* - * CFG802.11 network device handler for statistics retrieval. - */ -static struct net_device_stats *mwifiex_get_stats(struct net_device *dev) -{ - struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev); - - return &priv->stats; -} - -static u16 -mwifiex_netdev_select_wmm_queue(struct net_device *dev, struct sk_buff *skb, - void *accel_priv, select_queue_fallback_t fallback) -{ - skb->priority = cfg80211_classify8021d(skb, NULL); - return mwifiex_1d_to_wmm_queue[skb->priority]; -} - -/* Network device handlers */ -static const struct net_device_ops mwifiex_netdev_ops = { - .ndo_open = mwifiex_open, - .ndo_stop = mwifiex_close, - .ndo_start_xmit = mwifiex_hard_start_xmit, - .ndo_set_mac_address = mwifiex_set_mac_address, - .ndo_validate_addr = eth_validate_addr, - .ndo_tx_timeout = mwifiex_tx_timeout, - .ndo_get_stats = mwifiex_get_stats, - .ndo_set_rx_mode = mwifiex_set_multicast_list, - .ndo_select_queue = mwifiex_netdev_select_wmm_queue, -}; - -/* - * This function initializes the private structure parameters. - * - * The following wait queues are initialized - - * - IOCTL wait queue - * - Command wait queue - * - Statistics wait queue - * - * ...and the following default parameters are set - - * - Current key index : Set to 0 - * - Rate index : Set to auto - * - Media connected : Set to disconnected - * - Adhoc link sensed : Set to false - * - Nick name : Set to null - * - Number of Tx timeout : Set to 0 - * - Device address : Set to current address - * - Rx histogram statistc : Set to 0 - * - * In addition, the CFG80211 work queue is also created. - */ -void mwifiex_init_priv_params(struct mwifiex_private *priv, - struct net_device *dev) -{ - dev->netdev_ops = &mwifiex_netdev_ops; - dev->destructor = free_netdev; - /* Initialize private structure */ - priv->current_key_index = 0; - priv->media_connected = false; - memset(priv->mgmt_ie, 0, - sizeof(struct mwifiex_ie) * MAX_MGMT_IE_INDEX); - priv->beacon_idx = MWIFIEX_AUTO_IDX_MASK; - priv->proberesp_idx = MWIFIEX_AUTO_IDX_MASK; - priv->assocresp_idx = MWIFIEX_AUTO_IDX_MASK; - priv->gen_idx = MWIFIEX_AUTO_IDX_MASK; - priv->num_tx_timeout = 0; - ether_addr_copy(priv->curr_addr, priv->adapter->perm_addr); - memcpy(dev->dev_addr, priv->curr_addr, ETH_ALEN); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || - GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - priv->hist_data = kmalloc(sizeof(*priv->hist_data), GFP_KERNEL); - if (priv->hist_data) - mwifiex_hist_data_reset(priv); - } -} - -/* - * This function check if command is pending. - */ -int is_command_pending(struct mwifiex_adapter *adapter) -{ - unsigned long flags; - int is_cmd_pend_q_empty; - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, flags); - is_cmd_pend_q_empty = list_empty(&adapter->cmd_pending_q); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, flags); - - return !is_cmd_pend_q_empty; -} - -/* - * This is the RX work queue function. - * - * It handles the RX operations. - */ -static void mwifiex_rx_work_queue(struct work_struct *work) -{ - struct mwifiex_adapter *adapter = - container_of(work, struct mwifiex_adapter, rx_work); - - if (adapter->surprise_removed) - return; - mwifiex_process_rx(adapter); -} - -/* - * This is the main work queue function. - * - * It handles the main process, which in turn handles the complete - * driver operations. - */ -static void mwifiex_main_work_queue(struct work_struct *work) -{ - struct mwifiex_adapter *adapter = - container_of(work, struct mwifiex_adapter, main_work); - - if (adapter->surprise_removed) - return; - mwifiex_main_process(adapter); -} - -/* - * This function adds the card. - * - * This function follows the following major steps to set up the device - - * - Initialize software. This includes probing the card, registering - * the interface operations table, and allocating/initializing the - * adapter structure - * - Set up the netlink socket - * - Create and start the main work queue - * - Register the device - * - Initialize firmware and hardware - * - Add logical interfaces - */ -int -mwifiex_add_card(void *card, struct semaphore *sem, - struct mwifiex_if_ops *if_ops, u8 iface_type) -{ - struct mwifiex_adapter *adapter; - - if (down_interruptible(sem)) - goto exit_sem_err; - - if (mwifiex_register(card, if_ops, (void **)&adapter)) { - pr_err("%s: software init failed\n", __func__); - goto err_init_sw; - } - - adapter->iface_type = iface_type; - adapter->card_sem = sem; - - adapter->hw_status = MWIFIEX_HW_STATUS_INITIALIZING; - adapter->surprise_removed = false; - init_waitqueue_head(&adapter->init_wait_q); - adapter->is_suspended = false; - adapter->hs_activated = false; - init_waitqueue_head(&adapter->hs_activate_wait_q); - init_waitqueue_head(&adapter->cmd_wait_q.wait); - adapter->cmd_wait_q.status = 0; - adapter->scan_wait_q_woken = false; - - if ((num_possible_cpus() > 1) || adapter->iface_type == MWIFIEX_USB) { - adapter->rx_work_enabled = true; - pr_notice("rx work enabled, cpus %d\n", num_possible_cpus()); - } - - adapter->workqueue = - alloc_workqueue("MWIFIEX_WORK_QUEUE", - WQ_HIGHPRI | WQ_MEM_RECLAIM | WQ_UNBOUND, 1); - if (!adapter->workqueue) - goto err_kmalloc; - - INIT_WORK(&adapter->main_work, mwifiex_main_work_queue); - - if (adapter->rx_work_enabled) { - adapter->rx_workqueue = alloc_workqueue("MWIFIEX_RX_WORK_QUEUE", - WQ_HIGHPRI | - WQ_MEM_RECLAIM | - WQ_UNBOUND, 1); - if (!adapter->rx_workqueue) - goto err_kmalloc; - - INIT_WORK(&adapter->rx_work, mwifiex_rx_work_queue); - } - - /* Register the device. Fill up the private data structure with relevant - information from the card. */ - if (adapter->if_ops.register_dev(adapter)) { - pr_err("%s: failed to register mwifiex device\n", __func__); - goto err_registerdev; - } - - if (mwifiex_init_hw_fw(adapter)) { - pr_err("%s: firmware init failed\n", __func__); - goto err_init_fw; - } - - return 0; - -err_init_fw: - pr_debug("info: %s: unregister device\n", __func__); - if (adapter->if_ops.unregister_dev) - adapter->if_ops.unregister_dev(adapter); - if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) { - pr_debug("info: %s: shutdown mwifiex\n", __func__); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - } -err_registerdev: - adapter->surprise_removed = true; - mwifiex_terminate_workqueue(adapter); -err_kmalloc: - mwifiex_free_adapter(adapter); - -err_init_sw: - up(sem); - -exit_sem_err: - return -1; -} -EXPORT_SYMBOL_GPL(mwifiex_add_card); - -/* - * This function removes the card. - * - * This function follows the following major steps to remove the device - - * - Stop data traffic - * - Shutdown firmware - * - Remove the logical interfaces - * - Terminate the work queue - * - Unregister the device - * - Free the adapter structure - */ -int mwifiex_remove_card(struct mwifiex_adapter *adapter, struct semaphore *sem) -{ - struct mwifiex_private *priv = NULL; - int i; - - if (down_interruptible(sem)) - goto exit_sem_err; - - if (!adapter) - goto exit_remove; - - /* We can no longer handle interrupts once we start doing the teardown - * below. */ - if (adapter->if_ops.disable_int) - adapter->if_ops.disable_int(adapter); - - adapter->surprise_removed = true; - - mwifiex_terminate_workqueue(adapter); - - /* Stop data */ - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv && priv->netdev) { - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - } - } - - mwifiex_dbg(adapter, CMD, - "cmd: calling mwifiex_shutdown_drv...\n"); - adapter->init_wait_q_woken = false; - - if (mwifiex_shutdown_drv(adapter) == -EINPROGRESS) - wait_event_interruptible(adapter->init_wait_q, - adapter->init_wait_q_woken); - mwifiex_dbg(adapter, CMD, - "cmd: mwifiex_shutdown_drv done\n"); - if (atomic_read(&adapter->rx_pending) || - atomic_read(&adapter->tx_pending) || - atomic_read(&adapter->cmd_pending)) { - mwifiex_dbg(adapter, ERROR, - "rx_pending=%d, tx_pending=%d,\t" - "cmd_pending=%d\n", - atomic_read(&adapter->rx_pending), - atomic_read(&adapter->tx_pending), - atomic_read(&adapter->cmd_pending)); - } - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - - if (!priv) - continue; - - rtnl_lock(); - if (priv->netdev && - priv->wdev.iftype != NL80211_IFTYPE_UNSPECIFIED) - mwifiex_del_virtual_intf(adapter->wiphy, &priv->wdev); - rtnl_unlock(); - } - - wiphy_unregister(adapter->wiphy); - wiphy_free(adapter->wiphy); - - /* Unregister device */ - mwifiex_dbg(adapter, INFO, - "info: unregister device\n"); - if (adapter->if_ops.unregister_dev) - adapter->if_ops.unregister_dev(adapter); - /* Free adapter structure */ - mwifiex_dbg(adapter, INFO, - "info: free adapter\n"); - mwifiex_free_adapter(adapter); - -exit_remove: - up(sem); -exit_sem_err: - return 0; -} -EXPORT_SYMBOL_GPL(mwifiex_remove_card); - -void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask, - const char *fmt, ...) -{ - struct va_format vaf; - va_list args; - - if (!adapter->dev || !(adapter->debug_mask & mask)) - return; - - va_start(args, fmt); - - vaf.fmt = fmt; - vaf.va = &args; - - dev_info(adapter->dev, "%pV", &vaf); - - va_end(args); -} -EXPORT_SYMBOL_GPL(_mwifiex_dbg); - -/* - * This function initializes the module. - * - * The debug FS is also initialized if configured. - */ -static int -mwifiex_init_module(void) -{ -#ifdef CONFIG_DEBUG_FS - mwifiex_debugfs_init(); -#endif - return 0; -} - -/* - * This function cleans up the module. - * - * The debug FS is removed if available. - */ -static void -mwifiex_cleanup_module(void) -{ -#ifdef CONFIG_DEBUG_FS - mwifiex_debugfs_remove(); -#endif -} - -module_init(mwifiex_init_module); -module_exit(mwifiex_cleanup_module); - -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_DESCRIPTION("Marvell WiFi-Ex Driver version " VERSION); -MODULE_VERSION(VERSION); -MODULE_LICENSE("GPL v2"); diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h deleted file mode 100644 index 3959f1c97f4e..000000000000 --- a/drivers/net/wireless/mwifiex/main.h +++ /dev/null @@ -1,1579 +0,0 @@ -/* - * Marvell Wireless LAN device driver: major data structures and prototypes - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_MAIN_H_ -#define _MWIFIEX_MAIN_H_ - -#include <linux/kernel.h> -#include <linux/module.h> -#include <linux/sched.h> -#include <linux/semaphore.h> -#include <linux/ip.h> -#include <linux/skbuff.h> -#include <linux/if_arp.h> -#include <linux/etherdevice.h> -#include <net/sock.h> -#include <net/lib80211.h> -#include <linux/vmalloc.h> -#include <linux/firmware.h> -#include <linux/ctype.h> -#include <linux/of.h> -#include <linux/idr.h> -#include <linux/inetdevice.h> -#include <linux/devcoredump.h> - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "pcie.h" -#include "usb.h" -#include "sdio.h" - -extern const char driver_version[]; - -struct mwifiex_adapter; -struct mwifiex_private; - -enum { - MWIFIEX_ASYNC_CMD, - MWIFIEX_SYNC_CMD -}; - -#define MWIFIEX_DRIVER_MODE_STA BIT(0) -#define MWIFIEX_DRIVER_MODE_UAP BIT(1) -#define MWIFIEX_DRIVER_MODE_P2P BIT(2) -#define MWIFIEX_DRIVER_MODE_BITMASK (BIT(0) | BIT(1) | BIT(2)) - -#define MWIFIEX_MAX_AP 64 - -#define MWIFIEX_MAX_PKTS_TXQ 16 - -#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) - -#define MWIFIEX_TIMER_10S 10000 -#define MWIFIEX_TIMER_1S 1000 - -#define MAX_TX_PENDING 100 -#define LOW_TX_PENDING 80 - -#define HIGH_RX_PENDING 50 -#define LOW_RX_PENDING 20 - -#define MWIFIEX_UPLD_SIZE (2312) - -#define MAX_EVENT_SIZE 2048 - -#define ARP_FILTER_MAX_BUF_SIZE 68 - -#define MWIFIEX_KEY_BUFFER_SIZE 16 -#define MWIFIEX_DEFAULT_LISTEN_INTERVAL 10 -#define MWIFIEX_MAX_REGION_CODE 7 - -#define DEFAULT_BCN_AVG_FACTOR 8 -#define DEFAULT_DATA_AVG_FACTOR 8 - -#define FIRST_VALID_CHANNEL 0xff -#define DEFAULT_AD_HOC_CHANNEL 6 -#define DEFAULT_AD_HOC_CHANNEL_A 36 - -#define DEFAULT_BCN_MISS_TIMEOUT 5 - -#define MAX_SCAN_BEACON_BUFFER 8000 - -#define SCAN_BEACON_ENTRY_PAD 6 - -#define MWIFIEX_PASSIVE_SCAN_CHAN_TIME 110 -#define MWIFIEX_ACTIVE_SCAN_CHAN_TIME 30 -#define MWIFIEX_SPECIFIC_SCAN_CHAN_TIME 30 -#define MWIFIEX_DEF_SCAN_CHAN_GAP_TIME 50 - -#define SCAN_RSSI(RSSI) (0x100 - ((u8)(RSSI))) - -#define MWIFIEX_MAX_TOTAL_SCAN_TIME (MWIFIEX_TIMER_10S - MWIFIEX_TIMER_1S) - -#define RSN_GTK_OUI_OFFSET 2 - -#define MWIFIEX_OUI_NOT_PRESENT 0 -#define MWIFIEX_OUI_PRESENT 1 - -#define PKT_TYPE_MGMT 0xE5 - -/* - * Do not check for data_received for USB, as data_received - * is handled in mwifiex_usb_recv for USB - */ -#define IS_CARD_RX_RCVD(adapter) (adapter->cmd_resp_received || \ - adapter->event_received || \ - adapter->data_received) - -#define MWIFIEX_TYPE_CMD 1 -#define MWIFIEX_TYPE_DATA 0 -#define MWIFIEX_TYPE_AGGR_DATA 10 -#define MWIFIEX_TYPE_EVENT 3 - -#define MAX_BITMAP_RATES_SIZE 18 - -#define MAX_CHANNEL_BAND_BG 14 -#define MAX_CHANNEL_BAND_A 165 - -#define MAX_FREQUENCY_BAND_BG 2484 - -#define MWIFIEX_EVENT_HEADER_LEN 4 -#define MWIFIEX_UAP_EVENT_EXTRA_HEADER 2 - -#define MWIFIEX_TYPE_LEN 4 -#define MWIFIEX_USB_TYPE_CMD 0xF00DFACE -#define MWIFIEX_USB_TYPE_DATA 0xBEADC0DE -#define MWIFIEX_USB_TYPE_EVENT 0xBEEFFACE - -/* Threshold for tx_timeout_cnt before we trigger a card reset */ -#define TX_TIMEOUT_THRESHOLD 6 - -#define MWIFIEX_DRV_INFO_SIZE_MAX 0x40000 - -/* Address alignment */ -#define MWIFIEX_ALIGN_ADDR(p, a) (((long)(p) + (a) - 1) & ~((a) - 1)) - -/** - *enum mwifiex_debug_level - marvell wifi debug level - */ -enum MWIFIEX_DEBUG_LEVEL { - MWIFIEX_DBG_MSG = 0x00000001, - MWIFIEX_DBG_FATAL = 0x00000002, - MWIFIEX_DBG_ERROR = 0x00000004, - MWIFIEX_DBG_DATA = 0x00000008, - MWIFIEX_DBG_CMD = 0x00000010, - MWIFIEX_DBG_EVENT = 0x00000020, - MWIFIEX_DBG_INTR = 0x00000040, - MWIFIEX_DBG_IOCTL = 0x00000080, - - MWIFIEX_DBG_MPA_D = 0x00008000, - MWIFIEX_DBG_DAT_D = 0x00010000, - MWIFIEX_DBG_CMD_D = 0x00020000, - MWIFIEX_DBG_EVT_D = 0x00040000, - MWIFIEX_DBG_FW_D = 0x00080000, - MWIFIEX_DBG_IF_D = 0x00100000, - - MWIFIEX_DBG_ENTRY = 0x10000000, - MWIFIEX_DBG_WARN = 0x20000000, - MWIFIEX_DBG_INFO = 0x40000000, - MWIFIEX_DBG_DUMP = 0x80000000, - - MWIFIEX_DBG_ANY = 0xffffffff -}; - -#define MWIFIEX_DEFAULT_DEBUG_MASK (MWIFIEX_DBG_MSG | \ - MWIFIEX_DBG_FATAL | \ - MWIFIEX_DBG_ERROR) - -__printf(3, 4) -void _mwifiex_dbg(const struct mwifiex_adapter *adapter, int mask, - const char *fmt, ...); -#define mwifiex_dbg(adapter, mask, fmt, ...) \ - _mwifiex_dbg(adapter, MWIFIEX_DBG_##mask, fmt, ##__VA_ARGS__) - -#define DEBUG_DUMP_DATA_MAX_LEN 128 -#define mwifiex_dbg_dump(adapter, dbg_mask, str, buf, len) \ -do { \ - if ((adapter)->debug_mask & MWIFIEX_DBG_##dbg_mask) \ - print_hex_dump(KERN_DEBUG, str, \ - DUMP_PREFIX_OFFSET, 16, 1, \ - buf, len, false); \ -} while (0) - -struct mwifiex_dbg { - u32 num_cmd_host_to_card_failure; - u32 num_cmd_sleep_cfm_host_to_card_failure; - u32 num_tx_host_to_card_failure; - u32 num_event_deauth; - u32 num_event_disassoc; - u32 num_event_link_lost; - u32 num_cmd_deauth; - u32 num_cmd_assoc_success; - u32 num_cmd_assoc_failure; - u32 num_tx_timeout; - u16 timeout_cmd_id; - u16 timeout_cmd_act; - u16 last_cmd_id[DBG_CMD_NUM]; - u16 last_cmd_act[DBG_CMD_NUM]; - u16 last_cmd_index; - u16 last_cmd_resp_id[DBG_CMD_NUM]; - u16 last_cmd_resp_index; - u16 last_event[DBG_CMD_NUM]; - u16 last_event_index; -}; - -enum MWIFIEX_HARDWARE_STATUS { - MWIFIEX_HW_STATUS_READY, - MWIFIEX_HW_STATUS_INITIALIZING, - MWIFIEX_HW_STATUS_INIT_DONE, - MWIFIEX_HW_STATUS_RESET, - MWIFIEX_HW_STATUS_CLOSING, - MWIFIEX_HW_STATUS_NOT_READY -}; - -enum MWIFIEX_802_11_POWER_MODE { - MWIFIEX_802_11_POWER_MODE_CAM, - MWIFIEX_802_11_POWER_MODE_PSP -}; - -struct mwifiex_tx_param { - u32 next_pkt_len; -}; - -enum MWIFIEX_PS_STATE { - PS_STATE_AWAKE, - PS_STATE_PRE_SLEEP, - PS_STATE_SLEEP_CFM, - PS_STATE_SLEEP -}; - -enum mwifiex_iface_type { - MWIFIEX_SDIO, - MWIFIEX_PCIE, - MWIFIEX_USB -}; - -struct mwifiex_add_ba_param { - u32 tx_win_size; - u32 rx_win_size; - u32 timeout; - u8 tx_amsdu; - u8 rx_amsdu; -}; - -struct mwifiex_tx_aggr { - u8 ampdu_user; - u8 ampdu_ap; - u8 amsdu; -}; - -enum mwifiex_ba_status { - BA_SETUP_NONE = 0, - BA_SETUP_INPROGRESS, - BA_SETUP_COMPLETE -}; - -struct mwifiex_ra_list_tbl { - struct list_head list; - struct sk_buff_head skb_head; - u8 ra[ETH_ALEN]; - u32 is_11n_enabled; - u16 max_amsdu; - u16 ba_pkt_count; - u8 ba_packet_thr; - enum mwifiex_ba_status ba_status; - u8 amsdu_in_ampdu; - u16 total_pkt_count; - bool tdls_link; - bool tx_paused; -}; - -struct mwifiex_tid_tbl { - struct list_head ra_list; -}; - -#define WMM_HIGHEST_PRIORITY 7 -#define HIGH_PRIO_TID 7 -#define LOW_PRIO_TID 0 - -struct mwifiex_wmm_desc { - struct mwifiex_tid_tbl tid_tbl_ptr[MAX_NUM_TID]; - u32 packets_out[MAX_NUM_TID]; - u32 pkts_paused[MAX_NUM_TID]; - /* spin lock to protect ra_list */ - spinlock_t ra_list_spinlock; - struct mwifiex_wmm_ac_status ac_status[IEEE80211_NUM_ACS]; - enum mwifiex_wmm_ac_e ac_down_graded_vals[IEEE80211_NUM_ACS]; - u32 drv_pkt_delay_max; - u8 queue_priority[IEEE80211_NUM_ACS]; - u32 user_pri_pkt_tx_ctrl[WMM_HIGHEST_PRIORITY + 1]; /* UP: 0 to 7 */ - /* Number of transmit packets queued */ - atomic_t tx_pkts_queued; - /* Tracks highest priority with a packet queued */ - atomic_t highest_queued_prio; -}; - -struct mwifiex_802_11_security { - u8 wpa_enabled; - u8 wpa2_enabled; - u8 wapi_enabled; - u8 wapi_key_on; - u8 wep_enabled; - u32 authentication_mode; - u8 is_authtype_auto; - u32 encryption_mode; -}; - -struct ieee_types_header { - u8 element_id; - u8 len; -} __packed; - -struct ieee_types_vendor_specific { - struct ieee_types_vendor_header vend_hdr; - u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; -} __packed; - -struct ieee_types_generic { - struct ieee_types_header ieee_hdr; - u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_header)]; -} __packed; - -struct ieee_types_bss_co_2040 { - struct ieee_types_header ieee_hdr; - u8 bss_2040co; -} __packed; - -struct ieee_types_extcap { - struct ieee_types_header ieee_hdr; - u8 ext_capab[8]; -} __packed; - -struct ieee_types_vht_cap { - struct ieee_types_header ieee_hdr; - struct ieee80211_vht_cap vhtcap; -} __packed; - -struct ieee_types_vht_oper { - struct ieee_types_header ieee_hdr; - struct ieee80211_vht_operation vhtoper; -} __packed; - -struct ieee_types_aid { - struct ieee_types_header ieee_hdr; - u16 aid; -} __packed; - -struct mwifiex_bssdescriptor { - u8 mac_address[ETH_ALEN]; - struct cfg80211_ssid ssid; - u32 privacy; - s32 rssi; - u32 channel; - u32 freq; - u16 beacon_period; - u8 erp_flags; - u32 bss_mode; - u8 supported_rates[MWIFIEX_SUPPORTED_RATES]; - u8 data_rates[MWIFIEX_SUPPORTED_RATES]; - /* Network band. - * BAND_B(0x01): 'b' band - * BAND_G(0x02): 'g' band - * BAND_A(0X04): 'a' band - */ - u16 bss_band; - u64 fw_tsf; - u64 timestamp; - union ieee_types_phy_param_set phy_param_set; - union ieee_types_ss_param_set ss_param_set; - u16 cap_info_bitmap; - struct ieee_types_wmm_parameter wmm_ie; - u8 disable_11n; - struct ieee80211_ht_cap *bcn_ht_cap; - u16 ht_cap_offset; - struct ieee80211_ht_operation *bcn_ht_oper; - u16 ht_info_offset; - u8 *bcn_bss_co_2040; - u16 bss_co_2040_offset; - u8 *bcn_ext_cap; - u16 ext_cap_offset; - struct ieee80211_vht_cap *bcn_vht_cap; - u16 vht_cap_offset; - struct ieee80211_vht_operation *bcn_vht_oper; - u16 vht_info_offset; - struct ieee_types_oper_mode_ntf *oper_mode; - u16 oper_mode_offset; - u8 disable_11ac; - struct ieee_types_vendor_specific *bcn_wpa_ie; - u16 wpa_offset; - struct ieee_types_generic *bcn_rsn_ie; - u16 rsn_offset; - struct ieee_types_generic *bcn_wapi_ie; - u16 wapi_offset; - u8 *beacon_buf; - u32 beacon_buf_size; - u8 sensed_11h; - u8 local_constraint; - u8 chan_sw_ie_present; -}; - -struct mwifiex_current_bss_params { - struct mwifiex_bssdescriptor bss_descriptor; - u8 wmm_enabled; - u8 wmm_uapsd_enabled; - u8 band; - u32 num_of_rates; - u8 data_rates[MWIFIEX_SUPPORTED_RATES]; -}; - -struct mwifiex_sleep_params { - u16 sp_error; - u16 sp_offset; - u16 sp_stable_time; - u8 sp_cal_control; - u8 sp_ext_sleep_clk; - u16 sp_reserved; -}; - -struct mwifiex_sleep_period { - u16 period; - u16 reserved; -}; - -struct mwifiex_wep_key { - u32 length; - u32 key_index; - u32 key_length; - u8 key_material[MWIFIEX_KEY_BUFFER_SIZE]; -}; - -#define MAX_REGION_CHANNEL_NUM 2 - -struct mwifiex_chan_freq_power { - u16 channel; - u32 freq; - u16 max_tx_power; - u8 unsupported; -}; - -enum state_11d_t { - DISABLE_11D = 0, - ENABLE_11D = 1, -}; - -#define MWIFIEX_MAX_TRIPLET_802_11D 83 - -struct mwifiex_802_11d_domain_reg { - u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; - u8 no_of_triplet; - struct ieee80211_country_ie_triplet - triplet[MWIFIEX_MAX_TRIPLET_802_11D]; -}; - -struct mwifiex_vendor_spec_cfg_ie { - u16 mask; - u16 flag; - u8 ie[MWIFIEX_MAX_VSIE_LEN]; -}; - -struct wps { - u8 session_enable; -}; - -struct mwifiex_roc_cfg { - u64 cookie; - struct ieee80211_channel chan; -}; - -#define MWIFIEX_FW_DUMP_IDX 0xff -#define MWIFIEX_DRV_INFO_IDX 20 -#define FW_DUMP_MAX_NAME_LEN 8 -#define FW_DUMP_HOST_READY 0xEE -#define FW_DUMP_DONE 0xFF -#define FW_DUMP_READ_DONE 0xFE - -struct memory_type_mapping { - u8 mem_name[FW_DUMP_MAX_NAME_LEN]; - u8 *mem_ptr; - u32 mem_size; - u8 done_flag; -}; - -enum rdwr_status { - RDWR_STATUS_SUCCESS = 0, - RDWR_STATUS_FAILURE = 1, - RDWR_STATUS_DONE = 2 -}; - -enum mwifiex_iface_work_flags { - MWIFIEX_IFACE_WORK_DEVICE_DUMP, - MWIFIEX_IFACE_WORK_CARD_RESET, -}; - -struct mwifiex_private { - struct mwifiex_adapter *adapter; - u8 bss_type; - u8 bss_role; - u8 bss_priority; - u8 bss_num; - u8 bss_started; - u8 frame_type; - u8 curr_addr[ETH_ALEN]; - u8 media_connected; - u8 port_open; - u8 usb_port; - u32 num_tx_timeout; - /* track consecutive timeout */ - u8 tx_timeout_cnt; - struct net_device *netdev; - struct net_device_stats stats; - u16 curr_pkt_filter; - u32 bss_mode; - u32 pkt_tx_ctrl; - u16 tx_power_level; - u8 max_tx_power_level; - u8 min_tx_power_level; - u8 tx_rate; - u8 tx_htinfo; - u8 rxpd_htinfo; - u8 rxpd_rate; - u16 rate_bitmap; - u16 bitmap_rates[MAX_BITMAP_RATES_SIZE]; - u32 data_rate; - u8 is_data_rate_auto; - u16 bcn_avg_factor; - u16 data_avg_factor; - s16 data_rssi_last; - s16 data_nf_last; - s16 data_rssi_avg; - s16 data_nf_avg; - s16 bcn_rssi_last; - s16 bcn_nf_last; - s16 bcn_rssi_avg; - s16 bcn_nf_avg; - struct mwifiex_bssdescriptor *attempted_bss_desc; - struct cfg80211_ssid prev_ssid; - u8 prev_bssid[ETH_ALEN]; - struct mwifiex_current_bss_params curr_bss_params; - u16 beacon_period; - u8 dtim_period; - u16 listen_interval; - u16 atim_window; - u8 adhoc_channel; - u8 adhoc_is_link_sensed; - u8 adhoc_state; - struct mwifiex_802_11_security sec_info; - struct mwifiex_wep_key wep_key[NUM_WEP_KEYS]; - u16 wep_key_curr_index; - u8 wpa_ie[256]; - u8 wpa_ie_len; - u8 wpa_is_gtk_set; - struct host_cmd_ds_802_11_key_material aes_key; - struct host_cmd_ds_802_11_key_material_v2 aes_key_v2; - u8 wapi_ie[256]; - u8 wapi_ie_len; - u8 *wps_ie; - u8 wps_ie_len; - u8 wmm_required; - u8 wmm_enabled; - u8 wmm_qosinfo; - struct mwifiex_wmm_desc wmm; - atomic_t wmm_tx_pending[IEEE80211_NUM_ACS]; - struct list_head sta_list; - /* spin lock for associated station/TDLS peers list */ - spinlock_t sta_list_spinlock; - struct list_head auto_tdls_list; - /* spin lock for auto TDLS peer list */ - spinlock_t auto_tdls_lock; - struct list_head tx_ba_stream_tbl_ptr; - /* spin lock for tx_ba_stream_tbl_ptr queue */ - spinlock_t tx_ba_stream_tbl_lock; - struct mwifiex_tx_aggr aggr_prio_tbl[MAX_NUM_TID]; - struct mwifiex_add_ba_param add_ba_param; - u16 rx_seq[MAX_NUM_TID]; - u8 tos_to_tid_inv[MAX_NUM_TID]; - struct list_head rx_reorder_tbl_ptr; - /* spin lock for rx_reorder_tbl_ptr queue */ - spinlock_t rx_reorder_tbl_lock; - /* spin lock for Rx packets */ - spinlock_t rx_pkt_lock; - -#define MWIFIEX_ASSOC_RSP_BUF_SIZE 500 - u8 assoc_rsp_buf[MWIFIEX_ASSOC_RSP_BUF_SIZE]; - u32 assoc_rsp_size; - -#define MWIFIEX_GENIE_BUF_SIZE 256 - u8 gen_ie_buf[MWIFIEX_GENIE_BUF_SIZE]; - u8 gen_ie_buf_len; - - struct mwifiex_vendor_spec_cfg_ie vs_ie[MWIFIEX_MAX_VSIE_NUM]; - -#define MWIFIEX_ASSOC_TLV_BUF_SIZE 256 - u8 assoc_tlv_buf[MWIFIEX_ASSOC_TLV_BUF_SIZE]; - u8 assoc_tlv_buf_len; - - u8 *curr_bcn_buf; - u32 curr_bcn_size; - /* spin lock for beacon buffer */ - spinlock_t curr_bcn_buf_lock; - struct wireless_dev wdev; - struct mwifiex_chan_freq_power cfp; - char version_str[128]; -#ifdef CONFIG_DEBUG_FS - struct dentry *dfs_dev_dir; -#endif - u16 current_key_index; - struct semaphore async_sem; - struct cfg80211_scan_request *scan_request; - u8 cfg_bssid[6]; - struct wps wps; - u8 scan_block; - s32 cqm_rssi_thold; - u32 cqm_rssi_hyst; - u8 subsc_evt_rssi_state; - struct mwifiex_ds_misc_subsc_evt async_subsc_evt_storage; - struct mwifiex_ie mgmt_ie[MAX_MGMT_IE_INDEX]; - u16 beacon_idx; - u16 proberesp_idx; - u16 assocresp_idx; - u16 gen_idx; - u8 ap_11n_enabled; - u8 ap_11ac_enabled; - u32 mgmt_frame_mask; - struct mwifiex_roc_cfg roc_cfg; - bool scan_aborting; - u8 csa_chan; - unsigned long csa_expire_time; - u8 del_list_idx; - bool hs2_enabled; - struct mwifiex_uap_bss_param bss_cfg; - struct cfg80211_chan_def bss_chandef; - struct station_parameters *sta_params; - struct sk_buff_head tdls_txq; - u8 check_tdls_tx; - struct timer_list auto_tdls_timer; - bool auto_tdls_timer_active; - struct idr ack_status_frames; - /* spin lock for ack status */ - spinlock_t ack_status_lock; - /** rx histogram data */ - struct mwifiex_histogram_data *hist_data; - struct cfg80211_chan_def dfs_chandef; - struct workqueue_struct *dfs_cac_workqueue; - struct delayed_work dfs_cac_work; - struct timer_list dfs_chan_switch_timer; - struct workqueue_struct *dfs_chan_sw_workqueue; - struct delayed_work dfs_chan_sw_work; - struct cfg80211_beacon_data beacon_after; - struct mwifiex_11h_intf_state state_11h; - struct mwifiex_ds_mem_rw mem_rw; - struct sk_buff_head bypass_txq; - struct mwifiex_user_scan_chan hidden_chan[MWIFIEX_USER_SCAN_CHAN_MAX]; -}; - - -struct mwifiex_tx_ba_stream_tbl { - struct list_head list; - int tid; - u8 ra[ETH_ALEN]; - enum mwifiex_ba_status ba_status; - u8 amsdu; -}; - -struct mwifiex_rx_reorder_tbl; - -struct reorder_tmr_cnxt { - struct timer_list timer; - struct mwifiex_rx_reorder_tbl *ptr; - struct mwifiex_private *priv; - u8 timer_is_set; -}; - -struct mwifiex_rx_reorder_tbl { - struct list_head list; - int tid; - u8 ta[ETH_ALEN]; - int init_win; - int start_win; - int win_size; - void **rx_reorder_ptr; - struct reorder_tmr_cnxt timer_context; - u8 amsdu; - u8 flags; -}; - -struct mwifiex_bss_prio_node { - struct list_head list; - struct mwifiex_private *priv; -}; - -struct mwifiex_bss_prio_tbl { - struct list_head bss_prio_head; - /* spin lock for bss priority */ - spinlock_t bss_prio_lock; - struct mwifiex_bss_prio_node *bss_prio_cur; -}; - -struct cmd_ctrl_node { - struct list_head list; - struct mwifiex_private *priv; - u32 cmd_oid; - u32 cmd_flag; - struct sk_buff *cmd_skb; - struct sk_buff *resp_skb; - void *data_buf; - u32 wait_q_enabled; - struct sk_buff *skb; - u8 *condition; - u8 cmd_wait_q_woken; -}; - -struct mwifiex_bss_priv { - u8 band; - u64 fw_tsf; -}; - -struct mwifiex_tdls_capab { - __le16 capab; - u8 rates[32]; - u8 rates_len; - u8 qos_info; - u8 coex_2040; - u16 aid; - struct ieee80211_ht_cap ht_capb; - struct ieee80211_ht_operation ht_oper; - struct ieee_types_extcap extcap; - struct ieee_types_generic rsn_ie; - struct ieee80211_vht_cap vhtcap; - struct ieee80211_vht_operation vhtoper; -}; - -struct mwifiex_station_stats { - u64 last_rx; - s8 rssi; - u64 rx_bytes; - u64 tx_bytes; - u32 rx_packets; - u32 tx_packets; - u32 tx_failed; - u8 last_tx_rate; - u8 last_tx_htinfo; -}; - -/* This is AP/TDLS specific structure which stores information - * about associated/peer STA - */ -struct mwifiex_sta_node { - struct list_head list; - u8 mac_addr[ETH_ALEN]; - u8 is_wmm_enabled; - u8 is_11n_enabled; - u8 is_11ac_enabled; - u8 ampdu_sta[MAX_NUM_TID]; - u16 rx_seq[MAX_NUM_TID]; - u16 max_amsdu; - u8 tdls_status; - struct mwifiex_tdls_capab tdls_cap; - struct mwifiex_station_stats stats; - u8 tx_pause; -}; - -struct mwifiex_auto_tdls_peer { - struct list_head list; - u8 mac_addr[ETH_ALEN]; - u8 tdls_status; - int rssi; - long rssi_jiffies; - u8 failure_count; - u8 do_discover; - u8 do_setup; -}; - -struct mwifiex_if_ops { - int (*init_if) (struct mwifiex_adapter *); - void (*cleanup_if) (struct mwifiex_adapter *); - int (*check_fw_status) (struct mwifiex_adapter *, u32); - int (*prog_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); - int (*register_dev) (struct mwifiex_adapter *); - void (*unregister_dev) (struct mwifiex_adapter *); - int (*enable_int) (struct mwifiex_adapter *); - void (*disable_int) (struct mwifiex_adapter *); - int (*process_int_status) (struct mwifiex_adapter *); - int (*host_to_card) (struct mwifiex_adapter *, u8, struct sk_buff *, - struct mwifiex_tx_param *); - int (*wakeup) (struct mwifiex_adapter *); - int (*wakeup_complete) (struct mwifiex_adapter *); - - /* Interface specific functions */ - void (*update_mp_end_port) (struct mwifiex_adapter *, u16); - void (*cleanup_mpa_buf) (struct mwifiex_adapter *); - int (*cmdrsp_complete) (struct mwifiex_adapter *, struct sk_buff *); - int (*event_complete) (struct mwifiex_adapter *, struct sk_buff *); - int (*init_fw_port) (struct mwifiex_adapter *); - int (*dnld_fw) (struct mwifiex_adapter *, struct mwifiex_fw_image *); - void (*card_reset) (struct mwifiex_adapter *); - int (*reg_dump)(struct mwifiex_adapter *, char *); - void (*device_dump)(struct mwifiex_adapter *); - int (*clean_pcie_ring) (struct mwifiex_adapter *adapter); - void (*iface_work)(struct work_struct *work); - void (*submit_rem_rx_urbs)(struct mwifiex_adapter *adapter); - void (*deaggr_pkt)(struct mwifiex_adapter *, struct sk_buff *); - void (*multi_port_resync)(struct mwifiex_adapter *); - bool (*is_port_ready)(struct mwifiex_private *); -}; - -struct mwifiex_adapter { - u8 iface_type; - unsigned int debug_mask; - struct mwifiex_iface_comb iface_limit; - struct mwifiex_iface_comb curr_iface_comb; - struct mwifiex_private *priv[MWIFIEX_MAX_BSS_NUM]; - u8 priv_num; - const struct firmware *firmware; - char fw_name[32]; - int winner; - struct device *dev; - struct wiphy *wiphy; - u8 perm_addr[ETH_ALEN]; - bool surprise_removed; - u32 fw_release_number; - u16 init_wait_q_woken; - wait_queue_head_t init_wait_q; - void *card; - struct mwifiex_if_ops if_ops; - atomic_t bypass_tx_pending; - atomic_t rx_pending; - atomic_t tx_pending; - atomic_t cmd_pending; - struct workqueue_struct *workqueue; - struct work_struct main_work; - struct workqueue_struct *rx_workqueue; - struct work_struct rx_work; - struct workqueue_struct *dfs_workqueue; - struct work_struct dfs_work; - bool rx_work_enabled; - bool rx_processing; - bool delay_main_work; - bool rx_locked; - bool main_locked; - struct mwifiex_bss_prio_tbl bss_prio_tbl[MWIFIEX_MAX_BSS_NUM]; - /* spin lock for init/shutdown */ - spinlock_t mwifiex_lock; - /* spin lock for main process */ - spinlock_t main_proc_lock; - u32 mwifiex_processing; - u8 more_task_flag; - u16 tx_buf_size; - u16 curr_tx_buf_size; - /* sdio single port rx aggregation capability */ - bool host_disable_sdio_rx_aggr; - bool sdio_rx_aggr_enable; - u16 sdio_rx_block_size; - u32 ioport; - enum MWIFIEX_HARDWARE_STATUS hw_status; - u16 number_of_antenna; - u32 fw_cap_info; - /* spin lock for interrupt handling */ - spinlock_t int_lock; - u8 int_status; - u32 event_cause; - struct sk_buff *event_skb; - u8 upld_buf[MWIFIEX_UPLD_SIZE]; - u8 data_sent; - u8 cmd_sent; - u8 cmd_resp_received; - u8 event_received; - u8 data_received; - u16 seq_num; - struct cmd_ctrl_node *cmd_pool; - struct cmd_ctrl_node *curr_cmd; - /* spin lock for command */ - spinlock_t mwifiex_cmd_lock; - u8 is_cmd_timedout; - u16 last_init_cmd; - struct timer_list cmd_timer; - struct list_head cmd_free_q; - /* spin lock for cmd_free_q */ - spinlock_t cmd_free_q_lock; - struct list_head cmd_pending_q; - /* spin lock for cmd_pending_q */ - spinlock_t cmd_pending_q_lock; - struct list_head scan_pending_q; - /* spin lock for scan_pending_q */ - spinlock_t scan_pending_q_lock; - /* spin lock for RX processing routine */ - spinlock_t rx_proc_lock; - struct sk_buff_head tx_data_q; - atomic_t tx_queued; - u32 scan_processing; - u16 region_code; - struct mwifiex_802_11d_domain_reg domain_reg; - u16 scan_probes; - u32 scan_mode; - u16 specific_scan_time; - u16 active_scan_time; - u16 passive_scan_time; - u16 scan_chan_gap_time; - u8 fw_bands; - u8 adhoc_start_band; - u8 config_bands; - struct mwifiex_chan_scan_param_set *scan_channels; - u8 tx_lock_flag; - struct mwifiex_sleep_params sleep_params; - struct mwifiex_sleep_period sleep_period; - u16 ps_mode; - u32 ps_state; - u8 need_to_wakeup; - u16 multiple_dtim; - u16 local_listen_interval; - u16 null_pkt_interval; - struct sk_buff *sleep_cfm; - u16 bcn_miss_time_out; - u16 adhoc_awake_period; - u8 is_deep_sleep; - u8 delay_null_pkt; - u16 delay_to_ps; - u16 enhanced_ps_mode; - u8 pm_wakeup_card_req; - u16 gen_null_pkt; - u16 pps_uapsd_mode; - u32 pm_wakeup_fw_try; - struct timer_list wakeup_timer; - u8 is_hs_configured; - struct mwifiex_hs_config_param hs_cfg; - u8 hs_activated; - u16 hs_activate_wait_q_woken; - wait_queue_head_t hs_activate_wait_q; - bool is_suspended; - bool hs_enabling; - u8 event_body[MAX_EVENT_SIZE]; - u32 hw_dot_11n_dev_cap; - u8 hw_dev_mcs_support; - u8 user_dev_mcs_support; - u8 adhoc_11n_enabled; - u8 sec_chan_offset; - struct mwifiex_dbg dbg; - u8 arp_filter[ARP_FILTER_MAX_BUF_SIZE]; - u32 arp_filter_size; - struct mwifiex_wait_queue cmd_wait_q; - u8 scan_wait_q_woken; - spinlock_t queue_lock; /* lock for tx queues */ - u8 country_code[IEEE80211_COUNTRY_STRING_LEN]; - u16 max_mgmt_ie_index; - const struct firmware *cal_data; - struct device_node *dt_node; - - /* 11AC */ - u32 is_hw_11ac_capable; - u32 hw_dot_11ac_dev_cap; - u32 hw_dot_11ac_mcs_support; - u32 usr_dot_11ac_dev_cap_bg; - u32 usr_dot_11ac_dev_cap_a; - u32 usr_dot_11ac_mcs_support; - - atomic_t pending_bridged_pkts; - struct semaphore *card_sem; - bool ext_scan; - u8 fw_api_ver; - u8 key_api_major_ver, key_api_minor_ver; - struct memory_type_mapping *mem_type_mapping_tbl; - u8 num_mem_types; - void *drv_info_dump; - u32 drv_info_size; - bool scan_chan_gap_enabled; - struct sk_buff_head rx_data_q; - struct mwifiex_chan_stats *chan_stats; - u32 num_in_chan_stats; - int survey_idx; - bool auto_tdls; - u8 coex_scan; - u8 coex_min_scan_time; - u8 coex_max_scan_time; - u8 coex_win_size; - u8 coex_tx_win_size; - u8 coex_rx_win_size; - bool drcs_enabled; - u8 active_scan_triggered; - bool usb_mc_status; - bool usb_mc_setup; -}; - -void mwifiex_process_tx_queue(struct mwifiex_adapter *adapter); - -int mwifiex_init_lock_list(struct mwifiex_adapter *adapter); - -void mwifiex_set_trans_start(struct net_device *dev); - -void mwifiex_stop_net_dev_queue(struct net_device *netdev, - struct mwifiex_adapter *adapter); - -void mwifiex_wake_up_net_dev_queue(struct net_device *netdev, - struct mwifiex_adapter *adapter); - -int mwifiex_init_priv(struct mwifiex_private *priv); -void mwifiex_free_priv(struct mwifiex_private *priv); - -int mwifiex_init_fw(struct mwifiex_adapter *adapter); - -int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter); - -int mwifiex_shutdown_drv(struct mwifiex_adapter *adapter); - -int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter); - -int mwifiex_dnld_fw(struct mwifiex_adapter *, struct mwifiex_fw_image *); - -int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb); - -int mwifiex_process_mgmt_packet(struct mwifiex_private *priv, - struct sk_buff *skb); - -int mwifiex_process_event(struct mwifiex_adapter *adapter); - -int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node); - -int mwifiex_send_cmd(struct mwifiex_private *priv, u16 cmd_no, - u16 cmd_action, u32 cmd_oid, void *data_buf, bool sync); - -void mwifiex_cmd_timeout_func(unsigned long function_context); - -int mwifiex_get_debug_info(struct mwifiex_private *, - struct mwifiex_debug_info *); - -int mwifiex_alloc_cmd_buffer(struct mwifiex_adapter *adapter); -int mwifiex_free_cmd_buffer(struct mwifiex_adapter *adapter); -void mwifiex_cancel_all_pending_cmd(struct mwifiex_adapter *adapter); -void mwifiex_cancel_pending_ioctl(struct mwifiex_adapter *adapter); - -void mwifiex_insert_cmd_to_free_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node); -void mwifiex_recycle_cmd_node(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node); - -void mwifiex_insert_cmd_to_pending_q(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node, - u32 addtail); - -int mwifiex_exec_next_cmd(struct mwifiex_adapter *adapter); -int mwifiex_process_cmdresp(struct mwifiex_adapter *adapter); -int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb); -int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, - struct mwifiex_tx_param *tx_param); -int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags); -int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int aggr, int status); -void mwifiex_clean_txrx(struct mwifiex_private *priv); -u8 mwifiex_check_last_packet_indication(struct mwifiex_private *priv); -void mwifiex_check_ps_cond(struct mwifiex_adapter *adapter); -void mwifiex_process_sleep_confirm_resp(struct mwifiex_adapter *, u8 *, - u32); -int mwifiex_cmd_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, uint16_t ps_bitmap, - struct mwifiex_ds_auto_ds *auto_ds); -int mwifiex_ret_enh_power_mode(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct mwifiex_ds_pm_cfg *pm_cfg); -void mwifiex_process_hs_config(struct mwifiex_adapter *adapter); -void mwifiex_hs_activated_event(struct mwifiex_private *priv, - u8 activated); -int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, - int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg); -int mwifiex_ret_802_11_hs_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_process_rx_packet(struct mwifiex_private *priv, - struct sk_buff *skb); -int mwifiex_sta_prepare_cmd(struct mwifiex_private *, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *data_buf, void *cmd_buf); -int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *data_buf, void *cmd_buf); -int mwifiex_process_sta_cmdresp(struct mwifiex_private *, u16 cmdresp_no, - struct host_cmd_ds_command *resp); -int mwifiex_process_sta_rx_packet(struct mwifiex_private *, - struct sk_buff *skb); -int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, - struct sk_buff *skb); -int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, - struct sk_buff *skb); -int mwifiex_process_sta_event(struct mwifiex_private *); -int mwifiex_process_uap_event(struct mwifiex_private *); -void mwifiex_delete_all_station_list(struct mwifiex_private *priv); -void mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, - const u8 *ra_addr); -void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb); -void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb); -int mwifiex_sta_init_cmd(struct mwifiex_private *, u8 first_sta, bool init); -int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, - struct mwifiex_scan_cmd_config *scan_cfg); -void mwifiex_queue_scan_cmd(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node); -int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -s32 mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2); -int mwifiex_associate(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -void mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason); -u8 mwifiex_band_to_radio_type(u8 band); -int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); -void mwifiex_deauthenticate_all(struct mwifiex_adapter *adapter); -int mwifiex_adhoc_start(struct mwifiex_private *priv, - struct cfg80211_ssid *adhoc_ssid); -int mwifiex_adhoc_join(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_cmd_802_11_ad_hoc_start(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct cfg80211_ssid *req_ssid); -int mwifiex_cmd_802_11_ad_hoc_join(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_ret_802_11_ad_hoc(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd); -struct mwifiex_chan_freq_power *mwifiex_get_cfp(struct mwifiex_private *priv, - u8 band, u16 channel, u32 freq); -u32 mwifiex_index_to_data_rate(struct mwifiex_private *priv, - u8 index, u8 ht_info); -u32 mwifiex_index_to_acs_data_rate(struct mwifiex_private *priv, - u8 index, u8 ht_info); -u32 mwifiex_find_freq_from_band_chan(u8, u8); -int mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, u16 vsie_mask, - u8 **buffer); -u32 mwifiex_get_active_data_rates(struct mwifiex_private *priv, - u8 *rates); -u32 mwifiex_get_supported_rates(struct mwifiex_private *priv, u8 *rates); -u32 mwifiex_get_rates_from_cfg80211(struct mwifiex_private *priv, - u8 *rates, u8 radio_type); -u8 mwifiex_is_rate_auto(struct mwifiex_private *priv); -extern u16 region_code_index[MWIFIEX_MAX_REGION_CODE]; -void mwifiex_save_curr_bcn(struct mwifiex_private *priv); -void mwifiex_free_curr_bcn(struct mwifiex_private *priv); -int mwifiex_cmd_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd); -int mwifiex_ret_get_hw_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int is_command_pending(struct mwifiex_adapter *adapter); -void mwifiex_init_priv_params(struct mwifiex_private *priv, - struct net_device *dev); -int mwifiex_set_secure_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_config, - struct cfg80211_ap_settings *params); -void mwifiex_set_ht_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params); -void mwifiex_set_vht_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params); -void mwifiex_set_tpc_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params); -void mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params); -void mwifiex_set_vht_width(struct mwifiex_private *priv, - enum nl80211_chan_width width, - bool ap_11ac_disable); -void -mwifiex_set_wmm_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params); -void mwifiex_set_ba_params(struct mwifiex_private *priv); - -void mwifiex_update_ampdu_txwinsize(struct mwifiex_adapter *pmadapter); -void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv, - struct sk_buff *event_skb); - -void mwifiex_set_11ac_ba_params(struct mwifiex_private *priv); -int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf); -int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp); -int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, - void *buf); - -/* - * This function checks if the queuing is RA based or not. - */ -static inline u8 -mwifiex_queuing_ra_based(struct mwifiex_private *priv) -{ - /* - * Currently we assume if we are in Infra, then DA=RA. This might not be - * true in the future - */ - if ((priv->bss_mode == NL80211_IFTYPE_STATION) && - (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA)) - return false; - - return true; -} - -/* - * This function copies rates. - */ -static inline u32 -mwifiex_copy_rates(u8 *dest, u32 pos, u8 *src, int len) -{ - int i; - - for (i = 0; i < len && src[i]; i++, pos++) { - if (pos >= MWIFIEX_SUPPORTED_RATES) - break; - dest[pos] = src[i]; - } - - return pos; -} - -/* - * This function returns the correct private structure pointer based - * upon the BSS type and BSS number. - */ -static inline struct mwifiex_private * -mwifiex_get_priv_by_id(struct mwifiex_adapter *adapter, - u8 bss_num, u8 bss_type) -{ - int i; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - if ((adapter->priv[i]->bss_num == bss_num) && - (adapter->priv[i]->bss_type == bss_type)) - break; - } - } - return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -} - -/* - * This function returns the first available private structure pointer - * based upon the BSS role. - */ -static inline struct mwifiex_private * -mwifiex_get_priv(struct mwifiex_adapter *adapter, - enum mwifiex_bss_role bss_role) -{ - int i; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - if (bss_role == MWIFIEX_BSS_ROLE_ANY || - GET_BSS_ROLE(adapter->priv[i]) == bss_role) - break; - } - } - - return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -} - -/* - * This function returns the first available unused private structure pointer. - */ -static inline struct mwifiex_private * -mwifiex_get_unused_priv(struct mwifiex_adapter *adapter) -{ - int i; - - for (i = 0; i < adapter->priv_num; i++) { - if (adapter->priv[i]) { - if (adapter->priv[i]->bss_mode == - NL80211_IFTYPE_UNSPECIFIED) - break; - } - } - - return ((i < adapter->priv_num) ? adapter->priv[i] : NULL); -} - -/* - * This function returns the driver private structure of a network device. - */ -static inline struct mwifiex_private * -mwifiex_netdev_get_priv(struct net_device *dev) -{ - return (struct mwifiex_private *) (*(unsigned long *) netdev_priv(dev)); -} - -/* - * This function checks if a skb holds a management frame. - */ -static inline bool mwifiex_is_skb_mgmt_frame(struct sk_buff *skb) -{ - return (le32_to_cpu(*(__le32 *)skb->data) == PKT_TYPE_MGMT); -} - -/* This function retrieves channel closed for operation by Channel - * Switch Announcement. - */ -static inline u8 -mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv) -{ - if (!priv->csa_chan) - return 0; - - /* Clear csa channel, if DFS channel move time has passed */ - if (time_after(jiffies, priv->csa_expire_time)) { - priv->csa_chan = 0; - priv->csa_expire_time = 0; - } - - return priv->csa_chan; -} - -static inline u8 mwifiex_is_any_intf_active(struct mwifiex_private *priv) -{ - struct mwifiex_private *priv_num; - int i; - - for (i = 0; i < priv->adapter->priv_num; i++) { - priv_num = priv->adapter->priv[i]; - if (priv_num) { - if ((GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_UAP && - priv_num->bss_started) || - (GET_BSS_ROLE(priv_num) == MWIFIEX_BSS_ROLE_STA && - priv_num->media_connected)) - return 1; - } - } - - return 0; -} - -static inline u8 mwifiex_is_tdls_link_setup(u8 status) -{ - switch (status) { - case TDLS_SETUP_COMPLETE: - case TDLS_CHAN_SWITCHING: - case TDLS_IN_BASE_CHAN: - case TDLS_IN_OFF_CHAN: - return true; - default: - break; - } - - return false; -} - -int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, - u32 func_init_shutdown); -int mwifiex_add_card(void *, struct semaphore *, struct mwifiex_if_ops *, u8); -int mwifiex_remove_card(struct mwifiex_adapter *, struct semaphore *); - -void mwifiex_get_version(struct mwifiex_adapter *adapter, char *version, - int maxlen); -int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, - struct mwifiex_multicast_list *mcast_list); -int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, - struct net_device *dev); -int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_queued); -int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - struct cfg80211_ssid *req_ssid); -int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type); -int mwifiex_enable_hs(struct mwifiex_adapter *adapter); -int mwifiex_disable_auto_ds(struct mwifiex_private *priv); -int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate); -int mwifiex_request_scan(struct mwifiex_private *priv, - struct cfg80211_ssid *req_ssid); -int mwifiex_scan_networks(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg *user_scan_in); -int mwifiex_set_radio(struct mwifiex_private *priv, u8 option); - -int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, - const u8 *key, int key_len, u8 key_index, - const u8 *mac_addr, int disable); - -int mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len); - -int mwifiex_get_ver_ext(struct mwifiex_private *priv); - -int mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, - struct ieee80211_channel *chan, - unsigned int duration); - -int mwifiex_get_stats_info(struct mwifiex_private *priv, - struct mwifiex_ds_get_stats *log); - -int mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 reg_value); - -int mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 *value); - -int mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, - u8 *value); - -int mwifiex_set_11n_httx_cfg(struct mwifiex_private *priv, int data); - -int mwifiex_get_11n_httx_cfg(struct mwifiex_private *priv, int *data); - -int mwifiex_set_tx_rate_cfg(struct mwifiex_private *priv, int tx_rate_index); - -int mwifiex_get_tx_rate_cfg(struct mwifiex_private *priv, int *tx_rate_index); - -int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode); - -int mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, - char *version, int max_len); - -int mwifiex_set_tx_power(struct mwifiex_private *priv, - struct mwifiex_power_cfg *power_cfg); - -int mwifiex_main_process(struct mwifiex_adapter *); - -int mwifiex_queue_tx_pkt(struct mwifiex_private *priv, struct sk_buff *skb); - -int mwifiex_get_bss_info(struct mwifiex_private *, - struct mwifiex_bss_info *); -int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, - struct cfg80211_bss *bss, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, - struct mwifiex_bssdescriptor *bss_entry); -int mwifiex_check_network_compatibility(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc); - -u8 mwifiex_chan_type_to_sec_chan_offset(enum nl80211_channel_type chan_type); -u8 mwifiex_sec_chan_offset_to_chan_type(u8 second_chan_offset); - -struct wireless_dev *mwifiex_add_virtual_intf(struct wiphy *wiphy, - const char *name, - unsigned char name_assign_type, - enum nl80211_iftype type, - u32 *flags, - struct vif_params *params); -int mwifiex_del_virtual_intf(struct wiphy *wiphy, struct wireless_dev *wdev); - -void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config); - -int mwifiex_add_wowlan_magic_pkt_filter(struct mwifiex_adapter *adapter); - -int mwifiex_set_mgmt_ies(struct mwifiex_private *priv, - struct cfg80211_beacon_data *data); -int mwifiex_del_mgmt_ies(struct mwifiex_private *priv); -u8 *mwifiex_11d_code_2_region(u8 code); -void mwifiex_uap_set_channel(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_chan_def chandef); -int mwifiex_config_start_uap(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg); -void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, - struct mwifiex_sta_node *node); - -void mwifiex_init_11h_params(struct mwifiex_private *priv); -int mwifiex_is_11h_active(struct mwifiex_private *priv); -int mwifiex_11h_activate(struct mwifiex_private *priv, bool flag); - -void mwifiex_11h_process_join(struct mwifiex_private *priv, u8 **buffer, - struct mwifiex_bssdescriptor *bss_desc); -int mwifiex_11h_handle_event_chanswann(struct mwifiex_private *priv); -int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, - struct device_node *node, const char *prefix); -void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv); - -extern const struct ethtool_ops mwifiex_ethtool_ops; - -void mwifiex_del_all_sta_list(struct mwifiex_private *priv); -void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac); -void -mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, - int ies_len, struct mwifiex_sta_node *node); -struct mwifiex_sta_node * -mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac); -struct mwifiex_sta_node * -mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac); -u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv); -u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv); -u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv); -int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len); -int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len); -void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, - u8 *buf, int len); -int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action); -int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac); -int mwifiex_get_tdls_list(struct mwifiex_private *priv, - struct tdls_peer_info *buf); -void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv); -bool mwifiex_is_bss_in_11ac_mode(struct mwifiex_private *priv); -u8 mwifiex_get_center_freq_index(struct mwifiex_private *priv, u8 band, - u32 pri_chan, u8 chan_bw); -int mwifiex_init_channel_scan_gap(struct mwifiex_adapter *adapter); - -int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb); -void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv); -void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv, - const u8 *mac, u8 link_status); -void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv, - u8 *mac, s8 snr, s8 nflr); -void mwifiex_check_auto_tdls(unsigned long context); -void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac); -void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv); -void mwifiex_clean_auto_tdls(struct mwifiex_private *priv); -int mwifiex_config_tdls_enable(struct mwifiex_private *priv); -int mwifiex_config_tdls_disable(struct mwifiex_private *priv); -int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv); -int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac); -int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac, - u8 primary_chan, u8 second_chan_offset, u8 band); - -int mwifiex_cmd_issue_chan_report_request(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf); -int mwifiex_11h_handle_chanrpt_ready(struct mwifiex_private *priv, - struct sk_buff *skb); - -void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, - void *event_body); - -struct sk_buff * -mwifiex_clone_skb_for_tx_status(struct mwifiex_private *priv, - struct sk_buff *skb, u8 flag, u64 *cookie); -void mwifiex_dfs_cac_work_queue(struct work_struct *work); -void mwifiex_dfs_chan_sw_work_queue(struct work_struct *work); -void mwifiex_abort_cac(struct mwifiex_private *priv); -int mwifiex_stop_radar_detection(struct mwifiex_private *priv, - struct cfg80211_chan_def *chandef); -int mwifiex_11h_handle_radar_detected(struct mwifiex_private *priv, - struct sk_buff *skb); - -void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, - s8 nflr); -void mwifiex_hist_data_reset(struct mwifiex_private *priv); -void mwifiex_hist_data_add(struct mwifiex_private *priv, - u8 rx_rate, s8 snr, s8 nflr); -u8 mwifiex_adjust_data_rate(struct mwifiex_private *priv, - u8 rx_rate, u8 ht_info); - -void mwifiex_drv_info_dump(struct mwifiex_adapter *adapter); -void mwifiex_upload_device_dump(struct mwifiex_adapter *adapter); -void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags); -void mwifiex_queue_main_work(struct mwifiex_adapter *adapter); -void mwifiex_coex_ampdu_rxwinsize(struct mwifiex_adapter *adapter); -void mwifiex_11n_delba(struct mwifiex_private *priv, int tid); -int mwifiex_send_domain_info_cmd_fw(struct wiphy *wiphy); -void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, - struct sk_buff *event); -void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, - struct sk_buff *event_skb); -void mwifiex_multi_chan_resync(struct mwifiex_adapter *adapter); - -#ifdef CONFIG_DEBUG_FS -void mwifiex_debugfs_init(void); -void mwifiex_debugfs_remove(void); - -void mwifiex_dev_debugfs_init(struct mwifiex_private *priv); -void mwifiex_dev_debugfs_remove(struct mwifiex_private *priv); -#endif -#endif /* !_MWIFIEX_MAIN_H_ */ diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c deleted file mode 100644 index 21192b6f9c64..000000000000 --- a/drivers/net/wireless/mwifiex/pcie.c +++ /dev/null @@ -1,2742 +0,0 @@ -/* - * Marvell Wireless LAN device driver: PCIE specific handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include <linux/firmware.h> - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "pcie.h" - -#define PCIE_VERSION "1.0" -#define DRV_NAME "Marvell mwifiex PCIe" - -static u8 user_rmmod; - -static struct mwifiex_if_ops pcie_ops; - -static struct semaphore add_remove_card_sem; - -static struct memory_type_mapping mem_type_mapping_tbl[] = { - {"ITCM", NULL, 0, 0xF0}, - {"DTCM", NULL, 0, 0xF1}, - {"SQRAM", NULL, 0, 0xF2}, - {"IRAM", NULL, 0, 0xF3}, - {"APU", NULL, 0, 0xF4}, - {"CIU", NULL, 0, 0xF5}, - {"ICU", NULL, 0, 0xF6}, - {"MAC", NULL, 0, 0xF7}, -}; - -static int -mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb, - size_t size, int flags) -{ - struct pcie_service_card *card = adapter->card; - struct mwifiex_dma_mapping mapping; - - mapping.addr = pci_map_single(card->dev, skb->data, size, flags); - if (pci_dma_mapping_error(card->dev, mapping.addr)) { - mwifiex_dbg(adapter, ERROR, "failed to map pci memory!\n"); - return -1; - } - mapping.len = size; - mwifiex_store_mapping(skb, &mapping); - return 0; -} - -static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int flags) -{ - struct pcie_service_card *card = adapter->card; - struct mwifiex_dma_mapping mapping; - - mwifiex_get_mapping(skb, &mapping); - pci_unmap_single(card->dev, mapping.addr, mapping.len, flags); -} - -/* - * This function reads sleep cookie and checks if FW is ready - */ -static bool mwifiex_pcie_ok_to_access_hw(struct mwifiex_adapter *adapter) -{ - u32 *cookie_addr; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - if (!reg->sleep_cookie) - return true; - - if (card->sleep_cookie_vbase) { - cookie_addr = (u32 *)card->sleep_cookie_vbase; - mwifiex_dbg(adapter, INFO, - "info: ACCESS_HW: sleep cookie=0x%x\n", - *cookie_addr); - if (*cookie_addr == FW_AWAKE_COOKIE) - return true; - } - - return false; -} - -#ifdef CONFIG_PM_SLEEP -/* - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not suspended, this function allocates and sends a host - * sleep activate request to the firmware and turns off the traffic. - */ -static int mwifiex_pcie_suspend(struct device *dev) -{ - struct mwifiex_adapter *adapter; - struct pcie_service_card *card; - int hs_actived; - struct pci_dev *pdev = to_pci_dev(dev); - - if (pdev) { - card = pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_err("Card or adapter structure is not valid\n"); - return 0; - } - } else { - pr_err("PCIE device is not specified\n"); - return 0; - } - - adapter = card->adapter; - - hs_actived = mwifiex_enable_hs(adapter); - - /* Indicate device suspended */ - adapter->is_suspended = true; - adapter->hs_enabling = false; - - return 0; -} - -/* - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not resumed, this function turns on the traffic and - * sends a host sleep cancel request to the firmware. - */ -static int mwifiex_pcie_resume(struct device *dev) -{ - struct mwifiex_adapter *adapter; - struct pcie_service_card *card; - struct pci_dev *pdev = to_pci_dev(dev); - - if (pdev) { - card = pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_err("Card or adapter structure is not valid\n"); - return 0; - } - } else { - pr_err("PCIE device is not specified\n"); - return 0; - } - - adapter = card->adapter; - - if (!adapter->is_suspended) { - mwifiex_dbg(adapter, WARN, - "Device already resumed\n"); - return 0; - } - - adapter->is_suspended = false; - - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); - - return 0; -} -#endif - -/* - * This function probes an mwifiex device and registers it. It allocates - * the card structure, enables PCIE function number and initiates the - * device registration and initialization procedure by adding a logical - * interface. - */ -static int mwifiex_pcie_probe(struct pci_dev *pdev, - const struct pci_device_id *ent) -{ - struct pcie_service_card *card; - - pr_debug("info: vendor=0x%4.04X device=0x%4.04X rev=%d\n", - pdev->vendor, pdev->device, pdev->revision); - - card = kzalloc(sizeof(struct pcie_service_card), GFP_KERNEL); - if (!card) - return -ENOMEM; - - card->dev = pdev; - - if (ent->driver_data) { - struct mwifiex_pcie_device *data = (void *)ent->driver_data; - card->pcie.firmware = data->firmware; - card->pcie.reg = data->reg; - card->pcie.blksz_fw_dl = data->blksz_fw_dl; - card->pcie.tx_buf_size = data->tx_buf_size; - card->pcie.can_dump_fw = data->can_dump_fw; - card->pcie.can_ext_scan = data->can_ext_scan; - } - - if (mwifiex_add_card(card, &add_remove_card_sem, &pcie_ops, - MWIFIEX_PCIE)) { - pr_err("%s failed\n", __func__); - kfree(card); - return -1; - } - - return 0; -} - -/* - * This function removes the interface and frees up the card structure. - */ -static void mwifiex_pcie_remove(struct pci_dev *pdev) -{ - struct pcie_service_card *card; - struct mwifiex_adapter *adapter; - struct mwifiex_private *priv; - - card = pci_get_drvdata(pdev); - if (!card) - return; - - adapter = card->adapter; - if (!adapter || !adapter->priv_num) - return; - - if (user_rmmod) { -#ifdef CONFIG_PM_SLEEP - if (adapter->is_suspended) - mwifiex_pcie_resume(&pdev->dev); -#endif - - mwifiex_deauthenticate_all(adapter); - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - mwifiex_disable_auto_ds(priv); - - mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN); - } - - mwifiex_remove_card(card->adapter, &add_remove_card_sem); -} - -static void mwifiex_pcie_shutdown(struct pci_dev *pdev) -{ - user_rmmod = 1; - mwifiex_pcie_remove(pdev); - - return; -} - -static const struct pci_device_id mwifiex_ids[] = { - { - PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8766P, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - .driver_data = (unsigned long)&mwifiex_pcie8766, - }, - { - PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8897, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - .driver_data = (unsigned long)&mwifiex_pcie8897, - }, - { - PCIE_VENDOR_ID_MARVELL, PCIE_DEVICE_ID_MARVELL_88W8997, - PCI_ANY_ID, PCI_ANY_ID, 0, 0, - .driver_data = (unsigned long)&mwifiex_pcie8997, - }, - {}, -}; - -MODULE_DEVICE_TABLE(pci, mwifiex_ids); - -#ifdef CONFIG_PM_SLEEP -/* Power Management Hooks */ -static SIMPLE_DEV_PM_OPS(mwifiex_pcie_pm_ops, mwifiex_pcie_suspend, - mwifiex_pcie_resume); -#endif - -/* PCI Device Driver */ -static struct pci_driver __refdata mwifiex_pcie = { - .name = "mwifiex_pcie", - .id_table = mwifiex_ids, - .probe = mwifiex_pcie_probe, - .remove = mwifiex_pcie_remove, -#ifdef CONFIG_PM_SLEEP - .driver = { - .pm = &mwifiex_pcie_pm_ops, - }, -#endif - .shutdown = mwifiex_pcie_shutdown, -}; - -/* - * This function writes data into PCIE card register. - */ -static int mwifiex_write_reg(struct mwifiex_adapter *adapter, int reg, u32 data) -{ - struct pcie_service_card *card = adapter->card; - - iowrite32(data, card->pci_mmap1 + reg); - - return 0; -} - -/* - * This function reads data from PCIE card register. - */ -static int mwifiex_read_reg(struct mwifiex_adapter *adapter, int reg, u32 *data) -{ - struct pcie_service_card *card = adapter->card; - - *data = ioread32(card->pci_mmap1 + reg); - - return 0; -} - -/* This function reads u8 data from PCIE card register. */ -static int mwifiex_read_reg_byte(struct mwifiex_adapter *adapter, - int reg, u8 *data) -{ - struct pcie_service_card *card = adapter->card; - - *data = ioread8(card->pci_mmap1 + reg); - - return 0; -} - -/* - * This function adds delay loop to ensure FW is awake before proceeding. - */ -static void mwifiex_pcie_dev_wakeup_delay(struct mwifiex_adapter *adapter) -{ - int i = 0; - - while (mwifiex_pcie_ok_to_access_hw(adapter)) { - i++; - usleep_range(10, 20); - /* 50ms max wait */ - if (i == 5000) - break; - } - - return; -} - -static void mwifiex_delay_for_sleep_cookie(struct mwifiex_adapter *adapter, - u32 max_delay_loop_cnt) -{ - struct pcie_service_card *card = adapter->card; - u8 *buffer; - u32 sleep_cookie, count; - - for (count = 0; count < max_delay_loop_cnt; count++) { - buffer = card->cmdrsp_buf->data - INTF_HEADER_LEN; - sleep_cookie = *(u32 *)buffer; - - if (sleep_cookie == MWIFIEX_DEF_SLEEP_COOKIE) { - mwifiex_dbg(adapter, INFO, - "sleep cookie found at count %d\n", count); - break; - } - usleep_range(20, 30); - } - - if (count >= max_delay_loop_cnt) - mwifiex_dbg(adapter, INFO, - "max count reached while accessing sleep cookie\n"); -} - -/* This function wakes up the card by reading fw_status register. */ -static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) -{ - u32 fw_status; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - mwifiex_dbg(adapter, EVENT, - "event: Wakeup device...\n"); - - if (reg->sleep_cookie) - mwifiex_pcie_dev_wakeup_delay(adapter); - - /* Reading fw_status register will wakeup device */ - if (mwifiex_read_reg(adapter, reg->fw_status, &fw_status)) { - mwifiex_dbg(adapter, ERROR, - "Reading fw_status register failed\n"); - return -1; - } - - if (reg->sleep_cookie) { - mwifiex_pcie_dev_wakeup_delay(adapter); - mwifiex_dbg(adapter, INFO, - "PCIE wakeup: Setting PS_STATE_AWAKE\n"); - adapter->ps_state = PS_STATE_AWAKE; - } - - return 0; -} - -/* - * This function is called after the card has woken up. - * - * The card configuration register is reset. - */ -static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) -{ - mwifiex_dbg(adapter, CMD, - "cmd: Wakeup device completed\n"); - - return 0; -} - -/* - * This function disables the host interrupt. - * - * The host interrupt mask is read, the disable bit is reset and - * written back to the card host interrupt mask register. - */ -static int mwifiex_pcie_disable_host_int(struct mwifiex_adapter *adapter) -{ - if (mwifiex_pcie_ok_to_access_hw(adapter)) { - if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, - 0x00000000)) { - mwifiex_dbg(adapter, ERROR, - "Disable host interrupt failed\n"); - return -1; - } - } - - return 0; -} - -/* - * This function enables the host interrupt. - * - * The host interrupt enable mask is written to the card - * host interrupt mask register. - */ -static int mwifiex_pcie_enable_host_int(struct mwifiex_adapter *adapter) -{ - if (mwifiex_pcie_ok_to_access_hw(adapter)) { - /* Simply write the mask to the register */ - if (mwifiex_write_reg(adapter, PCIE_HOST_INT_MASK, - HOST_INTR_MASK)) { - mwifiex_dbg(adapter, ERROR, - "Enable host interrupt failed\n"); - return -1; - } - } - - return 0; -} - -/* - * This function initializes TX buffer ring descriptors - */ -static int mwifiex_init_txq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - card->tx_buf_list[i] = NULL; - if (reg->pfu_enabled) { - card->txbd_ring[i] = (void *)card->txbd_ring_vbase + - (sizeof(*desc2) * i); - desc2 = card->txbd_ring[i]; - memset(desc2, 0, sizeof(*desc2)); - } else { - card->txbd_ring[i] = (void *)card->txbd_ring_vbase + - (sizeof(*desc) * i); - desc = card->txbd_ring[i]; - memset(desc, 0, sizeof(*desc)); - } - } - - return 0; -} - -/* This function initializes RX buffer ring descriptors. Each SKB is allocated - * here and after mapping PCI memory, its physical address is assigned to - * PCIE Rx buffer descriptor's physical address. - */ -static int mwifiex_init_rxq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct sk_buff *skb; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - dma_addr_t buf_pa; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - /* Allocate skb here so that firmware can DMA data from it */ - skb = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE, - GFP_KERNEL | GFP_DMA); - if (!skb) { - mwifiex_dbg(adapter, ERROR, - "Unable to allocate skb for RX ring.\n"); - kfree(card->rxbd_ring_vbase); - return -ENOMEM; - } - - if (mwifiex_map_pci_memory(adapter, skb, - MWIFIEX_RX_DATA_BUF_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - - buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); - - mwifiex_dbg(adapter, INFO, - "info: RX ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", - skb, skb->len, skb->data, (u32)buf_pa, - (u32)((u64)buf_pa >> 32)); - - card->rx_buf_list[i] = skb; - if (reg->pfu_enabled) { - card->rxbd_ring[i] = (void *)card->rxbd_ring_vbase + - (sizeof(*desc2) * i); - desc2 = card->rxbd_ring[i]; - desc2->paddr = buf_pa; - desc2->len = (u16)skb->len; - desc2->frag_len = (u16)skb->len; - desc2->flags = reg->ring_flag_eop | reg->ring_flag_sop; - desc2->offset = 0; - } else { - card->rxbd_ring[i] = (void *)(card->rxbd_ring_vbase + - (sizeof(*desc) * i)); - desc = card->rxbd_ring[i]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = 0; - } - } - - return 0; -} - -/* This function initializes event buffer ring descriptors. Each SKB is - * allocated here and after mapping PCI memory, its physical address is assigned - * to PCIE Rx buffer descriptor's physical address - */ -static int mwifiex_pcie_init_evt_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - struct mwifiex_evt_buf_desc *desc; - struct sk_buff *skb; - dma_addr_t buf_pa; - int i; - - for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { - /* Allocate skb here so that firmware can DMA data from it */ - skb = dev_alloc_skb(MAX_EVENT_SIZE); - if (!skb) { - mwifiex_dbg(adapter, ERROR, - "Unable to allocate skb for EVENT buf.\n"); - kfree(card->evtbd_ring_vbase); - return -ENOMEM; - } - skb_put(skb, MAX_EVENT_SIZE); - - if (mwifiex_map_pci_memory(adapter, skb, MAX_EVENT_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - - buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); - - mwifiex_dbg(adapter, EVENT, - "info: EVT ring: skb=%p len=%d data=%p buf_pa=%#x:%x\n", - skb, skb->len, skb->data, (u32)buf_pa, - (u32)((u64)buf_pa >> 32)); - - card->evt_buf_list[i] = skb; - card->evtbd_ring[i] = (void *)(card->evtbd_ring_vbase + - (sizeof(*desc) * i)); - desc = card->evtbd_ring[i]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = 0; - } - - return 0; -} - -/* This function cleans up TX buffer rings. If any of the buffer list has valid - * SKB address, associated SKB is freed. - */ -static void mwifiex_cleanup_txq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct sk_buff *skb; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - if (reg->pfu_enabled) { - desc2 = card->txbd_ring[i]; - if (card->tx_buf_list[i]) { - skb = card->tx_buf_list[i]; - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(skb); - } - memset(desc2, 0, sizeof(*desc2)); - } else { - desc = card->txbd_ring[i]; - if (card->tx_buf_list[i]) { - skb = card->tx_buf_list[i]; - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_TODEVICE); - dev_kfree_skb_any(skb); - } - memset(desc, 0, sizeof(*desc)); - } - card->tx_buf_list[i] = NULL; - } - - return; -} - -/* This function cleans up RX buffer rings. If any of the buffer list has valid - * SKB address, associated SKB is freed. - */ -static void mwifiex_cleanup_rxq_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - struct sk_buff *skb; - int i; - - for (i = 0; i < MWIFIEX_MAX_TXRX_BD; i++) { - if (reg->pfu_enabled) { - desc2 = card->rxbd_ring[i]; - if (card->rx_buf_list[i]) { - skb = card->rx_buf_list[i]; - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - } - memset(desc2, 0, sizeof(*desc2)); - } else { - desc = card->rxbd_ring[i]; - if (card->rx_buf_list[i]) { - skb = card->rx_buf_list[i]; - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - } - memset(desc, 0, sizeof(*desc)); - } - card->rx_buf_list[i] = NULL; - } - - return; -} - -/* This function cleans up event buffer rings. If any of the buffer list has - * valid SKB address, associated SKB is freed. - */ -static void mwifiex_cleanup_evt_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - struct mwifiex_evt_buf_desc *desc; - struct sk_buff *skb; - int i; - - for (i = 0; i < MWIFIEX_MAX_EVT_BD; i++) { - desc = card->evtbd_ring[i]; - if (card->evt_buf_list[i]) { - skb = card->evt_buf_list[i]; - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(skb); - } - card->evt_buf_list[i] = NULL; - memset(desc, 0, sizeof(*desc)); - } - - return; -} - -/* This function creates buffer descriptor ring for TX - */ -static int mwifiex_pcie_create_txbd_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - /* - * driver maintaines the write pointer and firmware maintaines the read - * pointer. The write pointer starts at 0 (zero) while the read pointer - * starts at zero with rollover bit set - */ - card->txbd_wrptr = 0; - - if (reg->pfu_enabled) - card->txbd_rdptr = 0; - else - card->txbd_rdptr |= reg->tx_rollover_ind; - - /* allocate shared memory for the BD ring and divide the same in to - several descriptors */ - if (reg->pfu_enabled) - card->txbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - else - card->txbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - - mwifiex_dbg(adapter, INFO, - "info: txbd_ring: Allocating %d bytes\n", - card->txbd_ring_size); - card->txbd_ring_vbase = pci_alloc_consistent(card->dev, - card->txbd_ring_size, - &card->txbd_ring_pbase); - if (!card->txbd_ring_vbase) { - mwifiex_dbg(adapter, ERROR, - "allocate consistent memory (%d bytes) failed!\n", - card->txbd_ring_size); - return -ENOMEM; - } - mwifiex_dbg(adapter, DATA, - "info: txbd_ring - base: %p, pbase: %#x:%x, len: %x\n", - card->txbd_ring_vbase, (unsigned int)card->txbd_ring_pbase, - (u32)((u64)card->txbd_ring_pbase >> 32), - card->txbd_ring_size); - - return mwifiex_init_txq_ring(adapter); -} - -static int mwifiex_pcie_delete_txbd_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - mwifiex_cleanup_txq_ring(adapter); - - if (card->txbd_ring_vbase) - pci_free_consistent(card->dev, card->txbd_ring_size, - card->txbd_ring_vbase, - card->txbd_ring_pbase); - card->txbd_ring_size = 0; - card->txbd_wrptr = 0; - card->txbd_rdptr = 0 | reg->tx_rollover_ind; - card->txbd_ring_vbase = NULL; - card->txbd_ring_pbase = 0; - - return 0; -} - -/* - * This function creates buffer descriptor ring for RX - */ -static int mwifiex_pcie_create_rxbd_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - /* - * driver maintaines the read pointer and firmware maintaines the write - * pointer. The write pointer starts at 0 (zero) while the read pointer - * starts at zero with rollover bit set - */ - card->rxbd_wrptr = 0; - card->rxbd_rdptr = reg->rx_rollover_ind; - - if (reg->pfu_enabled) - card->rxbd_ring_size = sizeof(struct mwifiex_pfu_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - else - card->rxbd_ring_size = sizeof(struct mwifiex_pcie_buf_desc) * - MWIFIEX_MAX_TXRX_BD; - - mwifiex_dbg(adapter, INFO, - "info: rxbd_ring: Allocating %d bytes\n", - card->rxbd_ring_size); - card->rxbd_ring_vbase = pci_alloc_consistent(card->dev, - card->rxbd_ring_size, - &card->rxbd_ring_pbase); - if (!card->rxbd_ring_vbase) { - mwifiex_dbg(adapter, ERROR, - "allocate consistent memory (%d bytes) failed!\n", - card->rxbd_ring_size); - return -ENOMEM; - } - - mwifiex_dbg(adapter, DATA, - "info: rxbd_ring - base: %p, pbase: %#x:%x, len: %#x\n", - card->rxbd_ring_vbase, (u32)card->rxbd_ring_pbase, - (u32)((u64)card->rxbd_ring_pbase >> 32), - card->rxbd_ring_size); - - return mwifiex_init_rxq_ring(adapter); -} - -/* - * This function deletes Buffer descriptor ring for RX - */ -static int mwifiex_pcie_delete_rxbd_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - mwifiex_cleanup_rxq_ring(adapter); - - if (card->rxbd_ring_vbase) - pci_free_consistent(card->dev, card->rxbd_ring_size, - card->rxbd_ring_vbase, - card->rxbd_ring_pbase); - card->rxbd_ring_size = 0; - card->rxbd_wrptr = 0; - card->rxbd_rdptr = 0 | reg->rx_rollover_ind; - card->rxbd_ring_vbase = NULL; - card->rxbd_ring_pbase = 0; - - return 0; -} - -/* - * This function creates buffer descriptor ring for Events - */ -static int mwifiex_pcie_create_evtbd_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - /* - * driver maintaines the read pointer and firmware maintaines the write - * pointer. The write pointer starts at 0 (zero) while the read pointer - * starts at zero with rollover bit set - */ - card->evtbd_wrptr = 0; - card->evtbd_rdptr = reg->evt_rollover_ind; - - card->evtbd_ring_size = sizeof(struct mwifiex_evt_buf_desc) * - MWIFIEX_MAX_EVT_BD; - - mwifiex_dbg(adapter, INFO, - "info: evtbd_ring: Allocating %d bytes\n", - card->evtbd_ring_size); - card->evtbd_ring_vbase = pci_alloc_consistent(card->dev, - card->evtbd_ring_size, - &card->evtbd_ring_pbase); - if (!card->evtbd_ring_vbase) { - mwifiex_dbg(adapter, ERROR, - "allocate consistent memory (%d bytes) failed!\n", - card->evtbd_ring_size); - return -ENOMEM; - } - - mwifiex_dbg(adapter, EVENT, - "info: CMDRSP/EVT bd_ring - base: %p pbase: %#x:%x len: %#x\n", - card->evtbd_ring_vbase, (u32)card->evtbd_ring_pbase, - (u32)((u64)card->evtbd_ring_pbase >> 32), - card->evtbd_ring_size); - - return mwifiex_pcie_init_evt_ring(adapter); -} - -/* - * This function deletes Buffer descriptor ring for Events - */ -static int mwifiex_pcie_delete_evtbd_ring(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - mwifiex_cleanup_evt_ring(adapter); - - if (card->evtbd_ring_vbase) - pci_free_consistent(card->dev, card->evtbd_ring_size, - card->evtbd_ring_vbase, - card->evtbd_ring_pbase); - card->evtbd_wrptr = 0; - card->evtbd_rdptr = 0 | reg->evt_rollover_ind; - card->evtbd_ring_size = 0; - card->evtbd_ring_vbase = NULL; - card->evtbd_ring_pbase = 0; - - return 0; -} - -/* - * This function allocates a buffer for CMDRSP - */ -static int mwifiex_pcie_alloc_cmdrsp_buf(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - struct sk_buff *skb; - - /* Allocate memory for receiving command response data */ - skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE); - if (!skb) { - mwifiex_dbg(adapter, ERROR, - "Unable to allocate skb for command response data.\n"); - return -ENOMEM; - } - skb_put(skb, MWIFIEX_UPLD_SIZE); - if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - - card->cmdrsp_buf = skb; - - return 0; -} - -/* - * This function deletes a buffer for CMDRSP - */ -static int mwifiex_pcie_delete_cmdrsp_buf(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card; - - if (!adapter) - return 0; - - card = adapter->card; - - if (card && card->cmdrsp_buf) { - mwifiex_unmap_pci_memory(adapter, card->cmdrsp_buf, - PCI_DMA_FROMDEVICE); - dev_kfree_skb_any(card->cmdrsp_buf); - } - - if (card && card->cmd_buf) { - mwifiex_unmap_pci_memory(adapter, card->cmd_buf, - PCI_DMA_TODEVICE); - } - return 0; -} - -/* - * This function allocates a buffer for sleep cookie - */ -static int mwifiex_pcie_alloc_sleep_cookie_buf(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - - card->sleep_cookie_vbase = pci_alloc_consistent(card->dev, sizeof(u32), - &card->sleep_cookie_pbase); - if (!card->sleep_cookie_vbase) { - mwifiex_dbg(adapter, ERROR, - "pci_alloc_consistent failed!\n"); - return -ENOMEM; - } - /* Init val of Sleep Cookie */ - *(u32 *)card->sleep_cookie_vbase = FW_AWAKE_COOKIE; - - mwifiex_dbg(adapter, INFO, - "alloc_scook: sleep cookie=0x%x\n", - *((u32 *)card->sleep_cookie_vbase)); - - return 0; -} - -/* - * This function deletes buffer for sleep cookie - */ -static int mwifiex_pcie_delete_sleep_cookie_buf(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card; - - if (!adapter) - return 0; - - card = adapter->card; - - if (card && card->sleep_cookie_vbase) { - pci_free_consistent(card->dev, sizeof(u32), - card->sleep_cookie_vbase, - card->sleep_cookie_pbase); - card->sleep_cookie_vbase = NULL; - } - - return 0; -} - -/* This function flushes the TX buffer descriptor ring - * This function defined as handler is also called while cleaning TXRX - * during disconnect/ bss stop. - */ -static int mwifiex_clean_pcie_ring_buf(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - - if (!mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) { - card->txbd_flush = 1; - /* write pointer already set at last send - * send dnld-rdy intr again, wait for completion. - */ - if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, - CPU_INTR_DNLD_RDY)) { - mwifiex_dbg(adapter, ERROR, - "failed to assert dnld-rdy interrupt.\n"); - return -1; - } - } - return 0; -} - -/* - * This function unmaps and frees downloaded data buffer - */ -static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter) -{ - struct sk_buff *skb; - u32 wrdoneidx, rdptr, num_tx_buffs, unmap_count = 0; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - if (!mwifiex_pcie_ok_to_access_hw(adapter)) - mwifiex_pm_wakeup_card(adapter); - - /* Read the TX ring read pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->tx_rdptr, &rdptr)) { - mwifiex_dbg(adapter, ERROR, - "SEND COMP: failed to read reg->tx_rdptr\n"); - return -1; - } - - mwifiex_dbg(adapter, DATA, - "SEND COMP: rdptr_prev=0x%x, rdptr=0x%x\n", - card->txbd_rdptr, rdptr); - - num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr; - /* free from previous txbd_rdptr to current txbd_rdptr */ - while (((card->txbd_rdptr & reg->tx_mask) != - (rdptr & reg->tx_mask)) || - ((card->txbd_rdptr & reg->tx_rollover_ind) != - (rdptr & reg->tx_rollover_ind))) { - wrdoneidx = (card->txbd_rdptr & reg->tx_mask) >> - reg->tx_start_ptr; - - skb = card->tx_buf_list[wrdoneidx]; - - if (skb) { - mwifiex_dbg(adapter, DATA, - "SEND COMP: Detach skb %p at txbd_rdidx=%d\n", - skb, wrdoneidx); - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_TODEVICE); - - unmap_count++; - - if (card->txbd_flush) - mwifiex_write_data_complete(adapter, skb, 0, - -1); - else - mwifiex_write_data_complete(adapter, skb, 0, 0); - } - - card->tx_buf_list[wrdoneidx] = NULL; - - if (reg->pfu_enabled) { - desc2 = card->txbd_ring[wrdoneidx]; - memset(desc2, 0, sizeof(*desc2)); - } else { - desc = card->txbd_ring[wrdoneidx]; - memset(desc, 0, sizeof(*desc)); - } - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - card->txbd_rdptr++; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - case PCIE_DEVICE_ID_MARVELL_88W8997: - card->txbd_rdptr += reg->ring_tx_start_ptr; - break; - } - - - if ((card->txbd_rdptr & reg->tx_mask) == num_tx_buffs) - card->txbd_rdptr = ((card->txbd_rdptr & - reg->tx_rollover_ind) ^ - reg->tx_rollover_ind); - } - - if (unmap_count) - adapter->data_sent = false; - - if (card->txbd_flush) { - if (mwifiex_pcie_txbd_empty(card, card->txbd_rdptr)) - card->txbd_flush = 0; - else - mwifiex_clean_pcie_ring_buf(adapter); - } - - return 0; -} - -/* This function sends data buffer to device. First 4 bytes of payload - * are filled with payload length and payload type. Then this payload - * is mapped to PCI device memory. Tx ring pointers are advanced accordingly. - * Download ready interrupt to FW is deffered if Tx ring is not full and - * additional payload can be accomodated. - * Caller must ensure tx_param parameter to this function is not NULL. - */ -static int -mwifiex_pcie_send_data(struct mwifiex_adapter *adapter, struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - u32 wrindx, num_tx_buffs, rx_val; - int ret; - dma_addr_t buf_pa; - struct mwifiex_pcie_buf_desc *desc = NULL; - struct mwifiex_pfu_buf_desc *desc2 = NULL; - __le16 *tmp; - - if (!(skb->data && skb->len)) { - mwifiex_dbg(adapter, ERROR, - "%s(): invalid parameter <%p, %#x>\n", - __func__, skb->data, skb->len); - return -1; - } - - if (!mwifiex_pcie_ok_to_access_hw(adapter)) - mwifiex_pm_wakeup_card(adapter); - - num_tx_buffs = MWIFIEX_MAX_TXRX_BD << reg->tx_start_ptr; - mwifiex_dbg(adapter, DATA, - "info: SEND DATA: <Rd: %#x, Wr: %#x>\n", - card->txbd_rdptr, card->txbd_wrptr); - if (mwifiex_pcie_txbd_not_full(card)) { - u8 *payload; - - adapter->data_sent = true; - payload = skb->data; - tmp = (__le16 *)&payload[0]; - *tmp = cpu_to_le16((u16)skb->len); - tmp = (__le16 *)&payload[2]; - *tmp = cpu_to_le16(MWIFIEX_TYPE_DATA); - - if (mwifiex_map_pci_memory(adapter, skb, skb->len, - PCI_DMA_TODEVICE)) - return -1; - - wrindx = (card->txbd_wrptr & reg->tx_mask) >> reg->tx_start_ptr; - buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); - card->tx_buf_list[wrindx] = skb; - - if (reg->pfu_enabled) { - desc2 = card->txbd_ring[wrindx]; - desc2->paddr = buf_pa; - desc2->len = (u16)skb->len; - desc2->frag_len = (u16)skb->len; - desc2->offset = 0; - desc2->flags = MWIFIEX_BD_FLAG_FIRST_DESC | - MWIFIEX_BD_FLAG_LAST_DESC; - } else { - desc = card->txbd_ring[wrindx]; - desc->paddr = buf_pa; - desc->len = (u16)skb->len; - desc->flags = MWIFIEX_BD_FLAG_FIRST_DESC | - MWIFIEX_BD_FLAG_LAST_DESC; - } - - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - card->txbd_wrptr++; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - case PCIE_DEVICE_ID_MARVELL_88W8997: - card->txbd_wrptr += reg->ring_tx_start_ptr; - break; - } - - if ((card->txbd_wrptr & reg->tx_mask) == num_tx_buffs) - card->txbd_wrptr = ((card->txbd_wrptr & - reg->tx_rollover_ind) ^ - reg->tx_rollover_ind); - - rx_val = card->rxbd_rdptr & reg->rx_wrap_mask; - /* Write the TX ring write pointer in to reg->tx_wrptr */ - if (mwifiex_write_reg(adapter, reg->tx_wrptr, - card->txbd_wrptr | rx_val)) { - mwifiex_dbg(adapter, ERROR, - "SEND DATA: failed to write reg->tx_wrptr\n"); - ret = -1; - goto done_unmap; - } - if ((mwifiex_pcie_txbd_not_full(card)) && - tx_param->next_pkt_len) { - /* have more packets and TxBD still can hold more */ - mwifiex_dbg(adapter, DATA, - "SEND DATA: delay dnld-rdy interrupt.\n"); - adapter->data_sent = false; - } else { - /* Send the TX ready interrupt */ - if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, - CPU_INTR_DNLD_RDY)) { - mwifiex_dbg(adapter, ERROR, - "SEND DATA: failed to assert dnld-rdy interrupt.\n"); - ret = -1; - goto done_unmap; - } - } - mwifiex_dbg(adapter, DATA, - "info: SEND DATA: Updated <Rd: %#x, Wr:\t" - "%#x> and sent packet to firmware successfully\n", - card->txbd_rdptr, card->txbd_wrptr); - } else { - mwifiex_dbg(adapter, DATA, - "info: TX Ring full, can't send packets to fw\n"); - adapter->data_sent = true; - /* Send the TX ready interrupt */ - if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, - CPU_INTR_DNLD_RDY)) - mwifiex_dbg(adapter, ERROR, - "SEND DATA: failed to assert door-bell intr\n"); - return -EBUSY; - } - - return -EINPROGRESS; -done_unmap: - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); - card->tx_buf_list[wrindx] = NULL; - if (reg->pfu_enabled) - memset(desc2, 0, sizeof(*desc2)); - else - memset(desc, 0, sizeof(*desc)); - - return ret; -} - -/* - * This function handles received buffer ring and - * dispatches packets to upper - */ -static int mwifiex_pcie_process_recv_data(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - u32 wrptr, rd_index, tx_val; - dma_addr_t buf_pa; - int ret = 0; - struct sk_buff *skb_tmp = NULL; - struct mwifiex_pcie_buf_desc *desc; - struct mwifiex_pfu_buf_desc *desc2; - - if (!mwifiex_pcie_ok_to_access_hw(adapter)) - mwifiex_pm_wakeup_card(adapter); - - /* Read the RX ring Write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) { - mwifiex_dbg(adapter, ERROR, - "RECV DATA: failed to read reg->rx_wrptr\n"); - ret = -1; - goto done; - } - card->rxbd_wrptr = wrptr; - - while (((wrptr & reg->rx_mask) != - (card->rxbd_rdptr & reg->rx_mask)) || - ((wrptr & reg->rx_rollover_ind) == - (card->rxbd_rdptr & reg->rx_rollover_ind))) { - struct sk_buff *skb_data; - u16 rx_len; - __le16 pkt_len; - - rd_index = card->rxbd_rdptr & reg->rx_mask; - skb_data = card->rx_buf_list[rd_index]; - - /* If skb allocation was failed earlier for Rx packet, - * rx_buf_list[rd_index] would have been left with a NULL. - */ - if (!skb_data) - return -ENOMEM; - - mwifiex_unmap_pci_memory(adapter, skb_data, PCI_DMA_FROMDEVICE); - card->rx_buf_list[rd_index] = NULL; - - /* Get data length from interface header - - * first 2 bytes for len, next 2 bytes is for type - */ - pkt_len = *((__le16 *)skb_data->data); - rx_len = le16_to_cpu(pkt_len); - if (WARN_ON(rx_len <= INTF_HEADER_LEN || - rx_len > MWIFIEX_RX_DATA_BUF_SIZE)) { - mwifiex_dbg(adapter, ERROR, - "Invalid RX len %d, Rd=%#x, Wr=%#x\n", - rx_len, card->rxbd_rdptr, wrptr); - dev_kfree_skb_any(skb_data); - } else { - skb_put(skb_data, rx_len); - mwifiex_dbg(adapter, DATA, - "info: RECV DATA: Rd=%#x, Wr=%#x, Len=%d\n", - card->rxbd_rdptr, wrptr, rx_len); - skb_pull(skb_data, INTF_HEADER_LEN); - if (adapter->rx_work_enabled) { - skb_queue_tail(&adapter->rx_data_q, skb_data); - adapter->data_received = true; - atomic_inc(&adapter->rx_pending); - } else { - mwifiex_handle_rx_packet(adapter, skb_data); - } - } - - skb_tmp = mwifiex_alloc_dma_align_buf(MWIFIEX_RX_DATA_BUF_SIZE, - GFP_KERNEL | GFP_DMA); - if (!skb_tmp) { - mwifiex_dbg(adapter, ERROR, - "Unable to allocate skb.\n"); - return -ENOMEM; - } - - if (mwifiex_map_pci_memory(adapter, skb_tmp, - MWIFIEX_RX_DATA_BUF_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - - buf_pa = MWIFIEX_SKB_DMA_ADDR(skb_tmp); - - mwifiex_dbg(adapter, INFO, - "RECV DATA: Attach new sk_buff %p at rxbd_rdidx=%d\n", - skb_tmp, rd_index); - card->rx_buf_list[rd_index] = skb_tmp; - - if (reg->pfu_enabled) { - desc2 = card->rxbd_ring[rd_index]; - desc2->paddr = buf_pa; - desc2->len = skb_tmp->len; - desc2->frag_len = skb_tmp->len; - desc2->offset = 0; - desc2->flags = reg->ring_flag_sop | reg->ring_flag_eop; - } else { - desc = card->rxbd_ring[rd_index]; - desc->paddr = buf_pa; - desc->len = skb_tmp->len; - desc->flags = 0; - } - - if ((++card->rxbd_rdptr & reg->rx_mask) == - MWIFIEX_MAX_TXRX_BD) { - card->rxbd_rdptr = ((card->rxbd_rdptr & - reg->rx_rollover_ind) ^ - reg->rx_rollover_ind); - } - mwifiex_dbg(adapter, DATA, - "info: RECV DATA: <Rd: %#x, Wr: %#x>\n", - card->rxbd_rdptr, wrptr); - - tx_val = card->txbd_wrptr & reg->tx_wrap_mask; - /* Write the RX ring read pointer in to reg->rx_rdptr */ - if (mwifiex_write_reg(adapter, reg->rx_rdptr, - card->rxbd_rdptr | tx_val)) { - mwifiex_dbg(adapter, DATA, - "RECV DATA: failed to write reg->rx_rdptr\n"); - ret = -1; - goto done; - } - - /* Read the RX ring Write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->rx_wrptr, &wrptr)) { - mwifiex_dbg(adapter, ERROR, - "RECV DATA: failed to read reg->rx_wrptr\n"); - ret = -1; - goto done; - } - mwifiex_dbg(adapter, DATA, - "info: RECV DATA: Rcvd packet from fw successfully\n"); - card->rxbd_wrptr = wrptr; - } - -done: - return ret; -} - -/* - * This function downloads the boot command to device - */ -static int -mwifiex_pcie_send_boot_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) -{ - dma_addr_t buf_pa; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - if (!(skb->data && skb->len)) { - mwifiex_dbg(adapter, ERROR, - "Invalid parameter in %s <%p. len %d>\n", - __func__, skb->data, skb->len); - return -1; - } - - if (mwifiex_map_pci_memory(adapter, skb, skb->len , PCI_DMA_TODEVICE)) - return -1; - - buf_pa = MWIFIEX_SKB_DMA_ADDR(skb); - - /* Write the lower 32bits of the physical address to low command - * address scratch register - */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, (u32)buf_pa)) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to write download command to boot code.\n", - __func__); - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); - return -1; - } - - /* Write the upper 32bits of the physical address to high command - * address scratch register - */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_hi, - (u32)((u64)buf_pa >> 32))) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to write download command to boot code.\n", - __func__); - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); - return -1; - } - - /* Write the command length to cmd_size scratch register */ - if (mwifiex_write_reg(adapter, reg->cmd_size, skb->len)) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to write command len to cmd_size scratch reg\n", - __func__); - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); - return -1; - } - - /* Ring the door bell */ - if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, - CPU_INTR_DOOR_BELL)) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to assert door-bell intr\n", __func__); - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); - return -1; - } - - return 0; -} - -/* This function init rx port in firmware which in turn enables to receive data - * from device before transmitting any packet. - */ -static int mwifiex_pcie_init_fw_port(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - int tx_wrap = card->txbd_wrptr & reg->tx_wrap_mask; - - /* Write the RX ring read pointer in to reg->rx_rdptr */ - if (mwifiex_write_reg(adapter, reg->rx_rdptr, card->rxbd_rdptr | - tx_wrap)) { - mwifiex_dbg(adapter, ERROR, - "RECV DATA: failed to write reg->rx_rdptr\n"); - return -1; - } - return 0; -} - -/* This function downloads commands to the device - */ -static int -mwifiex_pcie_send_cmd(struct mwifiex_adapter *adapter, struct sk_buff *skb) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - int ret = 0; - dma_addr_t cmd_buf_pa, cmdrsp_buf_pa; - u8 *payload = (u8 *)skb->data; - - if (!(skb->data && skb->len)) { - mwifiex_dbg(adapter, ERROR, - "Invalid parameter in %s <%p, %#x>\n", - __func__, skb->data, skb->len); - return -1; - } - - /* Make sure a command response buffer is available */ - if (!card->cmdrsp_buf) { - mwifiex_dbg(adapter, ERROR, - "No response buffer available, send command failed\n"); - return -EBUSY; - } - - if (!mwifiex_pcie_ok_to_access_hw(adapter)) - mwifiex_pm_wakeup_card(adapter); - - adapter->cmd_sent = true; - - *(__le16 *)&payload[0] = cpu_to_le16((u16)skb->len); - *(__le16 *)&payload[2] = cpu_to_le16(MWIFIEX_TYPE_CMD); - - if (mwifiex_map_pci_memory(adapter, skb, skb->len, PCI_DMA_TODEVICE)) - return -1; - - card->cmd_buf = skb; - - /* To send a command, the driver will: - 1. Write the 64bit physical address of the data buffer to - cmd response address low + cmd response address high - 2. Ring the door bell (i.e. set the door bell interrupt) - - In response to door bell interrupt, the firmware will perform - the DMA of the command packet (first header to obtain the total - length and then rest of the command). - */ - - if (card->cmdrsp_buf) { - cmdrsp_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmdrsp_buf); - /* Write the lower 32bits of the cmdrsp buffer physical - address */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, - (u32)cmdrsp_buf_pa)) { - mwifiex_dbg(adapter, ERROR, - "Failed to write download cmd to boot code.\n"); - ret = -1; - goto done; - } - /* Write the upper 32bits of the cmdrsp buffer physical - address */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, - (u32)((u64)cmdrsp_buf_pa >> 32))) { - mwifiex_dbg(adapter, ERROR, - "Failed to write download cmd to boot code.\n"); - ret = -1; - goto done; - } - } - - cmd_buf_pa = MWIFIEX_SKB_DMA_ADDR(card->cmd_buf); - /* Write the lower 32bits of the physical address to reg->cmd_addr_lo */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_lo, - (u32)cmd_buf_pa)) { - mwifiex_dbg(adapter, ERROR, - "Failed to write download cmd to boot code.\n"); - ret = -1; - goto done; - } - /* Write the upper 32bits of the physical address to reg->cmd_addr_hi */ - if (mwifiex_write_reg(adapter, reg->cmd_addr_hi, - (u32)((u64)cmd_buf_pa >> 32))) { - mwifiex_dbg(adapter, ERROR, - "Failed to write download cmd to boot code.\n"); - ret = -1; - goto done; - } - - /* Write the command length to reg->cmd_size */ - if (mwifiex_write_reg(adapter, reg->cmd_size, - card->cmd_buf->len)) { - mwifiex_dbg(adapter, ERROR, - "Failed to write cmd len to reg->cmd_size\n"); - ret = -1; - goto done; - } - - /* Ring the door bell */ - if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, - CPU_INTR_DOOR_BELL)) { - mwifiex_dbg(adapter, ERROR, - "Failed to assert door-bell intr\n"); - ret = -1; - goto done; - } - -done: - if (ret) - adapter->cmd_sent = false; - - return 0; -} - -/* - * This function handles command complete interrupt - */ -static int mwifiex_pcie_process_cmd_complete(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - struct sk_buff *skb = card->cmdrsp_buf; - int count = 0; - u16 rx_len; - __le16 pkt_len; - - mwifiex_dbg(adapter, CMD, - "info: Rx CMD Response\n"); - - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_FROMDEVICE); - - /* Unmap the command as a response has been received. */ - if (card->cmd_buf) { - mwifiex_unmap_pci_memory(adapter, card->cmd_buf, - PCI_DMA_TODEVICE); - card->cmd_buf = NULL; - } - - pkt_len = *((__le16 *)skb->data); - rx_len = le16_to_cpu(pkt_len); - skb_trim(skb, rx_len); - skb_pull(skb, INTF_HEADER_LEN); - - if (!adapter->curr_cmd) { - if (adapter->ps_state == PS_STATE_SLEEP_CFM) { - mwifiex_process_sleep_confirm_resp(adapter, skb->data, - skb->len); - mwifiex_pcie_enable_host_int(adapter); - if (mwifiex_write_reg(adapter, - PCIE_CPU_INT_EVENT, - CPU_INTR_SLEEP_CFM_DONE)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return -1; - } - mwifiex_delay_for_sleep_cookie(adapter, - MWIFIEX_MAX_DELAY_COUNT); - while (reg->sleep_cookie && (count++ < 10) && - mwifiex_pcie_ok_to_access_hw(adapter)) - usleep_range(50, 60); - } else { - mwifiex_dbg(adapter, ERROR, - "There is no command but got cmdrsp\n"); - } - memcpy(adapter->upld_buf, skb->data, - min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, skb->len)); - skb_push(skb, INTF_HEADER_LEN); - if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - } else if (mwifiex_pcie_ok_to_access_hw(adapter)) { - adapter->curr_cmd->resp_skb = skb; - adapter->cmd_resp_received = true; - /* Take the pointer and set it to CMD node and will - return in the response complete callback */ - card->cmdrsp_buf = NULL; - - /* Clear the cmd-rsp buffer address in scratch registers. This - will prevent firmware from writing to the same response - buffer again. */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_lo, 0)) { - mwifiex_dbg(adapter, ERROR, - "cmd_done: failed to clear cmd_rsp_addr_lo\n"); - return -1; - } - /* Write the upper 32bits of the cmdrsp buffer physical - address */ - if (mwifiex_write_reg(adapter, reg->cmdrsp_addr_hi, 0)) { - mwifiex_dbg(adapter, ERROR, - "cmd_done: failed to clear cmd_rsp_addr_hi\n"); - return -1; - } - } - - return 0; -} - -/* - * Command Response processing complete handler - */ -static int mwifiex_pcie_cmdrsp_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - struct pcie_service_card *card = adapter->card; - - if (skb) { - card->cmdrsp_buf = skb; - skb_push(card->cmdrsp_buf, INTF_HEADER_LEN); - if (mwifiex_map_pci_memory(adapter, skb, MWIFIEX_UPLD_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - } - - return 0; -} - -/* - * This function handles firmware event ready interrupt - */ -static int mwifiex_pcie_process_event_ready(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; - u32 wrptr, event; - struct mwifiex_evt_buf_desc *desc; - - if (!mwifiex_pcie_ok_to_access_hw(adapter)) - mwifiex_pm_wakeup_card(adapter); - - if (adapter->event_received) { - mwifiex_dbg(adapter, EVENT, - "info: Event being processed,\t" - "do not process this interrupt just yet\n"); - return 0; - } - - if (rdptr >= MWIFIEX_MAX_EVT_BD) { - mwifiex_dbg(adapter, ERROR, - "info: Invalid read pointer...\n"); - return -1; - } - - /* Read the event ring write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) { - mwifiex_dbg(adapter, ERROR, - "EventReady: failed to read reg->evt_wrptr\n"); - return -1; - } - - mwifiex_dbg(adapter, EVENT, - "info: EventReady: Initial <Rd: 0x%x, Wr: 0x%x>", - card->evtbd_rdptr, wrptr); - if (((wrptr & MWIFIEX_EVTBD_MASK) != (card->evtbd_rdptr - & MWIFIEX_EVTBD_MASK)) || - ((wrptr & reg->evt_rollover_ind) == - (card->evtbd_rdptr & reg->evt_rollover_ind))) { - struct sk_buff *skb_cmd; - __le16 data_len = 0; - u16 evt_len; - - mwifiex_dbg(adapter, INFO, - "info: Read Index: %d\n", rdptr); - skb_cmd = card->evt_buf_list[rdptr]; - mwifiex_unmap_pci_memory(adapter, skb_cmd, PCI_DMA_FROMDEVICE); - - /* Take the pointer and set it to event pointer in adapter - and will return back after event handling callback */ - card->evt_buf_list[rdptr] = NULL; - desc = card->evtbd_ring[rdptr]; - memset(desc, 0, sizeof(*desc)); - - event = *(u32 *) &skb_cmd->data[INTF_HEADER_LEN]; - adapter->event_cause = event; - /* The first 4bytes will be the event transfer header - len is 2 bytes followed by type which is 2 bytes */ - memcpy(&data_len, skb_cmd->data, sizeof(__le16)); - evt_len = le16_to_cpu(data_len); - skb_trim(skb_cmd, evt_len); - skb_pull(skb_cmd, INTF_HEADER_LEN); - mwifiex_dbg(adapter, EVENT, - "info: Event length: %d\n", evt_len); - - if ((evt_len > 0) && (evt_len < MAX_EVENT_SIZE)) - memcpy(adapter->event_body, skb_cmd->data + - MWIFIEX_EVENT_HEADER_LEN, evt_len - - MWIFIEX_EVENT_HEADER_LEN); - - adapter->event_received = true; - adapter->event_skb = skb_cmd; - - /* Do not update the event read pointer here, wait till the - buffer is released. This is just to make things simpler, - we need to find a better method of managing these buffers. - */ - } else { - if (mwifiex_write_reg(adapter, PCIE_CPU_INT_EVENT, - CPU_INTR_EVENT_DONE)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return -1; - } - } - - return 0; -} - -/* - * Event processing complete handler - */ -static int mwifiex_pcie_event_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - int ret = 0; - u32 rdptr = card->evtbd_rdptr & MWIFIEX_EVTBD_MASK; - u32 wrptr; - struct mwifiex_evt_buf_desc *desc; - - if (!skb) - return 0; - - if (rdptr >= MWIFIEX_MAX_EVT_BD) { - mwifiex_dbg(adapter, ERROR, - "event_complete: Invalid rdptr 0x%x\n", - rdptr); - return -EINVAL; - } - - /* Read the event ring write pointer set by firmware */ - if (mwifiex_read_reg(adapter, reg->evt_wrptr, &wrptr)) { - mwifiex_dbg(adapter, ERROR, - "event_complete: failed to read reg->evt_wrptr\n"); - return -1; - } - - if (!card->evt_buf_list[rdptr]) { - skb_push(skb, INTF_HEADER_LEN); - skb_put(skb, MAX_EVENT_SIZE - skb->len); - if (mwifiex_map_pci_memory(adapter, skb, - MAX_EVENT_SIZE, - PCI_DMA_FROMDEVICE)) - return -1; - card->evt_buf_list[rdptr] = skb; - desc = card->evtbd_ring[rdptr]; - desc->paddr = MWIFIEX_SKB_DMA_ADDR(skb); - desc->len = (u16)skb->len; - desc->flags = 0; - skb = NULL; - } else { - mwifiex_dbg(adapter, ERROR, - "info: ERROR: buf still valid at index %d, <%p, %p>\n", - rdptr, card->evt_buf_list[rdptr], skb); - } - - if ((++card->evtbd_rdptr & MWIFIEX_EVTBD_MASK) == MWIFIEX_MAX_EVT_BD) { - card->evtbd_rdptr = ((card->evtbd_rdptr & - reg->evt_rollover_ind) ^ - reg->evt_rollover_ind); - } - - mwifiex_dbg(adapter, EVENT, - "info: Updated <Rd: 0x%x, Wr: 0x%x>", - card->evtbd_rdptr, wrptr); - - /* Write the event ring read pointer in to reg->evt_rdptr */ - if (mwifiex_write_reg(adapter, reg->evt_rdptr, - card->evtbd_rdptr)) { - mwifiex_dbg(adapter, ERROR, - "event_complete: failed to read reg->evt_rdptr\n"); - return -1; - } - - mwifiex_dbg(adapter, EVENT, - "info: Check Events Again\n"); - ret = mwifiex_pcie_process_event_ready(adapter); - - return ret; -} - -/* - * This function downloads the firmware to the card. - * - * Firmware is downloaded to the card in blocks. Every block download - * is tested for CRC errors, and retried a number of times before - * returning failure. - */ -static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *fw) -{ - int ret; - u8 *firmware = fw->fw_buf; - u32 firmware_len = fw->fw_len; - u32 offset = 0; - struct sk_buff *skb; - u32 txlen, tx_blocks = 0, tries, len; - u32 block_retry_cnt = 0; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - if (!firmware || !firmware_len) { - mwifiex_dbg(adapter, ERROR, - "No firmware image found! Terminating download\n"); - return -1; - } - - mwifiex_dbg(adapter, INFO, - "info: Downloading FW image (%d bytes)\n", - firmware_len); - - if (mwifiex_pcie_disable_host_int(adapter)) { - mwifiex_dbg(adapter, ERROR, - "%s: Disabling interrupts failed.\n", __func__); - return -1; - } - - skb = dev_alloc_skb(MWIFIEX_UPLD_SIZE); - if (!skb) { - ret = -ENOMEM; - goto done; - } - - /* Perform firmware data transfer */ - do { - u32 ireg_intr = 0; - - /* More data? */ - if (offset >= firmware_len) - break; - - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - ret = mwifiex_read_reg(adapter, reg->cmd_size, - &len); - if (ret) { - mwifiex_dbg(adapter, FATAL, - "Failed reading len from boot code\n"); - goto done; - } - if (len) - break; - usleep_range(10, 20); - } - - if (!len) { - break; - } else if (len > MWIFIEX_UPLD_SIZE) { - mwifiex_dbg(adapter, ERROR, - "FW download failure @ %d, invalid length %d\n", - offset, len); - ret = -1; - goto done; - } - - txlen = len; - - if (len & BIT(0)) { - block_retry_cnt++; - if (block_retry_cnt > MAX_WRITE_IOMEM_RETRY) { - mwifiex_dbg(adapter, ERROR, - "FW download failure @ %d, over max\t" - "retry count\n", offset); - ret = -1; - goto done; - } - mwifiex_dbg(adapter, ERROR, - "FW CRC error indicated by the\t" - "helper: len = 0x%04X, txlen = %d\n", - len, txlen); - len &= ~BIT(0); - /* Setting this to 0 to resend from same offset */ - txlen = 0; - } else { - block_retry_cnt = 0; - /* Set blocksize to transfer - checking for - last block */ - if (firmware_len - offset < txlen) - txlen = firmware_len - offset; - - mwifiex_dbg(adapter, INFO, "."); - - tx_blocks = (txlen + card->pcie.blksz_fw_dl - 1) / - card->pcie.blksz_fw_dl; - - /* Copy payload to buffer */ - memmove(skb->data, &firmware[offset], txlen); - } - - skb_put(skb, MWIFIEX_UPLD_SIZE - skb->len); - skb_trim(skb, tx_blocks * card->pcie.blksz_fw_dl); - - /* Send the boot command to device */ - if (mwifiex_pcie_send_boot_cmd(adapter, skb)) { - mwifiex_dbg(adapter, ERROR, - "Failed to send firmware download command\n"); - ret = -1; - goto done; - } - - /* Wait for the command done interrupt */ - do { - if (mwifiex_read_reg(adapter, PCIE_CPU_INT_STATUS, - &ireg_intr)) { - mwifiex_dbg(adapter, ERROR, - "%s: Failed to read\t" - "interrupt status during fw dnld.\n", - __func__); - mwifiex_unmap_pci_memory(adapter, skb, - PCI_DMA_TODEVICE); - ret = -1; - goto done; - } - } while ((ireg_intr & CPU_INTR_DOOR_BELL) == - CPU_INTR_DOOR_BELL); - - mwifiex_unmap_pci_memory(adapter, skb, PCI_DMA_TODEVICE); - - offset += txlen; - } while (true); - - mwifiex_dbg(adapter, MSG, - "info: FW download over, size %d bytes\n", offset); - - ret = 0; - -done: - dev_kfree_skb_any(skb); - return ret; -} - -/* - * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. - */ -static int -mwifiex_check_fw_status(struct mwifiex_adapter *adapter, u32 poll_num) -{ - int ret = 0; - u32 firmware_stat, winner_status; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - u32 tries; - - /* Mask spurios interrupts */ - if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS_MASK, - HOST_INTR_MASK)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return -1; - } - - mwifiex_dbg(adapter, INFO, - "Setting driver ready signature\n"); - if (mwifiex_write_reg(adapter, reg->drv_rdy, - FIRMWARE_READY_PCIE)) { - mwifiex_dbg(adapter, ERROR, - "Failed to write driver ready signature\n"); - return -1; - } - - /* Wait for firmware initialization event */ - for (tries = 0; tries < poll_num; tries++) { - if (mwifiex_read_reg(adapter, reg->fw_status, - &firmware_stat)) - ret = -1; - else - ret = 0; - if (ret) - continue; - if (firmware_stat == FIRMWARE_READY_PCIE) { - ret = 0; - break; - } else { - msleep(100); - ret = -1; - } - } - - if (ret) { - if (mwifiex_read_reg(adapter, reg->fw_status, - &winner_status)) - ret = -1; - else if (!winner_status) { - mwifiex_dbg(adapter, INFO, - "PCI-E is the winner\n"); - adapter->winner = 1; - } else { - mwifiex_dbg(adapter, ERROR, - "PCI-E is not the winner <%#x,%d>, exit dnld\n", - ret, adapter->winner); - } - } - - return ret; -} - -/* - * This function reads the interrupt status from card. - */ -static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) -{ - u32 pcie_ireg; - unsigned long flags; - - if (!mwifiex_pcie_ok_to_access_hw(adapter)) - return; - - if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, &pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, "Read register failed\n"); - return; - } - - if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { - - mwifiex_pcie_disable_host_int(adapter); - - /* Clear the pending interrupts */ - if (mwifiex_write_reg(adapter, PCIE_HOST_INT_STATUS, - ~pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return; - } - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= pcie_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - - if (!adapter->pps_uapsd_mode && - adapter->ps_state == PS_STATE_SLEEP && - mwifiex_pcie_ok_to_access_hw(adapter)) { - /* Potentially for PCIe we could get other - * interrupts like shared. Don't change power - * state until cookie is set */ - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - } - } -} - -/* - * Interrupt handler for PCIe root port - * - * This function reads the interrupt status from firmware and assigns - * the main process in workqueue which will handle the interrupt. - */ -static irqreturn_t mwifiex_pcie_interrupt(int irq, void *context) -{ - struct pci_dev *pdev = (struct pci_dev *)context; - struct pcie_service_card *card; - struct mwifiex_adapter *adapter; - - if (!pdev) { - pr_debug("info: %s: pdev is NULL\n", (u8 *)pdev); - goto exit; - } - - card = pci_get_drvdata(pdev); - if (!card || !card->adapter) { - pr_debug("info: %s: card=%p adapter=%p\n", __func__, card, - card ? card->adapter : NULL); - goto exit; - } - adapter = card->adapter; - - if (adapter->surprise_removed) - goto exit; - - mwifiex_interrupt_status(adapter); - mwifiex_queue_main_work(adapter); - -exit: - return IRQ_HANDLED; -} - -/* - * This function checks the current interrupt status. - * - * The following interrupts are checked and handled by this function - - * - Data sent - * - Command sent - * - Command received - * - Packets received - * - Events received - * - * In case of Rx packets received, the packets are uploaded from card to - * host and processed accordingly. - */ -static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) -{ - int ret; - u32 pcie_ireg; - unsigned long flags; - - spin_lock_irqsave(&adapter->int_lock, flags); - /* Clear out unused interrupts */ - pcie_ireg = adapter->int_status; - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); - - while (pcie_ireg & HOST_INTR_MASK) { - if (pcie_ireg & HOST_INTR_DNLD_DONE) { - pcie_ireg &= ~HOST_INTR_DNLD_DONE; - mwifiex_dbg(adapter, INTR, - "info: TX DNLD Done\n"); - ret = mwifiex_pcie_send_data_complete(adapter); - if (ret) - return ret; - } - if (pcie_ireg & HOST_INTR_UPLD_RDY) { - pcie_ireg &= ~HOST_INTR_UPLD_RDY; - mwifiex_dbg(adapter, INTR, - "info: Rx DATA\n"); - ret = mwifiex_pcie_process_recv_data(adapter); - if (ret) - return ret; - } - if (pcie_ireg & HOST_INTR_EVENT_RDY) { - pcie_ireg &= ~HOST_INTR_EVENT_RDY; - mwifiex_dbg(adapter, INTR, - "info: Rx EVENT\n"); - ret = mwifiex_pcie_process_event_ready(adapter); - if (ret) - return ret; - } - - if (pcie_ireg & HOST_INTR_CMD_DONE) { - pcie_ireg &= ~HOST_INTR_CMD_DONE; - if (adapter->cmd_sent) { - mwifiex_dbg(adapter, INTR, - "info: CMD sent Interrupt\n"); - adapter->cmd_sent = false; - } - /* Handle command response */ - ret = mwifiex_pcie_process_cmd_complete(adapter); - if (ret) - return ret; - } - - if (mwifiex_pcie_ok_to_access_hw(adapter)) { - if (mwifiex_read_reg(adapter, PCIE_HOST_INT_STATUS, - &pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Read register failed\n"); - return -1; - } - - if ((pcie_ireg != 0xFFFFFFFF) && (pcie_ireg)) { - if (mwifiex_write_reg(adapter, - PCIE_HOST_INT_STATUS, - ~pcie_ireg)) { - mwifiex_dbg(adapter, ERROR, - "Write register failed\n"); - return -1; - } - } - - } - } - mwifiex_dbg(adapter, INTR, - "info: cmd_sent=%d data_sent=%d\n", - adapter->cmd_sent, adapter->data_sent); - if (adapter->ps_state != PS_STATE_SLEEP) - mwifiex_pcie_enable_host_int(adapter); - - return 0; -} - -/* - * This function downloads data from driver to card. - * - * Both commands and data packets are transferred to the card by this - * function. - * - * This function adds the PCIE specific header to the front of the buffer - * before transferring. The header contains the length of the packet and - * the type. The firmware handles the packets based upon this set type. - */ -static int mwifiex_pcie_host_to_card(struct mwifiex_adapter *adapter, u8 type, - struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - if (!skb) { - mwifiex_dbg(adapter, ERROR, - "Passed NULL skb to %s\n", __func__); - return -1; - } - - if (type == MWIFIEX_TYPE_DATA) - return mwifiex_pcie_send_data(adapter, skb, tx_param); - else if (type == MWIFIEX_TYPE_CMD) - return mwifiex_pcie_send_cmd(adapter, skb); - - return 0; -} - -/* This function read/write firmware */ -static enum rdwr_status -mwifiex_pcie_rdwr_firmware(struct mwifiex_adapter *adapter, u8 doneflag) -{ - int ret, tries; - u8 ctrl_data; - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, FW_DUMP_HOST_READY); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "PCIE write err\n"); - return RDWR_STATUS_FAILURE; - } - - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - mwifiex_read_reg_byte(adapter, reg->fw_dump_ctrl, &ctrl_data); - if (ctrl_data == FW_DUMP_DONE) - return RDWR_STATUS_SUCCESS; - if (doneflag && ctrl_data == doneflag) - return RDWR_STATUS_DONE; - if (ctrl_data != FW_DUMP_HOST_READY) { - mwifiex_dbg(adapter, WARN, - "The ctrl reg was changed, re-try again!\n"); - ret = mwifiex_write_reg(adapter, reg->fw_dump_ctrl, - FW_DUMP_HOST_READY); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "PCIE write err\n"); - return RDWR_STATUS_FAILURE; - } - } - usleep_range(100, 200); - } - - mwifiex_dbg(adapter, ERROR, "Fail to pull ctrl_data\n"); - return RDWR_STATUS_FAILURE; -} - -/* This function dump firmware memory to file */ -static void mwifiex_pcie_fw_dump(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *creg = card->pcie.reg; - unsigned int reg, reg_start, reg_end; - u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; - enum rdwr_status stat; - u32 memory_size; - int ret; - - if (!card->pcie.can_dump_fw) - return; - - for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - } - - mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump start ==\n"); - - /* Read the number of the memories which will dump */ - stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - return; - - reg = creg->fw_dump_start; - mwifiex_read_reg_byte(adapter, reg, &dump_num); - - /* Read the length of every memory which will dump */ - for (idx = 0; idx < dump_num; idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; - - stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - return; - - memory_size = 0; - reg = creg->fw_dump_start; - for (i = 0; i < 4; i++) { - mwifiex_read_reg_byte(adapter, reg, &read_reg); - memory_size |= (read_reg << (i * 8)); - reg++; - } - - if (memory_size == 0) { - mwifiex_dbg(adapter, MSG, "Firmware dump Finished!\n"); - ret = mwifiex_write_reg(adapter, creg->fw_dump_ctrl, - FW_DUMP_READ_DONE); - if (ret) { - mwifiex_dbg(adapter, ERROR, "PCIE write err\n"); - return; - } - break; - } - - mwifiex_dbg(adapter, DUMP, - "%s_SIZE=0x%x\n", entry->mem_name, memory_size); - entry->mem_ptr = vmalloc(memory_size + 1); - entry->mem_size = memory_size; - if (!entry->mem_ptr) { - mwifiex_dbg(adapter, ERROR, - "Vmalloc %s failed\n", entry->mem_name); - return; - } - dbg_ptr = entry->mem_ptr; - end_ptr = dbg_ptr + memory_size; - - doneflag = entry->done_flag; - mwifiex_dbg(adapter, DUMP, "Start %s output, please wait...\n", - entry->mem_name); - - do { - stat = mwifiex_pcie_rdwr_firmware(adapter, doneflag); - if (RDWR_STATUS_FAILURE == stat) - return; - - reg_start = creg->fw_dump_start; - reg_end = creg->fw_dump_end; - for (reg = reg_start; reg <= reg_end; reg++) { - mwifiex_read_reg_byte(adapter, reg, dbg_ptr); - if (dbg_ptr < end_ptr) { - dbg_ptr++; - } else { - mwifiex_dbg(adapter, ERROR, - "Allocated buf not enough\n"); - return; - } - } - - if (stat != RDWR_STATUS_DONE) - continue; - - mwifiex_dbg(adapter, DUMP, - "%s done: size=0x%tx\n", - entry->mem_name, dbg_ptr - entry->mem_ptr); - break; - } while (true); - } - mwifiex_dbg(adapter, DUMP, "== mwifiex firmware dump end ==\n"); -} - -static void mwifiex_pcie_device_dump_work(struct mwifiex_adapter *adapter) -{ - mwifiex_drv_info_dump(adapter); - mwifiex_pcie_fw_dump(adapter); - mwifiex_upload_device_dump(adapter); -} - -static unsigned long iface_work_flags; -static struct mwifiex_adapter *save_adapter; -static void mwifiex_pcie_work(struct work_struct *work) -{ - if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, - &iface_work_flags)) - mwifiex_pcie_device_dump_work(save_adapter); -} - -static DECLARE_WORK(pcie_work, mwifiex_pcie_work); -/* This function dumps FW information */ -static void mwifiex_pcie_device_dump(struct mwifiex_adapter *adapter) -{ - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags)) - return; - - set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); - - schedule_work(&pcie_work); -} - -/* - * This function initializes the PCI-E host memory space, WCB rings, etc. - * - * The following initializations steps are followed - - * - Allocate TXBD ring buffers - * - Allocate RXBD ring buffers - * - Allocate event BD ring buffers - * - Allocate command response ring buffer - * - Allocate sleep cookie buffer - */ -static int mwifiex_pcie_init(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - int ret; - struct pci_dev *pdev = card->dev; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - pci_set_drvdata(pdev, card); - - ret = pci_enable_device(pdev); - if (ret) - goto err_enable_dev; - - pci_set_master(pdev); - - mwifiex_dbg(adapter, INFO, - "try set_consistent_dma_mask(32)\n"); - ret = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "set_dma_mask(32) failed\n"); - goto err_set_dma_mask; - } - - ret = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32)); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "set_consistent_dma_mask(64) failed\n"); - goto err_set_dma_mask; - } - - ret = pci_request_region(pdev, 0, DRV_NAME); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "req_reg(0) error\n"); - goto err_req_region0; - } - card->pci_mmap = pci_iomap(pdev, 0, 0); - if (!card->pci_mmap) { - mwifiex_dbg(adapter, ERROR, "iomap(0) error\n"); - ret = -EIO; - goto err_iomap0; - } - ret = pci_request_region(pdev, 2, DRV_NAME); - if (ret) { - mwifiex_dbg(adapter, ERROR, "req_reg(2) error\n"); - goto err_req_region2; - } - card->pci_mmap1 = pci_iomap(pdev, 2, 0); - if (!card->pci_mmap1) { - mwifiex_dbg(adapter, ERROR, - "iomap(2) error\n"); - ret = -EIO; - goto err_iomap2; - } - - mwifiex_dbg(adapter, INFO, - "PCI memory map Virt0: %p PCI memory map Virt2: %p\n", - card->pci_mmap, card->pci_mmap1); - - card->cmdrsp_buf = NULL; - ret = mwifiex_pcie_create_txbd_ring(adapter); - if (ret) - goto err_cre_txbd; - ret = mwifiex_pcie_create_rxbd_ring(adapter); - if (ret) - goto err_cre_rxbd; - ret = mwifiex_pcie_create_evtbd_ring(adapter); - if (ret) - goto err_cre_evtbd; - ret = mwifiex_pcie_alloc_cmdrsp_buf(adapter); - if (ret) - goto err_alloc_cmdbuf; - if (reg->sleep_cookie) { - ret = mwifiex_pcie_alloc_sleep_cookie_buf(adapter); - if (ret) - goto err_alloc_cookie; - } else { - card->sleep_cookie_vbase = NULL; - } - return ret; - -err_alloc_cookie: - mwifiex_pcie_delete_cmdrsp_buf(adapter); -err_alloc_cmdbuf: - mwifiex_pcie_delete_evtbd_ring(adapter); -err_cre_evtbd: - mwifiex_pcie_delete_rxbd_ring(adapter); -err_cre_rxbd: - mwifiex_pcie_delete_txbd_ring(adapter); -err_cre_txbd: - pci_iounmap(pdev, card->pci_mmap1); -err_iomap2: - pci_release_region(pdev, 2); -err_req_region2: - pci_iounmap(pdev, card->pci_mmap); -err_iomap0: - pci_release_region(pdev, 0); -err_req_region0: -err_set_dma_mask: - pci_disable_device(pdev); -err_enable_dev: - pci_set_drvdata(pdev, NULL); - return ret; -} - -/* - * This function cleans up the allocated card buffers. - * - * The following are freed by this function - - * - TXBD ring buffers - * - RXBD ring buffers - * - Event BD ring buffers - * - Command response ring buffer - * - Sleep cookie buffer - */ -static void mwifiex_pcie_cleanup(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - struct pci_dev *pdev = card->dev; - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - if (user_rmmod) { - mwifiex_dbg(adapter, INFO, - "Clearing driver ready signature\n"); - if (mwifiex_write_reg(adapter, reg->drv_rdy, 0x00000000)) - mwifiex_dbg(adapter, ERROR, - "Failed to write driver not-ready signature\n"); - } - - if (pdev) { - pci_iounmap(pdev, card->pci_mmap); - pci_iounmap(pdev, card->pci_mmap1); - pci_disable_device(pdev); - pci_release_region(pdev, 2); - pci_release_region(pdev, 0); - pci_set_drvdata(pdev, NULL); - } - kfree(card); -} - -/* - * This function registers the PCIE device. - * - * PCIE IRQ is claimed, block size is set and driver data is initialized. - */ -static int mwifiex_register_dev(struct mwifiex_adapter *adapter) -{ - int ret; - struct pcie_service_card *card = adapter->card; - struct pci_dev *pdev = card->dev; - - /* save adapter pointer in card */ - card->adapter = adapter; - - ret = request_irq(pdev->irq, mwifiex_pcie_interrupt, IRQF_SHARED, - "MRVL_PCIE", pdev); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "request_irq failed: ret=%d\n", ret); - adapter->card = NULL; - return -1; - } - - adapter->dev = &pdev->dev; - adapter->tx_buf_size = card->pcie.tx_buf_size; - adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; - adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); - strcpy(adapter->fw_name, card->pcie.firmware); - adapter->ext_scan = card->pcie.can_ext_scan; - - return 0; -} - -/* - * This function unregisters the PCIE device. - * - * The PCIE IRQ is released, the function is disabled and driver - * data is set to null. - */ -static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) -{ - struct pcie_service_card *card = adapter->card; - const struct mwifiex_pcie_card_reg *reg; - - if (card) { - mwifiex_dbg(adapter, INFO, - "%s(): calling free_irq()\n", __func__); - free_irq(card->dev->irq, card->dev); - - reg = card->pcie.reg; - if (reg->sleep_cookie) - mwifiex_pcie_delete_sleep_cookie_buf(adapter); - - mwifiex_pcie_delete_cmdrsp_buf(adapter); - mwifiex_pcie_delete_evtbd_ring(adapter); - mwifiex_pcie_delete_rxbd_ring(adapter); - mwifiex_pcie_delete_txbd_ring(adapter); - card->cmdrsp_buf = NULL; - } -} - -static struct mwifiex_if_ops pcie_ops = { - .init_if = mwifiex_pcie_init, - .cleanup_if = mwifiex_pcie_cleanup, - .check_fw_status = mwifiex_check_fw_status, - .prog_fw = mwifiex_prog_fw_w_helper, - .register_dev = mwifiex_register_dev, - .unregister_dev = mwifiex_unregister_dev, - .enable_int = mwifiex_pcie_enable_host_int, - .process_int_status = mwifiex_process_int_status, - .host_to_card = mwifiex_pcie_host_to_card, - .wakeup = mwifiex_pm_wakeup_card, - .wakeup_complete = mwifiex_pm_wakeup_card_complete, - - /* PCIE specific */ - .cmdrsp_complete = mwifiex_pcie_cmdrsp_complete, - .event_complete = mwifiex_pcie_event_complete, - .update_mp_end_port = NULL, - .cleanup_mpa_buf = NULL, - .init_fw_port = mwifiex_pcie_init_fw_port, - .clean_pcie_ring = mwifiex_clean_pcie_ring_buf, - .device_dump = mwifiex_pcie_device_dump, -}; - -/* - * This function initializes the PCIE driver module. - * - * This initiates the semaphore and registers the device with - * PCIE bus. - */ -static int mwifiex_pcie_init_module(void) -{ - int ret; - - pr_debug("Marvell PCIe Driver\n"); - - sema_init(&add_remove_card_sem, 1); - - /* Clear the flag in case user removes the card. */ - user_rmmod = 0; - - ret = pci_register_driver(&mwifiex_pcie); - if (ret) - pr_err("Driver register failed!\n"); - else - pr_debug("info: Driver registered successfully!\n"); - - return ret; -} - -/* - * This function cleans up the PCIE driver. - * - * The following major steps are followed for cleanup - - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from PCIE bus. - */ -static void mwifiex_pcie_cleanup_module(void) -{ - if (!down_interruptible(&add_remove_card_sem)) - up(&add_remove_card_sem); - - /* Set the flag as user is removing this module. */ - user_rmmod = 1; - - cancel_work_sync(&pcie_work); - pci_unregister_driver(&mwifiex_pcie); -} - -module_init(mwifiex_pcie_init_module); -module_exit(mwifiex_pcie_cleanup_module); - -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_DESCRIPTION("Marvell WiFi-Ex PCI-Express Driver version " PCIE_VERSION); -MODULE_VERSION(PCIE_VERSION); -MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE(PCIE8766_DEFAULT_FW_NAME); -MODULE_FIRMWARE(PCIE8897_DEFAULT_FW_NAME); -MODULE_FIRMWARE(PCIE8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/pcie.h b/drivers/net/wireless/mwifiex/pcie.h deleted file mode 100644 index 48e549c3b285..000000000000 --- a/drivers/net/wireless/mwifiex/pcie.h +++ /dev/null @@ -1,382 +0,0 @@ -/* @file mwifiex_pcie.h - * - * @brief This file contains definitions for PCI-E interface. - * driver. - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_PCIE_H -#define _MWIFIEX_PCIE_H - -#include <linux/pci.h> -#include <linux/pcieport_if.h> -#include <linux/interrupt.h> - -#include "main.h" - -#define PCIE8766_DEFAULT_FW_NAME "mrvl/pcie8766_uapsta.bin" -#define PCIE8897_DEFAULT_FW_NAME "mrvl/pcie8897_uapsta.bin" -#define PCIE8997_DEFAULT_FW_NAME "mrvl/pcie8997_uapsta.bin" - -#define PCIE_VENDOR_ID_MARVELL (0x11ab) -#define PCIE_DEVICE_ID_MARVELL_88W8766P (0x2b30) -#define PCIE_DEVICE_ID_MARVELL_88W8897 (0x2b38) -#define PCIE_DEVICE_ID_MARVELL_88W8997 (0x2b42) - -/* Constants for Buffer Descriptor (BD) rings */ -#define MWIFIEX_MAX_TXRX_BD 0x20 -#define MWIFIEX_TXBD_MASK 0x3F -#define MWIFIEX_RXBD_MASK 0x3F - -#define MWIFIEX_MAX_EVT_BD 0x08 -#define MWIFIEX_EVTBD_MASK 0x0f - -/* PCIE INTERNAL REGISTERS */ -#define PCIE_SCRATCH_0_REG 0xC10 -#define PCIE_SCRATCH_1_REG 0xC14 -#define PCIE_CPU_INT_EVENT 0xC18 -#define PCIE_CPU_INT_STATUS 0xC1C -#define PCIE_HOST_INT_STATUS 0xC30 -#define PCIE_HOST_INT_MASK 0xC34 -#define PCIE_HOST_INT_STATUS_MASK 0xC3C -#define PCIE_SCRATCH_2_REG 0xC40 -#define PCIE_SCRATCH_3_REG 0xC44 -#define PCIE_SCRATCH_4_REG 0xCD0 -#define PCIE_SCRATCH_5_REG 0xCD4 -#define PCIE_SCRATCH_6_REG 0xCD8 -#define PCIE_SCRATCH_7_REG 0xCDC -#define PCIE_SCRATCH_8_REG 0xCE0 -#define PCIE_SCRATCH_9_REG 0xCE4 -#define PCIE_SCRATCH_10_REG 0xCE8 -#define PCIE_SCRATCH_11_REG 0xCEC -#define PCIE_SCRATCH_12_REG 0xCF0 -#define PCIE_RD_DATA_PTR_Q0_Q1 0xC08C -#define PCIE_WR_DATA_PTR_Q0_Q1 0xC05C - -#define CPU_INTR_DNLD_RDY BIT(0) -#define CPU_INTR_DOOR_BELL BIT(1) -#define CPU_INTR_SLEEP_CFM_DONE BIT(2) -#define CPU_INTR_RESET BIT(3) -#define CPU_INTR_EVENT_DONE BIT(5) - -#define HOST_INTR_DNLD_DONE BIT(0) -#define HOST_INTR_UPLD_RDY BIT(1) -#define HOST_INTR_CMD_DONE BIT(2) -#define HOST_INTR_EVENT_RDY BIT(3) -#define HOST_INTR_MASK (HOST_INTR_DNLD_DONE | \ - HOST_INTR_UPLD_RDY | \ - HOST_INTR_CMD_DONE | \ - HOST_INTR_EVENT_RDY) - -#define MWIFIEX_BD_FLAG_ROLLOVER_IND BIT(7) -#define MWIFIEX_BD_FLAG_FIRST_DESC BIT(0) -#define MWIFIEX_BD_FLAG_LAST_DESC BIT(1) -#define MWIFIEX_BD_FLAG_SOP BIT(0) -#define MWIFIEX_BD_FLAG_EOP BIT(1) -#define MWIFIEX_BD_FLAG_XS_SOP BIT(2) -#define MWIFIEX_BD_FLAG_XS_EOP BIT(3) -#define MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND BIT(7) -#define MWIFIEX_BD_FLAG_RX_ROLLOVER_IND BIT(10) -#define MWIFIEX_BD_FLAG_TX_START_PTR BIT(16) -#define MWIFIEX_BD_FLAG_TX_ROLLOVER_IND BIT(26) - -/* Max retry number of command write */ -#define MAX_WRITE_IOMEM_RETRY 2 -/* Define PCIE block size for firmware download */ -#define MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD 256 -/* FW awake cookie after FW ready */ -#define FW_AWAKE_COOKIE (0xAA55AA55) -#define MWIFIEX_DEF_SLEEP_COOKIE 0xBEEFBEEF -#define MWIFIEX_MAX_DELAY_COUNT 5 - -struct mwifiex_pcie_card_reg { - u16 cmd_addr_lo; - u16 cmd_addr_hi; - u16 fw_status; - u16 cmd_size; - u16 cmdrsp_addr_lo; - u16 cmdrsp_addr_hi; - u16 tx_rdptr; - u16 tx_wrptr; - u16 rx_rdptr; - u16 rx_wrptr; - u16 evt_rdptr; - u16 evt_wrptr; - u16 drv_rdy; - u16 tx_start_ptr; - u32 tx_mask; - u32 tx_wrap_mask; - u32 rx_mask; - u32 rx_wrap_mask; - u32 tx_rollover_ind; - u32 rx_rollover_ind; - u32 evt_rollover_ind; - u8 ring_flag_sop; - u8 ring_flag_eop; - u8 ring_flag_xs_sop; - u8 ring_flag_xs_eop; - u32 ring_tx_start_ptr; - u8 pfu_enabled; - u8 sleep_cookie; - u16 fw_dump_ctrl; - u16 fw_dump_start; - u16 fw_dump_end; -}; - -static const struct mwifiex_pcie_card_reg mwifiex_reg_8766 = { - .cmd_addr_lo = PCIE_SCRATCH_0_REG, - .cmd_addr_hi = PCIE_SCRATCH_1_REG, - .cmd_size = PCIE_SCRATCH_2_REG, - .fw_status = PCIE_SCRATCH_3_REG, - .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG, - .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG, - .tx_rdptr = PCIE_SCRATCH_6_REG, - .tx_wrptr = PCIE_SCRATCH_7_REG, - .rx_rdptr = PCIE_SCRATCH_8_REG, - .rx_wrptr = PCIE_SCRATCH_9_REG, - .evt_rdptr = PCIE_SCRATCH_10_REG, - .evt_wrptr = PCIE_SCRATCH_11_REG, - .drv_rdy = PCIE_SCRATCH_12_REG, - .tx_start_ptr = 0, - .tx_mask = MWIFIEX_TXBD_MASK, - .tx_wrap_mask = 0, - .rx_mask = MWIFIEX_RXBD_MASK, - .rx_wrap_mask = 0, - .tx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND, - .rx_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND, - .evt_rollover_ind = MWIFIEX_BD_FLAG_ROLLOVER_IND, - .ring_flag_sop = 0, - .ring_flag_eop = 0, - .ring_flag_xs_sop = 0, - .ring_flag_xs_eop = 0, - .ring_tx_start_ptr = 0, - .pfu_enabled = 0, - .sleep_cookie = 1, -}; - -static const struct mwifiex_pcie_card_reg mwifiex_reg_8897 = { - .cmd_addr_lo = PCIE_SCRATCH_0_REG, - .cmd_addr_hi = PCIE_SCRATCH_1_REG, - .cmd_size = PCIE_SCRATCH_2_REG, - .fw_status = PCIE_SCRATCH_3_REG, - .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG, - .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG, - .tx_rdptr = PCIE_RD_DATA_PTR_Q0_Q1, - .tx_wrptr = PCIE_WR_DATA_PTR_Q0_Q1, - .rx_rdptr = PCIE_WR_DATA_PTR_Q0_Q1, - .rx_wrptr = PCIE_RD_DATA_PTR_Q0_Q1, - .evt_rdptr = PCIE_SCRATCH_10_REG, - .evt_wrptr = PCIE_SCRATCH_11_REG, - .drv_rdy = PCIE_SCRATCH_12_REG, - .tx_start_ptr = 16, - .tx_mask = 0x03FF0000, - .tx_wrap_mask = 0x07FF0000, - .rx_mask = 0x000003FF, - .rx_wrap_mask = 0x000007FF, - .tx_rollover_ind = MWIFIEX_BD_FLAG_TX_ROLLOVER_IND, - .rx_rollover_ind = MWIFIEX_BD_FLAG_RX_ROLLOVER_IND, - .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND, - .ring_flag_sop = MWIFIEX_BD_FLAG_SOP, - .ring_flag_eop = MWIFIEX_BD_FLAG_EOP, - .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP, - .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP, - .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, - .pfu_enabled = 1, - .sleep_cookie = 0, - .fw_dump_ctrl = 0xcf4, - .fw_dump_start = 0xcf8, - .fw_dump_end = 0xcff, -}; - -static const struct mwifiex_pcie_card_reg mwifiex_reg_8997 = { - .cmd_addr_lo = PCIE_SCRATCH_0_REG, - .cmd_addr_hi = PCIE_SCRATCH_1_REG, - .cmd_size = PCIE_SCRATCH_2_REG, - .fw_status = PCIE_SCRATCH_3_REG, - .cmdrsp_addr_lo = PCIE_SCRATCH_4_REG, - .cmdrsp_addr_hi = PCIE_SCRATCH_5_REG, - .tx_rdptr = 0xC1A4, - .tx_wrptr = 0xC1A8, - .rx_rdptr = 0xC1A8, - .rx_wrptr = 0xC1A4, - .evt_rdptr = PCIE_SCRATCH_10_REG, - .evt_wrptr = PCIE_SCRATCH_11_REG, - .drv_rdy = PCIE_SCRATCH_12_REG, - .tx_start_ptr = 16, - .tx_mask = 0x0FFF0000, - .tx_wrap_mask = 0x01FF0000, - .rx_mask = 0x00000FFF, - .rx_wrap_mask = 0x000001FF, - .tx_rollover_ind = BIT(28), - .rx_rollover_ind = BIT(12), - .evt_rollover_ind = MWIFIEX_BD_FLAG_EVT_ROLLOVER_IND, - .ring_flag_sop = MWIFIEX_BD_FLAG_SOP, - .ring_flag_eop = MWIFIEX_BD_FLAG_EOP, - .ring_flag_xs_sop = MWIFIEX_BD_FLAG_XS_SOP, - .ring_flag_xs_eop = MWIFIEX_BD_FLAG_XS_EOP, - .ring_tx_start_ptr = MWIFIEX_BD_FLAG_TX_START_PTR, - .pfu_enabled = 1, - .sleep_cookie = 0, -}; - -struct mwifiex_pcie_device { - const char *firmware; - const struct mwifiex_pcie_card_reg *reg; - u16 blksz_fw_dl; - u16 tx_buf_size; - bool can_dump_fw; - bool can_ext_scan; -}; - -static const struct mwifiex_pcie_device mwifiex_pcie8766 = { - .firmware = PCIE8766_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_8766, - .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, - .can_dump_fw = false, - .can_ext_scan = true, -}; - -static const struct mwifiex_pcie_device mwifiex_pcie8897 = { - .firmware = PCIE8897_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_8897, - .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, - .can_dump_fw = true, - .can_ext_scan = true, -}; - -static const struct mwifiex_pcie_device mwifiex_pcie8997 = { - .firmware = PCIE8997_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_8997, - .blksz_fw_dl = MWIFIEX_PCIE_BLOCK_SIZE_FW_DNLD, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, - .can_dump_fw = false, - .can_ext_scan = true, -}; - -struct mwifiex_evt_buf_desc { - u64 paddr; - u16 len; - u16 flags; -} __packed; - -struct mwifiex_pcie_buf_desc { - u64 paddr; - u16 len; - u16 flags; -} __packed; - -struct mwifiex_pfu_buf_desc { - u16 flags; - u16 offset; - u16 frag_len; - u16 len; - u64 paddr; - u32 reserved; -} __packed; - -struct pcie_service_card { - struct pci_dev *dev; - struct mwifiex_adapter *adapter; - struct mwifiex_pcie_device pcie; - - u8 txbd_flush; - u32 txbd_wrptr; - u32 txbd_rdptr; - u32 txbd_ring_size; - u8 *txbd_ring_vbase; - dma_addr_t txbd_ring_pbase; - void *txbd_ring[MWIFIEX_MAX_TXRX_BD]; - struct sk_buff *tx_buf_list[MWIFIEX_MAX_TXRX_BD]; - - u32 rxbd_wrptr; - u32 rxbd_rdptr; - u32 rxbd_ring_size; - u8 *rxbd_ring_vbase; - dma_addr_t rxbd_ring_pbase; - void *rxbd_ring[MWIFIEX_MAX_TXRX_BD]; - struct sk_buff *rx_buf_list[MWIFIEX_MAX_TXRX_BD]; - - u32 evtbd_wrptr; - u32 evtbd_rdptr; - u32 evtbd_ring_size; - u8 *evtbd_ring_vbase; - dma_addr_t evtbd_ring_pbase; - void *evtbd_ring[MWIFIEX_MAX_EVT_BD]; - struct sk_buff *evt_buf_list[MWIFIEX_MAX_EVT_BD]; - - struct sk_buff *cmd_buf; - struct sk_buff *cmdrsp_buf; - u8 *sleep_cookie_vbase; - dma_addr_t sleep_cookie_pbase; - void __iomem *pci_mmap; - void __iomem *pci_mmap1; -}; - -static inline int -mwifiex_pcie_txbd_empty(struct pcie_service_card *card, u32 rdptr) -{ - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - if (((card->txbd_wrptr & reg->tx_mask) == - (rdptr & reg->tx_mask)) && - ((card->txbd_wrptr & reg->tx_rollover_ind) != - (rdptr & reg->tx_rollover_ind))) - return 1; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - if (((card->txbd_wrptr & reg->tx_mask) == - (rdptr & reg->tx_mask)) && - ((card->txbd_wrptr & reg->tx_rollover_ind) == - (rdptr & reg->tx_rollover_ind))) - return 1; - break; - } - - return 0; -} - -static inline int -mwifiex_pcie_txbd_not_full(struct pcie_service_card *card) -{ - const struct mwifiex_pcie_card_reg *reg = card->pcie.reg; - - switch (card->dev->device) { - case PCIE_DEVICE_ID_MARVELL_88W8766P: - if (((card->txbd_wrptr & reg->tx_mask) != - (card->txbd_rdptr & reg->tx_mask)) || - ((card->txbd_wrptr & reg->tx_rollover_ind) != - (card->txbd_rdptr & reg->tx_rollover_ind))) - return 1; - break; - case PCIE_DEVICE_ID_MARVELL_88W8897: - case PCIE_DEVICE_ID_MARVELL_88W8997: - if (((card->txbd_wrptr & reg->tx_mask) != - (card->txbd_rdptr & reg->tx_mask)) || - ((card->txbd_wrptr & reg->tx_rollover_ind) == - (card->txbd_rdptr & reg->tx_rollover_ind))) - return 1; - break; - } - - return 0; -} - -#endif /* _MWIFIEX_PCIE_H */ diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c deleted file mode 100644 index c20017ced566..000000000000 --- a/drivers/net/wireless/mwifiex/scan.c +++ /dev/null @@ -1,2639 +0,0 @@ -/* - * Marvell Wireless LAN device driver: scan ioctl and command handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "11n.h" -#include "cfg80211.h" - -/* The maximum number of channels the firmware can scan per command */ -#define MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN 14 - -#define MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD 4 - -/* Memory needed to store a max sized Channel List TLV for a firmware scan */ -#define CHAN_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_header) \ - + (MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN \ - *sizeof(struct mwifiex_chan_scan_param_set))) - -/* Memory needed to store supported rate */ -#define RATE_TLV_MAX_SIZE (sizeof(struct mwifiex_ie_types_rates_param_set) \ - + HOSTCMD_SUPPORTED_RATES) - -/* Memory needed to store a max number/size WildCard SSID TLV for a firmware - scan */ -#define WILDCARD_SSID_TLV_MAX_SIZE \ - (MWIFIEX_MAX_SSID_LIST_LENGTH * \ - (sizeof(struct mwifiex_ie_types_wildcard_ssid_params) \ - + IEEE80211_MAX_SSID_LEN)) - -/* Maximum memory needed for a mwifiex_scan_cmd_config with all TLVs at max */ -#define MAX_SCAN_CFG_ALLOC (sizeof(struct mwifiex_scan_cmd_config) \ - + sizeof(struct mwifiex_ie_types_num_probes) \ - + sizeof(struct mwifiex_ie_types_htcap) \ - + CHAN_TLV_MAX_SIZE \ - + RATE_TLV_MAX_SIZE \ - + WILDCARD_SSID_TLV_MAX_SIZE) - - -union mwifiex_scan_cmd_config_tlv { - /* Scan configuration (variable length) */ - struct mwifiex_scan_cmd_config config; - /* Max allocated block */ - u8 config_alloc_buf[MAX_SCAN_CFG_ALLOC]; -}; - -enum cipher_suite { - CIPHER_SUITE_TKIP, - CIPHER_SUITE_CCMP, - CIPHER_SUITE_MAX -}; -static u8 mwifiex_wpa_oui[CIPHER_SUITE_MAX][4] = { - { 0x00, 0x50, 0xf2, 0x02 }, /* TKIP */ - { 0x00, 0x50, 0xf2, 0x04 }, /* AES */ -}; -static u8 mwifiex_rsn_oui[CIPHER_SUITE_MAX][4] = { - { 0x00, 0x0f, 0xac, 0x02 }, /* TKIP */ - { 0x00, 0x0f, 0xac, 0x04 }, /* AES */ -}; - -/* - * This function parses a given IE for a given OUI. - * - * This is used to parse a WPA/RSN IE to find if it has - * a given oui in PTK. - */ -static u8 -mwifiex_search_oui_in_ie(struct ie_body *iebody, u8 *oui) -{ - u8 count; - - count = iebody->ptk_cnt[0]; - - /* There could be multiple OUIs for PTK hence - 1) Take the length. - 2) Check all the OUIs for AES. - 3) If one of them is AES then pass success. */ - while (count) { - if (!memcmp(iebody->ptk_body, oui, sizeof(iebody->ptk_body))) - return MWIFIEX_OUI_PRESENT; - - --count; - if (count) - iebody = (struct ie_body *) ((u8 *) iebody + - sizeof(iebody->ptk_body)); - } - - pr_debug("info: %s: OUI is not found in PTK\n", __func__); - return MWIFIEX_OUI_NOT_PRESENT; -} - -/* - * This function checks if a given OUI is present in a RSN IE. - * - * The function first checks if a RSN IE is present or not in the - * BSS descriptor. It tries to locate the OUI only if such an IE is - * present. - */ -static u8 -mwifiex_is_rsn_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) -{ - u8 *oui; - struct ie_body *iebody; - u8 ret = MWIFIEX_OUI_NOT_PRESENT; - - if (((bss_desc->bcn_rsn_ie) && ((*(bss_desc->bcn_rsn_ie)). - ieee_hdr.element_id == WLAN_EID_RSN))) { - iebody = (struct ie_body *) - (((u8 *) bss_desc->bcn_rsn_ie->data) + - RSN_GTK_OUI_OFFSET); - oui = &mwifiex_rsn_oui[cipher][0]; - ret = mwifiex_search_oui_in_ie(iebody, oui); - if (ret) - return ret; - } - return ret; -} - -/* - * This function checks if a given OUI is present in a WPA IE. - * - * The function first checks if a WPA IE is present or not in the - * BSS descriptor. It tries to locate the OUI only if such an IE is - * present. - */ -static u8 -mwifiex_is_wpa_oui_present(struct mwifiex_bssdescriptor *bss_desc, u32 cipher) -{ - u8 *oui; - struct ie_body *iebody; - u8 ret = MWIFIEX_OUI_NOT_PRESENT; - - if (((bss_desc->bcn_wpa_ie) && - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id == - WLAN_EID_VENDOR_SPECIFIC))) { - iebody = (struct ie_body *) bss_desc->bcn_wpa_ie->data; - oui = &mwifiex_wpa_oui[cipher][0]; - ret = mwifiex_search_oui_in_ie(iebody, oui); - if (ret) - return ret; - } - return ret; -} - -/* - * This function compares two SSIDs and checks if they match. - */ -s32 -mwifiex_ssid_cmp(struct cfg80211_ssid *ssid1, struct cfg80211_ssid *ssid2) -{ - if (!ssid1 || !ssid2 || (ssid1->ssid_len != ssid2->ssid_len)) - return -1; - return memcmp(ssid1->ssid, ssid2->ssid, ssid1->ssid_len); -} - -/* - * This function checks if wapi is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_bss_wapi(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (priv->sec_info.wapi_enabled && - (bss_desc->bcn_wapi_ie && - ((*(bss_desc->bcn_wapi_ie)).ieee_hdr.element_id == - WLAN_EID_BSS_AC_ACCESS_DELAY))) { - return true; - } - return false; -} - -/* - * This function checks if driver is configured with no security mode and - * scanned network is compatible with it. - */ -static bool -mwifiex_is_bss_no_sec(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)).vend_hdr.element_id != - WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != - WLAN_EID_RSN)) && - !priv->sec_info.encryption_mode && !bss_desc->privacy) { - return true; - } - return false; -} - -/* - * This function checks if static WEP is enabled in driver and scanned network - * is compatible with it. - */ -static bool -mwifiex_is_bss_static_wep(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && bss_desc->privacy) { - return true; - } - return false; -} - -/* - * This function checks if wpa is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_bss_wpa(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (!priv->sec_info.wep_enabled && priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && ((bss_desc->bcn_wpa_ie) && - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)) - /* - * Privacy bit may NOT be set in some APs like - * LinkSys WRT54G && bss_desc->privacy - */ - ) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: WPA:\t" - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" - "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); - return true; - } - return false; -} - -/* - * This function checks if wpa2 is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_bss_wpa2(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (!priv->sec_info.wep_enabled && - !priv->sec_info.wpa_enabled && - priv->sec_info.wpa2_enabled && - ((bss_desc->bcn_rsn_ie) && - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id == WLAN_EID_RSN))) { - /* - * Privacy bit may NOT be set in some APs like - * LinkSys WRT54G && bss_desc->privacy - */ - mwifiex_dbg(priv->adapter, INFO, - "info: %s: WPA2:\t" - "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s\t" - "EncMode=%#x privacy=%#x\n", __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, - bss_desc->privacy); - return true; - } - return false; -} - -/* - * This function checks if adhoc AES is enabled in driver and scanned network is - * compatible with it. - */ -static bool -mwifiex_is_bss_adhoc_aes(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && - ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && - !priv->sec_info.encryption_mode && bss_desc->privacy) { - return true; - } - return false; -} - -/* - * This function checks if dynamic WEP is enabled in driver and scanned network - * is compatible with it. - */ -static bool -mwifiex_is_bss_dynamic_wep(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - if (!priv->sec_info.wep_enabled && !priv->sec_info.wpa_enabled && - !priv->sec_info.wpa2_enabled && - ((!bss_desc->bcn_wpa_ie) || - ((*(bss_desc->bcn_wpa_ie)). - vend_hdr.element_id != WLAN_EID_VENDOR_SPECIFIC)) && - ((!bss_desc->bcn_rsn_ie) || - ((*(bss_desc->bcn_rsn_ie)).ieee_hdr.element_id != WLAN_EID_RSN)) && - priv->sec_info.encryption_mode && bss_desc->privacy) { - mwifiex_dbg(priv->adapter, INFO, - "info: %s: dynamic\t" - "WEP: wpa_ie=%#x wpa2_ie=%#x\t" - "EncMode=%#x privacy=%#x\n", - __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie). - vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie). - ieee_hdr.element_id : 0, - priv->sec_info.encryption_mode, - bss_desc->privacy); - return true; - } - return false; -} - -/* - * This function checks if a scanned network is compatible with the driver - * settings. - * - * WEP WPA WPA2 ad-hoc encrypt Network - * enabled enabled enabled AES mode Privacy WPA WPA2 Compatible - * 0 0 0 0 NONE 0 0 0 yes No security - * 0 1 0 0 x 1x 1 x yes WPA (disable - * HT if no AES) - * 0 0 1 0 x 1x x 1 yes WPA2 (disable - * HT if no AES) - * 0 0 0 1 NONE 1 0 0 yes Ad-hoc AES - * 1 0 0 0 NONE 1 0 0 yes Static WEP - * (disable HT) - * 0 0 0 0 !=NONE 1 0 0 yes Dynamic WEP - * - * Compatibility is not matched while roaming, except for mode. - */ -static s32 -mwifiex_is_network_compatible(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc, u32 mode) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - bss_desc->disable_11n = false; - - /* Don't check for compatibility if roaming */ - if (priv->media_connected && - (priv->bss_mode == NL80211_IFTYPE_STATION) && - (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) - return 0; - - if (priv->wps.session_enable) { - mwifiex_dbg(adapter, IOCTL, - "info: return success directly in WPS period\n"); - return 0; - } - - if (bss_desc->chan_sw_ie_present) { - mwifiex_dbg(adapter, INFO, - "Don't connect to AP with WLAN_EID_CHANNEL_SWITCH\n"); - return -1; - } - - if (mwifiex_is_bss_wapi(priv, bss_desc)) { - mwifiex_dbg(adapter, INFO, - "info: return success for WAPI AP\n"); - return 0; - } - - if (bss_desc->bss_mode == mode) { - if (mwifiex_is_bss_no_sec(priv, bss_desc)) { - /* No security */ - return 0; - } else if (mwifiex_is_bss_static_wep(priv, bss_desc)) { - /* Static WEP enabled */ - mwifiex_dbg(adapter, INFO, - "info: Disable 11n in WEP mode.\n"); - bss_desc->disable_11n = true; - return 0; - } else if (mwifiex_is_bss_wpa(priv, bss_desc)) { - /* WPA enabled */ - if (((priv->adapter->config_bands & BAND_GN || - priv->adapter->config_bands & BAND_AN) && - bss_desc->bcn_ht_cap) && - !mwifiex_is_wpa_oui_present(bss_desc, - CIPHER_SUITE_CCMP)) { - - if (mwifiex_is_wpa_oui_present - (bss_desc, CIPHER_SUITE_TKIP)) { - mwifiex_dbg(adapter, INFO, - "info: Disable 11n if AES\t" - "is not supported by AP\n"); - bss_desc->disable_11n = true; - } else { - return -1; - } - } - return 0; - } else if (mwifiex_is_bss_wpa2(priv, bss_desc)) { - /* WPA2 enabled */ - if (((priv->adapter->config_bands & BAND_GN || - priv->adapter->config_bands & BAND_AN) && - bss_desc->bcn_ht_cap) && - !mwifiex_is_rsn_oui_present(bss_desc, - CIPHER_SUITE_CCMP)) { - - if (mwifiex_is_rsn_oui_present - (bss_desc, CIPHER_SUITE_TKIP)) { - mwifiex_dbg(adapter, INFO, - "info: Disable 11n if AES\t" - "is not supported by AP\n"); - bss_desc->disable_11n = true; - } else { - return -1; - } - } - return 0; - } else if (mwifiex_is_bss_adhoc_aes(priv, bss_desc)) { - /* Ad-hoc AES enabled */ - return 0; - } else if (mwifiex_is_bss_dynamic_wep(priv, bss_desc)) { - /* Dynamic WEP enabled */ - return 0; - } - - /* Security doesn't match */ - mwifiex_dbg(adapter, ERROR, - "info: %s: failed: wpa_ie=%#x wpa2_ie=%#x WEP=%s\t" - "WPA=%s WPA2=%s EncMode=%#x privacy=%#x\n", - __func__, - (bss_desc->bcn_wpa_ie) ? - (*bss_desc->bcn_wpa_ie).vend_hdr.element_id : 0, - (bss_desc->bcn_rsn_ie) ? - (*bss_desc->bcn_rsn_ie).ieee_hdr.element_id : 0, - (priv->sec_info.wep_enabled) ? "e" : "d", - (priv->sec_info.wpa_enabled) ? "e" : "d", - (priv->sec_info.wpa2_enabled) ? "e" : "d", - priv->sec_info.encryption_mode, bss_desc->privacy); - return -1; - } - - /* Mode doesn't match */ - return -1; -} - -/* - * This function creates a channel list for the driver to scan, based - * on region/band information. - * - * This routine is used for any scan that is not provided with a - * specific channel list to scan. - */ -static int -mwifiex_scan_create_channel_list(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg - *user_scan_in, - struct mwifiex_chan_scan_param_set - *scan_chan_list, - u8 filtered_scan) -{ - enum ieee80211_band band; - struct ieee80211_supported_band *sband; - struct ieee80211_channel *ch; - struct mwifiex_adapter *adapter = priv->adapter; - int chan_idx = 0, i; - - for (band = 0; (band < IEEE80211_NUM_BANDS) ; band++) { - - if (!priv->wdev.wiphy->bands[band]) - continue; - - sband = priv->wdev.wiphy->bands[band]; - - for (i = 0; (i < sband->n_channels) ; i++) { - ch = &sband->channels[i]; - if (ch->flags & IEEE80211_CHAN_DISABLED) - continue; - scan_chan_list[chan_idx].radio_type = band; - - if (user_scan_in && - user_scan_in->chan_list[0].scan_time) - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16((u16) user_scan_in-> - chan_list[0].scan_time); - else if (ch->flags & IEEE80211_CHAN_NO_IR) - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->passive_scan_time); - else - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->active_scan_time); - - if (ch->flags & IEEE80211_CHAN_NO_IR) - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= (MWIFIEX_PASSIVE_SCAN | - MWIFIEX_HIDDEN_SSID_REPORT); - else - scan_chan_list[chan_idx].chan_scan_mode_bitmap - &= ~MWIFIEX_PASSIVE_SCAN; - scan_chan_list[chan_idx].chan_number = - (u32) ch->hw_value; - if (filtered_scan) { - scan_chan_list[chan_idx].max_scan_time = - cpu_to_le16(adapter->specific_scan_time); - scan_chan_list[chan_idx].chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; - } - chan_idx++; - } - - } - return chan_idx; -} - -/* This function appends rate TLV to scan config command. */ -static int -mwifiex_append_rate_tlv(struct mwifiex_private *priv, - struct mwifiex_scan_cmd_config *scan_cfg_out, - u8 radio) -{ - struct mwifiex_ie_types_rates_param_set *rates_tlv; - u8 rates[MWIFIEX_SUPPORTED_RATES], *tlv_pos; - u32 rates_size; - - memset(rates, 0, sizeof(rates)); - - tlv_pos = (u8 *)scan_cfg_out->tlv_buf + scan_cfg_out->tlv_buf_len; - - if (priv->scan_request) - rates_size = mwifiex_get_rates_from_cfg80211(priv, rates, - radio); - else - rates_size = mwifiex_get_supported_rates(priv, rates); - - mwifiex_dbg(priv->adapter, CMD, - "info: SCAN_CMD: Rates size = %d\n", - rates_size); - rates_tlv = (struct mwifiex_ie_types_rates_param_set *)tlv_pos; - rates_tlv->header.type = cpu_to_le16(WLAN_EID_SUPP_RATES); - rates_tlv->header.len = cpu_to_le16((u16) rates_size); - memcpy(rates_tlv->rates, rates, rates_size); - scan_cfg_out->tlv_buf_len += sizeof(rates_tlv->header) + rates_size; - - return rates_size; -} - -/* - * This function constructs and sends multiple scan config commands to - * the firmware. - * - * Previous routines in the code flow have created a scan command configuration - * with any requested TLVs. This function splits the channel TLV into maximum - * channels supported per scan lists and sends the portion of the channel TLV, - * along with the other TLVs, to the firmware. - */ -static int -mwifiex_scan_channel_list(struct mwifiex_private *priv, - u32 max_chan_per_scan, u8 filtered_scan, - struct mwifiex_scan_cmd_config *scan_cfg_out, - struct mwifiex_ie_types_chan_list_param_set - *chan_tlv_out, - struct mwifiex_chan_scan_param_set *scan_chan_list) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - struct mwifiex_chan_scan_param_set *tmp_chan_list; - struct mwifiex_chan_scan_param_set *start_chan; - struct cmd_ctrl_node *cmd_node, *tmp_node; - unsigned long flags; - u32 tlv_idx, rates_size, cmd_no; - u32 total_scan_time; - u32 done_early; - u8 radio_type; - - if (!scan_cfg_out || !chan_tlv_out || !scan_chan_list) { - mwifiex_dbg(priv->adapter, ERROR, - "info: Scan: Null detect: %p, %p, %p\n", - scan_cfg_out, chan_tlv_out, scan_chan_list); - return -1; - } - - /* Check csa channel expiry before preparing scan list */ - mwifiex_11h_get_csa_closed_channel(priv); - - chan_tlv_out->header.type = cpu_to_le16(TLV_TYPE_CHANLIST); - - /* Set the temp channel struct pointer to the start of the desired - list */ - tmp_chan_list = scan_chan_list; - - /* Loop through the desired channel list, sending a new firmware scan - commands for each max_chan_per_scan channels (or for 1,6,11 - individually if configured accordingly) */ - while (tmp_chan_list->chan_number) { - - tlv_idx = 0; - total_scan_time = 0; - radio_type = 0; - chan_tlv_out->header.len = 0; - start_chan = tmp_chan_list; - done_early = false; - - /* - * Construct the Channel TLV for the scan command. Continue to - * insert channel TLVs until: - * - the tlv_idx hits the maximum configured per scan command - * - the next channel to insert is 0 (end of desired channel - * list) - * - done_early is set (controlling individual scanning of - * 1,6,11) - */ - while (tlv_idx < max_chan_per_scan && - tmp_chan_list->chan_number && !done_early) { - - if (tmp_chan_list->chan_number == priv->csa_chan) { - tmp_chan_list++; - continue; - } - - radio_type = tmp_chan_list->radio_type; - mwifiex_dbg(priv->adapter, INFO, - "info: Scan: Chan(%3d), Radio(%d),\t" - "Mode(%d, %d), Dur(%d)\n", - tmp_chan_list->chan_number, - tmp_chan_list->radio_type, - tmp_chan_list->chan_scan_mode_bitmap - & MWIFIEX_PASSIVE_SCAN, - (tmp_chan_list->chan_scan_mode_bitmap - & MWIFIEX_DISABLE_CHAN_FILT) >> 1, - le16_to_cpu(tmp_chan_list->max_scan_time)); - - /* Copy the current channel TLV to the command being - prepared */ - memcpy(chan_tlv_out->chan_scan_param + tlv_idx, - tmp_chan_list, - sizeof(chan_tlv_out->chan_scan_param)); - - /* Increment the TLV header length by the size - appended */ - le16_add_cpu(&chan_tlv_out->header.len, - sizeof(chan_tlv_out->chan_scan_param)); - - /* - * The tlv buffer length is set to the number of bytes - * of the between the channel tlv pointer and the start - * of the tlv buffer. This compensates for any TLVs - * that were appended before the channel list. - */ - scan_cfg_out->tlv_buf_len = (u32) ((u8 *) chan_tlv_out - - scan_cfg_out->tlv_buf); - - /* Add the size of the channel tlv header and the data - length */ - scan_cfg_out->tlv_buf_len += - (sizeof(chan_tlv_out->header) - + le16_to_cpu(chan_tlv_out->header.len)); - - /* Increment the index to the channel tlv we are - constructing */ - tlv_idx++; - - /* Count the total scan time per command */ - total_scan_time += - le16_to_cpu(tmp_chan_list->max_scan_time); - - done_early = false; - - /* Stop the loop if the *current* channel is in the - 1,6,11 set and we are not filtering on a BSSID - or SSID. */ - if (!filtered_scan && - (tmp_chan_list->chan_number == 1 || - tmp_chan_list->chan_number == 6 || - tmp_chan_list->chan_number == 11)) - done_early = true; - - /* Increment the tmp pointer to the next channel to - be scanned */ - tmp_chan_list++; - - /* Stop the loop if the *next* channel is in the 1,6,11 - set. This will cause it to be the only channel - scanned on the next interation */ - if (!filtered_scan && - (tmp_chan_list->chan_number == 1 || - tmp_chan_list->chan_number == 6 || - tmp_chan_list->chan_number == 11)) - done_early = true; - } - - /* The total scan time should be less than scan command timeout - value */ - if (total_scan_time > MWIFIEX_MAX_TOTAL_SCAN_TIME) { - mwifiex_dbg(priv->adapter, ERROR, - "total scan time %dms\t" - "is over limit (%dms), scan skipped\n", - total_scan_time, - MWIFIEX_MAX_TOTAL_SCAN_TIME); - ret = -1; - break; - } - - rates_size = mwifiex_append_rate_tlv(priv, scan_cfg_out, - radio_type); - - priv->adapter->scan_channels = start_chan; - - /* Send the scan command to the firmware with the specified - cfg */ - if (priv->adapter->ext_scan) - cmd_no = HostCmd_CMD_802_11_SCAN_EXT; - else - cmd_no = HostCmd_CMD_802_11_SCAN; - - ret = mwifiex_send_cmd(priv, cmd_no, HostCmd_ACT_GEN_SET, - 0, scan_cfg_out, false); - - /* rate IE is updated per scan command but same starting - * pointer is used each time so that rate IE from earlier - * scan_cfg_out->buf is overwritten with new one. - */ - scan_cfg_out->tlv_buf_len -= - sizeof(struct mwifiex_ie_types_header) + rates_size; - - if (ret) { - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, - list) { - list_del(&cmd_node->list); - cmd_node->wait_q_enabled = false; - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - break; - } - } - - if (ret) - return -1; - - return 0; -} - -/* - * This function constructs a scan command configuration structure to use - * in scan commands. - * - * Application layer or other functions can invoke network scanning - * with a scan configuration supplied in a user scan configuration structure. - * This structure is used as the basis of one or many scan command configuration - * commands that are sent to the command processing module and eventually to the - * firmware. - * - * This function creates a scan command configuration structure based on the - * following user supplied parameters (if present): - * - SSID filter - * - BSSID filter - * - Number of Probes to be sent - * - Channel list - * - * If the SSID or BSSID filter is not present, the filter is disabled/cleared. - * If the number of probes is not set, adapter default setting is used. - */ -static void -mwifiex_config_scan(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg *user_scan_in, - struct mwifiex_scan_cmd_config *scan_cfg_out, - struct mwifiex_ie_types_chan_list_param_set **chan_list_out, - struct mwifiex_chan_scan_param_set *scan_chan_list, - u8 *max_chan_per_scan, u8 *filtered_scan, - u8 *scan_current_only) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_num_probes *num_probes_tlv; - struct mwifiex_ie_types_scan_chan_gap *chan_gap_tlv; - struct mwifiex_ie_types_wildcard_ssid_params *wildcard_ssid_tlv; - struct mwifiex_ie_types_bssid_list *bssid_tlv; - u8 *tlv_pos; - u32 num_probes; - u32 ssid_len; - u32 chan_idx; - u32 chan_num; - u32 scan_type; - u16 scan_dur; - u8 channel; - u8 radio_type; - int i; - u8 ssid_filter; - struct mwifiex_ie_types_htcap *ht_cap; - struct mwifiex_ie_types_bss_mode *bss_mode; - - /* The tlv_buf_len is calculated for each scan command. The TLVs added - in this routine will be preserved since the routine that sends the - command will append channelTLVs at *chan_list_out. The difference - between the *chan_list_out and the tlv_buf start will be used to - calculate the size of anything we add in this routine. */ - scan_cfg_out->tlv_buf_len = 0; - - /* Running tlv pointer. Assigned to chan_list_out at end of function - so later routines know where channels can be added to the command - buf */ - tlv_pos = scan_cfg_out->tlv_buf; - - /* Initialize the scan as un-filtered; the flag is later set to TRUE - below if a SSID or BSSID filter is sent in the command */ - *filtered_scan = false; - - /* Initialize the scan as not being only on the current channel. If - the channel list is customized, only contains one channel, and is - the active channel, this is set true and data flow is not halted. */ - *scan_current_only = false; - - if (user_scan_in) { - - /* Default the ssid_filter flag to TRUE, set false under - certain wildcard conditions and qualified by the existence - of an SSID list before marking the scan as filtered */ - ssid_filter = true; - - /* Set the BSS type scan filter, use Adapter setting if - unset */ - scan_cfg_out->bss_mode = - (user_scan_in->bss_mode ? (u8) user_scan_in-> - bss_mode : (u8) adapter->scan_mode); - - /* Set the number of probes to send, use Adapter setting - if unset */ - num_probes = - (user_scan_in->num_probes ? user_scan_in-> - num_probes : adapter->scan_probes); - - /* - * Set the BSSID filter to the incoming configuration, - * if non-zero. If not set, it will remain disabled - * (all zeros). - */ - memcpy(scan_cfg_out->specific_bssid, - user_scan_in->specific_bssid, - sizeof(scan_cfg_out->specific_bssid)); - - if (adapter->ext_scan && - !is_zero_ether_addr(scan_cfg_out->specific_bssid)) { - bssid_tlv = - (struct mwifiex_ie_types_bssid_list *)tlv_pos; - bssid_tlv->header.type = cpu_to_le16(TLV_TYPE_BSSID); - bssid_tlv->header.len = cpu_to_le16(ETH_ALEN); - memcpy(bssid_tlv->bssid, user_scan_in->specific_bssid, - ETH_ALEN); - tlv_pos += sizeof(struct mwifiex_ie_types_bssid_list); - } - - for (i = 0; i < user_scan_in->num_ssids; i++) { - ssid_len = user_scan_in->ssid_list[i].ssid_len; - - wildcard_ssid_tlv = - (struct mwifiex_ie_types_wildcard_ssid_params *) - tlv_pos; - wildcard_ssid_tlv->header.type = - cpu_to_le16(TLV_TYPE_WILDCARDSSID); - wildcard_ssid_tlv->header.len = cpu_to_le16( - (u16) (ssid_len + sizeof(wildcard_ssid_tlv-> - max_ssid_length))); - - /* - * max_ssid_length = 0 tells firmware to perform - * specific scan for the SSID filled, whereas - * max_ssid_length = IEEE80211_MAX_SSID_LEN is for - * wildcard scan. - */ - if (ssid_len) - wildcard_ssid_tlv->max_ssid_length = 0; - else - wildcard_ssid_tlv->max_ssid_length = - IEEE80211_MAX_SSID_LEN; - - if (!memcmp(user_scan_in->ssid_list[i].ssid, - "DIRECT-", 7)) - wildcard_ssid_tlv->max_ssid_length = 0xfe; - - memcpy(wildcard_ssid_tlv->ssid, - user_scan_in->ssid_list[i].ssid, ssid_len); - - tlv_pos += (sizeof(wildcard_ssid_tlv->header) - + le16_to_cpu(wildcard_ssid_tlv->header.len)); - - mwifiex_dbg(adapter, INFO, - "info: scan: ssid[%d]: %s, %d\n", - i, wildcard_ssid_tlv->ssid, - wildcard_ssid_tlv->max_ssid_length); - - /* Empty wildcard ssid with a maxlen will match many or - potentially all SSIDs (maxlen == 32), therefore do - not treat the scan as - filtered. */ - if (!ssid_len && wildcard_ssid_tlv->max_ssid_length) - ssid_filter = false; - } - - /* - * The default number of channels sent in the command is low to - * ensure the response buffer from the firmware does not - * truncate scan results. That is not an issue with an SSID - * or BSSID filter applied to the scan results in the firmware. - */ - if ((i && ssid_filter) || - !is_zero_ether_addr(scan_cfg_out->specific_bssid)) - *filtered_scan = true; - - if (user_scan_in->scan_chan_gap) { - mwifiex_dbg(adapter, INFO, - "info: scan: channel gap = %d\n", - user_scan_in->scan_chan_gap); - *max_chan_per_scan = - MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; - - chan_gap_tlv = (void *)tlv_pos; - chan_gap_tlv->header.type = - cpu_to_le16(TLV_TYPE_SCAN_CHANNEL_GAP); - chan_gap_tlv->header.len = - cpu_to_le16(sizeof(chan_gap_tlv->chan_gap)); - chan_gap_tlv->chan_gap = - cpu_to_le16((user_scan_in->scan_chan_gap)); - tlv_pos += - sizeof(struct mwifiex_ie_types_scan_chan_gap); - } - } else { - scan_cfg_out->bss_mode = (u8) adapter->scan_mode; - num_probes = adapter->scan_probes; - } - - /* - * If a specific BSSID or SSID is used, the number of channels in the - * scan command will be increased to the absolute maximum. - */ - if (*filtered_scan) - *max_chan_per_scan = MWIFIEX_MAX_CHANNELS_PER_SPECIFIC_SCAN; - else - *max_chan_per_scan = MWIFIEX_DEF_CHANNELS_PER_SCAN_CMD; - - if (adapter->ext_scan) { - bss_mode = (struct mwifiex_ie_types_bss_mode *)tlv_pos; - bss_mode->header.type = cpu_to_le16(TLV_TYPE_BSS_MODE); - bss_mode->header.len = cpu_to_le16(sizeof(bss_mode->bss_mode)); - bss_mode->bss_mode = scan_cfg_out->bss_mode; - tlv_pos += sizeof(bss_mode->header) + - le16_to_cpu(bss_mode->header.len); - } - - /* If the input config or adapter has the number of Probes set, - add tlv */ - if (num_probes) { - - mwifiex_dbg(adapter, INFO, - "info: scan: num_probes = %d\n", - num_probes); - - num_probes_tlv = (struct mwifiex_ie_types_num_probes *) tlv_pos; - num_probes_tlv->header.type = cpu_to_le16(TLV_TYPE_NUMPROBES); - num_probes_tlv->header.len = - cpu_to_le16(sizeof(num_probes_tlv->num_probes)); - num_probes_tlv->num_probes = cpu_to_le16((u16) num_probes); - - tlv_pos += sizeof(num_probes_tlv->header) + - le16_to_cpu(num_probes_tlv->header.len); - - } - - if (ISSUPP_11NENABLED(priv->adapter->fw_cap_info) && - (priv->adapter->config_bands & BAND_GN || - priv->adapter->config_bands & BAND_AN)) { - ht_cap = (struct mwifiex_ie_types_htcap *) tlv_pos; - memset(ht_cap, 0, sizeof(struct mwifiex_ie_types_htcap)); - ht_cap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_cap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - radio_type = - mwifiex_band_to_radio_type(priv->adapter->config_bands); - mwifiex_fill_cap_info(priv, radio_type, &ht_cap->ht_cap); - tlv_pos += sizeof(struct mwifiex_ie_types_htcap); - } - - /* Append vendor specific IE TLV */ - mwifiex_cmd_append_vsie_tlv(priv, MWIFIEX_VSIE_MASK_SCAN, &tlv_pos); - - /* - * Set the output for the channel TLV to the address in the tlv buffer - * past any TLVs that were added in this function (SSID, num_probes). - * Channel TLVs will be added past this for each scan command, - * preserving the TLVs that were previously added. - */ - *chan_list_out = - (struct mwifiex_ie_types_chan_list_param_set *) tlv_pos; - - if (user_scan_in && user_scan_in->chan_list[0].chan_number) { - - mwifiex_dbg(adapter, INFO, - "info: Scan: Using supplied channel list\n"); - - for (chan_idx = 0; - chan_idx < MWIFIEX_USER_SCAN_CHAN_MAX && - user_scan_in->chan_list[chan_idx].chan_number; - chan_idx++) { - - channel = user_scan_in->chan_list[chan_idx].chan_number; - (scan_chan_list + chan_idx)->chan_number = channel; - - radio_type = - user_scan_in->chan_list[chan_idx].radio_type; - (scan_chan_list + chan_idx)->radio_type = radio_type; - - scan_type = user_scan_in->chan_list[chan_idx].scan_type; - - if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap - |= (MWIFIEX_PASSIVE_SCAN | - MWIFIEX_HIDDEN_SSID_REPORT); - else - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap - &= ~MWIFIEX_PASSIVE_SCAN; - - if (*filtered_scan) - (scan_chan_list + - chan_idx)->chan_scan_mode_bitmap - |= MWIFIEX_DISABLE_CHAN_FILT; - - if (user_scan_in->chan_list[chan_idx].scan_time) { - scan_dur = (u16) user_scan_in-> - chan_list[chan_idx].scan_time; - } else { - if (scan_type == MWIFIEX_SCAN_TYPE_PASSIVE) - scan_dur = adapter->passive_scan_time; - else if (*filtered_scan) - scan_dur = adapter->specific_scan_time; - else - scan_dur = adapter->active_scan_time; - } - - (scan_chan_list + chan_idx)->min_scan_time = - cpu_to_le16(scan_dur); - (scan_chan_list + chan_idx)->max_scan_time = - cpu_to_le16(scan_dur); - } - - /* Check if we are only scanning the current channel */ - if ((chan_idx == 1) && - (user_scan_in->chan_list[0].chan_number == - priv->curr_bss_params.bss_descriptor.channel)) { - *scan_current_only = true; - mwifiex_dbg(adapter, INFO, - "info: Scan: Scanning current channel only\n"); - } - chan_num = chan_idx; - } else { - mwifiex_dbg(adapter, INFO, - "info: Scan: Creating full region channel list\n"); - chan_num = mwifiex_scan_create_channel_list(priv, user_scan_in, - scan_chan_list, - *filtered_scan); - } - -} - -/* - * This function inspects the scan response buffer for pointers to - * expected TLVs. - * - * TLVs can be included at the end of the scan response BSS information. - * - * Data in the buffer is parsed pointers to TLVs that can potentially - * be passed back in the response. - */ -static void -mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter, - struct mwifiex_ie_types_data *tlv, - u32 tlv_buf_size, u32 req_tlv_type, - struct mwifiex_ie_types_data **tlv_data) -{ - struct mwifiex_ie_types_data *current_tlv; - u32 tlv_buf_left; - u32 tlv_type; - u32 tlv_len; - - current_tlv = tlv; - tlv_buf_left = tlv_buf_size; - *tlv_data = NULL; - - mwifiex_dbg(adapter, INFO, - "info: SCAN_RESP: tlv_buf_size = %d\n", - tlv_buf_size); - - while (tlv_buf_left >= sizeof(struct mwifiex_ie_types_header)) { - - tlv_type = le16_to_cpu(current_tlv->header.type); - tlv_len = le16_to_cpu(current_tlv->header.len); - - if (sizeof(tlv->header) + tlv_len > tlv_buf_left) { - mwifiex_dbg(adapter, ERROR, - "SCAN_RESP: TLV buffer corrupt\n"); - break; - } - - if (req_tlv_type == tlv_type) { - switch (tlv_type) { - case TLV_TYPE_TSFTIMESTAMP: - mwifiex_dbg(adapter, INFO, - "info: SCAN_RESP: TSF\t" - "timestamp TLV, len = %d\n", - tlv_len); - *tlv_data = current_tlv; - break; - case TLV_TYPE_CHANNELBANDLIST: - mwifiex_dbg(adapter, INFO, - "info: SCAN_RESP: channel\t" - "band list TLV, len = %d\n", - tlv_len); - *tlv_data = current_tlv; - break; - default: - mwifiex_dbg(adapter, ERROR, - "SCAN_RESP: unhandled TLV = %d\n", - tlv_type); - /* Give up, this seems corrupted */ - return; - } - } - - if (*tlv_data) - break; - - - tlv_buf_left -= (sizeof(tlv->header) + tlv_len); - current_tlv = - (struct mwifiex_ie_types_data *) (current_tlv->data + - tlv_len); - - } /* while */ -} - -/* - * This function parses provided beacon buffer and updates - * respective fields in bss descriptor structure. - */ -int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter, - struct mwifiex_bssdescriptor *bss_entry) -{ - int ret = 0; - u8 element_id; - struct ieee_types_fh_param_set *fh_param_set; - struct ieee_types_ds_param_set *ds_param_set; - struct ieee_types_cf_param_set *cf_param_set; - struct ieee_types_ibss_param_set *ibss_param_set; - u8 *current_ptr; - u8 *rate; - u8 element_len; - u16 total_ie_len; - u8 bytes_to_copy; - u8 rate_size; - u8 found_data_rate_ie; - u32 bytes_left; - struct ieee_types_vendor_specific *vendor_ie; - const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; - const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; - - found_data_rate_ie = false; - rate_size = 0; - current_ptr = bss_entry->beacon_buf; - bytes_left = bss_entry->beacon_buf_size; - - /* Process variable IE */ - while (bytes_left >= 2) { - element_id = *current_ptr; - element_len = *(current_ptr + 1); - total_ie_len = element_len + sizeof(struct ieee_types_header); - - if (bytes_left < total_ie_len) { - mwifiex_dbg(adapter, ERROR, - "err: InterpretIE: in processing\t" - "IE, bytes left < IE length\n"); - return -1; - } - switch (element_id) { - case WLAN_EID_SSID: - bss_entry->ssid.ssid_len = element_len; - memcpy(bss_entry->ssid.ssid, (current_ptr + 2), - element_len); - mwifiex_dbg(adapter, INFO, - "info: InterpretIE: ssid: %-32s\n", - bss_entry->ssid.ssid); - break; - - case WLAN_EID_SUPP_RATES: - memcpy(bss_entry->data_rates, current_ptr + 2, - element_len); - memcpy(bss_entry->supported_rates, current_ptr + 2, - element_len); - rate_size = element_len; - found_data_rate_ie = true; - break; - - case WLAN_EID_FH_PARAMS: - fh_param_set = - (struct ieee_types_fh_param_set *) current_ptr; - memcpy(&bss_entry->phy_param_set.fh_param_set, - fh_param_set, - sizeof(struct ieee_types_fh_param_set)); - break; - - case WLAN_EID_DS_PARAMS: - ds_param_set = - (struct ieee_types_ds_param_set *) current_ptr; - - bss_entry->channel = ds_param_set->current_chan; - - memcpy(&bss_entry->phy_param_set.ds_param_set, - ds_param_set, - sizeof(struct ieee_types_ds_param_set)); - break; - - case WLAN_EID_CF_PARAMS: - cf_param_set = - (struct ieee_types_cf_param_set *) current_ptr; - memcpy(&bss_entry->ss_param_set.cf_param_set, - cf_param_set, - sizeof(struct ieee_types_cf_param_set)); - break; - - case WLAN_EID_IBSS_PARAMS: - ibss_param_set = - (struct ieee_types_ibss_param_set *) - current_ptr; - memcpy(&bss_entry->ss_param_set.ibss_param_set, - ibss_param_set, - sizeof(struct ieee_types_ibss_param_set)); - break; - - case WLAN_EID_ERP_INFO: - bss_entry->erp_flags = *(current_ptr + 2); - break; - - case WLAN_EID_PWR_CONSTRAINT: - bss_entry->local_constraint = *(current_ptr + 2); - bss_entry->sensed_11h = true; - break; - - case WLAN_EID_CHANNEL_SWITCH: - bss_entry->chan_sw_ie_present = true; - case WLAN_EID_PWR_CAPABILITY: - case WLAN_EID_TPC_REPORT: - case WLAN_EID_QUIET: - bss_entry->sensed_11h = true; - break; - - case WLAN_EID_EXT_SUPP_RATES: - /* - * Only process extended supported rate - * if data rate is already found. - * Data rate IE should come before - * extended supported rate IE - */ - if (found_data_rate_ie) { - if ((element_len + rate_size) > - MWIFIEX_SUPPORTED_RATES) - bytes_to_copy = - (MWIFIEX_SUPPORTED_RATES - - rate_size); - else - bytes_to_copy = element_len; - - rate = (u8 *) bss_entry->data_rates; - rate += rate_size; - memcpy(rate, current_ptr + 2, bytes_to_copy); - - rate = (u8 *) bss_entry->supported_rates; - rate += rate_size; - memcpy(rate, current_ptr + 2, bytes_to_copy); - } - break; - - case WLAN_EID_VENDOR_SPECIFIC: - vendor_ie = (struct ieee_types_vendor_specific *) - current_ptr; - - if (!memcmp - (vendor_ie->vend_hdr.oui, wpa_oui, - sizeof(wpa_oui))) { - bss_entry->bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - current_ptr; - bss_entry->wpa_offset = (u16) - (current_ptr - bss_entry->beacon_buf); - } else if (!memcmp(vendor_ie->vend_hdr.oui, wmm_oui, - sizeof(wmm_oui))) { - if (total_ie_len == - sizeof(struct ieee_types_wmm_parameter) || - total_ie_len == - sizeof(struct ieee_types_wmm_info)) - /* - * Only accept and copy the WMM IE if - * it matches the size expected for the - * WMM Info IE or the WMM Parameter IE. - */ - memcpy((u8 *) &bss_entry->wmm_ie, - current_ptr, total_ie_len); - } - break; - case WLAN_EID_RSN: - bss_entry->bcn_rsn_ie = - (struct ieee_types_generic *) current_ptr; - bss_entry->rsn_offset = (u16) (current_ptr - - bss_entry->beacon_buf); - break; - case WLAN_EID_BSS_AC_ACCESS_DELAY: - bss_entry->bcn_wapi_ie = - (struct ieee_types_generic *) current_ptr; - bss_entry->wapi_offset = (u16) (current_ptr - - bss_entry->beacon_buf); - break; - case WLAN_EID_HT_CAPABILITY: - bss_entry->bcn_ht_cap = (struct ieee80211_ht_cap *) - (current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->ht_cap_offset = (u16) (current_ptr + - sizeof(struct ieee_types_header) - - bss_entry->beacon_buf); - break; - case WLAN_EID_HT_OPERATION: - bss_entry->bcn_ht_oper = - (struct ieee80211_ht_operation *)(current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->ht_info_offset = (u16) (current_ptr + - sizeof(struct ieee_types_header) - - bss_entry->beacon_buf); - break; - case WLAN_EID_VHT_CAPABILITY: - bss_entry->disable_11ac = false; - bss_entry->bcn_vht_cap = - (void *)(current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->vht_cap_offset = - (u16)((u8 *)bss_entry->bcn_vht_cap - - bss_entry->beacon_buf); - break; - case WLAN_EID_VHT_OPERATION: - bss_entry->bcn_vht_oper = - (void *)(current_ptr + - sizeof(struct ieee_types_header)); - bss_entry->vht_info_offset = - (u16)((u8 *)bss_entry->bcn_vht_oper - - bss_entry->beacon_buf); - break; - case WLAN_EID_BSS_COEX_2040: - bss_entry->bcn_bss_co_2040 = current_ptr; - bss_entry->bss_co_2040_offset = - (u16) (current_ptr - bss_entry->beacon_buf); - break; - case WLAN_EID_EXT_CAPABILITY: - bss_entry->bcn_ext_cap = current_ptr; - bss_entry->ext_cap_offset = - (u16) (current_ptr - bss_entry->beacon_buf); - break; - case WLAN_EID_OPMODE_NOTIF: - bss_entry->oper_mode = (void *)current_ptr; - bss_entry->oper_mode_offset = - (u16)((u8 *)bss_entry->oper_mode - - bss_entry->beacon_buf); - break; - default: - break; - } - - current_ptr += element_len + 2; - - /* Need to account for IE ID and IE Len */ - bytes_left -= (element_len + 2); - - } /* while (bytes_left > 2) */ - return ret; -} - -/* - * This function converts radio type scan parameter to a band configuration - * to be used in join command. - */ -static u8 -mwifiex_radio_type_to_band(u8 radio_type) -{ - switch (radio_type) { - case HostCmd_SCAN_RADIO_TYPE_A: - return BAND_A; - case HostCmd_SCAN_RADIO_TYPE_BG: - default: - return BAND_G; - } -} - -/* - * This is an internal function used to start a scan based on an input - * configuration. - * - * This uses the input user scan configuration information when provided in - * order to send the appropriate scan commands to firmware to populate or - * update the internal driver scan table. - */ -int mwifiex_scan_networks(struct mwifiex_private *priv, - const struct mwifiex_user_scan_cfg *user_scan_in) -{ - int ret; - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node; - union mwifiex_scan_cmd_config_tlv *scan_cfg_out; - struct mwifiex_ie_types_chan_list_param_set *chan_list_out; - struct mwifiex_chan_scan_param_set *scan_chan_list; - u8 filtered_scan; - u8 scan_current_chan_only; - u8 max_chan_per_scan; - unsigned long flags; - - if (adapter->scan_processing) { - mwifiex_dbg(adapter, WARN, - "cmd: Scan already in process...\n"); - return -EBUSY; - } - - if (priv->scan_block) { - mwifiex_dbg(adapter, WARN, - "cmd: Scan is blocked during association...\n"); - return -EBUSY; - } - - if (adapter->surprise_removed || adapter->is_cmd_timedout) { - mwifiex_dbg(adapter, ERROR, - "Ignore scan. Card removed or firmware in bad state\n"); - return -EFAULT; - } - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = true; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - scan_cfg_out = kzalloc(sizeof(union mwifiex_scan_cmd_config_tlv), - GFP_KERNEL); - if (!scan_cfg_out) { - ret = -ENOMEM; - goto done; - } - - scan_chan_list = kcalloc(MWIFIEX_USER_SCAN_CHAN_MAX, - sizeof(struct mwifiex_chan_scan_param_set), - GFP_KERNEL); - if (!scan_chan_list) { - kfree(scan_cfg_out); - ret = -ENOMEM; - goto done; - } - - mwifiex_config_scan(priv, user_scan_in, &scan_cfg_out->config, - &chan_list_out, scan_chan_list, &max_chan_per_scan, - &filtered_scan, &scan_current_chan_only); - - ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, - &scan_cfg_out->config, chan_list_out, - scan_chan_list); - - /* Get scan command from scan_pending_q and put to cmd_pending_q */ - if (!ret) { - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - if (!list_empty(&adapter->scan_pending_q)) { - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, - true); - queue_work(adapter->workqueue, &adapter->main_work); - - /* Perform internal scan synchronously */ - if (!priv->scan_request) { - mwifiex_dbg(adapter, INFO, - "wait internal scan\n"); - mwifiex_wait_queue_complete(adapter, cmd_node); - } - } else { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - } - } - - kfree(scan_cfg_out); - kfree(scan_chan_list); -done: - if (ret) { - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - } - return ret; -} - -/* - * This function prepares a scan command to be sent to the firmware. - * - * This uses the scan command configuration sent to the command processing - * module in command preparation stage to configure a scan command structure - * to send to firmware. - * - * The fixed fields specifying the BSS type and BSSID filters as well as a - * variable number/length of TLVs are sent in the command to firmware. - * - * Preparation also includes - - * - Setting command ID, and proper size - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd, - struct mwifiex_scan_cmd_config *scan_cfg) -{ - struct host_cmd_ds_802_11_scan *scan_cmd = &cmd->params.scan; - - /* Set fixed field variables in scan command */ - scan_cmd->bss_mode = scan_cfg->bss_mode; - memcpy(scan_cmd->bssid, scan_cfg->specific_bssid, - sizeof(scan_cmd->bssid)); - memcpy(scan_cmd->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN); - - /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ - cmd->size = cpu_to_le16((u16) (sizeof(scan_cmd->bss_mode) - + sizeof(scan_cmd->bssid) - + scan_cfg->tlv_buf_len + S_DS_GEN)); - - return 0; -} - -/* - * This function checks compatibility of requested network with current - * driver settings. - */ -int mwifiex_check_network_compatibility(struct mwifiex_private *priv, - struct mwifiex_bssdescriptor *bss_desc) -{ - int ret = -1; - - if (!bss_desc) - return -1; - - if ((mwifiex_get_cfp(priv, (u8) bss_desc->bss_band, - (u16) bss_desc->channel, 0))) { - switch (priv->bss_mode) { - case NL80211_IFTYPE_STATION: - case NL80211_IFTYPE_ADHOC: - ret = mwifiex_is_network_compatible(priv, bss_desc, - priv->bss_mode); - if (ret) - mwifiex_dbg(priv->adapter, ERROR, - "Incompatible network settings\n"); - break; - default: - ret = 0; - } - } - - return ret; -} - -/* This function checks if SSID string contains all zeroes or length is zero */ -static bool mwifiex_is_hidden_ssid(struct cfg80211_ssid *ssid) -{ - int idx; - - for (idx = 0; idx < ssid->ssid_len; idx++) { - if (ssid->ssid[idx]) - return false; - } - - return true; -} - -/* This function checks if any hidden SSID found in passive scan channels - * and save those channels for specific SSID active scan - */ -static int mwifiex_save_hidden_ssid_channels(struct mwifiex_private *priv, - struct cfg80211_bss *bss) -{ - struct mwifiex_bssdescriptor *bss_desc; - int ret; - int chid; - - /* Allocate and fill new bss descriptor */ - bss_desc = kzalloc(sizeof(*bss_desc), GFP_KERNEL); - if (!bss_desc) - return -ENOMEM; - - ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc); - if (ret) - goto done; - - if (mwifiex_is_hidden_ssid(&bss_desc->ssid)) { - mwifiex_dbg(priv->adapter, INFO, "found hidden SSID\n"); - for (chid = 0 ; chid < MWIFIEX_USER_SCAN_CHAN_MAX; chid++) { - if (priv->hidden_chan[chid].chan_number == - bss->channel->hw_value) - break; - - if (!priv->hidden_chan[chid].chan_number) { - priv->hidden_chan[chid].chan_number = - bss->channel->hw_value; - priv->hidden_chan[chid].radio_type = - bss->channel->band; - priv->hidden_chan[chid].scan_type = - MWIFIEX_SCAN_TYPE_ACTIVE; - break; - } - } - } - -done: - kfree(bss_desc); - return 0; -} - -static int mwifiex_update_curr_bss_params(struct mwifiex_private *priv, - struct cfg80211_bss *bss) -{ - struct mwifiex_bssdescriptor *bss_desc; - int ret; - unsigned long flags; - - /* Allocate and fill new bss descriptor */ - bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), GFP_KERNEL); - if (!bss_desc) - return -ENOMEM; - - ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc); - if (ret) - goto done; - - ret = mwifiex_check_network_compatibility(priv, bss_desc); - if (ret) - goto done; - - spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags); - /* Make a copy of current BSSID descriptor */ - memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc, - sizeof(priv->curr_bss_params.bss_descriptor)); - - /* The contents of beacon_ie will be copied to its own buffer - * in mwifiex_save_curr_bcn() - */ - mwifiex_save_curr_bcn(priv); - spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags); - -done: - /* beacon_ie buffer was allocated in function - * mwifiex_fill_new_bss_desc(). Free it now. - */ - kfree(bss_desc->beacon_buf); - kfree(bss_desc); - return 0; -} - -static int -mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info, - u32 *bytes_left, u64 fw_tsf, u8 *radio_type, - bool ext_scan, s32 rssi_val) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_chan_freq_power *cfp; - struct cfg80211_bss *bss; - u8 bssid[ETH_ALEN]; - s32 rssi; - const u8 *ie_buf; - size_t ie_len; - u16 channel = 0; - u16 beacon_size = 0; - u32 curr_bcn_bytes; - u32 freq; - u16 beacon_period; - u16 cap_info_bitmap; - u8 *current_ptr; - u64 timestamp; - struct mwifiex_fixed_bcn_param *bcn_param; - struct mwifiex_bss_priv *bss_priv; - - if (*bytes_left >= sizeof(beacon_size)) { - /* Extract & convert beacon size from command buffer */ - beacon_size = le16_to_cpu(*(__le16 *)(*bss_info)); - *bytes_left -= sizeof(beacon_size); - *bss_info += sizeof(beacon_size); - } - - if (!beacon_size || beacon_size > *bytes_left) { - *bss_info += *bytes_left; - *bytes_left = 0; - return -EFAULT; - } - - /* Initialize the current working beacon pointer for this BSS - * iteration - */ - current_ptr = *bss_info; - - /* Advance the return beacon pointer past the current beacon */ - *bss_info += beacon_size; - *bytes_left -= beacon_size; - - curr_bcn_bytes = beacon_size; - - /* First 5 fields are bssid, RSSI(for legacy scan only), - * time stamp, beacon interval, and capability information - */ - if (curr_bcn_bytes < ETH_ALEN + sizeof(u8) + - sizeof(struct mwifiex_fixed_bcn_param)) { - mwifiex_dbg(adapter, ERROR, - "InterpretIE: not enough bytes left\n"); - return -EFAULT; - } - - memcpy(bssid, current_ptr, ETH_ALEN); - current_ptr += ETH_ALEN; - curr_bcn_bytes -= ETH_ALEN; - - if (!ext_scan) { - rssi = (s32) *current_ptr; - rssi = (-rssi) * 100; /* Convert dBm to mBm */ - current_ptr += sizeof(u8); - curr_bcn_bytes -= sizeof(u8); - mwifiex_dbg(adapter, INFO, - "info: InterpretIE: RSSI=%d\n", rssi); - } else { - rssi = rssi_val; - } - - bcn_param = (struct mwifiex_fixed_bcn_param *)current_ptr; - current_ptr += sizeof(*bcn_param); - curr_bcn_bytes -= sizeof(*bcn_param); - - timestamp = le64_to_cpu(bcn_param->timestamp); - beacon_period = le16_to_cpu(bcn_param->beacon_period); - - cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap); - mwifiex_dbg(adapter, INFO, - "info: InterpretIE: capabilities=0x%X\n", - cap_info_bitmap); - - /* Rest of the current buffer are IE's */ - ie_buf = current_ptr; - ie_len = curr_bcn_bytes; - mwifiex_dbg(adapter, INFO, - "info: InterpretIE: IELength for this AP = %d\n", - curr_bcn_bytes); - - while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) { - u8 element_id, element_len; - - element_id = *current_ptr; - element_len = *(current_ptr + 1); - if (curr_bcn_bytes < element_len + - sizeof(struct ieee_types_header)) { - mwifiex_dbg(adapter, ERROR, - "%s: bytes left < IE length\n", __func__); - return -EFAULT; - } - if (element_id == WLAN_EID_DS_PARAMS) { - channel = *(current_ptr + - sizeof(struct ieee_types_header)); - break; - } - - current_ptr += element_len + sizeof(struct ieee_types_header); - curr_bcn_bytes -= element_len + - sizeof(struct ieee_types_header); - } - - if (channel) { - struct ieee80211_channel *chan; - u8 band; - - /* Skip entry if on csa closed channel */ - if (channel == priv->csa_chan) { - mwifiex_dbg(adapter, WARN, - "Dropping entry on csa closed channel\n"); - return 0; - } - - band = BAND_G; - if (radio_type) - band = mwifiex_radio_type_to_band(*radio_type & - (BIT(0) | BIT(1))); - - cfp = mwifiex_get_cfp(priv, band, channel, 0); - - freq = cfp ? cfp->freq : 0; - - chan = ieee80211_get_channel(priv->wdev.wiphy, freq); - - if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) { - bss = cfg80211_inform_bss(priv->wdev.wiphy, - chan, CFG80211_BSS_FTYPE_UNKNOWN, - bssid, timestamp, - cap_info_bitmap, beacon_period, - ie_buf, ie_len, rssi, GFP_KERNEL); - if (bss) { - bss_priv = (struct mwifiex_bss_priv *)bss->priv; - bss_priv->band = band; - bss_priv->fw_tsf = fw_tsf; - if (priv->media_connected && - !memcmp(bssid, priv->curr_bss_params. - bss_descriptor.mac_address, - ETH_ALEN)) - mwifiex_update_curr_bss_params(priv, - bss); - cfg80211_put_bss(priv->wdev.wiphy, bss); - } - - if ((chan->flags & IEEE80211_CHAN_RADAR) || - (chan->flags & IEEE80211_CHAN_NO_IR)) { - mwifiex_dbg(adapter, INFO, - "radar or passive channel %d\n", - channel); - mwifiex_save_hidden_ssid_channels(priv, bss); - } - } - } else { - mwifiex_dbg(adapter, WARN, "missing BSS channel IE\n"); - } - - return 0; -} - -static void mwifiex_complete_scan(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - adapter->survey_idx = 0; - if (adapter->curr_cmd->wait_q_enabled) { - adapter->cmd_wait_q.status = 0; - if (!priv->scan_request) { - mwifiex_dbg(adapter, INFO, - "complete internal scan\n"); - mwifiex_complete_cmd(adapter, adapter->curr_cmd); - } - } -} - -/* This function checks if any hidden SSID found in passive scan channels - * and do specific SSID active scan for those channels - */ -static int -mwifiex_active_scan_req_for_passive_chan(struct mwifiex_private *priv) -{ - int ret; - struct mwifiex_adapter *adapter = priv->adapter; - u8 id = 0; - struct mwifiex_user_scan_cfg *user_scan_cfg; - - if (adapter->active_scan_triggered || !priv->scan_request) { - adapter->active_scan_triggered = false; - return 0; - } - - if (!priv->hidden_chan[0].chan_number) { - mwifiex_dbg(adapter, INFO, "No BSS with hidden SSID found on DFS channels\n"); - return 0; - } - user_scan_cfg = kzalloc(sizeof(*user_scan_cfg), GFP_KERNEL); - - if (!user_scan_cfg) - return -ENOMEM; - - memset(user_scan_cfg, 0, sizeof(*user_scan_cfg)); - - for (id = 0; id < MWIFIEX_USER_SCAN_CHAN_MAX; id++) { - if (!priv->hidden_chan[id].chan_number) - break; - memcpy(&user_scan_cfg->chan_list[id], - &priv->hidden_chan[id], - sizeof(struct mwifiex_user_scan_chan)); - } - - adapter->active_scan_triggered = true; - user_scan_cfg->num_ssids = priv->scan_request->n_ssids; - user_scan_cfg->ssid_list = priv->scan_request->ssids; - - ret = mwifiex_scan_networks(priv, user_scan_cfg); - kfree(user_scan_cfg); - - memset(&priv->hidden_chan, 0, sizeof(priv->hidden_chan)); - - if (ret) { - dev_err(priv->adapter->dev, "scan failed: %d\n", ret); - return ret; - } - - return 0; -} -static void mwifiex_check_next_scan_command(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct cmd_ctrl_node *cmd_node, *tmp_node; - unsigned long flags; - - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - if (list_empty(&adapter->scan_pending_q)) { - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - mwifiex_active_scan_req_for_passive_chan(priv); - - if (!adapter->ext_scan) - mwifiex_complete_scan(priv); - - if (priv->scan_request) { - mwifiex_dbg(adapter, INFO, - "info: notifying scan done\n"); - cfg80211_scan_done(priv->scan_request, 0); - priv->scan_request = NULL; - } else { - priv->scan_aborting = false; - mwifiex_dbg(adapter, INFO, - "info: scan already aborted\n"); - } - } else if ((priv->scan_aborting && !priv->scan_request) || - priv->scan_block) { - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - - if (!adapter->active_scan_triggered) { - if (priv->scan_request) { - mwifiex_dbg(adapter, INFO, - "info: aborting scan\n"); - cfg80211_scan_done(priv->scan_request, 1); - priv->scan_request = NULL; - } else { - priv->scan_aborting = false; - mwifiex_dbg(adapter, INFO, - "info: scan already aborted\n"); - } - } - } else { - /* Get scan command from scan_pending_q and put to - * cmd_pending_q - */ - cmd_node = list_first_entry(&adapter->scan_pending_q, - struct cmd_ctrl_node, list); - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - mwifiex_insert_cmd_to_pending_q(adapter, cmd_node, true); - } - - return; -} - -/* - * This function handles the command response of scan. - * - * The response buffer for the scan command has the following - * memory layout: - * - * .-------------------------------------------------------------. - * | Header (4 * sizeof(t_u16)): Standard command response hdr | - * .-------------------------------------------------------------. - * | BufSize (t_u16) : sizeof the BSS Description data | - * .-------------------------------------------------------------. - * | NumOfSet (t_u8) : Number of BSS Descs returned | - * .-------------------------------------------------------------. - * | BSSDescription data (variable, size given in BufSize) | - * .-------------------------------------------------------------. - * | TLV data (variable, size calculated using Header->Size, | - * | BufSize and sizeof the fixed fields above) | - * .-------------------------------------------------------------. - */ -int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_scan_rsp *scan_rsp; - struct mwifiex_ie_types_data *tlv_data; - struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; - u8 *bss_info; - u32 scan_resp_size; - u32 bytes_left; - u32 idx; - u32 tlv_buf_size; - struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; - struct chan_band_param_set *chan_band; - u8 is_bgscan_resp; - __le64 fw_tsf = 0; - u8 *radio_type; - - is_bgscan_resp = (le16_to_cpu(resp->command) - == HostCmd_CMD_802_11_BG_SCAN_QUERY); - if (is_bgscan_resp) - scan_rsp = &resp->params.bg_scan_query_resp.scan_resp; - else - scan_rsp = &resp->params.scan_resp; - - - if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) { - mwifiex_dbg(adapter, ERROR, - "SCAN_RESP: too many AP returned (%d)\n", - scan_rsp->number_of_sets); - ret = -1; - goto check_next_scan; - } - - /* Check csa channel expiry before parsing scan response */ - mwifiex_11h_get_csa_closed_channel(priv); - - bytes_left = le16_to_cpu(scan_rsp->bss_descript_size); - mwifiex_dbg(adapter, INFO, - "info: SCAN_RESP: bss_descript_size %d\n", - bytes_left); - - scan_resp_size = le16_to_cpu(resp->size); - - mwifiex_dbg(adapter, INFO, - "info: SCAN_RESP: returned %d APs before parsing\n", - scan_rsp->number_of_sets); - - bss_info = scan_rsp->bss_desc_and_tlv_buffer; - - /* - * The size of the TLV buffer is equal to the entire command response - * size (scan_resp_size) minus the fixed fields (sizeof()'s), the - * BSS Descriptions (bss_descript_size as bytesLef) and the command - * response header (S_DS_GEN) - */ - tlv_buf_size = scan_resp_size - (bytes_left - + sizeof(scan_rsp->bss_descript_size) - + sizeof(scan_rsp->number_of_sets) - + S_DS_GEN); - - tlv_data = (struct mwifiex_ie_types_data *) (scan_rsp-> - bss_desc_and_tlv_buffer + - bytes_left); - - /* Search the TLV buffer space in the scan response for any valid - TLVs */ - mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, - TLV_TYPE_TSFTIMESTAMP, - (struct mwifiex_ie_types_data **) - &tsf_tlv); - - /* Search the TLV buffer space in the scan response for any valid - TLVs */ - mwifiex_ret_802_11_scan_get_tlv_ptrs(adapter, tlv_data, tlv_buf_size, - TLV_TYPE_CHANNELBANDLIST, - (struct mwifiex_ie_types_data **) - &chan_band_tlv); - - for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { - /* - * If the TSF TLV was appended to the scan results, save this - * entry's TSF value in the fw_tsf field. It is the firmware's - * TSF value at the time the beacon or probe response was - * received. - */ - if (tsf_tlv) - memcpy(&fw_tsf, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE], - sizeof(fw_tsf)); - - if (chan_band_tlv) { - chan_band = &chan_band_tlv->chan_band_param[idx]; - radio_type = &chan_band->radio_type; - } else { - radio_type = NULL; - } - - ret = mwifiex_parse_single_response_buf(priv, &bss_info, - &bytes_left, - le64_to_cpu(fw_tsf), - radio_type, false, 0); - if (ret) - goto check_next_scan; - } - -check_next_scan: - mwifiex_check_next_scan_command(priv); - return ret; -} - -/* - * This function prepares an extended scan command to be sent to the firmware - * - * This uses the scan command configuration sent to the command processing - * module in command preparation stage to configure a extended scan command - * structure to send to firmware. - */ -int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) -{ - struct host_cmd_ds_802_11_scan_ext *ext_scan = &cmd->params.ext_scan; - struct mwifiex_scan_cmd_config *scan_cfg = data_buf; - - memcpy(ext_scan->tlv_buffer, scan_cfg->tlv_buf, scan_cfg->tlv_buf_len); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SCAN_EXT); - - /* Size is equal to the sizeof(fixed portions) + the TLV len + header */ - cmd->size = cpu_to_le16((u16)(sizeof(ext_scan->reserved) - + scan_cfg->tlv_buf_len + S_DS_GEN)); - - return 0; -} - -static void -mwifiex_update_chan_statistics(struct mwifiex_private *priv, - struct mwifiex_ietypes_chanstats *tlv_stat) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 i, num_chan; - struct mwifiex_fw_chan_stats *fw_chan_stats; - struct mwifiex_chan_stats chan_stats; - - fw_chan_stats = (void *)((u8 *)tlv_stat + - sizeof(struct mwifiex_ie_types_header)); - num_chan = le16_to_cpu(tlv_stat->header.len) / - sizeof(struct mwifiex_chan_stats); - - for (i = 0 ; i < num_chan; i++) { - chan_stats.chan_num = fw_chan_stats->chan_num; - chan_stats.bandcfg = fw_chan_stats->bandcfg; - chan_stats.flags = fw_chan_stats->flags; - chan_stats.noise = fw_chan_stats->noise; - chan_stats.total_bss = le16_to_cpu(fw_chan_stats->total_bss); - chan_stats.cca_scan_dur = - le16_to_cpu(fw_chan_stats->cca_scan_dur); - chan_stats.cca_busy_dur = - le16_to_cpu(fw_chan_stats->cca_busy_dur); - mwifiex_dbg(adapter, INFO, - "chan=%d, noise=%d, total_network=%d scan_duration=%d, busy_duration=%d\n", - chan_stats.chan_num, - chan_stats.noise, - chan_stats.total_bss, - chan_stats.cca_scan_dur, - chan_stats.cca_busy_dur); - memcpy(&adapter->chan_stats[adapter->survey_idx++], &chan_stats, - sizeof(struct mwifiex_chan_stats)); - fw_chan_stats++; - } -} - -/* This function handles the command response of extended scan */ -int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_scan_ext *ext_scan_resp; - struct mwifiex_ie_types_header *tlv; - struct mwifiex_ietypes_chanstats *tlv_stat; - u16 buf_left, type, len; - - struct host_cmd_ds_command *cmd_ptr; - struct cmd_ctrl_node *cmd_node; - unsigned long cmd_flags, scan_flags; - bool complete_scan = false; - - mwifiex_dbg(adapter, INFO, "info: EXT scan returns successfully\n"); - - ext_scan_resp = &resp->params.ext_scan; - - tlv = (void *)ext_scan_resp->tlv_buffer; - buf_left = le16_to_cpu(resp->size) - (sizeof(*ext_scan_resp) + S_DS_GEN - - 1); - - while (buf_left >= sizeof(struct mwifiex_ie_types_header)) { - type = le16_to_cpu(tlv->type); - len = le16_to_cpu(tlv->len); - - if (buf_left < (sizeof(struct mwifiex_ie_types_header) + len)) { - mwifiex_dbg(adapter, ERROR, - "error processing scan response TLVs"); - break; - } - - switch (type) { - case TLV_TYPE_CHANNEL_STATS: - tlv_stat = (void *)tlv; - mwifiex_update_chan_statistics(priv, tlv_stat); - break; - default: - break; - } - - buf_left -= len + sizeof(struct mwifiex_ie_types_header); - tlv = (void *)((u8 *)tlv + len + - sizeof(struct mwifiex_ie_types_header)); - } - - spin_lock_irqsave(&adapter->cmd_pending_q_lock, cmd_flags); - spin_lock_irqsave(&adapter->scan_pending_q_lock, scan_flags); - if (list_empty(&adapter->scan_pending_q)) { - complete_scan = true; - list_for_each_entry(cmd_node, &adapter->cmd_pending_q, list) { - cmd_ptr = (void *)cmd_node->cmd_skb->data; - if (le16_to_cpu(cmd_ptr->command) == - HostCmd_CMD_802_11_SCAN_EXT) { - mwifiex_dbg(adapter, INFO, - "Scan pending in command pending list"); - complete_scan = false; - break; - } - } - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, scan_flags); - spin_unlock_irqrestore(&adapter->cmd_pending_q_lock, cmd_flags); - - if (complete_scan) - mwifiex_complete_scan(priv); - - return 0; -} - -/* This function This function handles the event extended scan report. It - * parses extended scan results and informs to cfg80211 stack. - */ -int mwifiex_handle_event_ext_scan_report(struct mwifiex_private *priv, - void *buf) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - u8 *bss_info; - u32 bytes_left, bytes_left_for_tlv, idx; - u16 type, len; - struct mwifiex_ie_types_data *tlv; - struct mwifiex_ie_types_bss_scan_rsp *scan_rsp_tlv; - struct mwifiex_ie_types_bss_scan_info *scan_info_tlv; - u8 *radio_type; - u64 fw_tsf = 0; - s32 rssi = 0; - struct mwifiex_event_scan_result *event_scan = buf; - u8 num_of_set = event_scan->num_of_set; - u8 *scan_resp = buf + sizeof(struct mwifiex_event_scan_result); - u16 scan_resp_size = le16_to_cpu(event_scan->buf_size); - - if (num_of_set > MWIFIEX_MAX_AP) { - mwifiex_dbg(adapter, ERROR, - "EXT_SCAN: Invalid number of AP returned (%d)!!\n", - num_of_set); - ret = -1; - goto check_next_scan; - } - - bytes_left = scan_resp_size; - mwifiex_dbg(adapter, INFO, - "EXT_SCAN: size %d, returned %d APs...", - scan_resp_size, num_of_set); - mwifiex_dbg_dump(adapter, CMD_D, "EXT_SCAN buffer:", buf, - scan_resp_size + - sizeof(struct mwifiex_event_scan_result)); - - tlv = (struct mwifiex_ie_types_data *)scan_resp; - - for (idx = 0; idx < num_of_set && bytes_left; idx++) { - type = le16_to_cpu(tlv->header.type); - len = le16_to_cpu(tlv->header.len); - if (bytes_left < sizeof(struct mwifiex_ie_types_header) + len) { - mwifiex_dbg(adapter, ERROR, - "EXT_SCAN: Error bytes left < TLV length\n"); - break; - } - scan_rsp_tlv = NULL; - scan_info_tlv = NULL; - bytes_left_for_tlv = bytes_left; - - /* BSS response TLV with beacon or probe response buffer - * at the initial position of each descriptor - */ - if (type != TLV_TYPE_BSS_SCAN_RSP) - break; - - bss_info = (u8 *)tlv; - scan_rsp_tlv = (struct mwifiex_ie_types_bss_scan_rsp *)tlv; - tlv = (struct mwifiex_ie_types_data *)(tlv->data + len); - bytes_left_for_tlv -= - (len + sizeof(struct mwifiex_ie_types_header)); - - while (bytes_left_for_tlv >= - sizeof(struct mwifiex_ie_types_header) && - le16_to_cpu(tlv->header.type) != TLV_TYPE_BSS_SCAN_RSP) { - type = le16_to_cpu(tlv->header.type); - len = le16_to_cpu(tlv->header.len); - if (bytes_left_for_tlv < - sizeof(struct mwifiex_ie_types_header) + len) { - mwifiex_dbg(adapter, ERROR, - "EXT_SCAN: Error in processing TLV,\t" - "bytes left < TLV length\n"); - scan_rsp_tlv = NULL; - bytes_left_for_tlv = 0; - continue; - } - switch (type) { - case TLV_TYPE_BSS_SCAN_INFO: - scan_info_tlv = - (struct mwifiex_ie_types_bss_scan_info *)tlv; - if (len != - sizeof(struct mwifiex_ie_types_bss_scan_info) - - sizeof(struct mwifiex_ie_types_header)) { - bytes_left_for_tlv = 0; - continue; - } - break; - default: - break; - } - tlv = (struct mwifiex_ie_types_data *)(tlv->data + len); - bytes_left -= - (len + sizeof(struct mwifiex_ie_types_header)); - bytes_left_for_tlv -= - (len + sizeof(struct mwifiex_ie_types_header)); - } - - if (!scan_rsp_tlv) - break; - - /* Advance pointer to the beacon buffer length and - * update the bytes count so that the function - * wlan_interpret_bss_desc_with_ie() can handle the - * scan buffer withut any change - */ - bss_info += sizeof(u16); - bytes_left -= sizeof(u16); - - if (scan_info_tlv) { - rssi = (s32)(s16)(le16_to_cpu(scan_info_tlv->rssi)); - rssi *= 100; /* Convert dBm to mBm */ - mwifiex_dbg(adapter, INFO, - "info: InterpretIE: RSSI=%d\n", rssi); - fw_tsf = le64_to_cpu(scan_info_tlv->tsf); - radio_type = &scan_info_tlv->radio_type; - } else { - radio_type = NULL; - } - ret = mwifiex_parse_single_response_buf(priv, &bss_info, - &bytes_left, fw_tsf, - radio_type, true, rssi); - if (ret) - goto check_next_scan; - } - -check_next_scan: - if (!event_scan->more_event) - mwifiex_check_next_scan_command(priv); - - return ret; -} - -/* - * This function prepares command for background scan query. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting background scan flush parameter - * - Ensuring correct endian-ness - */ -int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd) -{ - struct host_cmd_ds_802_11_bg_scan_query *bg_query = - &cmd->params.bg_scan_query; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_BG_SCAN_QUERY); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_bg_scan_query) - + S_DS_GEN); - - bg_query->flush = 1; - - return 0; -} - -/* - * This function inserts scan command node to the scan pending queue. - */ -void -mwifiex_queue_scan_cmd(struct mwifiex_private *priv, - struct cmd_ctrl_node *cmd_node) -{ - struct mwifiex_adapter *adapter = priv->adapter; - unsigned long flags; - - cmd_node->wait_q_enabled = true; - cmd_node->condition = &adapter->scan_wait_q_woken; - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_add_tail(&cmd_node->list, &adapter->scan_pending_q); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); -} - -/* - * This function sends a scan command for all available channels to the - * firmware, filtered on a specific SSID. - */ -static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv, - struct cfg80211_ssid *req_ssid) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret; - struct mwifiex_user_scan_cfg *scan_cfg; - - if (adapter->scan_processing) { - mwifiex_dbg(adapter, WARN, - "cmd: Scan already in process...\n"); - return -EBUSY; - } - - if (priv->scan_block) { - mwifiex_dbg(adapter, WARN, - "cmd: Scan is blocked during association...\n"); - return -EBUSY; - } - - scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); - if (!scan_cfg) - return -ENOMEM; - - scan_cfg->ssid_list = req_ssid; - scan_cfg->num_ssids = 1; - - ret = mwifiex_scan_networks(priv, scan_cfg); - - kfree(scan_cfg); - return ret; -} - -/* - * Sends IOCTL request to start a scan. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - * - * Scan command can be issued for both normal scan and specific SSID - * scan, depending upon whether an SSID is provided or not. - */ -int mwifiex_request_scan(struct mwifiex_private *priv, - struct cfg80211_ssid *req_ssid) -{ - int ret; - - if (down_interruptible(&priv->async_sem)) { - mwifiex_dbg(priv->adapter, ERROR, - "%s: acquire semaphore fail\n", - __func__); - return -1; - } - - priv->adapter->scan_wait_q_woken = false; - - if (req_ssid && req_ssid->ssid_len != 0) - /* Specific SSID scan */ - ret = mwifiex_scan_specific_ssid(priv, req_ssid); - else - /* Normal scan */ - ret = mwifiex_scan_networks(priv, NULL); - - up(&priv->async_sem); - - return ret; -} - -/* - * This function appends the vendor specific IE TLV to a buffer. - */ -int -mwifiex_cmd_append_vsie_tlv(struct mwifiex_private *priv, - u16 vsie_mask, u8 **buffer) -{ - int id, ret_len = 0; - struct mwifiex_ie_types_vendor_param_set *vs_param_set; - - if (!buffer) - return 0; - if (!(*buffer)) - return 0; - - /* - * Traverse through the saved vendor specific IE array and append - * the selected(scan/assoc/adhoc) IE as TLV to the command - */ - for (id = 0; id < MWIFIEX_MAX_VSIE_NUM; id++) { - if (priv->vs_ie[id].mask & vsie_mask) { - vs_param_set = - (struct mwifiex_ie_types_vendor_param_set *) - *buffer; - vs_param_set->header.type = - cpu_to_le16(TLV_TYPE_PASSTHROUGH); - vs_param_set->header.len = - cpu_to_le16((((u16) priv->vs_ie[id].ie[1]) - & 0x00FF) + 2); - memcpy(vs_param_set->ie, priv->vs_ie[id].ie, - le16_to_cpu(vs_param_set->header.len)); - *buffer += le16_to_cpu(vs_param_set->header.len) + - sizeof(struct mwifiex_ie_types_header); - ret_len += le16_to_cpu(vs_param_set->header.len) + - sizeof(struct mwifiex_ie_types_header); - } - } - return ret_len; -} - -/* - * This function saves a beacon buffer of the current BSS descriptor. - * - * The current beacon buffer is saved so that it can be restored in the - * following cases that makes the beacon buffer not to contain the current - * ssid's beacon buffer. - * - The current ssid was not found somehow in the last scan. - * - The current ssid was the last entry of the scan table and overloaded. - */ -void -mwifiex_save_curr_bcn(struct mwifiex_private *priv) -{ - struct mwifiex_bssdescriptor *curr_bss = - &priv->curr_bss_params.bss_descriptor; - - if (!curr_bss->beacon_buf_size) - return; - - /* allocate beacon buffer at 1st time; or if it's size has changed */ - if (!priv->curr_bcn_buf || - priv->curr_bcn_size != curr_bss->beacon_buf_size) { - priv->curr_bcn_size = curr_bss->beacon_buf_size; - - kfree(priv->curr_bcn_buf); - priv->curr_bcn_buf = kmalloc(curr_bss->beacon_buf_size, - GFP_ATOMIC); - if (!priv->curr_bcn_buf) - return; - } - - memcpy(priv->curr_bcn_buf, curr_bss->beacon_buf, - curr_bss->beacon_buf_size); - mwifiex_dbg(priv->adapter, INFO, - "info: current beacon saved %d\n", - priv->curr_bcn_size); - - curr_bss->beacon_buf = priv->curr_bcn_buf; - - /* adjust the pointers in the current BSS descriptor */ - if (curr_bss->bcn_wpa_ie) - curr_bss->bcn_wpa_ie = - (struct ieee_types_vendor_specific *) - (curr_bss->beacon_buf + - curr_bss->wpa_offset); - - if (curr_bss->bcn_rsn_ie) - curr_bss->bcn_rsn_ie = (struct ieee_types_generic *) - (curr_bss->beacon_buf + - curr_bss->rsn_offset); - - if (curr_bss->bcn_ht_cap) - curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *) - (curr_bss->beacon_buf + - curr_bss->ht_cap_offset); - - if (curr_bss->bcn_ht_oper) - curr_bss->bcn_ht_oper = (struct ieee80211_ht_operation *) - (curr_bss->beacon_buf + - curr_bss->ht_info_offset); - - if (curr_bss->bcn_vht_cap) - curr_bss->bcn_vht_cap = (void *)(curr_bss->beacon_buf + - curr_bss->vht_cap_offset); - - if (curr_bss->bcn_vht_oper) - curr_bss->bcn_vht_oper = (void *)(curr_bss->beacon_buf + - curr_bss->vht_info_offset); - - if (curr_bss->bcn_bss_co_2040) - curr_bss->bcn_bss_co_2040 = - (curr_bss->beacon_buf + curr_bss->bss_co_2040_offset); - - if (curr_bss->bcn_ext_cap) - curr_bss->bcn_ext_cap = curr_bss->beacon_buf + - curr_bss->ext_cap_offset; - - if (curr_bss->oper_mode) - curr_bss->oper_mode = (void *)(curr_bss->beacon_buf + - curr_bss->oper_mode_offset); -} - -/* - * This function frees the current BSS descriptor beacon buffer. - */ -void -mwifiex_free_curr_bcn(struct mwifiex_private *priv) -{ - kfree(priv->curr_bcn_buf); - priv->curr_bcn_buf = NULL; -} diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c deleted file mode 100644 index 78a8474e1a3d..000000000000 --- a/drivers/net/wireless/mwifiex/sdio.c +++ /dev/null @@ -1,2684 +0,0 @@ -/* - * Marvell Wireless LAN device driver: SDIO specific handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include <linux/firmware.h> - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "sdio.h" - - -#define SDIO_VERSION "1.0" - -/* The mwifiex_sdio_remove() callback function is called when - * user removes this module from kernel space or ejects - * the card from the slot. The driver handles these 2 cases - * differently. - * If the user is removing the module, the few commands (FUNC_SHUTDOWN, - * HS_CANCEL etc.) are sent to the firmware. - * If the card is removed, there is no need to send these command. - * - * The variable 'user_rmmod' is used to distinguish these two - * scenarios. This flag is initialized as FALSE in case the card - * is removed, and will be set to TRUE for module removal when - * module_exit function is called. - */ -static u8 user_rmmod; - -static struct mwifiex_if_ops sdio_ops; -static unsigned long iface_work_flags; - -static struct semaphore add_remove_card_sem; - -static struct memory_type_mapping generic_mem_type_map[] = { - {"DUMP", NULL, 0, 0xDD}, -}; - -static struct memory_type_mapping mem_type_mapping_tbl[] = { - {"ITCM", NULL, 0, 0xF0}, - {"DTCM", NULL, 0, 0xF1}, - {"SQRAM", NULL, 0, 0xF2}, - {"APU", NULL, 0, 0xF3}, - {"CIU", NULL, 0, 0xF4}, - {"ICU", NULL, 0, 0xF5}, - {"MAC", NULL, 0, 0xF6}, - {"EXT7", NULL, 0, 0xF7}, - {"EXT8", NULL, 0, 0xF8}, - {"EXT9", NULL, 0, 0xF9}, - {"EXT10", NULL, 0, 0xFA}, - {"EXT11", NULL, 0, 0xFB}, - {"EXT12", NULL, 0, 0xFC}, - {"EXT13", NULL, 0, 0xFD}, - {"EXTLAST", NULL, 0, 0xFE}, -}; - -/* - * SDIO probe. - * - * This function probes an mwifiex device and registers it. It allocates - * the card structure, enables SDIO function number and initiates the - * device registration and initialization procedure by adding a logical - * interface. - */ -static int -mwifiex_sdio_probe(struct sdio_func *func, const struct sdio_device_id *id) -{ - int ret; - struct sdio_mmc_card *card = NULL; - - pr_debug("info: vendor=0x%4.04X device=0x%4.04X class=%d function=%d\n", - func->vendor, func->device, func->class, func->num); - - card = kzalloc(sizeof(struct sdio_mmc_card), GFP_KERNEL); - if (!card) - return -ENOMEM; - - card->func = func; - card->device_id = id; - - func->card->quirks |= MMC_QUIRK_BLKSZ_FOR_BYTE_MODE; - - if (id->driver_data) { - struct mwifiex_sdio_device *data = (void *)id->driver_data; - - card->firmware = data->firmware; - card->reg = data->reg; - card->max_ports = data->max_ports; - card->mp_agg_pkt_limit = data->mp_agg_pkt_limit; - card->supports_sdio_new_mode = data->supports_sdio_new_mode; - card->has_control_mask = data->has_control_mask; - card->tx_buf_size = data->tx_buf_size; - card->mp_tx_agg_buf_size = data->mp_tx_agg_buf_size; - card->mp_rx_agg_buf_size = data->mp_rx_agg_buf_size; - card->can_dump_fw = data->can_dump_fw; - card->fw_dump_enh = data->fw_dump_enh; - card->can_auto_tdls = data->can_auto_tdls; - card->can_ext_scan = data->can_ext_scan; - } - - sdio_claim_host(func); - ret = sdio_enable_func(func); - sdio_release_host(func); - - if (ret) { - pr_err("%s: failed to enable function\n", __func__); - kfree(card); - return -EIO; - } - - if (mwifiex_add_card(card, &add_remove_card_sem, &sdio_ops, - MWIFIEX_SDIO)) { - pr_err("%s: add card failed\n", __func__); - kfree(card); - sdio_claim_host(func); - ret = sdio_disable_func(func); - sdio_release_host(func); - ret = -1; - } - - return ret; -} - -/* - * SDIO resume. - * - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not resumed, this function turns on the traffic and - * sends a host sleep cancel request to the firmware. - */ -static int mwifiex_sdio_resume(struct device *dev) -{ - struct sdio_func *func = dev_to_sdio_func(dev); - struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter; - mmc_pm_flag_t pm_flag = 0; - - if (func) { - pm_flag = sdio_get_host_pm_caps(func); - card = sdio_get_drvdata(func); - if (!card || !card->adapter) { - pr_err("resume: invalid card or adapter\n"); - return 0; - } - } else { - pr_err("resume: sdio_func is not specified\n"); - return 0; - } - - adapter = card->adapter; - - if (!adapter->is_suspended) { - mwifiex_dbg(adapter, WARN, - "device already resumed\n"); - return 0; - } - - adapter->is_suspended = false; - - /* Disable Host Sleep */ - mwifiex_cancel_hs(mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_STA), - MWIFIEX_ASYNC_CMD); - - return 0; -} - -/* - * SDIO remove. - * - * This function removes the interface and frees up the card structure. - */ -static void -mwifiex_sdio_remove(struct sdio_func *func) -{ - struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter; - struct mwifiex_private *priv; - - card = sdio_get_drvdata(func); - if (!card) - return; - - adapter = card->adapter; - if (!adapter || !adapter->priv_num) - return; - - mwifiex_dbg(adapter, INFO, "info: SDIO func num=%d\n", func->num); - - if (user_rmmod) { - if (adapter->is_suspended) - mwifiex_sdio_resume(adapter->dev); - - mwifiex_deauthenticate_all(adapter); - - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - mwifiex_disable_auto_ds(priv); - mwifiex_init_shutdown_fw(priv, MWIFIEX_FUNC_SHUTDOWN); - } - - mwifiex_remove_card(card->adapter, &add_remove_card_sem); -} - -/* - * SDIO suspend. - * - * Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not suspended, this function allocates and sends a host - * sleep activate request to the firmware and turns off the traffic. - */ -static int mwifiex_sdio_suspend(struct device *dev) -{ - struct sdio_func *func = dev_to_sdio_func(dev); - struct sdio_mmc_card *card; - struct mwifiex_adapter *adapter; - mmc_pm_flag_t pm_flag = 0; - int ret = 0; - - if (func) { - pm_flag = sdio_get_host_pm_caps(func); - pr_debug("cmd: %s: suspend: PM flag = 0x%x\n", - sdio_func_id(func), pm_flag); - if (!(pm_flag & MMC_PM_KEEP_POWER)) { - pr_err("%s: cannot remain alive while host is" - " suspended\n", sdio_func_id(func)); - return -ENOSYS; - } - - card = sdio_get_drvdata(func); - if (!card || !card->adapter) { - pr_err("suspend: invalid card or adapter\n"); - return 0; - } - } else { - pr_err("suspend: sdio_func is not specified\n"); - return 0; - } - - adapter = card->adapter; - - /* Enable the Host Sleep */ - if (!mwifiex_enable_hs(adapter)) { - mwifiex_dbg(adapter, ERROR, - "cmd: failed to suspend\n"); - adapter->hs_enabling = false; - return -EFAULT; - } - - mwifiex_dbg(adapter, INFO, - "cmd: suspend with MMC_PM_KEEP_POWER\n"); - ret = sdio_set_host_pm_flags(func, MMC_PM_KEEP_POWER); - - /* Indicate device suspended */ - adapter->is_suspended = true; - adapter->hs_enabling = false; - - return ret; -} - -/* Device ID for SD8786 */ -#define SDIO_DEVICE_ID_MARVELL_8786 (0x9116) -/* Device ID for SD8787 */ -#define SDIO_DEVICE_ID_MARVELL_8787 (0x9119) -/* Device ID for SD8797 */ -#define SDIO_DEVICE_ID_MARVELL_8797 (0x9129) -/* Device ID for SD8897 */ -#define SDIO_DEVICE_ID_MARVELL_8897 (0x912d) -/* Device ID for SD8887 */ -#define SDIO_DEVICE_ID_MARVELL_8887 (0x9135) -/* Device ID for SD8801 */ -#define SDIO_DEVICE_ID_MARVELL_8801 (0x9139) -/* Device ID for SD8997 */ -#define SDIO_DEVICE_ID_MARVELL_8997 (0x9141) - - -/* WLAN IDs */ -static const struct sdio_device_id mwifiex_ids[] = { - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8786), - .driver_data = (unsigned long) &mwifiex_sdio_sd8786}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8787), - .driver_data = (unsigned long) &mwifiex_sdio_sd8787}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8797), - .driver_data = (unsigned long) &mwifiex_sdio_sd8797}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8897), - .driver_data = (unsigned long) &mwifiex_sdio_sd8897}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8887), - .driver_data = (unsigned long)&mwifiex_sdio_sd8887}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8801), - .driver_data = (unsigned long)&mwifiex_sdio_sd8801}, - {SDIO_DEVICE(SDIO_VENDOR_ID_MARVELL, SDIO_DEVICE_ID_MARVELL_8997), - .driver_data = (unsigned long)&mwifiex_sdio_sd8997}, - {}, -}; - -MODULE_DEVICE_TABLE(sdio, mwifiex_ids); - -static const struct dev_pm_ops mwifiex_sdio_pm_ops = { - .suspend = mwifiex_sdio_suspend, - .resume = mwifiex_sdio_resume, -}; - -static struct sdio_driver mwifiex_sdio = { - .name = "mwifiex_sdio", - .id_table = mwifiex_ids, - .probe = mwifiex_sdio_probe, - .remove = mwifiex_sdio_remove, - .drv = { - .owner = THIS_MODULE, - .pm = &mwifiex_sdio_pm_ops, - } -}; - -/* Write data into SDIO card register. Caller claims SDIO device. */ -static int -mwifiex_write_reg_locked(struct sdio_func *func, u32 reg, u8 data) -{ - int ret = -1; - sdio_writeb(func, data, reg, &ret); - return ret; -} - -/* - * This function writes data into SDIO card register. - */ -static int -mwifiex_write_reg(struct mwifiex_adapter *adapter, u32 reg, u8 data) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - - sdio_claim_host(card->func); - ret = mwifiex_write_reg_locked(card->func, reg, data); - sdio_release_host(card->func); - - return ret; -} - -/* - * This function reads data from SDIO card register. - */ -static int -mwifiex_read_reg(struct mwifiex_adapter *adapter, u32 reg, u8 *data) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = -1; - u8 val; - - sdio_claim_host(card->func); - val = sdio_readb(card->func, reg, &ret); - sdio_release_host(card->func); - - *data = val; - - return ret; -} - -/* - * This function writes multiple data into SDIO card memory. - * - * This does not work in suspended mode. - */ -static int -mwifiex_write_data_sync(struct mwifiex_adapter *adapter, - u8 *buffer, u32 pkt_len, u32 port) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - u8 blk_mode = - (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE : BLOCK_MODE; - u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; - u32 blk_cnt = - (blk_mode == - BLOCK_MODE) ? (pkt_len / - MWIFIEX_SDIO_BLOCK_SIZE) : pkt_len; - u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); - - if (adapter->is_suspended) { - mwifiex_dbg(adapter, ERROR, - "%s: not allowed while suspended\n", __func__); - return -1; - } - - sdio_claim_host(card->func); - - ret = sdio_writesb(card->func, ioport, buffer, blk_cnt * blk_size); - - sdio_release_host(card->func); - - return ret; -} - -/* - * This function reads multiple data from SDIO card memory. - */ -static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *buffer, - u32 len, u32 port, u8 claim) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - u8 blk_mode = (port & MWIFIEX_SDIO_BYTE_MODE_MASK) ? BYTE_MODE - : BLOCK_MODE; - u32 blk_size = (blk_mode == BLOCK_MODE) ? MWIFIEX_SDIO_BLOCK_SIZE : 1; - u32 blk_cnt = (blk_mode == BLOCK_MODE) ? (len / MWIFIEX_SDIO_BLOCK_SIZE) - : len; - u32 ioport = (port & MWIFIEX_SDIO_IO_PORT_MASK); - - if (claim) - sdio_claim_host(card->func); - - ret = sdio_readsb(card->func, buffer, ioport, blk_cnt * blk_size); - - if (claim) - sdio_release_host(card->func); - - return ret; -} - -/* - * This function wakes up the card. - * - * A host power up command is written to the card configuration - * register to wake up the card. - */ -static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) -{ - mwifiex_dbg(adapter, EVENT, - "event: wakeup device...\n"); - - return mwifiex_write_reg(adapter, CONFIGURATION_REG, HOST_POWER_UP); -} - -/* - * This function is called after the card has woken up. - * - * The card configuration register is reset. - */ -static int mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) -{ - mwifiex_dbg(adapter, EVENT, - "cmd: wakeup device completed\n"); - - return mwifiex_write_reg(adapter, CONFIGURATION_REG, 0); -} - -/* - * This function is used to initialize IO ports for the - * chipsets supporting SDIO new mode eg SD8897. - */ -static int mwifiex_init_sdio_new_mode(struct mwifiex_adapter *adapter) -{ - u8 reg; - struct sdio_mmc_card *card = adapter->card; - - adapter->ioport = MEM_PORT; - - /* enable sdio new mode */ - if (mwifiex_read_reg(adapter, card->reg->card_cfg_2_1_reg, ®)) - return -1; - if (mwifiex_write_reg(adapter, card->reg->card_cfg_2_1_reg, - reg | CMD53_NEW_MODE)) - return -1; - - /* Configure cmd port and enable reading rx length from the register */ - if (mwifiex_read_reg(adapter, card->reg->cmd_cfg_0, ®)) - return -1; - if (mwifiex_write_reg(adapter, card->reg->cmd_cfg_0, - reg | CMD_PORT_RD_LEN_EN)) - return -1; - - /* Enable Dnld/Upld ready auto reset for cmd port after cmd53 is - * completed - */ - if (mwifiex_read_reg(adapter, card->reg->cmd_cfg_1, ®)) - return -1; - if (mwifiex_write_reg(adapter, card->reg->cmd_cfg_1, - reg | CMD_PORT_AUTO_EN)) - return -1; - - return 0; -} - -/* This function initializes the IO ports. - * - * The following operations are performed - - * - Read the IO ports (0, 1 and 2) - * - Set host interrupt Reset-To-Read to clear - * - Set auto re-enable interrupt - */ -static int mwifiex_init_sdio_ioport(struct mwifiex_adapter *adapter) -{ - u8 reg; - struct sdio_mmc_card *card = adapter->card; - - adapter->ioport = 0; - - if (card->supports_sdio_new_mode) { - if (mwifiex_init_sdio_new_mode(adapter)) - return -1; - goto cont; - } - - /* Read the IO port */ - if (!mwifiex_read_reg(adapter, card->reg->io_port_0_reg, ®)) - adapter->ioport |= (reg & 0xff); - else - return -1; - - if (!mwifiex_read_reg(adapter, card->reg->io_port_1_reg, ®)) - adapter->ioport |= ((reg & 0xff) << 8); - else - return -1; - - if (!mwifiex_read_reg(adapter, card->reg->io_port_2_reg, ®)) - adapter->ioport |= ((reg & 0xff) << 16); - else - return -1; -cont: - mwifiex_dbg(adapter, INFO, - "info: SDIO FUNC1 IO port: %#x\n", adapter->ioport); - - /* Set Host interrupt reset to read to clear */ - if (!mwifiex_read_reg(adapter, card->reg->host_int_rsr_reg, ®)) - mwifiex_write_reg(adapter, card->reg->host_int_rsr_reg, - reg | card->reg->sdio_int_mask); - else - return -1; - - /* Dnld/Upld ready set to auto reset */ - if (!mwifiex_read_reg(adapter, card->reg->card_misc_cfg_reg, ®)) - mwifiex_write_reg(adapter, card->reg->card_misc_cfg_reg, - reg | AUTO_RE_ENABLE_INT); - else - return -1; - - return 0; -} - -/* - * This function sends data to the card. - */ -static int mwifiex_write_data_to_card(struct mwifiex_adapter *adapter, - u8 *payload, u32 pkt_len, u32 port) -{ - u32 i = 0; - int ret; - - do { - ret = mwifiex_write_data_sync(adapter, payload, pkt_len, port); - if (ret) { - i++; - mwifiex_dbg(adapter, ERROR, - "host_to_card, write iomem\t" - "(%d) failed: %d\n", i, ret); - if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04)) - mwifiex_dbg(adapter, ERROR, - "write CFG reg failed\n"); - - ret = -1; - if (i > MAX_WRITE_IOMEM_RETRY) - return ret; - } - } while (ret == -1); - - return ret; -} - -/* - * This function gets the read port. - * - * If control port bit is set in MP read bitmap, the control port - * is returned, otherwise the current read port is returned and - * the value is increased (provided it does not reach the maximum - * limit, in which case it is reset to 1) - */ -static int mwifiex_get_rd_port(struct mwifiex_adapter *adapter, u8 *port) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - u32 rd_bitmap = card->mp_rd_bitmap; - - mwifiex_dbg(adapter, DATA, - "data: mp_rd_bitmap=0x%08x\n", rd_bitmap); - - if (card->supports_sdio_new_mode) { - if (!(rd_bitmap & reg->data_port_mask)) - return -1; - } else { - if (!(rd_bitmap & (CTRL_PORT_MASK | reg->data_port_mask))) - return -1; - } - - if ((card->has_control_mask) && - (card->mp_rd_bitmap & CTRL_PORT_MASK)) { - card->mp_rd_bitmap &= (u32) (~CTRL_PORT_MASK); - *port = CTRL_PORT; - mwifiex_dbg(adapter, DATA, - "data: port=%d mp_rd_bitmap=0x%08x\n", - *port, card->mp_rd_bitmap); - return 0; - } - - if (!(card->mp_rd_bitmap & (1 << card->curr_rd_port))) - return -1; - - /* We are now handling the SDIO data ports */ - card->mp_rd_bitmap &= (u32)(~(1 << card->curr_rd_port)); - *port = card->curr_rd_port; - - if (++card->curr_rd_port == card->max_ports) - card->curr_rd_port = reg->start_rd_port; - - mwifiex_dbg(adapter, DATA, - "data: port=%d mp_rd_bitmap=0x%08x -> 0x%08x\n", - *port, rd_bitmap, card->mp_rd_bitmap); - - return 0; -} - -/* - * This function gets the write port for data. - * - * The current write port is returned if available and the value is - * increased (provided it does not reach the maximum limit, in which - * case it is reset to 1) - */ -static int mwifiex_get_wr_port_data(struct mwifiex_adapter *adapter, u32 *port) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - u32 wr_bitmap = card->mp_wr_bitmap; - - mwifiex_dbg(adapter, DATA, - "data: mp_wr_bitmap=0x%08x\n", wr_bitmap); - - if (!(wr_bitmap & card->mp_data_port_mask)) { - adapter->data_sent = true; - return -EBUSY; - } - - if (card->mp_wr_bitmap & (1 << card->curr_wr_port)) { - card->mp_wr_bitmap &= (u32) (~(1 << card->curr_wr_port)); - *port = card->curr_wr_port; - if (++card->curr_wr_port == card->mp_end_port) - card->curr_wr_port = reg->start_wr_port; - } else { - adapter->data_sent = true; - return -EBUSY; - } - - if ((card->has_control_mask) && (*port == CTRL_PORT)) { - mwifiex_dbg(adapter, ERROR, - "invalid data port=%d cur port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", - *port, card->curr_wr_port, wr_bitmap, - card->mp_wr_bitmap); - return -1; - } - - mwifiex_dbg(adapter, DATA, - "data: port=%d mp_wr_bitmap=0x%08x -> 0x%08x\n", - *port, wr_bitmap, card->mp_wr_bitmap); - - return 0; -} - -/* - * This function polls the card status. - */ -static int -mwifiex_sdio_poll_card_status(struct mwifiex_adapter *adapter, u8 bits) -{ - struct sdio_mmc_card *card = adapter->card; - u32 tries; - u8 cs; - - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - if (mwifiex_read_reg(adapter, card->reg->poll_reg, &cs)) - break; - else if ((cs & bits) == bits) - return 0; - - usleep_range(10, 20); - } - - mwifiex_dbg(adapter, ERROR, - "poll card status failed, tries = %d\n", tries); - - return -1; -} - -/* - * This function reads the firmware status. - */ -static int -mwifiex_sdio_read_fw_status(struct mwifiex_adapter *adapter, u16 *dat) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - u8 fws0, fws1; - - if (mwifiex_read_reg(adapter, reg->status_reg_0, &fws0)) - return -1; - - if (mwifiex_read_reg(adapter, reg->status_reg_1, &fws1)) - return -1; - - *dat = (u16) ((fws1 << 8) | fws0); - - return 0; -} - -/* - * This function disables the host interrupt. - * - * The host interrupt mask is read, the disable bit is reset and - * written back to the card host interrupt mask register. - */ -static void mwifiex_sdio_disable_host_int(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - struct sdio_func *func = card->func; - - sdio_claim_host(func); - mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg, 0); - sdio_release_irq(func); - sdio_release_host(func); -} - -/* - * This function reads the interrupt status from card. - */ -static void mwifiex_interrupt_status(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - u8 sdio_ireg; - unsigned long flags; - - if (mwifiex_read_data_sync(adapter, card->mp_regs, - card->reg->max_mp_regs, - REG_PORT | MWIFIEX_SDIO_BYTE_MODE_MASK, 0)) { - mwifiex_dbg(adapter, ERROR, "read mp_regs failed\n"); - return; - } - - sdio_ireg = card->mp_regs[card->reg->host_int_status_reg]; - if (sdio_ireg) { - /* - * DN_LD_HOST_INT_STATUS and/or UP_LD_HOST_INT_STATUS - * For SDIO new mode CMD port interrupts - * DN_LD_CMD_PORT_HOST_INT_STATUS and/or - * UP_LD_CMD_PORT_HOST_INT_STATUS - * Clear the interrupt status register - */ - mwifiex_dbg(adapter, INTR, - "int: sdio_ireg = %#x\n", sdio_ireg); - spin_lock_irqsave(&adapter->int_lock, flags); - adapter->int_status |= sdio_ireg; - spin_unlock_irqrestore(&adapter->int_lock, flags); - } -} - -/* - * SDIO interrupt handler. - * - * This function reads the interrupt status from firmware and handles - * the interrupt in current thread (ksdioirqd) right away. - */ -static void -mwifiex_sdio_interrupt(struct sdio_func *func) -{ - struct mwifiex_adapter *adapter; - struct sdio_mmc_card *card; - - card = sdio_get_drvdata(func); - if (!card || !card->adapter) { - pr_debug("int: func=%p card=%p adapter=%p\n", - func, card, card ? card->adapter : NULL); - return; - } - adapter = card->adapter; - - if (!adapter->pps_uapsd_mode && adapter->ps_state == PS_STATE_SLEEP) - adapter->ps_state = PS_STATE_AWAKE; - - mwifiex_interrupt_status(adapter); - mwifiex_main_process(adapter); -} - -/* - * This function enables the host interrupt. - * - * The host interrupt enable mask is written to the card - * host interrupt mask register. - */ -static int mwifiex_sdio_enable_host_int(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - struct sdio_func *func = card->func; - int ret; - - sdio_claim_host(func); - - /* Request the SDIO IRQ */ - ret = sdio_claim_irq(func, mwifiex_sdio_interrupt); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "claim irq failed: ret=%d\n", ret); - goto out; - } - - /* Simply write the mask to the register */ - ret = mwifiex_write_reg_locked(func, card->reg->host_int_mask_reg, - card->reg->host_int_enable); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "enable host interrupt failed\n"); - sdio_release_irq(func); - } - -out: - sdio_release_host(func); - return ret; -} - -/* - * This function sends a data buffer to the card. - */ -static int mwifiex_sdio_card_to_host(struct mwifiex_adapter *adapter, - u32 *type, u8 *buffer, - u32 npayload, u32 ioport) -{ - int ret; - u32 nb; - - if (!buffer) { - mwifiex_dbg(adapter, ERROR, - "%s: buffer is NULL\n", __func__); - return -1; - } - - ret = mwifiex_read_data_sync(adapter, buffer, npayload, ioport, 1); - - if (ret) { - mwifiex_dbg(adapter, ERROR, - "%s: read iomem failed: %d\n", __func__, - ret); - return -1; - } - - nb = le16_to_cpu(*(__le16 *) (buffer)); - if (nb > npayload) { - mwifiex_dbg(adapter, ERROR, - "%s: invalid packet, nb=%d npayload=%d\n", - __func__, nb, npayload); - return -1; - } - - *type = le16_to_cpu(*(__le16 *) (buffer + 2)); - - return ret; -} - -/* - * This function downloads the firmware to the card. - * - * Firmware is downloaded to the card in blocks. Every block download - * is tested for CRC errors, and retried a number of times before - * returning failure. - */ -static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *fw) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - int ret; - u8 *firmware = fw->fw_buf; - u32 firmware_len = fw->fw_len; - u32 offset = 0; - u8 base0, base1; - u8 *fwbuf; - u16 len = 0; - u32 txlen, tx_blocks = 0, tries; - u32 i = 0; - - if (!firmware_len) { - mwifiex_dbg(adapter, ERROR, - "firmware image not found! Terminating download\n"); - return -1; - } - - mwifiex_dbg(adapter, INFO, - "info: downloading FW image (%d bytes)\n", - firmware_len); - - /* Assume that the allocated buffer is 8-byte aligned */ - fwbuf = kzalloc(MWIFIEX_UPLD_SIZE, GFP_KERNEL); - if (!fwbuf) - return -ENOMEM; - - sdio_claim_host(card->func); - - /* Perform firmware data transfer */ - do { - /* The host polls for the DN_LD_CARD_RDY and CARD_IO_READY - bits */ - ret = mwifiex_sdio_poll_card_status(adapter, CARD_IO_READY | - DN_LD_CARD_RDY); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "FW download with helper:\t" - "poll status timeout @ %d\n", offset); - goto done; - } - - /* More data? */ - if (offset >= firmware_len) - break; - - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - ret = mwifiex_read_reg(adapter, reg->base_0_reg, - &base0); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "dev BASE0 register read failed:\t" - "base0=%#04X(%d). Terminating dnld\n", - base0, base0); - goto done; - } - ret = mwifiex_read_reg(adapter, reg->base_1_reg, - &base1); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "dev BASE1 register read failed:\t" - "base1=%#04X(%d). Terminating dnld\n", - base1, base1); - goto done; - } - len = (u16) (((base1 & 0xff) << 8) | (base0 & 0xff)); - - if (len) - break; - - usleep_range(10, 20); - } - - if (!len) { - break; - } else if (len > MWIFIEX_UPLD_SIZE) { - mwifiex_dbg(adapter, ERROR, - "FW dnld failed @ %d, invalid length %d\n", - offset, len); - ret = -1; - goto done; - } - - txlen = len; - - if (len & BIT(0)) { - i++; - if (i > MAX_WRITE_IOMEM_RETRY) { - mwifiex_dbg(adapter, ERROR, - "FW dnld failed @ %d, over max retry\n", - offset); - ret = -1; - goto done; - } - mwifiex_dbg(adapter, ERROR, - "CRC indicated by the helper:\t" - "len = 0x%04X, txlen = %d\n", len, txlen); - len &= ~BIT(0); - /* Setting this to 0 to resend from same offset */ - txlen = 0; - } else { - i = 0; - - /* Set blocksize to transfer - checking for last - block */ - if (firmware_len - offset < txlen) - txlen = firmware_len - offset; - - tx_blocks = (txlen + MWIFIEX_SDIO_BLOCK_SIZE - 1) - / MWIFIEX_SDIO_BLOCK_SIZE; - - /* Copy payload to buffer */ - memmove(fwbuf, &firmware[offset], txlen); - } - - ret = mwifiex_write_data_sync(adapter, fwbuf, tx_blocks * - MWIFIEX_SDIO_BLOCK_SIZE, - adapter->ioport); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "FW download, write iomem (%d) failed @ %d\n", - i, offset); - if (mwifiex_write_reg(adapter, CONFIGURATION_REG, 0x04)) - mwifiex_dbg(adapter, ERROR, - "write CFG reg failed\n"); - - ret = -1; - goto done; - } - - offset += txlen; - } while (true); - - sdio_release_host(card->func); - - mwifiex_dbg(adapter, MSG, - "info: FW download over, size %d bytes\n", offset); - - ret = 0; -done: - kfree(fwbuf); - return ret; -} - -/* - * This function checks the firmware status in card. - * - * The winner interface is also determined by this function. - */ -static int mwifiex_check_fw_status(struct mwifiex_adapter *adapter, - u32 poll_num) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - u16 firmware_stat; - u32 tries; - u8 winner_status; - - /* Wait for firmware initialization event */ - for (tries = 0; tries < poll_num; tries++) { - ret = mwifiex_sdio_read_fw_status(adapter, &firmware_stat); - if (ret) - continue; - if (firmware_stat == FIRMWARE_READY_SDIO) { - ret = 0; - break; - } else { - msleep(100); - ret = -1; - } - } - - if (ret) { - if (mwifiex_read_reg - (adapter, card->reg->status_reg_0, &winner_status)) - winner_status = 0; - - if (winner_status) - adapter->winner = 0; - else - adapter->winner = 1; - } - return ret; -} - -/* - * This function decode sdio aggreation pkt. - * - * Based on the the data block size and pkt_len, - * skb data will be decoded to few packets. - */ -static void mwifiex_deaggr_sdio_pkt(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - u32 total_pkt_len, pkt_len; - struct sk_buff *skb_deaggr; - u32 pkt_type; - u16 blk_size; - u8 blk_num; - u8 *data; - - data = skb->data; - total_pkt_len = skb->len; - - while (total_pkt_len >= (SDIO_HEADER_OFFSET + INTF_HEADER_LEN)) { - if (total_pkt_len < adapter->sdio_rx_block_size) - break; - blk_num = *(data + BLOCK_NUMBER_OFFSET); - blk_size = adapter->sdio_rx_block_size * blk_num; - if (blk_size > total_pkt_len) { - mwifiex_dbg(adapter, ERROR, - "%s: error in blk_size,\t" - "blk_num=%d, blk_size=%d, total_pkt_len=%d\n", - __func__, blk_num, blk_size, total_pkt_len); - break; - } - pkt_len = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET)); - pkt_type = le16_to_cpu(*(__le16 *)(data + SDIO_HEADER_OFFSET + - 2)); - if ((pkt_len + SDIO_HEADER_OFFSET) > blk_size) { - mwifiex_dbg(adapter, ERROR, - "%s: error in pkt_len,\t" - "pkt_len=%d, blk_size=%d\n", - __func__, pkt_len, blk_size); - break; - } - skb_deaggr = mwifiex_alloc_dma_align_buf(pkt_len, - GFP_KERNEL | GFP_DMA); - if (!skb_deaggr) - break; - skb_put(skb_deaggr, pkt_len); - memcpy(skb_deaggr->data, data + SDIO_HEADER_OFFSET, pkt_len); - skb_pull(skb_deaggr, INTF_HEADER_LEN); - - mwifiex_handle_rx_packet(adapter, skb_deaggr); - data += blk_size; - total_pkt_len -= blk_size; - } -} - -/* - * This function decodes a received packet. - * - * Based on the type, the packet is treated as either a data, or - * a command response, or an event, and the correct handler - * function is invoked. - */ -static int mwifiex_decode_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb, u32 upld_typ) -{ - u8 *cmd_buf; - __le16 *curr_ptr = (__le16 *)skb->data; - u16 pkt_len = le16_to_cpu(*curr_ptr); - struct mwifiex_rxinfo *rx_info; - - if (upld_typ != MWIFIEX_TYPE_AGGR_DATA) { - skb_trim(skb, pkt_len); - skb_pull(skb, INTF_HEADER_LEN); - } - - switch (upld_typ) { - case MWIFIEX_TYPE_AGGR_DATA: - mwifiex_dbg(adapter, INFO, - "info: --- Rx: Aggr Data packet ---\n"); - rx_info = MWIFIEX_SKB_RXCB(skb); - rx_info->buf_type = MWIFIEX_TYPE_AGGR_DATA; - if (adapter->rx_work_enabled) { - skb_queue_tail(&adapter->rx_data_q, skb); - atomic_inc(&adapter->rx_pending); - adapter->data_received = true; - } else { - mwifiex_deaggr_sdio_pkt(adapter, skb); - dev_kfree_skb_any(skb); - } - break; - - case MWIFIEX_TYPE_DATA: - mwifiex_dbg(adapter, DATA, - "info: --- Rx: Data packet ---\n"); - if (adapter->rx_work_enabled) { - skb_queue_tail(&adapter->rx_data_q, skb); - adapter->data_received = true; - atomic_inc(&adapter->rx_pending); - } else { - mwifiex_handle_rx_packet(adapter, skb); - } - break; - - case MWIFIEX_TYPE_CMD: - mwifiex_dbg(adapter, CMD, - "info: --- Rx: Cmd Response ---\n"); - /* take care of curr_cmd = NULL case */ - if (!adapter->curr_cmd) { - cmd_buf = adapter->upld_buf; - - if (adapter->ps_state == PS_STATE_SLEEP_CFM) - mwifiex_process_sleep_confirm_resp(adapter, - skb->data, - skb->len); - - memcpy(cmd_buf, skb->data, - min_t(u32, MWIFIEX_SIZE_OF_CMD_BUFFER, - skb->len)); - - dev_kfree_skb_any(skb); - } else { - adapter->cmd_resp_received = true; - adapter->curr_cmd->resp_skb = skb; - } - break; - - case MWIFIEX_TYPE_EVENT: - mwifiex_dbg(adapter, EVENT, - "info: --- Rx: Event ---\n"); - adapter->event_cause = le32_to_cpu(*(__le32 *) skb->data); - - if ((skb->len > 0) && (skb->len < MAX_EVENT_SIZE)) - memcpy(adapter->event_body, - skb->data + MWIFIEX_EVENT_HEADER_LEN, - skb->len); - - /* event cause has been saved to adapter->event_cause */ - adapter->event_received = true; - adapter->event_skb = skb; - - break; - - default: - mwifiex_dbg(adapter, ERROR, - "unknown upload type %#x\n", upld_typ); - dev_kfree_skb_any(skb); - break; - } - - return 0; -} - -/* - * This function transfers received packets from card to driver, performing - * aggregation if required. - * - * For data received on control port, or if aggregation is disabled, the - * received buffers are uploaded as separate packets. However, if aggregation - * is enabled and required, the buffers are copied onto an aggregation buffer, - * provided there is space left, processed and finally uploaded. - */ -static int mwifiex_sdio_card_to_host_mp_aggr(struct mwifiex_adapter *adapter, - u16 rx_len, u8 port) -{ - struct sdio_mmc_card *card = adapter->card; - s32 f_do_rx_aggr = 0; - s32 f_do_rx_cur = 0; - s32 f_aggr_cur = 0; - s32 f_post_aggr_cur = 0; - struct sk_buff *skb_deaggr; - struct sk_buff *skb = NULL; - u32 pkt_len, pkt_type, mport, pind; - u8 *curr_ptr; - - if ((card->has_control_mask) && (port == CTRL_PORT)) { - /* Read the command Resp without aggr */ - mwifiex_dbg(adapter, CMD, - "info: %s: no aggregation for cmd\t" - "response\n", __func__); - - f_do_rx_cur = 1; - goto rx_curr_single; - } - - if (!card->mpa_rx.enabled) { - mwifiex_dbg(adapter, WARN, - "info: %s: rx aggregation disabled\n", - __func__); - - f_do_rx_cur = 1; - goto rx_curr_single; - } - - if ((!card->has_control_mask && (card->mp_rd_bitmap & - card->reg->data_port_mask)) || - (card->has_control_mask && (card->mp_rd_bitmap & - (~((u32) CTRL_PORT_MASK))))) { - /* Some more data RX pending */ - mwifiex_dbg(adapter, INFO, - "info: %s: not last packet\n", __func__); - - if (MP_RX_AGGR_IN_PROGRESS(card)) { - if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) { - f_aggr_cur = 1; - } else { - /* No room in Aggr buf, do rx aggr now */ - f_do_rx_aggr = 1; - f_post_aggr_cur = 1; - } - } else { - /* Rx aggr not in progress */ - f_aggr_cur = 1; - } - - } else { - /* No more data RX pending */ - mwifiex_dbg(adapter, INFO, - "info: %s: last packet\n", __func__); - - if (MP_RX_AGGR_IN_PROGRESS(card)) { - f_do_rx_aggr = 1; - if (MP_RX_AGGR_BUF_HAS_ROOM(card, rx_len)) - f_aggr_cur = 1; - else - /* No room in Aggr buf, do rx aggr now */ - f_do_rx_cur = 1; - } else { - f_do_rx_cur = 1; - } - } - - if (f_aggr_cur) { - mwifiex_dbg(adapter, INFO, - "info: current packet aggregation\n"); - /* Curr pkt can be aggregated */ - mp_rx_aggr_setup(card, rx_len, port); - - if (MP_RX_AGGR_PKT_LIMIT_REACHED(card) || - mp_rx_aggr_port_limit_reached(card)) { - mwifiex_dbg(adapter, INFO, - "info: %s: aggregated packet\t" - "limit reached\n", __func__); - /* No more pkts allowed in Aggr buf, rx it */ - f_do_rx_aggr = 1; - } - } - - if (f_do_rx_aggr) { - /* do aggr RX now */ - mwifiex_dbg(adapter, DATA, - "info: do_rx_aggr: num of packets: %d\n", - card->mpa_rx.pkt_cnt); - - if (card->supports_sdio_new_mode) { - int i; - u32 port_count; - - for (i = 0, port_count = 0; i < card->max_ports; i++) - if (card->mpa_rx.ports & BIT(i)) - port_count++; - - /* Reading data from "start_port + 0" to "start_port + - * port_count -1", so decrease the count by 1 - */ - port_count--; - mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | - (port_count << 8)) + card->mpa_rx.start_port; - } else { - mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | - (card->mpa_rx.ports << 4)) + - card->mpa_rx.start_port; - } - - if (mwifiex_read_data_sync(adapter, card->mpa_rx.buf, - card->mpa_rx.buf_len, mport, 1)) - goto error; - - curr_ptr = card->mpa_rx.buf; - - for (pind = 0; pind < card->mpa_rx.pkt_cnt; pind++) { - u32 *len_arr = card->mpa_rx.len_arr; - - /* get curr PKT len & type */ - pkt_len = le16_to_cpu(*(__le16 *) &curr_ptr[0]); - pkt_type = le16_to_cpu(*(__le16 *) &curr_ptr[2]); - - /* copy pkt to deaggr buf */ - skb_deaggr = mwifiex_alloc_dma_align_buf(len_arr[pind], - GFP_KERNEL | - GFP_DMA); - if (!skb_deaggr) { - mwifiex_dbg(adapter, ERROR, "skb allocation failure\t" - "drop pkt len=%d type=%d\n", - pkt_len, pkt_type); - curr_ptr += len_arr[pind]; - continue; - } - - skb_put(skb_deaggr, len_arr[pind]); - - if ((pkt_type == MWIFIEX_TYPE_DATA || - (pkt_type == MWIFIEX_TYPE_AGGR_DATA && - adapter->sdio_rx_aggr_enable)) && - (pkt_len <= len_arr[pind])) { - - memcpy(skb_deaggr->data, curr_ptr, pkt_len); - - skb_trim(skb_deaggr, pkt_len); - - /* Process de-aggr packet */ - mwifiex_decode_rx_packet(adapter, skb_deaggr, - pkt_type); - } else { - mwifiex_dbg(adapter, ERROR, - "drop wrong aggr pkt:\t" - "sdio_single_port_rx_aggr=%d\t" - "type=%d len=%d max_len=%d\n", - adapter->sdio_rx_aggr_enable, - pkt_type, pkt_len, len_arr[pind]); - dev_kfree_skb_any(skb_deaggr); - } - curr_ptr += len_arr[pind]; - } - MP_RX_AGGR_BUF_RESET(card); - } - -rx_curr_single: - if (f_do_rx_cur) { - mwifiex_dbg(adapter, INFO, "info: RX: port: %d, rx_len: %d\n", - port, rx_len); - - skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA); - if (!skb) { - mwifiex_dbg(adapter, ERROR, - "single skb allocated fail,\t" - "drop pkt port=%d len=%d\n", port, rx_len); - if (mwifiex_sdio_card_to_host(adapter, &pkt_type, - card->mpa_rx.buf, rx_len, - adapter->ioport + port)) - goto error; - return 0; - } - - skb_put(skb, rx_len); - - if (mwifiex_sdio_card_to_host(adapter, &pkt_type, - skb->data, skb->len, - adapter->ioport + port)) - goto error; - if (!adapter->sdio_rx_aggr_enable && - pkt_type == MWIFIEX_TYPE_AGGR_DATA) { - mwifiex_dbg(adapter, ERROR, "drop wrong pkt type %d\t" - "current SDIO RX Aggr not enabled\n", - pkt_type); - dev_kfree_skb_any(skb); - return 0; - } - - mwifiex_decode_rx_packet(adapter, skb, pkt_type); - } - if (f_post_aggr_cur) { - mwifiex_dbg(adapter, INFO, - "info: current packet aggregation\n"); - /* Curr pkt can be aggregated */ - mp_rx_aggr_setup(card, rx_len, port); - } - - return 0; -error: - if (MP_RX_AGGR_IN_PROGRESS(card)) - MP_RX_AGGR_BUF_RESET(card); - - if (f_do_rx_cur && skb) - /* Single transfer pending. Free curr buff also */ - dev_kfree_skb_any(skb); - - return -1; -} - -/* - * This function checks the current interrupt status. - * - * The following interrupts are checked and handled by this function - - * - Data sent - * - Command sent - * - Packets received - * - * Since the firmware does not generate download ready interrupt if the - * port updated is command port only, command sent interrupt checking - * should be done manually, and for every SDIO interrupt. - * - * In case of Rx packets received, the packets are uploaded from card to - * host and processed accordingly. - */ -static int mwifiex_process_int_status(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - int ret = 0; - u8 sdio_ireg; - struct sk_buff *skb; - u8 port = CTRL_PORT; - u32 len_reg_l, len_reg_u; - u32 rx_blocks; - u16 rx_len; - unsigned long flags; - u32 bitmap; - u8 cr; - - spin_lock_irqsave(&adapter->int_lock, flags); - sdio_ireg = adapter->int_status; - adapter->int_status = 0; - spin_unlock_irqrestore(&adapter->int_lock, flags); - - if (!sdio_ireg) - return ret; - - /* Following interrupt is only for SDIO new mode */ - if (sdio_ireg & DN_LD_CMD_PORT_HOST_INT_STATUS && adapter->cmd_sent) - adapter->cmd_sent = false; - - /* Following interrupt is only for SDIO new mode */ - if (sdio_ireg & UP_LD_CMD_PORT_HOST_INT_STATUS) { - u32 pkt_type; - - /* read the len of control packet */ - rx_len = card->mp_regs[reg->cmd_rd_len_1] << 8; - rx_len |= (u16)card->mp_regs[reg->cmd_rd_len_0]; - rx_blocks = DIV_ROUND_UP(rx_len, MWIFIEX_SDIO_BLOCK_SIZE); - if (rx_len <= INTF_HEADER_LEN || - (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > - MWIFIEX_RX_DATA_BUF_SIZE) - return -1; - rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); - mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n", rx_len); - - skb = mwifiex_alloc_dma_align_buf(rx_len, GFP_KERNEL | GFP_DMA); - if (!skb) - return -1; - - skb_put(skb, rx_len); - - if (mwifiex_sdio_card_to_host(adapter, &pkt_type, skb->data, - skb->len, adapter->ioport | - CMD_PORT_SLCT)) { - mwifiex_dbg(adapter, ERROR, - "%s: failed to card_to_host", __func__); - dev_kfree_skb_any(skb); - goto term_cmd; - } - - if ((pkt_type != MWIFIEX_TYPE_CMD) && - (pkt_type != MWIFIEX_TYPE_EVENT)) - mwifiex_dbg(adapter, ERROR, - "%s:Received wrong packet on cmd port", - __func__); - - mwifiex_decode_rx_packet(adapter, skb, pkt_type); - } - - if (sdio_ireg & DN_LD_HOST_INT_STATUS) { - bitmap = (u32) card->mp_regs[reg->wr_bitmap_l]; - bitmap |= ((u32) card->mp_regs[reg->wr_bitmap_u]) << 8; - if (card->supports_sdio_new_mode) { - bitmap |= - ((u32) card->mp_regs[reg->wr_bitmap_1l]) << 16; - bitmap |= - ((u32) card->mp_regs[reg->wr_bitmap_1u]) << 24; - } - card->mp_wr_bitmap = bitmap; - - mwifiex_dbg(adapter, INTR, - "int: DNLD: wr_bitmap=0x%x\n", - card->mp_wr_bitmap); - if (adapter->data_sent && - (card->mp_wr_bitmap & card->mp_data_port_mask)) { - mwifiex_dbg(adapter, INTR, - "info: <--- Tx DONE Interrupt --->\n"); - adapter->data_sent = false; - } - } - - /* As firmware will not generate download ready interrupt if the port - updated is command port only, cmd_sent should be done for any SDIO - interrupt. */ - if (card->has_control_mask && adapter->cmd_sent) { - /* Check if firmware has attach buffer at command port and - update just that in wr_bit_map. */ - card->mp_wr_bitmap |= - (u32) card->mp_regs[reg->wr_bitmap_l] & CTRL_PORT_MASK; - if (card->mp_wr_bitmap & CTRL_PORT_MASK) - adapter->cmd_sent = false; - } - - mwifiex_dbg(adapter, INTR, "info: cmd_sent=%d data_sent=%d\n", - adapter->cmd_sent, adapter->data_sent); - if (sdio_ireg & UP_LD_HOST_INT_STATUS) { - bitmap = (u32) card->mp_regs[reg->rd_bitmap_l]; - bitmap |= ((u32) card->mp_regs[reg->rd_bitmap_u]) << 8; - if (card->supports_sdio_new_mode) { - bitmap |= - ((u32) card->mp_regs[reg->rd_bitmap_1l]) << 16; - bitmap |= - ((u32) card->mp_regs[reg->rd_bitmap_1u]) << 24; - } - card->mp_rd_bitmap = bitmap; - mwifiex_dbg(adapter, INTR, - "int: UPLD: rd_bitmap=0x%x\n", - card->mp_rd_bitmap); - - while (true) { - ret = mwifiex_get_rd_port(adapter, &port); - if (ret) { - mwifiex_dbg(adapter, INFO, - "info: no more rd_port available\n"); - break; - } - len_reg_l = reg->rd_len_p0_l + (port << 1); - len_reg_u = reg->rd_len_p0_u + (port << 1); - rx_len = ((u16) card->mp_regs[len_reg_u]) << 8; - rx_len |= (u16) card->mp_regs[len_reg_l]; - mwifiex_dbg(adapter, INFO, - "info: RX: port=%d rx_len=%u\n", - port, rx_len); - rx_blocks = - (rx_len + MWIFIEX_SDIO_BLOCK_SIZE - - 1) / MWIFIEX_SDIO_BLOCK_SIZE; - if (rx_len <= INTF_HEADER_LEN || - (card->mpa_rx.enabled && - ((rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE) > - card->mpa_rx.buf_size))) { - mwifiex_dbg(adapter, ERROR, - "invalid rx_len=%d\n", - rx_len); - return -1; - } - - rx_len = (u16) (rx_blocks * MWIFIEX_SDIO_BLOCK_SIZE); - mwifiex_dbg(adapter, INFO, "info: rx_len = %d\n", - rx_len); - - if (mwifiex_sdio_card_to_host_mp_aggr(adapter, rx_len, - port)) { - mwifiex_dbg(adapter, ERROR, - "card_to_host_mpa failed: int status=%#x\n", - sdio_ireg); - goto term_cmd; - } - } - } - - return 0; - -term_cmd: - /* terminate cmd */ - if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr)) - mwifiex_dbg(adapter, ERROR, "read CFG reg failed\n"); - else - mwifiex_dbg(adapter, INFO, - "info: CFG reg val = %d\n", cr); - - if (mwifiex_write_reg(adapter, CONFIGURATION_REG, (cr | 0x04))) - mwifiex_dbg(adapter, ERROR, - "write CFG reg failed\n"); - else - mwifiex_dbg(adapter, INFO, "info: write success\n"); - - if (mwifiex_read_reg(adapter, CONFIGURATION_REG, &cr)) - mwifiex_dbg(adapter, ERROR, - "read CFG reg failed\n"); - else - mwifiex_dbg(adapter, INFO, - "info: CFG reg val =%x\n", cr); - - return -1; -} - -/* - * This function aggregates transmission buffers in driver and downloads - * the aggregated packet to card. - * - * The individual packets are aggregated by copying into an aggregation - * buffer and then downloaded to the card. Previous unsent packets in the - * aggregation buffer are pre-copied first before new packets are added. - * Aggregation is done till there is space left in the aggregation buffer, - * or till new packets are available. - * - * The function will only download the packet to the card when aggregation - * stops, otherwise it will just aggregate the packet in aggregation buffer - * and return. - */ -static int mwifiex_host_to_card_mp_aggr(struct mwifiex_adapter *adapter, - u8 *payload, u32 pkt_len, u32 port, - u32 next_pkt_len) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - s32 f_send_aggr_buf = 0; - s32 f_send_cur_buf = 0; - s32 f_precopy_cur_buf = 0; - s32 f_postcopy_cur_buf = 0; - u32 mport; - - if (!card->mpa_tx.enabled || - (card->has_control_mask && (port == CTRL_PORT)) || - (card->supports_sdio_new_mode && (port == CMD_PORT_SLCT))) { - mwifiex_dbg(adapter, WARN, - "info: %s: tx aggregation disabled\n", - __func__); - - f_send_cur_buf = 1; - goto tx_curr_single; - } - - if (next_pkt_len) { - /* More pkt in TX queue */ - mwifiex_dbg(adapter, INFO, - "info: %s: more packets in queue.\n", - __func__); - - if (MP_TX_AGGR_IN_PROGRESS(card)) { - if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) { - f_precopy_cur_buf = 1; - - if (!(card->mp_wr_bitmap & - (1 << card->curr_wr_port)) || - !MP_TX_AGGR_BUF_HAS_ROOM( - card, pkt_len + next_pkt_len)) - f_send_aggr_buf = 1; - } else { - /* No room in Aggr buf, send it */ - f_send_aggr_buf = 1; - - if (!(card->mp_wr_bitmap & - (1 << card->curr_wr_port))) - f_send_cur_buf = 1; - else - f_postcopy_cur_buf = 1; - } - } else { - if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len) && - (card->mp_wr_bitmap & (1 << card->curr_wr_port))) - f_precopy_cur_buf = 1; - else - f_send_cur_buf = 1; - } - } else { - /* Last pkt in TX queue */ - mwifiex_dbg(adapter, INFO, - "info: %s: Last packet in Tx Queue.\n", - __func__); - - if (MP_TX_AGGR_IN_PROGRESS(card)) { - /* some packs in Aggr buf already */ - f_send_aggr_buf = 1; - - if (MP_TX_AGGR_BUF_HAS_ROOM(card, pkt_len)) - f_precopy_cur_buf = 1; - else - /* No room in Aggr buf, send it */ - f_send_cur_buf = 1; - } else { - f_send_cur_buf = 1; - } - } - - if (f_precopy_cur_buf) { - mwifiex_dbg(adapter, DATA, - "data: %s: precopy current buffer\n", - __func__); - MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); - - if (MP_TX_AGGR_PKT_LIMIT_REACHED(card) || - mp_tx_aggr_port_limit_reached(card)) - /* No more pkts allowed in Aggr buf, send it */ - f_send_aggr_buf = 1; - } - - if (f_send_aggr_buf) { - mwifiex_dbg(adapter, DATA, - "data: %s: send aggr buffer: %d %d\n", - __func__, card->mpa_tx.start_port, - card->mpa_tx.ports); - if (card->supports_sdio_new_mode) { - u32 port_count; - int i; - - for (i = 0, port_count = 0; i < card->max_ports; i++) - if (card->mpa_tx.ports & BIT(i)) - port_count++; - - /* Writing data from "start_port + 0" to "start_port + - * port_count -1", so decrease the count by 1 - */ - port_count--; - mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | - (port_count << 8)) + card->mpa_tx.start_port; - } else { - mport = (adapter->ioport | SDIO_MPA_ADDR_BASE | - (card->mpa_tx.ports << 4)) + - card->mpa_tx.start_port; - } - - ret = mwifiex_write_data_to_card(adapter, card->mpa_tx.buf, - card->mpa_tx.buf_len, mport); - - MP_TX_AGGR_BUF_RESET(card); - } - -tx_curr_single: - if (f_send_cur_buf) { - mwifiex_dbg(adapter, DATA, - "data: %s: send current buffer %d\n", - __func__, port); - ret = mwifiex_write_data_to_card(adapter, payload, pkt_len, - adapter->ioport + port); - } - - if (f_postcopy_cur_buf) { - mwifiex_dbg(adapter, DATA, - "data: %s: postcopy current buffer\n", - __func__); - MP_TX_AGGR_BUF_PUT(card, payload, pkt_len, port); - } - - return ret; -} - -/* - * This function downloads data from driver to card. - * - * Both commands and data packets are transferred to the card by this - * function. - * - * This function adds the SDIO specific header to the front of the buffer - * before transferring. The header contains the length of the packet and - * the type. The firmware handles the packets based upon this set type. - */ -static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter, - u8 type, struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - struct sdio_mmc_card *card = adapter->card; - int ret; - u32 buf_block_len; - u32 blk_size; - u32 port = CTRL_PORT; - u8 *payload = (u8 *)skb->data; - u32 pkt_len = skb->len; - - /* Allocate buffer and copy payload */ - blk_size = MWIFIEX_SDIO_BLOCK_SIZE; - buf_block_len = (pkt_len + blk_size - 1) / blk_size; - *(__le16 *)&payload[0] = cpu_to_le16((u16)pkt_len); - *(__le16 *)&payload[2] = cpu_to_le16(type); - - /* - * This is SDIO specific header - * u16 length, - * u16 type (MWIFIEX_TYPE_DATA = 0, MWIFIEX_TYPE_CMD = 1, - * MWIFIEX_TYPE_EVENT = 3) - */ - if (type == MWIFIEX_TYPE_DATA) { - ret = mwifiex_get_wr_port_data(adapter, &port); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "%s: no wr_port available\n", - __func__); - return ret; - } - } else { - adapter->cmd_sent = true; - /* Type must be MWIFIEX_TYPE_CMD */ - - if (pkt_len <= INTF_HEADER_LEN || - pkt_len > MWIFIEX_UPLD_SIZE) - mwifiex_dbg(adapter, ERROR, - "%s: payload=%p, nb=%d\n", - __func__, payload, pkt_len); - - if (card->supports_sdio_new_mode) - port = CMD_PORT_SLCT; - } - - /* Transfer data to card */ - pkt_len = buf_block_len * blk_size; - - if (tx_param) - ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, - port, tx_param->next_pkt_len - ); - else - ret = mwifiex_host_to_card_mp_aggr(adapter, payload, pkt_len, - port, 0); - - if (ret) { - if (type == MWIFIEX_TYPE_CMD) - adapter->cmd_sent = false; - if (type == MWIFIEX_TYPE_DATA) { - adapter->data_sent = false; - /* restore curr_wr_port in error cases */ - card->curr_wr_port = port; - card->mp_wr_bitmap |= (u32)(1 << card->curr_wr_port); - } - } else { - if (type == MWIFIEX_TYPE_DATA) { - if (!(card->mp_wr_bitmap & (1 << card->curr_wr_port))) - adapter->data_sent = true; - else - adapter->data_sent = false; - } - } - - return ret; -} - -/* - * This function allocates the MPA Tx and Rx buffers. - */ -static int mwifiex_alloc_sdio_mpa_buffers(struct mwifiex_adapter *adapter, - u32 mpa_tx_buf_size, u32 mpa_rx_buf_size) -{ - struct sdio_mmc_card *card = adapter->card; - u32 rx_buf_size; - int ret = 0; - - card->mpa_tx.buf = kzalloc(mpa_tx_buf_size, GFP_KERNEL); - if (!card->mpa_tx.buf) { - ret = -1; - goto error; - } - - card->mpa_tx.buf_size = mpa_tx_buf_size; - - rx_buf_size = max_t(u32, mpa_rx_buf_size, - (u32)SDIO_MAX_AGGR_BUF_SIZE); - card->mpa_rx.buf = kzalloc(rx_buf_size, GFP_KERNEL); - if (!card->mpa_rx.buf) { - ret = -1; - goto error; - } - - card->mpa_rx.buf_size = rx_buf_size; - -error: - if (ret) { - kfree(card->mpa_tx.buf); - kfree(card->mpa_rx.buf); - card->mpa_tx.buf_size = 0; - card->mpa_rx.buf_size = 0; - } - - return ret; -} - -/* - * This function unregisters the SDIO device. - * - * The SDIO IRQ is released, the function is disabled and driver - * data is set to null. - */ -static void -mwifiex_unregister_dev(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - if (adapter->card) { - sdio_claim_host(card->func); - sdio_disable_func(card->func); - sdio_release_host(card->func); - } -} - -/* - * This function registers the SDIO device. - * - * SDIO IRQ is claimed, block size is set and driver data is initialized. - */ -static int mwifiex_register_dev(struct mwifiex_adapter *adapter) -{ - int ret; - struct sdio_mmc_card *card = adapter->card; - struct sdio_func *func = card->func; - - /* save adapter pointer in card */ - card->adapter = adapter; - adapter->tx_buf_size = card->tx_buf_size; - - sdio_claim_host(func); - - /* Set block size */ - ret = sdio_set_block_size(card->func, MWIFIEX_SDIO_BLOCK_SIZE); - sdio_release_host(func); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "cannot set SDIO block size\n"); - return ret; - } - - - adapter->dev = &func->dev; - - strcpy(adapter->fw_name, card->firmware); - if (card->fw_dump_enh) { - adapter->mem_type_mapping_tbl = generic_mem_type_map; - adapter->num_mem_types = 1; - } else { - adapter->mem_type_mapping_tbl = mem_type_mapping_tbl; - adapter->num_mem_types = ARRAY_SIZE(mem_type_mapping_tbl); - } - - return 0; -} - -/* - * This function initializes the SDIO driver. - * - * The following initializations steps are followed - - * - Read the Host interrupt status register to acknowledge - * the first interrupt got from bootloader - * - Disable host interrupt mask register - * - Get SDIO port - * - Initialize SDIO variables in card - * - Allocate MP registers - * - Allocate MPA Tx and Rx buffers - */ -static int mwifiex_init_sdio(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - int ret; - u8 sdio_ireg; - - sdio_set_drvdata(card->func, card); - - /* - * Read the host_int_status_reg for ACK the first interrupt got - * from the bootloader. If we don't do this we get a interrupt - * as soon as we register the irq. - */ - mwifiex_read_reg(adapter, card->reg->host_int_status_reg, &sdio_ireg); - - /* Get SDIO ioport */ - mwifiex_init_sdio_ioport(adapter); - - /* Initialize SDIO variables in card */ - card->mp_rd_bitmap = 0; - card->mp_wr_bitmap = 0; - card->curr_rd_port = reg->start_rd_port; - card->curr_wr_port = reg->start_wr_port; - - card->mp_data_port_mask = reg->data_port_mask; - - card->mpa_tx.buf_len = 0; - card->mpa_tx.pkt_cnt = 0; - card->mpa_tx.start_port = 0; - - card->mpa_tx.enabled = 1; - card->mpa_tx.pkt_aggr_limit = card->mp_agg_pkt_limit; - - card->mpa_rx.buf_len = 0; - card->mpa_rx.pkt_cnt = 0; - card->mpa_rx.start_port = 0; - - card->mpa_rx.enabled = 1; - card->mpa_rx.pkt_aggr_limit = card->mp_agg_pkt_limit; - - /* Allocate buffers for SDIO MP-A */ - card->mp_regs = kzalloc(reg->max_mp_regs, GFP_KERNEL); - if (!card->mp_regs) - return -ENOMEM; - - /* Allocate skb pointer buffers */ - card->mpa_rx.skb_arr = kzalloc((sizeof(void *)) * - card->mp_agg_pkt_limit, GFP_KERNEL); - card->mpa_rx.len_arr = kzalloc(sizeof(*card->mpa_rx.len_arr) * - card->mp_agg_pkt_limit, GFP_KERNEL); - ret = mwifiex_alloc_sdio_mpa_buffers(adapter, - card->mp_tx_agg_buf_size, - card->mp_rx_agg_buf_size); - - /* Allocate 32k MPA Tx/Rx buffers if 64k memory allocation fails */ - if (ret && (card->mp_tx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX || - card->mp_rx_agg_buf_size == MWIFIEX_MP_AGGR_BUF_SIZE_MAX)) { - /* Disable rx single port aggregation */ - adapter->host_disable_sdio_rx_aggr = true; - - ret = mwifiex_alloc_sdio_mpa_buffers - (adapter, MWIFIEX_MP_AGGR_BUF_SIZE_32K, - MWIFIEX_MP_AGGR_BUF_SIZE_32K); - if (ret) { - /* Disable multi port aggregation */ - card->mpa_tx.enabled = 0; - card->mpa_rx.enabled = 0; - } - } - - adapter->auto_tdls = card->can_auto_tdls; - adapter->ext_scan = card->can_ext_scan; - return 0; -} - -/* - * This function resets the MPA Tx and Rx buffers. - */ -static void mwifiex_cleanup_mpa_buf(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - MP_TX_AGGR_BUF_RESET(card); - MP_RX_AGGR_BUF_RESET(card); -} - -/* - * This function cleans up the allocated card buffers. - * - * The following are freed by this function - - * - MP registers - * - MPA Tx buffer - * - MPA Rx buffer - */ -static void mwifiex_cleanup_sdio(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - kfree(card->mp_regs); - kfree(card->mpa_rx.skb_arr); - kfree(card->mpa_rx.len_arr); - kfree(card->mpa_tx.buf); - kfree(card->mpa_rx.buf); - sdio_set_drvdata(card->func, NULL); - kfree(card); -} - -/* - * This function updates the MP end port in card. - */ -static void -mwifiex_update_mp_end_port(struct mwifiex_adapter *adapter, u16 port) -{ - struct sdio_mmc_card *card = adapter->card; - const struct mwifiex_sdio_card_reg *reg = card->reg; - int i; - - card->mp_end_port = port; - - card->mp_data_port_mask = reg->data_port_mask; - - if (reg->start_wr_port) { - for (i = 1; i <= card->max_ports - card->mp_end_port; i++) - card->mp_data_port_mask &= - ~(1 << (card->max_ports - i)); - } - - card->curr_wr_port = reg->start_wr_port; - - mwifiex_dbg(adapter, CMD, - "cmd: mp_end_port %d, data port mask 0x%x\n", - port, card->mp_data_port_mask); -} - -static void mwifiex_recreate_adapter(struct sdio_mmc_card *card) -{ - struct sdio_func *func = card->func; - const struct sdio_device_id *device_id = card->device_id; - - /* TODO mmc_hw_reset does not require destroying and re-probing the - * whole adapter. Hence there was no need to for this rube-goldberg - * design to reload the fw from an external workqueue. If we don't - * destroy the adapter we could reload the fw from - * mwifiex_main_work_queue directly. - * The real difficulty with fw reset is to restore all the user - * settings applied through ioctl. By destroying and recreating the - * adapter, we take the easy way out, since we rely on user space to - * restore them. We assume that user space will treat the new - * incarnation of the adapter(interfaces) as if they had been just - * discovered and initializes them from scratch. - */ - - mwifiex_sdio_remove(func); - - /* power cycle the adapter */ - sdio_claim_host(func); - mmc_hw_reset(func->card->host); - sdio_release_host(func); - - mwifiex_sdio_probe(func, device_id); -} - -static struct mwifiex_adapter *save_adapter; -static void mwifiex_sdio_card_reset_work(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - /* TODO card pointer is unprotected. If the adapter is removed - * physically, sdio core might trigger mwifiex_sdio_remove, before this - * workqueue is run, which will destroy the adapter struct. When this - * workqueue eventually exceutes it will dereference an invalid adapter - * pointer - */ - mwifiex_recreate_adapter(card); -} - -/* This function read/write firmware */ -static enum -rdwr_status mwifiex_sdio_rdwr_firmware(struct mwifiex_adapter *adapter, - u8 doneflag) -{ - struct sdio_mmc_card *card = adapter->card; - int ret, tries; - u8 ctrl_data = 0; - - sdio_writeb(card->func, card->reg->fw_dump_host_ready, - card->reg->fw_dump_ctrl, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, "SDIO Write ERR\n"); - return RDWR_STATUS_FAILURE; - } - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - ctrl_data = sdio_readb(card->func, card->reg->fw_dump_ctrl, - &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, "SDIO read err\n"); - return RDWR_STATUS_FAILURE; - } - if (ctrl_data == FW_DUMP_DONE) - break; - if (doneflag && ctrl_data == doneflag) - return RDWR_STATUS_DONE; - if (ctrl_data != card->reg->fw_dump_host_ready) { - mwifiex_dbg(adapter, WARN, - "The ctrl reg was changed, re-try again\n"); - sdio_writeb(card->func, card->reg->fw_dump_host_ready, - card->reg->fw_dump_ctrl, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, "SDIO write err\n"); - return RDWR_STATUS_FAILURE; - } - } - usleep_range(100, 200); - } - if (ctrl_data == card->reg->fw_dump_host_ready) { - mwifiex_dbg(adapter, ERROR, - "Fail to pull ctrl_data\n"); - return RDWR_STATUS_FAILURE; - } - - return RDWR_STATUS_SUCCESS; -} - -/* This function dump firmware memory to file */ -static void mwifiex_sdio_fw_dump(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - int ret = 0; - unsigned int reg, reg_start, reg_end; - u8 *dbg_ptr, *end_ptr, dump_num, idx, i, read_reg, doneflag = 0; - enum rdwr_status stat; - u32 memory_size; - - if (!card->can_dump_fw) - return; - - for (idx = 0; idx < ARRAY_SIZE(mem_type_mapping_tbl); idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; - - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - } - - mwifiex_pm_wakeup_card(adapter); - sdio_claim_host(card->func); - - mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n"); - - stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - goto done; - - reg = card->reg->fw_dump_start; - /* Read the number of the memories which will dump */ - dump_num = sdio_readb(card->func, reg, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, "SDIO read memory length err\n"); - goto done; - } - - /* Read the length of every memory which will dump */ - for (idx = 0; idx < dump_num; idx++) { - struct memory_type_mapping *entry = &mem_type_mapping_tbl[idx]; - - stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - goto done; - - memory_size = 0; - reg = card->reg->fw_dump_start; - for (i = 0; i < 4; i++) { - read_reg = sdio_readb(card->func, reg, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, "SDIO read err\n"); - goto done; - } - memory_size |= (read_reg << i*8); - reg++; - } - - if (memory_size == 0) { - mwifiex_dbg(adapter, DUMP, "Firmware dump Finished!\n"); - ret = mwifiex_write_reg(adapter, - card->reg->fw_dump_ctrl, - FW_DUMP_READ_DONE); - if (ret) { - mwifiex_dbg(adapter, ERROR, "SDIO write err\n"); - return; - } - break; - } - - mwifiex_dbg(adapter, DUMP, - "%s_SIZE=0x%x\n", entry->mem_name, memory_size); - entry->mem_ptr = vmalloc(memory_size + 1); - entry->mem_size = memory_size; - if (!entry->mem_ptr) { - mwifiex_dbg(adapter, ERROR, "Vmalloc %s failed\n", - entry->mem_name); - goto done; - } - dbg_ptr = entry->mem_ptr; - end_ptr = dbg_ptr + memory_size; - - doneflag = entry->done_flag; - mwifiex_dbg(adapter, DUMP, - "Start %s output, please wait...\n", - entry->mem_name); - - do { - stat = mwifiex_sdio_rdwr_firmware(adapter, doneflag); - if (stat == RDWR_STATUS_FAILURE) - goto done; - - reg_start = card->reg->fw_dump_start; - reg_end = card->reg->fw_dump_end; - for (reg = reg_start; reg <= reg_end; reg++) { - *dbg_ptr = sdio_readb(card->func, reg, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "SDIO read err\n"); - goto done; - } - if (dbg_ptr < end_ptr) - dbg_ptr++; - else - mwifiex_dbg(adapter, ERROR, - "Allocated buf not enough\n"); - } - - if (stat != RDWR_STATUS_DONE) - continue; - - mwifiex_dbg(adapter, DUMP, "%s done: size=0x%tx\n", - entry->mem_name, dbg_ptr - entry->mem_ptr); - break; - } while (1); - } - mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n"); - -done: - sdio_release_host(card->func); -} - -static void mwifiex_sdio_generic_fw_dump(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - struct memory_type_mapping *entry = &generic_mem_type_map[0]; - unsigned int reg, reg_start, reg_end; - u8 start_flag = 0, done_flag = 0; - u8 *dbg_ptr, *end_ptr; - enum rdwr_status stat; - int ret = -1, tries; - - if (!card->fw_dump_enh) - return; - - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - - mwifiex_pm_wakeup_card(adapter); - sdio_claim_host(card->func); - - mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump start ==\n"); - - stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag); - if (stat == RDWR_STATUS_FAILURE) - goto done; - - reg_start = card->reg->fw_dump_start; - reg_end = card->reg->fw_dump_end; - for (reg = reg_start; reg <= reg_end; reg++) { - for (tries = 0; tries < MAX_POLL_TRIES; tries++) { - start_flag = sdio_readb(card->func, reg, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "SDIO read err\n"); - goto done; - } - if (start_flag == 0) - break; - if (tries == MAX_POLL_TRIES) { - mwifiex_dbg(adapter, ERROR, - "FW not ready to dump\n"); - ret = -1; - goto done; - } - } - usleep_range(100, 200); - } - - entry->mem_ptr = vmalloc(0xf0000 + 1); - if (!entry->mem_ptr) { - ret = -1; - goto done; - } - dbg_ptr = entry->mem_ptr; - entry->mem_size = 0xf0000; - end_ptr = dbg_ptr + entry->mem_size; - - done_flag = entry->done_flag; - mwifiex_dbg(adapter, DUMP, - "Start %s output, please wait...\n", entry->mem_name); - - while (true) { - stat = mwifiex_sdio_rdwr_firmware(adapter, done_flag); - if (stat == RDWR_STATUS_FAILURE) - goto done; - for (reg = reg_start; reg <= reg_end; reg++) { - *dbg_ptr = sdio_readb(card->func, reg, &ret); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "SDIO read err\n"); - goto done; - } - dbg_ptr++; - if (dbg_ptr >= end_ptr) { - u8 *tmp_ptr; - - tmp_ptr = vmalloc(entry->mem_size + 0x4000 + 1); - if (!tmp_ptr) - goto done; - - memcpy(tmp_ptr, entry->mem_ptr, - entry->mem_size); - vfree(entry->mem_ptr); - entry->mem_ptr = tmp_ptr; - tmp_ptr = NULL; - dbg_ptr = entry->mem_ptr + entry->mem_size; - entry->mem_size += 0x4000; - end_ptr = entry->mem_ptr + entry->mem_size; - } - } - if (stat == RDWR_STATUS_DONE) { - entry->mem_size = dbg_ptr - entry->mem_ptr; - mwifiex_dbg(adapter, DUMP, "dump %s done size=0x%x\n", - entry->mem_name, entry->mem_size); - ret = 0; - break; - } - } - mwifiex_dbg(adapter, MSG, "== mwifiex firmware dump end ==\n"); - -done: - if (ret) { - mwifiex_dbg(adapter, ERROR, "firmware dump failed\n"); - if (entry->mem_ptr) { - vfree(entry->mem_ptr); - entry->mem_ptr = NULL; - } - entry->mem_size = 0; - } - sdio_release_host(card->func); -} - -static void mwifiex_sdio_device_dump_work(struct mwifiex_adapter *adapter) -{ - struct sdio_mmc_card *card = adapter->card; - - mwifiex_drv_info_dump(adapter); - if (card->fw_dump_enh) - mwifiex_sdio_generic_fw_dump(adapter); - else - mwifiex_sdio_fw_dump(adapter); - mwifiex_upload_device_dump(adapter); -} - -static void mwifiex_sdio_work(struct work_struct *work) -{ - if (test_and_clear_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, - &iface_work_flags)) - mwifiex_sdio_device_dump_work(save_adapter); - if (test_and_clear_bit(MWIFIEX_IFACE_WORK_CARD_RESET, - &iface_work_flags)) - mwifiex_sdio_card_reset_work(save_adapter); -} - -static DECLARE_WORK(sdio_work, mwifiex_sdio_work); -/* This function resets the card */ -static void mwifiex_sdio_card_reset(struct mwifiex_adapter *adapter) -{ - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags)) - return; - - set_bit(MWIFIEX_IFACE_WORK_CARD_RESET, &iface_work_flags); - - schedule_work(&sdio_work); -} - -/* This function dumps FW information */ -static void mwifiex_sdio_device_dump(struct mwifiex_adapter *adapter) -{ - save_adapter = adapter; - if (test_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags)) - return; - - set_bit(MWIFIEX_IFACE_WORK_DEVICE_DUMP, &iface_work_flags); - schedule_work(&sdio_work); -} - -/* Function to dump SDIO function registers and SDIO scratch registers in case - * of FW crash - */ -static int -mwifiex_sdio_reg_dump(struct mwifiex_adapter *adapter, char *drv_buf) -{ - char *p = drv_buf; - struct sdio_mmc_card *cardp = adapter->card; - int ret = 0; - u8 count, func, data, index = 0, size = 0; - u8 reg, reg_start, reg_end; - char buf[256], *ptr; - - if (!p) - return 0; - - mwifiex_dbg(adapter, MSG, "SDIO register dump start\n"); - - mwifiex_pm_wakeup_card(adapter); - - sdio_claim_host(cardp->func); - - for (count = 0; count < 5; count++) { - memset(buf, 0, sizeof(buf)); - ptr = buf; - - switch (count) { - case 0: - /* Read the registers of SDIO function0 */ - func = count; - reg_start = 0; - reg_end = 9; - break; - case 1: - /* Read the registers of SDIO function1 */ - func = count; - reg_start = cardp->reg->func1_dump_reg_start; - reg_end = cardp->reg->func1_dump_reg_end; - break; - case 2: - index = 0; - func = 1; - reg_start = cardp->reg->func1_spec_reg_table[index++]; - size = cardp->reg->func1_spec_reg_num; - reg_end = cardp->reg->func1_spec_reg_table[size-1]; - break; - default: - /* Read the scratch registers of SDIO function1 */ - if (count == 4) - mdelay(100); - func = 1; - reg_start = cardp->reg->func1_scratch_reg; - reg_end = reg_start + MWIFIEX_SDIO_SCRATCH_SIZE; - } - - if (count != 2) - ptr += sprintf(ptr, "SDIO Func%d (%#x-%#x): ", - func, reg_start, reg_end); - else - ptr += sprintf(ptr, "SDIO Func%d: ", func); - - for (reg = reg_start; reg <= reg_end;) { - if (func == 0) - data = sdio_f0_readb(cardp->func, reg, &ret); - else - data = sdio_readb(cardp->func, reg, &ret); - - if (count == 2) - ptr += sprintf(ptr, "(%#x) ", reg); - if (!ret) { - ptr += sprintf(ptr, "%02x ", data); - } else { - ptr += sprintf(ptr, "ERR"); - break; - } - - if (count == 2 && reg < reg_end) - reg = cardp->reg->func1_spec_reg_table[index++]; - else - reg++; - } - - mwifiex_dbg(adapter, MSG, "%s\n", buf); - p += sprintf(p, "%s\n", buf); - } - - sdio_release_host(cardp->func); - - mwifiex_dbg(adapter, MSG, "SDIO register dump end\n"); - - return p - drv_buf; -} - -static struct mwifiex_if_ops sdio_ops = { - .init_if = mwifiex_init_sdio, - .cleanup_if = mwifiex_cleanup_sdio, - .check_fw_status = mwifiex_check_fw_status, - .prog_fw = mwifiex_prog_fw_w_helper, - .register_dev = mwifiex_register_dev, - .unregister_dev = mwifiex_unregister_dev, - .enable_int = mwifiex_sdio_enable_host_int, - .disable_int = mwifiex_sdio_disable_host_int, - .process_int_status = mwifiex_process_int_status, - .host_to_card = mwifiex_sdio_host_to_card, - .wakeup = mwifiex_pm_wakeup_card, - .wakeup_complete = mwifiex_pm_wakeup_card_complete, - - /* SDIO specific */ - .update_mp_end_port = mwifiex_update_mp_end_port, - .cleanup_mpa_buf = mwifiex_cleanup_mpa_buf, - .cmdrsp_complete = mwifiex_sdio_cmdrsp_complete, - .event_complete = mwifiex_sdio_event_complete, - .card_reset = mwifiex_sdio_card_reset, - .reg_dump = mwifiex_sdio_reg_dump, - .device_dump = mwifiex_sdio_device_dump, - .deaggr_pkt = mwifiex_deaggr_sdio_pkt, -}; - -/* - * This function initializes the SDIO driver. - * - * This initiates the semaphore and registers the device with - * SDIO bus. - */ -static int -mwifiex_sdio_init_module(void) -{ - sema_init(&add_remove_card_sem, 1); - - /* Clear the flag in case user removes the card. */ - user_rmmod = 0; - - return sdio_register_driver(&mwifiex_sdio); -} - -/* - * This function cleans up the SDIO driver. - * - * The following major steps are followed for cleanup - - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from SDIO bus. - */ -static void -mwifiex_sdio_cleanup_module(void) -{ - if (!down_interruptible(&add_remove_card_sem)) - up(&add_remove_card_sem); - - /* Set the flag as user is removing this module. */ - user_rmmod = 1; - cancel_work_sync(&sdio_work); - - sdio_unregister_driver(&mwifiex_sdio); -} - -module_init(mwifiex_sdio_init_module); -module_exit(mwifiex_sdio_cleanup_module); - -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_DESCRIPTION("Marvell WiFi-Ex SDIO Driver version " SDIO_VERSION); -MODULE_VERSION(SDIO_VERSION); -MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE(SD8786_DEFAULT_FW_NAME); -MODULE_FIRMWARE(SD8787_DEFAULT_FW_NAME); -MODULE_FIRMWARE(SD8797_DEFAULT_FW_NAME); -MODULE_FIRMWARE(SD8897_DEFAULT_FW_NAME); -MODULE_FIRMWARE(SD8887_DEFAULT_FW_NAME); -MODULE_FIRMWARE(SD8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/sdio.h b/drivers/net/wireless/mwifiex/sdio.h deleted file mode 100644 index b9fbc5cf6262..000000000000 --- a/drivers/net/wireless/mwifiex/sdio.h +++ /dev/null @@ -1,672 +0,0 @@ -/* - * Marvell Wireless LAN device driver: SDIO specific definitions - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_SDIO_H -#define _MWIFIEX_SDIO_H - - -#include <linux/mmc/sdio.h> -#include <linux/mmc/sdio_ids.h> -#include <linux/mmc/sdio_func.h> -#include <linux/mmc/card.h> -#include <linux/mmc/host.h> - -#include "main.h" - -#define SD8786_DEFAULT_FW_NAME "mrvl/sd8786_uapsta.bin" -#define SD8787_DEFAULT_FW_NAME "mrvl/sd8787_uapsta.bin" -#define SD8797_DEFAULT_FW_NAME "mrvl/sd8797_uapsta.bin" -#define SD8897_DEFAULT_FW_NAME "mrvl/sd8897_uapsta.bin" -#define SD8887_DEFAULT_FW_NAME "mrvl/sd8887_uapsta.bin" -#define SD8801_DEFAULT_FW_NAME "mrvl/sd8801_uapsta.bin" -#define SD8997_DEFAULT_FW_NAME "mrvl/sd8997_uapsta.bin" - -#define BLOCK_MODE 1 -#define BYTE_MODE 0 - -#define REG_PORT 0 - -#define MWIFIEX_SDIO_IO_PORT_MASK 0xfffff - -#define MWIFIEX_SDIO_BYTE_MODE_MASK 0x80000000 - -#define MWIFIEX_MAX_FUNC2_REG_NUM 13 -#define MWIFIEX_SDIO_SCRATCH_SIZE 10 - -#define SDIO_MPA_ADDR_BASE 0x1000 -#define CTRL_PORT 0 -#define CTRL_PORT_MASK 0x0001 - -#define CMD_PORT_UPLD_INT_MASK (0x1U<<6) -#define CMD_PORT_DNLD_INT_MASK (0x1U<<7) -#define HOST_TERM_CMD53 (0x1U << 2) -#define REG_PORT 0 -#define MEM_PORT 0x10000 - -#define CMD53_NEW_MODE (0x1U << 0) -#define CMD_PORT_RD_LEN_EN (0x1U << 2) -#define CMD_PORT_AUTO_EN (0x1U << 0) -#define CMD_PORT_SLCT 0x8000 -#define UP_LD_CMD_PORT_HOST_INT_STATUS (0x40U) -#define DN_LD_CMD_PORT_HOST_INT_STATUS (0x80U) - -#define MWIFIEX_MP_AGGR_BUF_SIZE_16K (16384) -#define MWIFIEX_MP_AGGR_BUF_SIZE_32K (32768) -/* we leave one block of 256 bytes for DMA alignment*/ -#define MWIFIEX_MP_AGGR_BUF_SIZE_MAX (65280) - -/* Misc. Config Register : Auto Re-enable interrupts */ -#define AUTO_RE_ENABLE_INT BIT(4) - -/* Host Control Registers : Configuration */ -#define CONFIGURATION_REG 0x00 -/* Host Control Registers : Host power up */ -#define HOST_POWER_UP (0x1U << 1) - -/* Host Control Registers : Upload host interrupt mask */ -#define UP_LD_HOST_INT_MASK (0x1U) -/* Host Control Registers : Download host interrupt mask */ -#define DN_LD_HOST_INT_MASK (0x2U) - -/* Host Control Registers : Upload host interrupt status */ -#define UP_LD_HOST_INT_STATUS (0x1U) -/* Host Control Registers : Download host interrupt status */ -#define DN_LD_HOST_INT_STATUS (0x2U) - -/* Host Control Registers : Host interrupt status */ -#define CARD_INT_STATUS_REG 0x28 - -/* Card Control Registers : Card I/O ready */ -#define CARD_IO_READY (0x1U << 3) -/* Card Control Registers : Download card ready */ -#define DN_LD_CARD_RDY (0x1U << 0) - -/* Max retry number of CMD53 write */ -#define MAX_WRITE_IOMEM_RETRY 2 - -/* SDIO Tx aggregation in progress ? */ -#define MP_TX_AGGR_IN_PROGRESS(a) (a->mpa_tx.pkt_cnt > 0) - -/* SDIO Tx aggregation buffer room for next packet ? */ -#define MP_TX_AGGR_BUF_HAS_ROOM(a, len) ((a->mpa_tx.buf_len+len) \ - <= a->mpa_tx.buf_size) - -/* Copy current packet (SDIO Tx aggregation buffer) to SDIO buffer */ -#define MP_TX_AGGR_BUF_PUT(a, payload, pkt_len, port) do { \ - memmove(&a->mpa_tx.buf[a->mpa_tx.buf_len], \ - payload, pkt_len); \ - a->mpa_tx.buf_len += pkt_len; \ - if (!a->mpa_tx.pkt_cnt) \ - a->mpa_tx.start_port = port; \ - if (a->mpa_tx.start_port <= port) \ - a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt)); \ - else \ - a->mpa_tx.ports |= (1<<(a->mpa_tx.pkt_cnt+1+ \ - (a->max_ports - \ - a->mp_end_port))); \ - a->mpa_tx.pkt_cnt++; \ -} while (0) - -/* SDIO Tx aggregation limit ? */ -#define MP_TX_AGGR_PKT_LIMIT_REACHED(a) \ - (a->mpa_tx.pkt_cnt == a->mpa_tx.pkt_aggr_limit) - -/* Reset SDIO Tx aggregation buffer parameters */ -#define MP_TX_AGGR_BUF_RESET(a) do { \ - a->mpa_tx.pkt_cnt = 0; \ - a->mpa_tx.buf_len = 0; \ - a->mpa_tx.ports = 0; \ - a->mpa_tx.start_port = 0; \ -} while (0) - -/* SDIO Rx aggregation limit ? */ -#define MP_RX_AGGR_PKT_LIMIT_REACHED(a) \ - (a->mpa_rx.pkt_cnt == a->mpa_rx.pkt_aggr_limit) - -/* SDIO Rx aggregation in progress ? */ -#define MP_RX_AGGR_IN_PROGRESS(a) (a->mpa_rx.pkt_cnt > 0) - -/* SDIO Rx aggregation buffer room for next packet ? */ -#define MP_RX_AGGR_BUF_HAS_ROOM(a, rx_len) \ - ((a->mpa_rx.buf_len+rx_len) <= a->mpa_rx.buf_size) - -/* Reset SDIO Rx aggregation buffer parameters */ -#define MP_RX_AGGR_BUF_RESET(a) do { \ - a->mpa_rx.pkt_cnt = 0; \ - a->mpa_rx.buf_len = 0; \ - a->mpa_rx.ports = 0; \ - a->mpa_rx.start_port = 0; \ -} while (0) - -/* data structure for SDIO MPA TX */ -struct mwifiex_sdio_mpa_tx { - /* multiport tx aggregation buffer pointer */ - u8 *buf; - u32 buf_len; - u32 pkt_cnt; - u32 ports; - u16 start_port; - u8 enabled; - u32 buf_size; - u32 pkt_aggr_limit; -}; - -struct mwifiex_sdio_mpa_rx { - u8 *buf; - u32 buf_len; - u32 pkt_cnt; - u32 ports; - u16 start_port; - - struct sk_buff **skb_arr; - u32 *len_arr; - - u8 enabled; - u32 buf_size; - u32 pkt_aggr_limit; -}; - -int mwifiex_bus_register(void); -void mwifiex_bus_unregister(void); - -struct mwifiex_sdio_card_reg { - u8 start_rd_port; - u8 start_wr_port; - u8 base_0_reg; - u8 base_1_reg; - u8 poll_reg; - u8 host_int_enable; - u8 host_int_rsr_reg; - u8 host_int_status_reg; - u8 host_int_mask_reg; - u8 status_reg_0; - u8 status_reg_1; - u8 sdio_int_mask; - u32 data_port_mask; - u8 io_port_0_reg; - u8 io_port_1_reg; - u8 io_port_2_reg; - u8 max_mp_regs; - u8 rd_bitmap_l; - u8 rd_bitmap_u; - u8 rd_bitmap_1l; - u8 rd_bitmap_1u; - u8 wr_bitmap_l; - u8 wr_bitmap_u; - u8 wr_bitmap_1l; - u8 wr_bitmap_1u; - u8 rd_len_p0_l; - u8 rd_len_p0_u; - u8 card_misc_cfg_reg; - u8 card_cfg_2_1_reg; - u8 cmd_rd_len_0; - u8 cmd_rd_len_1; - u8 cmd_rd_len_2; - u8 cmd_rd_len_3; - u8 cmd_cfg_0; - u8 cmd_cfg_1; - u8 cmd_cfg_2; - u8 cmd_cfg_3; - u8 fw_dump_host_ready; - u8 fw_dump_ctrl; - u8 fw_dump_start; - u8 fw_dump_end; - u8 func1_dump_reg_start; - u8 func1_dump_reg_end; - u8 func1_scratch_reg; - u8 func1_spec_reg_num; - u8 func1_spec_reg_table[MWIFIEX_MAX_FUNC2_REG_NUM]; -}; - -struct sdio_mmc_card { - struct sdio_func *func; - struct mwifiex_adapter *adapter; - - const char *firmware; - const struct mwifiex_sdio_card_reg *reg; - u8 max_ports; - u8 mp_agg_pkt_limit; - u16 tx_buf_size; - u32 mp_tx_agg_buf_size; - u32 mp_rx_agg_buf_size; - - u32 mp_rd_bitmap; - u32 mp_wr_bitmap; - - u16 mp_end_port; - u32 mp_data_port_mask; - - u8 curr_rd_port; - u8 curr_wr_port; - - u8 *mp_regs; - bool supports_sdio_new_mode; - bool has_control_mask; - bool can_dump_fw; - bool fw_dump_enh; - bool can_auto_tdls; - bool can_ext_scan; - - struct mwifiex_sdio_mpa_tx mpa_tx; - struct mwifiex_sdio_mpa_rx mpa_rx; - - /* needed for card reset */ - const struct sdio_device_id *device_id; -}; - -struct mwifiex_sdio_device { - const char *firmware; - const struct mwifiex_sdio_card_reg *reg; - u8 max_ports; - u8 mp_agg_pkt_limit; - u16 tx_buf_size; - u32 mp_tx_agg_buf_size; - u32 mp_rx_agg_buf_size; - bool supports_sdio_new_mode; - bool has_control_mask; - bool can_dump_fw; - bool fw_dump_enh; - bool can_auto_tdls; - bool can_ext_scan; -}; - -static const struct mwifiex_sdio_card_reg mwifiex_reg_sd87xx = { - .start_rd_port = 1, - .start_wr_port = 1, - .base_0_reg = 0x0040, - .base_1_reg = 0x0041, - .poll_reg = 0x30, - .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK, - .host_int_rsr_reg = 0x1, - .host_int_mask_reg = 0x02, - .host_int_status_reg = 0x03, - .status_reg_0 = 0x60, - .status_reg_1 = 0x61, - .sdio_int_mask = 0x3f, - .data_port_mask = 0x0000fffe, - .io_port_0_reg = 0x78, - .io_port_1_reg = 0x79, - .io_port_2_reg = 0x7A, - .max_mp_regs = 64, - .rd_bitmap_l = 0x04, - .rd_bitmap_u = 0x05, - .wr_bitmap_l = 0x06, - .wr_bitmap_u = 0x07, - .rd_len_p0_l = 0x08, - .rd_len_p0_u = 0x09, - .card_misc_cfg_reg = 0x6c, - .func1_dump_reg_start = 0x0, - .func1_dump_reg_end = 0x9, - .func1_scratch_reg = 0x60, - .func1_spec_reg_num = 5, - .func1_spec_reg_table = {0x28, 0x30, 0x34, 0x38, 0x3c}, -}; - -static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8897 = { - .start_rd_port = 0, - .start_wr_port = 0, - .base_0_reg = 0x60, - .base_1_reg = 0x61, - .poll_reg = 0x50, - .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | - CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, - .host_int_rsr_reg = 0x1, - .host_int_status_reg = 0x03, - .host_int_mask_reg = 0x02, - .status_reg_0 = 0xc0, - .status_reg_1 = 0xc1, - .sdio_int_mask = 0xff, - .data_port_mask = 0xffffffff, - .io_port_0_reg = 0xD8, - .io_port_1_reg = 0xD9, - .io_port_2_reg = 0xDA, - .max_mp_regs = 184, - .rd_bitmap_l = 0x04, - .rd_bitmap_u = 0x05, - .rd_bitmap_1l = 0x06, - .rd_bitmap_1u = 0x07, - .wr_bitmap_l = 0x08, - .wr_bitmap_u = 0x09, - .wr_bitmap_1l = 0x0a, - .wr_bitmap_1u = 0x0b, - .rd_len_p0_l = 0x0c, - .rd_len_p0_u = 0x0d, - .card_misc_cfg_reg = 0xcc, - .card_cfg_2_1_reg = 0xcd, - .cmd_rd_len_0 = 0xb4, - .cmd_rd_len_1 = 0xb5, - .cmd_rd_len_2 = 0xb6, - .cmd_rd_len_3 = 0xb7, - .cmd_cfg_0 = 0xb8, - .cmd_cfg_1 = 0xb9, - .cmd_cfg_2 = 0xba, - .cmd_cfg_3 = 0xbb, - .fw_dump_host_ready = 0xee, - .fw_dump_ctrl = 0xe2, - .fw_dump_start = 0xe3, - .fw_dump_end = 0xea, - .func1_dump_reg_start = 0x0, - .func1_dump_reg_end = 0xb, - .func1_scratch_reg = 0xc0, - .func1_spec_reg_num = 8, - .func1_spec_reg_table = {0x4C, 0x50, 0x54, 0x55, 0x58, - 0x59, 0x5c, 0x5d}, -}; - -static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8997 = { - .start_rd_port = 0, - .start_wr_port = 0, - .base_0_reg = 0xF8, - .base_1_reg = 0xF9, - .poll_reg = 0x5C, - .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | - CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, - .host_int_rsr_reg = 0x4, - .host_int_status_reg = 0x0C, - .host_int_mask_reg = 0x08, - .status_reg_0 = 0xE8, - .status_reg_1 = 0xE9, - .sdio_int_mask = 0xff, - .data_port_mask = 0xffffffff, - .io_port_0_reg = 0xE4, - .io_port_1_reg = 0xE5, - .io_port_2_reg = 0xE6, - .max_mp_regs = 196, - .rd_bitmap_l = 0x10, - .rd_bitmap_u = 0x11, - .rd_bitmap_1l = 0x12, - .rd_bitmap_1u = 0x13, - .wr_bitmap_l = 0x14, - .wr_bitmap_u = 0x15, - .wr_bitmap_1l = 0x16, - .wr_bitmap_1u = 0x17, - .rd_len_p0_l = 0x18, - .rd_len_p0_u = 0x19, - .card_misc_cfg_reg = 0xd8, - .card_cfg_2_1_reg = 0xd9, - .cmd_rd_len_0 = 0xc0, - .cmd_rd_len_1 = 0xc1, - .cmd_rd_len_2 = 0xc2, - .cmd_rd_len_3 = 0xc3, - .cmd_cfg_0 = 0xc4, - .cmd_cfg_1 = 0xc5, - .cmd_cfg_2 = 0xc6, - .cmd_cfg_3 = 0xc7, - .fw_dump_host_ready = 0xcc, - .fw_dump_ctrl = 0xf0, - .fw_dump_start = 0xf1, - .fw_dump_end = 0xf8, - .func1_dump_reg_start = 0x10, - .func1_dump_reg_end = 0x17, - .func1_scratch_reg = 0xe8, - .func1_spec_reg_num = 13, - .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D, - 0x60, 0x61, 0x62, 0x64, - 0x65, 0x66, 0x68, 0x69, - 0x6a}, -}; - -static const struct mwifiex_sdio_card_reg mwifiex_reg_sd8887 = { - .start_rd_port = 0, - .start_wr_port = 0, - .base_0_reg = 0x6C, - .base_1_reg = 0x6D, - .poll_reg = 0x5C, - .host_int_enable = UP_LD_HOST_INT_MASK | DN_LD_HOST_INT_MASK | - CMD_PORT_UPLD_INT_MASK | CMD_PORT_DNLD_INT_MASK, - .host_int_rsr_reg = 0x4, - .host_int_status_reg = 0x0C, - .host_int_mask_reg = 0x08, - .status_reg_0 = 0x90, - .status_reg_1 = 0x91, - .sdio_int_mask = 0xff, - .data_port_mask = 0xffffffff, - .io_port_0_reg = 0xE4, - .io_port_1_reg = 0xE5, - .io_port_2_reg = 0xE6, - .max_mp_regs = 196, - .rd_bitmap_l = 0x10, - .rd_bitmap_u = 0x11, - .rd_bitmap_1l = 0x12, - .rd_bitmap_1u = 0x13, - .wr_bitmap_l = 0x14, - .wr_bitmap_u = 0x15, - .wr_bitmap_1l = 0x16, - .wr_bitmap_1u = 0x17, - .rd_len_p0_l = 0x18, - .rd_len_p0_u = 0x19, - .card_misc_cfg_reg = 0xd8, - .card_cfg_2_1_reg = 0xd9, - .cmd_rd_len_0 = 0xc0, - .cmd_rd_len_1 = 0xc1, - .cmd_rd_len_2 = 0xc2, - .cmd_rd_len_3 = 0xc3, - .cmd_cfg_0 = 0xc4, - .cmd_cfg_1 = 0xc5, - .cmd_cfg_2 = 0xc6, - .cmd_cfg_3 = 0xc7, - .func1_dump_reg_start = 0x10, - .func1_dump_reg_end = 0x17, - .func1_scratch_reg = 0x90, - .func1_spec_reg_num = 13, - .func1_spec_reg_table = {0x08, 0x58, 0x5C, 0x5D, 0x60, - 0x61, 0x62, 0x64, 0x65, 0x66, - 0x68, 0x69, 0x6a}, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8786 = { - .firmware = SD8786_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd87xx, - .max_ports = 16, - .mp_agg_pkt_limit = 8, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .supports_sdio_new_mode = false, - .has_control_mask = true, - .can_dump_fw = false, - .can_auto_tdls = false, - .can_ext_scan = false, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8787 = { - .firmware = SD8787_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd87xx, - .max_ports = 16, - .mp_agg_pkt_limit = 8, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .supports_sdio_new_mode = false, - .has_control_mask = true, - .can_dump_fw = false, - .can_auto_tdls = false, - .can_ext_scan = true, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8797 = { - .firmware = SD8797_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd87xx, - .max_ports = 16, - .mp_agg_pkt_limit = 8, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .supports_sdio_new_mode = false, - .has_control_mask = true, - .can_dump_fw = false, - .can_auto_tdls = false, - .can_ext_scan = true, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8897 = { - .firmware = SD8897_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd8897, - .max_ports = 32, - .mp_agg_pkt_limit = 16, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, - .supports_sdio_new_mode = true, - .has_control_mask = false, - .can_dump_fw = true, - .can_auto_tdls = false, - .can_ext_scan = true, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8997 = { - .firmware = SD8997_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd8997, - .max_ports = 32, - .mp_agg_pkt_limit = 16, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_MAX, - .supports_sdio_new_mode = true, - .has_control_mask = false, - .can_dump_fw = true, - .fw_dump_enh = true, - .can_auto_tdls = false, - .can_ext_scan = true, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8887 = { - .firmware = SD8887_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd8887, - .max_ports = 32, - .mp_agg_pkt_limit = 16, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_32K, - .supports_sdio_new_mode = true, - .has_control_mask = false, - .can_dump_fw = false, - .can_auto_tdls = true, - .can_ext_scan = true, -}; - -static const struct mwifiex_sdio_device mwifiex_sdio_sd8801 = { - .firmware = SD8801_DEFAULT_FW_NAME, - .reg = &mwifiex_reg_sd87xx, - .max_ports = 16, - .mp_agg_pkt_limit = 8, - .supports_sdio_new_mode = false, - .has_control_mask = true, - .tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K, - .mp_tx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .mp_rx_agg_buf_size = MWIFIEX_MP_AGGR_BUF_SIZE_16K, - .can_dump_fw = false, - .can_auto_tdls = false, - .can_ext_scan = true, -}; - -/* - * .cmdrsp_complete handler - */ -static inline int mwifiex_sdio_cmdrsp_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - dev_kfree_skb_any(skb); - return 0; -} - -/* - * .event_complete handler - */ -static inline int mwifiex_sdio_event_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - dev_kfree_skb_any(skb); - return 0; -} - -static inline bool -mp_rx_aggr_port_limit_reached(struct sdio_mmc_card *card) -{ - u8 tmp; - - if (card->curr_rd_port < card->mpa_rx.start_port) { - if (card->supports_sdio_new_mode) - tmp = card->mp_end_port >> 1; - else - tmp = card->mp_agg_pkt_limit; - - if (((card->max_ports - card->mpa_rx.start_port) + - card->curr_rd_port) >= tmp) - return true; - } - - if (!card->supports_sdio_new_mode) - return false; - - if ((card->curr_rd_port - card->mpa_rx.start_port) >= - (card->mp_end_port >> 1)) - return true; - - return false; -} - -static inline bool -mp_tx_aggr_port_limit_reached(struct sdio_mmc_card *card) -{ - u16 tmp; - - if (card->curr_wr_port < card->mpa_tx.start_port) { - if (card->supports_sdio_new_mode) - tmp = card->mp_end_port >> 1; - else - tmp = card->mp_agg_pkt_limit; - - if (((card->max_ports - card->mpa_tx.start_port) + - card->curr_wr_port) >= tmp) - return true; - } - - if (!card->supports_sdio_new_mode) - return false; - - if ((card->curr_wr_port - card->mpa_tx.start_port) >= - (card->mp_end_port >> 1)) - return true; - - return false; -} - -/* Prepare to copy current packet from card to SDIO Rx aggregation buffer */ -static inline void mp_rx_aggr_setup(struct sdio_mmc_card *card, - u16 rx_len, u8 port) -{ - card->mpa_rx.buf_len += rx_len; - - if (!card->mpa_rx.pkt_cnt) - card->mpa_rx.start_port = port; - - if (card->supports_sdio_new_mode) { - card->mpa_rx.ports |= (1 << port); - } else { - if (card->mpa_rx.start_port <= port) - card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt); - else - card->mpa_rx.ports |= 1 << (card->mpa_rx.pkt_cnt + 1); - } - card->mpa_rx.skb_arr[card->mpa_rx.pkt_cnt] = NULL; - card->mpa_rx.len_arr[card->mpa_rx.pkt_cnt] = rx_len; - card->mpa_rx.pkt_cnt++; -} -#endif /* _MWIFIEX_SDIO_H */ diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c deleted file mode 100644 index e486867a4c67..000000000000 --- a/drivers/net/wireless/mwifiex/sta_cmd.c +++ /dev/null @@ -1,2282 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station command handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11ac.h" - -static bool drcs; -module_param(drcs, bool, 0644); -MODULE_PARM_DESC(drcs, "multi-channel operation:1, single-channel operation:0"); - -static bool disable_auto_ds; -module_param(disable_auto_ds, bool, 0); -MODULE_PARM_DESC(disable_auto_ds, - "deepsleep enabled=0(default), deepsleep disabled=1"); -/* - * This function prepares command to set/get RSSI information. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting data/beacon average factors - * - Resetting SNR/NF/RSSI values in private structure - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_rssi_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 cmd_action) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_RSSI_INFO); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_rssi_info) + - S_DS_GEN); - cmd->params.rssi_info.action = cpu_to_le16(cmd_action); - cmd->params.rssi_info.ndata = cpu_to_le16(priv->data_avg_factor); - cmd->params.rssi_info.nbcn = cpu_to_le16(priv->bcn_avg_factor); - - /* Reset SNR/NF/RSSI values in private structure */ - priv->data_rssi_last = 0; - priv->data_nf_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->bcn_rssi_last = 0; - priv->bcn_nf_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - - return 0; -} - -/* - * This function prepares command to set MAC control. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_mac_control(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u16 *action) -{ - struct host_cmd_ds_mac_control *mac_ctrl = &cmd->params.mac_ctrl; - - if (cmd_action != HostCmd_ACT_GEN_SET) { - mwifiex_dbg(priv->adapter, ERROR, - "mac_control: only support set cmd\n"); - return -1; - } - - cmd->command = cpu_to_le16(HostCmd_CMD_MAC_CONTROL); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_ds_mac_control) + S_DS_GEN); - mac_ctrl->action = cpu_to_le16(*action); - - return 0; -} - -/* - * This function prepares command to set/get SNMP MIB. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting SNMP MIB OID number and value - * (as required) - * - Ensuring correct endian-ness - * - * The following SNMP MIB OIDs are supported - - * - FRAG_THRESH_I : Fragmentation threshold - * - RTS_THRESH_I : RTS threshold - * - SHORT_RETRY_LIM_I : Short retry limit - * - DOT11D_I : 11d support - */ -static int mwifiex_cmd_802_11_snmp_mib(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u32 cmd_oid, - u16 *ul_temp) -{ - struct host_cmd_ds_802_11_snmp_mib *snmp_mib = &cmd->params.smib; - - mwifiex_dbg(priv->adapter, CMD, - "cmd: SNMP_CMD: cmd_oid = 0x%x\n", cmd_oid); - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SNMP_MIB); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_snmp_mib) - - 1 + S_DS_GEN); - - snmp_mib->oid = cpu_to_le16((u16)cmd_oid); - if (cmd_action == HostCmd_ACT_GEN_GET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_GET); - snmp_mib->buf_size = cpu_to_le16(MAX_SNMP_BUF_SIZE); - le16_add_cpu(&cmd->size, MAX_SNMP_BUF_SIZE); - } else if (cmd_action == HostCmd_ACT_GEN_SET) { - snmp_mib->query_type = cpu_to_le16(HostCmd_ACT_GEN_SET); - snmp_mib->buf_size = cpu_to_le16(sizeof(u16)); - *((__le16 *) (snmp_mib->value)) = cpu_to_le16(*ul_temp); - le16_add_cpu(&cmd->size, sizeof(u16)); - } - - mwifiex_dbg(priv->adapter, CMD, - "cmd: SNMP_CMD: Action=0x%x, OID=0x%x,\t" - "OIDSize=0x%x, Value=0x%x\n", - cmd_action, cmd_oid, le16_to_cpu(snmp_mib->buf_size), - le16_to_cpu(*(__le16 *)snmp_mib->value)); - return 0; -} - -/* - * This function prepares command to get log. - * - * Preparation includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_get_log(struct host_cmd_ds_command *cmd) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_GET_LOG); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_get_log) + - S_DS_GEN); - return 0; -} - -/* - * This function prepares command to set/get Tx data rate configuration. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting configuration index, rate scope and rate drop pattern - * parameters (as required) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_tx_rate_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u16 *pbitmap_rates) -{ - struct host_cmd_ds_tx_rate_cfg *rate_cfg = &cmd->params.tx_rate_cfg; - struct mwifiex_rate_scope *rate_scope; - struct mwifiex_rate_drop_pattern *rate_drop; - u32 i; - - cmd->command = cpu_to_le16(HostCmd_CMD_TX_RATE_CFG); - - rate_cfg->action = cpu_to_le16(cmd_action); - rate_cfg->cfg_index = 0; - - rate_scope = (struct mwifiex_rate_scope *) ((u8 *) rate_cfg + - sizeof(struct host_cmd_ds_tx_rate_cfg)); - rate_scope->type = cpu_to_le16(TLV_TYPE_RATE_SCOPE); - rate_scope->length = cpu_to_le16 - (sizeof(*rate_scope) - sizeof(struct mwifiex_ie_types_header)); - if (pbitmap_rates != NULL) { - rate_scope->hr_dsss_rate_bitmap = cpu_to_le16(pbitmap_rates[0]); - rate_scope->ofdm_rate_bitmap = cpu_to_le16(pbitmap_rates[1]); - for (i = 0; - i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); - i++) - rate_scope->ht_mcs_rate_bitmap[i] = - cpu_to_le16(pbitmap_rates[2 + i]); - if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { - for (i = 0; - i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); - i++) - rate_scope->vht_mcs_rate_bitmap[i] = - cpu_to_le16(pbitmap_rates[10 + i]); - } - } else { - rate_scope->hr_dsss_rate_bitmap = - cpu_to_le16(priv->bitmap_rates[0]); - rate_scope->ofdm_rate_bitmap = - cpu_to_le16(priv->bitmap_rates[1]); - for (i = 0; - i < sizeof(rate_scope->ht_mcs_rate_bitmap) / sizeof(u16); - i++) - rate_scope->ht_mcs_rate_bitmap[i] = - cpu_to_le16(priv->bitmap_rates[2 + i]); - if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { - for (i = 0; - i < ARRAY_SIZE(rate_scope->vht_mcs_rate_bitmap); - i++) - rate_scope->vht_mcs_rate_bitmap[i] = - cpu_to_le16(priv->bitmap_rates[10 + i]); - } - } - - rate_drop = (struct mwifiex_rate_drop_pattern *) ((u8 *) rate_scope + - sizeof(struct mwifiex_rate_scope)); - rate_drop->type = cpu_to_le16(TLV_TYPE_RATE_DROP_CONTROL); - rate_drop->length = cpu_to_le16(sizeof(rate_drop->rate_drop_mode)); - rate_drop->rate_drop_mode = 0; - - cmd->size = - cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_tx_rate_cfg) + - sizeof(struct mwifiex_rate_scope) + - sizeof(struct mwifiex_rate_drop_pattern)); - - return 0; -} - -/* - * This function prepares command to set/get Tx power configuration. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting Tx power mode, power group TLV - * (as required) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_tx_power_cfg(struct host_cmd_ds_command *cmd, - u16 cmd_action, - struct host_cmd_ds_txpwr_cfg *txp) -{ - struct mwifiex_types_power_group *pg_tlv; - struct host_cmd_ds_txpwr_cfg *cmd_txp_cfg = &cmd->params.txp_cfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_TXPWR_CFG); - cmd->size = - cpu_to_le16(S_DS_GEN + sizeof(struct host_cmd_ds_txpwr_cfg)); - switch (cmd_action) { - case HostCmd_ACT_GEN_SET: - if (txp->mode) { - pg_tlv = (struct mwifiex_types_power_group - *) ((unsigned long) txp + - sizeof(struct host_cmd_ds_txpwr_cfg)); - memmove(cmd_txp_cfg, txp, - sizeof(struct host_cmd_ds_txpwr_cfg) + - sizeof(struct mwifiex_types_power_group) + - le16_to_cpu(pg_tlv->length)); - - pg_tlv = (struct mwifiex_types_power_group *) ((u8 *) - cmd_txp_cfg + - sizeof(struct host_cmd_ds_txpwr_cfg)); - cmd->size = cpu_to_le16(le16_to_cpu(cmd->size) + - sizeof(struct mwifiex_types_power_group) + - le16_to_cpu(pg_tlv->length)); - } else { - memmove(cmd_txp_cfg, txp, sizeof(*txp)); - } - cmd_txp_cfg->action = cpu_to_le16(cmd_action); - break; - case HostCmd_ACT_GEN_GET: - cmd_txp_cfg->action = cpu_to_le16(cmd_action); - break; - } - - return 0; -} - -/* - * This function prepares command to get RF Tx power. - */ -static int mwifiex_cmd_rf_tx_power(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_rf_tx_pwr *txp = &cmd->params.txp; - - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_tx_pwr) - + S_DS_GEN); - cmd->command = cpu_to_le16(HostCmd_CMD_RF_TX_PWR); - txp->action = cpu_to_le16(cmd_action); - - return 0; -} - -/* - * This function prepares command to set rf antenna. - */ -static int mwifiex_cmd_rf_antenna(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, - struct mwifiex_ds_ant_cfg *ant_cfg) -{ - struct host_cmd_ds_rf_ant_mimo *ant_mimo = &cmd->params.ant_mimo; - struct host_cmd_ds_rf_ant_siso *ant_siso = &cmd->params.ant_siso; - - cmd->command = cpu_to_le16(HostCmd_CMD_RF_ANTENNA); - - if (cmd_action != HostCmd_ACT_GEN_SET) - return 0; - - if (priv->adapter->hw_dev_mcs_support == HT_STREAM_2X2) { - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_mimo) + - S_DS_GEN); - ant_mimo->action_tx = cpu_to_le16(HostCmd_ACT_SET_TX); - ant_mimo->tx_ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant); - ant_mimo->action_rx = cpu_to_le16(HostCmd_ACT_SET_RX); - ant_mimo->rx_ant_mode = cpu_to_le16((u16)ant_cfg->rx_ant); - } else { - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_rf_ant_siso) + - S_DS_GEN); - ant_siso->action = cpu_to_le16(HostCmd_ACT_SET_BOTH); - ant_siso->ant_mode = cpu_to_le16((u16)ant_cfg->tx_ant); - } - - return 0; -} - -/* - * This function prepares command to set Host Sleep configuration. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting Host Sleep action, conditions, ARP filters - * (as required) - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_hs_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, - struct mwifiex_hs_config_param *hscfg_param) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_hs_cfg_enh *hs_cfg = &cmd->params.opt_hs_cfg; - bool hs_activate = false; - - if (!hscfg_param) - /* New Activate command */ - hs_activate = true; - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_HS_CFG_ENH); - - if (!hs_activate && - (hscfg_param->conditions != cpu_to_le32(HS_CFG_CANCEL)) && - ((adapter->arp_filter_size > 0) && - (adapter->arp_filter_size <= ARP_FILTER_MAX_BUF_SIZE))) { - mwifiex_dbg(adapter, CMD, - "cmd: Attach %d bytes ArpFilter to HSCfg cmd\n", - adapter->arp_filter_size); - memcpy(((u8 *) hs_cfg) + - sizeof(struct host_cmd_ds_802_11_hs_cfg_enh), - adapter->arp_filter, adapter->arp_filter_size); - cmd->size = cpu_to_le16 - (adapter->arp_filter_size + - sizeof(struct host_cmd_ds_802_11_hs_cfg_enh) - + S_DS_GEN); - } else { - cmd->size = cpu_to_le16(S_DS_GEN + sizeof(struct - host_cmd_ds_802_11_hs_cfg_enh)); - } - if (hs_activate) { - hs_cfg->action = cpu_to_le16(HS_ACTIVATE); - hs_cfg->params.hs_activate.resp_ctrl = cpu_to_le16(RESP_NEEDED); - } else { - hs_cfg->action = cpu_to_le16(HS_CONFIGURE); - hs_cfg->params.hs_config.conditions = hscfg_param->conditions; - hs_cfg->params.hs_config.gpio = hscfg_param->gpio; - hs_cfg->params.hs_config.gap = hscfg_param->gap; - mwifiex_dbg(adapter, CMD, - "cmd: HS_CFG_CMD: condition:0x%x gpio:0x%x gap:0x%x\n", - hs_cfg->params.hs_config.conditions, - hs_cfg->params.hs_config.gpio, - hs_cfg->params.hs_config.gap); - } - - return 0; -} - -/* - * This function prepares command to set/get MAC address. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting MAC address (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_mac_address(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_MAC_ADDRESS); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_mac_address) + - S_DS_GEN); - cmd->result = 0; - - cmd->params.mac_addr.action = cpu_to_le16(cmd_action); - - if (cmd_action == HostCmd_ACT_GEN_SET) - memcpy(cmd->params.mac_addr.mac_addr, priv->curr_addr, - ETH_ALEN); - return 0; -} - -/* - * This function prepares command to set MAC multicast address. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting MAC multicast address - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_mac_multicast_adr(struct host_cmd_ds_command *cmd, - u16 cmd_action, - struct mwifiex_multicast_list *mcast_list) -{ - struct host_cmd_ds_mac_multicast_adr *mcast_addr = &cmd->params.mc_addr; - - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mac_multicast_adr) + - S_DS_GEN); - cmd->command = cpu_to_le16(HostCmd_CMD_MAC_MULTICAST_ADR); - - mcast_addr->action = cpu_to_le16(cmd_action); - mcast_addr->num_of_adrs = - cpu_to_le16((u16) mcast_list->num_multicast_addr); - memcpy(mcast_addr->mac_list, mcast_list->mac_list, - mcast_list->num_multicast_addr * ETH_ALEN); - - return 0; -} - -/* - * This function prepares command to deauthenticate. - * - * Preparation includes - - * - Setting command ID and proper size - * - Setting AP MAC address and reason code - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_deauthenticate(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u8 *mac) -{ - struct host_cmd_ds_802_11_deauthenticate *deauth = &cmd->params.deauth; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_DEAUTHENTICATE); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_deauthenticate) - + S_DS_GEN); - - /* Set AP MAC address */ - memcpy(deauth->mac_addr, mac, ETH_ALEN); - - mwifiex_dbg(priv->adapter, CMD, "cmd: Deauth: %pM\n", deauth->mac_addr); - - deauth->reason_code = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); - - return 0; -} - -/* - * This function prepares command to stop Ad-Hoc network. - * - * Preparation includes - - * - Setting command ID and proper size - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11_ad_hoc_stop(struct host_cmd_ds_command *cmd) -{ - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_AD_HOC_STOP); - cmd->size = cpu_to_le16(S_DS_GEN); - return 0; -} - -/* - * This function sets WEP key(s) to key parameter TLV(s). - * - * Multi-key parameter TLVs are supported, so we can send multiple - * WEP keys in a single buffer. - */ -static int -mwifiex_set_keyparamset_wep(struct mwifiex_private *priv, - struct mwifiex_ie_type_key_param_set *key_param_set, - u16 *key_param_len) -{ - int cur_key_param_len; - u8 i; - - /* Multi-key_param_set TLV is supported */ - for (i = 0; i < NUM_WEP_KEYS; i++) { - if ((priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP40) || - (priv->wep_key[i].key_length == WLAN_KEY_LEN_WEP104)) { - key_param_set->type = - cpu_to_le16(TLV_TYPE_KEY_MATERIAL); -/* Key_param_set WEP fixed length */ -#define KEYPARAMSET_WEP_FIXED_LEN 8 - key_param_set->length = cpu_to_le16((u16) - (priv->wep_key[i]. - key_length + - KEYPARAMSET_WEP_FIXED_LEN)); - key_param_set->key_type_id = - cpu_to_le16(KEY_TYPE_ID_WEP); - key_param_set->key_info = - cpu_to_le16(KEY_ENABLED | KEY_UNICAST | - KEY_MCAST); - key_param_set->key_len = - cpu_to_le16(priv->wep_key[i].key_length); - /* Set WEP key index */ - key_param_set->key[0] = i; - /* Set default Tx key flag */ - if (i == - (priv-> - wep_key_curr_index & HostCmd_WEP_KEY_INDEX_MASK)) - key_param_set->key[1] = 1; - else - key_param_set->key[1] = 0; - memmove(&key_param_set->key[2], - priv->wep_key[i].key_material, - priv->wep_key[i].key_length); - - cur_key_param_len = priv->wep_key[i].key_length + - KEYPARAMSET_WEP_FIXED_LEN + - sizeof(struct mwifiex_ie_types_header); - *key_param_len += (u16) cur_key_param_len; - key_param_set = - (struct mwifiex_ie_type_key_param_set *) - ((u8 *)key_param_set + - cur_key_param_len); - } else if (!priv->wep_key[i].key_length) { - continue; - } else { - mwifiex_dbg(priv->adapter, ERROR, - "key%d Length = %d is incorrect\n", - (i + 1), priv->wep_key[i].key_length); - return -1; - } - } - - return 0; -} - -/* This function populates key material v2 command - * to set network key for AES & CMAC AES. - */ -static int mwifiex_set_aes_key_v2(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_ds_encrypt_key *enc_key, - struct host_cmd_ds_802_11_key_material_v2 *km) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u16 size, len = KEY_PARAMS_FIXED_LEN; - - if (enc_key->is_igtk_key) { - mwifiex_dbg(adapter, INFO, - "%s: Set CMAC AES Key\n", __func__); - if (enc_key->is_rx_seq_valid) - memcpy(km->key_param_set.key_params.cmac_aes.ipn, - enc_key->pn, enc_key->pn_len); - km->key_param_set.key_info &= cpu_to_le16(~KEY_MCAST); - km->key_param_set.key_info |= cpu_to_le16(KEY_IGTK); - km->key_param_set.key_type = KEY_TYPE_ID_AES_CMAC; - km->key_param_set.key_params.cmac_aes.key_len = - cpu_to_le16(enc_key->key_len); - memcpy(km->key_param_set.key_params.cmac_aes.key, - enc_key->key_material, enc_key->key_len); - len += sizeof(struct mwifiex_cmac_aes_param); - } else { - mwifiex_dbg(adapter, INFO, - "%s: Set AES Key\n", __func__); - if (enc_key->is_rx_seq_valid) - memcpy(km->key_param_set.key_params.aes.pn, - enc_key->pn, enc_key->pn_len); - km->key_param_set.key_type = KEY_TYPE_ID_AES; - km->key_param_set.key_params.aes.key_len = - cpu_to_le16(enc_key->key_len); - memcpy(km->key_param_set.key_params.aes.key, - enc_key->key_material, enc_key->key_len); - len += sizeof(struct mwifiex_aes_param); - } - - km->key_param_set.len = cpu_to_le16(len); - size = len + sizeof(struct mwifiex_ie_types_header) + - sizeof(km->action) + S_DS_GEN; - cmd->size = cpu_to_le16(size); - - return 0; -} - -/* This function prepares command to set/get/reset network key(s). - * This function prepares key material command for V2 format. - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting WEP keys, WAPI keys or WPA keys along with required - * encryption (TKIP, AES) (as required) - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_key_material_v2(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u32 cmd_oid, - struct mwifiex_ds_encrypt_key *enc_key) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 *mac = enc_key->mac_addr; - u16 key_info, len = KEY_PARAMS_FIXED_LEN; - struct host_cmd_ds_802_11_key_material_v2 *km = - &cmd->params.key_material_v2; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); - km->action = cpu_to_le16(cmd_action); - - if (cmd_action == HostCmd_ACT_GEN_GET) { - mwifiex_dbg(adapter, INFO, "%s: Get key\n", __func__); - km->key_param_set.key_idx = - enc_key->key_index & KEY_INDEX_MASK; - km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); - km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); - memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); - - if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) - key_info = KEY_UNICAST; - else - key_info = KEY_MCAST; - - if (enc_key->is_igtk_key) - key_info |= KEY_IGTK; - - km->key_param_set.key_info = cpu_to_le16(key_info); - - cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + - S_DS_GEN + KEY_PARAMS_FIXED_LEN + - sizeof(km->action)); - return 0; - } - - memset(&km->key_param_set, 0, - sizeof(struct mwifiex_ie_type_key_param_set_v2)); - - if (enc_key->key_disable) { - mwifiex_dbg(adapter, INFO, "%s: Remove key\n", __func__); - km->action = cpu_to_le16(HostCmd_ACT_GEN_REMOVE); - km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); - km->key_param_set.len = cpu_to_le16(KEY_PARAMS_FIXED_LEN); - km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; - key_info = KEY_MCAST | KEY_UNICAST; - km->key_param_set.key_info = cpu_to_le16(key_info); - memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); - cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + - S_DS_GEN + KEY_PARAMS_FIXED_LEN + - sizeof(km->action)); - return 0; - } - - km->action = cpu_to_le16(HostCmd_ACT_GEN_SET); - km->key_param_set.key_idx = enc_key->key_index & KEY_INDEX_MASK; - km->key_param_set.type = cpu_to_le16(TLV_TYPE_KEY_PARAM_V2); - key_info = KEY_ENABLED; - memcpy(km->key_param_set.mac_addr, mac, ETH_ALEN); - - if (enc_key->key_len <= WLAN_KEY_LEN_WEP104) { - mwifiex_dbg(adapter, INFO, "%s: Set WEP Key\n", __func__); - len += sizeof(struct mwifiex_wep_param); - km->key_param_set.len = cpu_to_le16(len); - km->key_param_set.key_type = KEY_TYPE_ID_WEP; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - key_info |= KEY_MCAST | KEY_UNICAST; - } else { - if (enc_key->is_current_wep_key) { - key_info |= KEY_MCAST | KEY_UNICAST; - if (km->key_param_set.key_idx == - (priv->wep_key_curr_index & KEY_INDEX_MASK)) - key_info |= KEY_DEFAULT; - } else { - if (mac) { - if (is_broadcast_ether_addr(mac)) - key_info |= KEY_MCAST; - else - key_info |= KEY_UNICAST | - KEY_DEFAULT; - } else { - key_info |= KEY_MCAST; - } - } - } - km->key_param_set.key_info = cpu_to_le16(key_info); - - km->key_param_set.key_params.wep.key_len = - cpu_to_le16(enc_key->key_len); - memcpy(km->key_param_set.key_params.wep.key, - enc_key->key_material, enc_key->key_len); - - cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + - len + sizeof(km->action) + S_DS_GEN); - return 0; - } - - if (is_broadcast_ether_addr(mac)) - key_info |= KEY_MCAST | KEY_RX_KEY; - else - key_info |= KEY_UNICAST | KEY_TX_KEY | KEY_RX_KEY; - - if (enc_key->is_wapi_key) { - mwifiex_dbg(adapter, INFO, "%s: Set WAPI Key\n", __func__); - km->key_param_set.key_type = KEY_TYPE_ID_WAPI; - memcpy(km->key_param_set.key_params.wapi.pn, enc_key->pn, - PN_LEN); - km->key_param_set.key_params.wapi.key_len = - cpu_to_le16(enc_key->key_len); - memcpy(km->key_param_set.key_params.wapi.key, - enc_key->key_material, enc_key->key_len); - if (is_broadcast_ether_addr(mac)) - priv->sec_info.wapi_key_on = true; - - if (!priv->sec_info.wapi_key_on) - key_info |= KEY_DEFAULT; - km->key_param_set.key_info = cpu_to_le16(key_info); - - len += sizeof(struct mwifiex_wapi_param); - km->key_param_set.len = cpu_to_le16(len); - cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + - len + sizeof(km->action) + S_DS_GEN); - return 0; - } - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - key_info |= KEY_DEFAULT; - /* Enable unicast bit for WPA-NONE/ADHOC_AES */ - if (!priv->sec_info.wpa2_enabled && - !is_broadcast_ether_addr(mac)) - key_info |= KEY_UNICAST; - } else { - /* Enable default key for WPA/WPA2 */ - if (!priv->wpa_is_gtk_set) - key_info |= KEY_DEFAULT; - } - - km->key_param_set.key_info = cpu_to_le16(key_info); - - if (enc_key->key_len == WLAN_KEY_LEN_CCMP) - return mwifiex_set_aes_key_v2(priv, cmd, enc_key, km); - - if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { - mwifiex_dbg(adapter, INFO, - "%s: Set TKIP Key\n", __func__); - if (enc_key->is_rx_seq_valid) - memcpy(km->key_param_set.key_params.tkip.pn, - enc_key->pn, enc_key->pn_len); - km->key_param_set.key_type = KEY_TYPE_ID_TKIP; - km->key_param_set.key_params.tkip.key_len = - cpu_to_le16(enc_key->key_len); - memcpy(km->key_param_set.key_params.tkip.key, - enc_key->key_material, enc_key->key_len); - - len += sizeof(struct mwifiex_tkip_param); - km->key_param_set.len = cpu_to_le16(len); - cmd->size = cpu_to_le16(sizeof(struct mwifiex_ie_types_header) + - len + sizeof(km->action) + S_DS_GEN); - } - - return 0; -} - -/* - * This function prepares command to set/get/reset network key(s). - * This function prepares key material command for V1 format. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting WEP keys, WAPI keys or WPA keys along with required - * encryption (TKIP, AES) (as required) - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_802_11_key_material_v1(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u32 cmd_oid, - struct mwifiex_ds_encrypt_key *enc_key) -{ - struct host_cmd_ds_802_11_key_material *key_material = - &cmd->params.key_material; - struct host_cmd_tlv_mac_addr *tlv_mac; - u16 key_param_len = 0, cmd_size; - int ret = 0; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_KEY_MATERIAL); - key_material->action = cpu_to_le16(cmd_action); - - if (cmd_action == HostCmd_ACT_GEN_GET) { - cmd->size = - cpu_to_le16(sizeof(key_material->action) + S_DS_GEN); - return ret; - } - - if (!enc_key) { - memset(&key_material->key_param_set, 0, - (NUM_WEP_KEYS * - sizeof(struct mwifiex_ie_type_key_param_set))); - ret = mwifiex_set_keyparamset_wep(priv, - &key_material->key_param_set, - &key_param_len); - cmd->size = cpu_to_le16(key_param_len + - sizeof(key_material->action) + S_DS_GEN); - return ret; - } else - memset(&key_material->key_param_set, 0, - sizeof(struct mwifiex_ie_type_key_param_set)); - if (enc_key->is_wapi_key) { - mwifiex_dbg(priv->adapter, INFO, "info: Set WAPI Key\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_WAPI); - if (cmd_oid == KEY_INFO_ENABLED) - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - else - key_material->key_param_set.key_info = - cpu_to_le16(!KEY_ENABLED); - - key_material->key_param_set.key[0] = enc_key->key_index; - if (!priv->sec_info.wapi_key_on) - key_material->key_param_set.key[1] = 1; - else - /* set 0 when re-key */ - key_material->key_param_set.key[1] = 0; - - if (!is_broadcast_ether_addr(enc_key->mac_addr)) { - /* WAPI pairwise key: unicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_UNICAST); - } else { /* WAPI group key: multicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_MCAST); - priv->sec_info.wapi_key_on = true; - } - - key_material->key_param_set.type = - cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - key_material->key_param_set.key_len = - cpu_to_le16(WAPI_KEY_LEN); - memcpy(&key_material->key_param_set.key[2], - enc_key->key_material, enc_key->key_len); - memcpy(&key_material->key_param_set.key[2 + enc_key->key_len], - enc_key->pn, PN_LEN); - key_material->key_param_set.length = - cpu_to_le16(WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN); - - key_param_len = (WAPI_KEY_LEN + KEYPARAMSET_FIXED_LEN) + - sizeof(struct mwifiex_ie_types_header); - cmd->size = cpu_to_le16(sizeof(key_material->action) - + S_DS_GEN + key_param_len); - return ret; - } - if (enc_key->key_len == WLAN_KEY_LEN_CCMP) { - if (enc_key->is_igtk_key) { - mwifiex_dbg(priv->adapter, CMD, "cmd: CMAC_AES\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_AES_CMAC); - if (cmd_oid == KEY_INFO_ENABLED) - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - else - key_material->key_param_set.key_info = - cpu_to_le16(!KEY_ENABLED); - - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_IGTK); - } else { - mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_AES\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_AES); - if (cmd_oid == KEY_INFO_ENABLED) - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - else - key_material->key_param_set.key_info = - cpu_to_le16(!KEY_ENABLED); - - if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) - /* AES pairwise key: unicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_UNICAST); - else /* AES group key: multicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_MCAST); - } - } else if (enc_key->key_len == WLAN_KEY_LEN_TKIP) { - mwifiex_dbg(priv->adapter, CMD, "cmd: WPA_TKIP\n"); - key_material->key_param_set.key_type_id = - cpu_to_le16(KEY_TYPE_ID_TKIP); - key_material->key_param_set.key_info = - cpu_to_le16(KEY_ENABLED); - - if (enc_key->key_index & MWIFIEX_KEY_INDEX_UNICAST) - /* TKIP pairwise key: unicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_UNICAST); - else /* TKIP group key: multicast */ - key_material->key_param_set.key_info |= - cpu_to_le16(KEY_MCAST); - } - - if (key_material->key_param_set.key_type_id) { - key_material->key_param_set.type = - cpu_to_le16(TLV_TYPE_KEY_MATERIAL); - key_material->key_param_set.key_len = - cpu_to_le16((u16) enc_key->key_len); - memcpy(key_material->key_param_set.key, enc_key->key_material, - enc_key->key_len); - key_material->key_param_set.length = - cpu_to_le16((u16) enc_key->key_len + - KEYPARAMSET_FIXED_LEN); - - key_param_len = (u16)(enc_key->key_len + KEYPARAMSET_FIXED_LEN) - + sizeof(struct mwifiex_ie_types_header); - - if (le16_to_cpu(key_material->key_param_set.key_type_id) == - KEY_TYPE_ID_AES_CMAC) { - struct mwifiex_cmac_param *param = - (void *)key_material->key_param_set.key; - - memcpy(param->ipn, enc_key->pn, IGTK_PN_LEN); - memcpy(param->key, enc_key->key_material, - WLAN_KEY_LEN_AES_CMAC); - - key_param_len = sizeof(struct mwifiex_cmac_param); - key_material->key_param_set.key_len = - cpu_to_le16(key_param_len); - key_param_len += KEYPARAMSET_FIXED_LEN; - key_material->key_param_set.length = - cpu_to_le16(key_param_len); - key_param_len += sizeof(struct mwifiex_ie_types_header); - } - - cmd->size = cpu_to_le16(sizeof(key_material->action) + S_DS_GEN - + key_param_len); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - tlv_mac = (void *)((u8 *)&key_material->key_param_set + - key_param_len); - tlv_mac->header.type = - cpu_to_le16(TLV_TYPE_STA_MAC_ADDR); - tlv_mac->header.len = cpu_to_le16(ETH_ALEN); - memcpy(tlv_mac->mac_addr, enc_key->mac_addr, ETH_ALEN); - cmd_size = key_param_len + S_DS_GEN + - sizeof(key_material->action) + - sizeof(struct host_cmd_tlv_mac_addr); - } else { - cmd_size = key_param_len + S_DS_GEN + - sizeof(key_material->action); - } - cmd->size = cpu_to_le16(cmd_size); - } - - return ret; -} - -/* Wrapper function for setting network key depending upon FW KEY API version */ -static int -mwifiex_cmd_802_11_key_material(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, u32 cmd_oid, - struct mwifiex_ds_encrypt_key *enc_key) -{ - if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) - return mwifiex_cmd_802_11_key_material_v2(priv, cmd, - cmd_action, cmd_oid, - enc_key); - - else - return mwifiex_cmd_802_11_key_material_v1(priv, cmd, - cmd_action, cmd_oid, - enc_key); -} - -/* - * This function prepares command to set/get 11d domain information. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting domain information fields (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_802_11d_domain_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11d_domain_info *domain_info = - &cmd->params.domain_info; - struct mwifiex_ietypes_domain_param_set *domain = - &domain_info->domain; - u8 no_of_triplet = adapter->domain_reg.no_of_triplet; - - mwifiex_dbg(adapter, INFO, - "info: 11D: no_of_triplet=0x%x\n", no_of_triplet); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11D_DOMAIN_INFO); - domain_info->action = cpu_to_le16(cmd_action); - if (cmd_action == HostCmd_ACT_GEN_GET) { - cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); - return 0; - } - - /* Set domain info fields */ - domain->header.type = cpu_to_le16(WLAN_EID_COUNTRY); - memcpy(domain->country_code, adapter->domain_reg.country_code, - sizeof(domain->country_code)); - - domain->header.len = - cpu_to_le16((no_of_triplet * - sizeof(struct ieee80211_country_ie_triplet)) - + sizeof(domain->country_code)); - - if (no_of_triplet) { - memcpy(domain->triplet, adapter->domain_reg.triplet, - no_of_triplet * sizeof(struct - ieee80211_country_ie_triplet)); - - cmd->size = cpu_to_le16(sizeof(domain_info->action) + - le16_to_cpu(domain->header.len) + - sizeof(struct mwifiex_ie_types_header) - + S_DS_GEN); - } else { - cmd->size = cpu_to_le16(sizeof(domain_info->action) + S_DS_GEN); - } - - return 0; -} - -/* - * This function prepares command to set/get IBSS coalescing status. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting status to enable or disable (for SET only) - * - Ensuring correct endian-ness - */ -static int mwifiex_cmd_ibss_coalescing_status(struct host_cmd_ds_command *cmd, - u16 cmd_action, u16 *enable) -{ - struct host_cmd_ds_802_11_ibss_status *ibss_coal = - &(cmd->params.ibss_coalescing); - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_IBSS_COALESCING_STATUS); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_ibss_status) + - S_DS_GEN); - cmd->result = 0; - ibss_coal->action = cpu_to_le16(cmd_action); - - switch (cmd_action) { - case HostCmd_ACT_GEN_SET: - if (enable) - ibss_coal->enable = cpu_to_le16(*enable); - else - ibss_coal->enable = 0; - break; - - /* In other case.. Nothing to do */ - case HostCmd_ACT_GEN_GET: - default: - break; - } - - return 0; -} - -/* This function prepares command buffer to get/set memory location value. - */ -static int -mwifiex_cmd_mem_access(struct host_cmd_ds_command *cmd, u16 cmd_action, - void *pdata_buf) -{ - struct mwifiex_ds_mem_rw *mem_rw = (void *)pdata_buf; - struct host_cmd_ds_mem_access *mem_access = (void *)&cmd->params.mem; - - cmd->command = cpu_to_le16(HostCmd_CMD_MEM_ACCESS); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_mem_access) + - S_DS_GEN); - - mem_access->action = cpu_to_le16(cmd_action); - mem_access->addr = cpu_to_le32(mem_rw->addr); - mem_access->value = cpu_to_le32(mem_rw->value); - - return 0; -} - -/* - * This function prepares command to set/get register value. - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting register offset (for both GET and SET) and - * register value (for SET only) - * - Ensuring correct endian-ness - * - * The following type of registers can be accessed with this function - - * - MAC register - * - BBP register - * - RF register - * - PMIC register - * - CAU register - * - EEPROM - */ -static int mwifiex_cmd_reg_access(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct mwifiex_ds_reg_rw *reg_rw = data_buf; - - switch (le16_to_cpu(cmd->command)) { - case HostCmd_CMD_MAC_REG_ACCESS: - { - struct host_cmd_ds_mac_reg_access *mac_reg; - - cmd->size = cpu_to_le16(sizeof(*mac_reg) + S_DS_GEN); - mac_reg = &cmd->params.mac_reg; - mac_reg->action = cpu_to_le16(cmd_action); - mac_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - mac_reg->value = reg_rw->value; - break; - } - case HostCmd_CMD_BBP_REG_ACCESS: - { - struct host_cmd_ds_bbp_reg_access *bbp_reg; - - cmd->size = cpu_to_le16(sizeof(*bbp_reg) + S_DS_GEN); - bbp_reg = &cmd->params.bbp_reg; - bbp_reg->action = cpu_to_le16(cmd_action); - bbp_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - bbp_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_RF_REG_ACCESS: - { - struct host_cmd_ds_rf_reg_access *rf_reg; - - cmd->size = cpu_to_le16(sizeof(*rf_reg) + S_DS_GEN); - rf_reg = &cmd->params.rf_reg; - rf_reg->action = cpu_to_le16(cmd_action); - rf_reg->offset = cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - rf_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_PMIC_REG_ACCESS: - { - struct host_cmd_ds_pmic_reg_access *pmic_reg; - - cmd->size = cpu_to_le16(sizeof(*pmic_reg) + S_DS_GEN); - pmic_reg = &cmd->params.pmic_reg; - pmic_reg->action = cpu_to_le16(cmd_action); - pmic_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - pmic_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_CAU_REG_ACCESS: - { - struct host_cmd_ds_rf_reg_access *cau_reg; - - cmd->size = cpu_to_le16(sizeof(*cau_reg) + S_DS_GEN); - cau_reg = &cmd->params.rf_reg; - cau_reg->action = cpu_to_le16(cmd_action); - cau_reg->offset = - cpu_to_le16((u16) le32_to_cpu(reg_rw->offset)); - cau_reg->value = (u8) le32_to_cpu(reg_rw->value); - break; - } - case HostCmd_CMD_802_11_EEPROM_ACCESS: - { - struct mwifiex_ds_read_eeprom *rd_eeprom = data_buf; - struct host_cmd_ds_802_11_eeprom_access *cmd_eeprom = - &cmd->params.eeprom; - - cmd->size = cpu_to_le16(sizeof(*cmd_eeprom) + S_DS_GEN); - cmd_eeprom->action = cpu_to_le16(cmd_action); - cmd_eeprom->offset = rd_eeprom->offset; - cmd_eeprom->byte_count = rd_eeprom->byte_count; - cmd_eeprom->value = 0; - break; - } - default: - return -1; - } - - return 0; -} - -/* - * This function prepares command to set PCI-Express - * host buffer configuration - * - * Preparation includes - - * - Setting command ID, action and proper size - * - Setting host buffer configuration - * - Ensuring correct endian-ness - */ -static int -mwifiex_cmd_pcie_host_spec(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u16 action) -{ - struct host_cmd_ds_pcie_details *host_spec = - &cmd->params.pcie_host_spec; - struct pcie_service_card *card = priv->adapter->card; - - cmd->command = cpu_to_le16(HostCmd_CMD_PCIE_DESC_DETAILS); - cmd->size = cpu_to_le16(sizeof(struct - host_cmd_ds_pcie_details) + S_DS_GEN); - cmd->result = 0; - - memset(host_spec, 0, sizeof(struct host_cmd_ds_pcie_details)); - - if (action != HostCmd_ACT_GEN_SET) - return 0; - - /* Send the ring base addresses and count to firmware */ - host_spec->txbd_addr_lo = (u32)(card->txbd_ring_pbase); - host_spec->txbd_addr_hi = (u32)(((u64)card->txbd_ring_pbase)>>32); - host_spec->txbd_count = MWIFIEX_MAX_TXRX_BD; - host_spec->rxbd_addr_lo = (u32)(card->rxbd_ring_pbase); - host_spec->rxbd_addr_hi = (u32)(((u64)card->rxbd_ring_pbase)>>32); - host_spec->rxbd_count = MWIFIEX_MAX_TXRX_BD; - host_spec->evtbd_addr_lo = (u32)(card->evtbd_ring_pbase); - host_spec->evtbd_addr_hi = (u32)(((u64)card->evtbd_ring_pbase)>>32); - host_spec->evtbd_count = MWIFIEX_MAX_EVT_BD; - if (card->sleep_cookie_vbase) { - host_spec->sleep_cookie_addr_lo = - (u32)(card->sleep_cookie_pbase); - host_spec->sleep_cookie_addr_hi = - (u32)(((u64)(card->sleep_cookie_pbase)) >> 32); - mwifiex_dbg(priv->adapter, INFO, - "sleep_cook_lo phy addr: 0x%x\n", - host_spec->sleep_cookie_addr_lo); - } - - return 0; -} - -/* - * This function prepares command for event subscription, configuration - * and query. Events can be subscribed or unsubscribed. Current subscribed - * events can be queried. Also, current subscribed events are reported in - * every FW response. - */ -static int -mwifiex_cmd_802_11_subsc_evt(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_ds_misc_subsc_evt *subsc_evt_cfg) -{ - struct host_cmd_ds_802_11_subsc_evt *subsc_evt = &cmd->params.subsc_evt; - struct mwifiex_ie_types_rssi_threshold *rssi_tlv; - u16 event_bitmap; - u8 *pos; - - cmd->command = cpu_to_le16(HostCmd_CMD_802_11_SUBSCRIBE_EVENT); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_802_11_subsc_evt) + - S_DS_GEN); - - subsc_evt->action = cpu_to_le16(subsc_evt_cfg->action); - mwifiex_dbg(priv->adapter, CMD, - "cmd: action: %d\n", subsc_evt_cfg->action); - - /*For query requests, no configuration TLV structures are to be added.*/ - if (subsc_evt_cfg->action == HostCmd_ACT_GEN_GET) - return 0; - - subsc_evt->events = cpu_to_le16(subsc_evt_cfg->events); - - event_bitmap = subsc_evt_cfg->events; - mwifiex_dbg(priv->adapter, CMD, "cmd: event bitmap : %16x\n", - event_bitmap); - - if (((subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) || - (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_SET)) && - (event_bitmap == 0)) { - mwifiex_dbg(priv->adapter, ERROR, - "Error: No event specified\t" - "for bitwise action type\n"); - return -EINVAL; - } - - /* - * Append TLV structures for each of the specified events for - * subscribing or re-configuring. This is not required for - * bitwise unsubscribing request. - */ - if (subsc_evt_cfg->action == HostCmd_ACT_BITWISE_CLR) - return 0; - - pos = ((u8 *)subsc_evt) + - sizeof(struct host_cmd_ds_802_11_subsc_evt); - - if (event_bitmap & BITMASK_BCN_RSSI_LOW) { - rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos; - - rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_LOW); - rssi_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) - - sizeof(struct mwifiex_ie_types_header)); - rssi_tlv->abs_value = subsc_evt_cfg->bcn_l_rssi_cfg.abs_value; - rssi_tlv->evt_freq = subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq; - - mwifiex_dbg(priv->adapter, EVENT, - "Cfg Beacon Low Rssi event,\t" - "RSSI:-%d dBm, Freq:%d\n", - subsc_evt_cfg->bcn_l_rssi_cfg.abs_value, - subsc_evt_cfg->bcn_l_rssi_cfg.evt_freq); - - pos += sizeof(struct mwifiex_ie_types_rssi_threshold); - le16_add_cpu(&cmd->size, - sizeof(struct mwifiex_ie_types_rssi_threshold)); - } - - if (event_bitmap & BITMASK_BCN_RSSI_HIGH) { - rssi_tlv = (struct mwifiex_ie_types_rssi_threshold *) pos; - - rssi_tlv->header.type = cpu_to_le16(TLV_TYPE_RSSI_HIGH); - rssi_tlv->header.len = - cpu_to_le16(sizeof(struct mwifiex_ie_types_rssi_threshold) - - sizeof(struct mwifiex_ie_types_header)); - rssi_tlv->abs_value = subsc_evt_cfg->bcn_h_rssi_cfg.abs_value; - rssi_tlv->evt_freq = subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq; - - mwifiex_dbg(priv->adapter, EVENT, - "Cfg Beacon High Rssi event,\t" - "RSSI:-%d dBm, Freq:%d\n", - subsc_evt_cfg->bcn_h_rssi_cfg.abs_value, - subsc_evt_cfg->bcn_h_rssi_cfg.evt_freq); - - pos += sizeof(struct mwifiex_ie_types_rssi_threshold); - le16_add_cpu(&cmd->size, - sizeof(struct mwifiex_ie_types_rssi_threshold)); - } - - return 0; -} - -static int -mwifiex_cmd_append_rpn_expression(struct mwifiex_private *priv, - struct mwifiex_mef_entry *mef_entry, - u8 **buffer) -{ - struct mwifiex_mef_filter *filter = mef_entry->filter; - int i, byte_len; - u8 *stack_ptr = *buffer; - - for (i = 0; i < MWIFIEX_MEF_MAX_FILTERS; i++) { - filter = &mef_entry->filter[i]; - if (!filter->filt_type) - break; - *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->repeat); - stack_ptr += 4; - *stack_ptr = TYPE_DNUM; - stack_ptr += 1; - - byte_len = filter->byte_seq[MWIFIEX_MEF_MAX_BYTESEQ]; - memcpy(stack_ptr, filter->byte_seq, byte_len); - stack_ptr += byte_len; - *stack_ptr = byte_len; - stack_ptr += 1; - *stack_ptr = TYPE_BYTESEQ; - stack_ptr += 1; - - *(__le32 *)stack_ptr = cpu_to_le32((u32)filter->offset); - stack_ptr += 4; - *stack_ptr = TYPE_DNUM; - stack_ptr += 1; - - *stack_ptr = filter->filt_type; - stack_ptr += 1; - - if (filter->filt_action) { - *stack_ptr = filter->filt_action; - stack_ptr += 1; - } - - if (stack_ptr - *buffer > STACK_NBYTES) - return -1; - } - - *buffer = stack_ptr; - return 0; -} - -static int -mwifiex_cmd_mef_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - struct mwifiex_ds_mef_cfg *mef) -{ - struct host_cmd_ds_mef_cfg *mef_cfg = &cmd->params.mef_cfg; - struct mwifiex_fw_mef_entry *mef_entry = NULL; - u8 *pos = (u8 *)mef_cfg; - u16 i; - - cmd->command = cpu_to_le16(HostCmd_CMD_MEF_CFG); - - mef_cfg->criteria = cpu_to_le32(mef->criteria); - mef_cfg->num_entries = cpu_to_le16(mef->num_entries); - pos += sizeof(*mef_cfg); - - for (i = 0; i < mef->num_entries; i++) { - mef_entry = (struct mwifiex_fw_mef_entry *)pos; - mef_entry->mode = mef->mef_entry[i].mode; - mef_entry->action = mef->mef_entry[i].action; - pos += sizeof(*mef_cfg->mef_entry); - - if (mwifiex_cmd_append_rpn_expression(priv, - &mef->mef_entry[i], &pos)) - return -1; - - mef_entry->exprsize = - cpu_to_le16(pos - mef_entry->expr); - } - cmd->size = cpu_to_le16((u16) (pos - (u8 *)mef_cfg) + S_DS_GEN); - - return 0; -} - -/* This function parse cal data from ASCII to hex */ -static u32 mwifiex_parse_cal_cfg(u8 *src, size_t len, u8 *dst) -{ - u8 *s = src, *d = dst; - - while (s - src < len) { - if (*s && (isspace(*s) || *s == '\t')) { - s++; - continue; - } - if (isxdigit(*s)) { - *d++ = simple_strtol(s, NULL, 16); - s += 2; - } else { - s++; - } - } - - return d - dst; -} - -int mwifiex_dnld_dt_cfgdata(struct mwifiex_private *priv, - struct device_node *node, const char *prefix) -{ -#ifdef CONFIG_OF - struct property *prop; - size_t len = strlen(prefix); - int ret; - - /* look for all matching property names */ - for_each_property_of_node(node, prop) { - if (len > strlen(prop->name) || - strncmp(prop->name, prefix, len)) - continue; - - /* property header is 6 bytes, data must fit in cmd buffer */ - if (prop && prop->value && prop->length > 6 && - prop->length <= MWIFIEX_SIZE_OF_CMD_BUFFER - S_DS_GEN) { - ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, - HostCmd_ACT_GEN_SET, 0, - prop, true); - if (ret) - return ret; - } - } -#endif - return 0; -} - -/* This function prepares command of set_cfg_data. */ -static int mwifiex_cmd_cfg_data(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, void *data_buf) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct property *prop = data_buf; - u32 len; - u8 *data = (u8 *)cmd + S_DS_GEN; - int ret; - - if (prop) { - len = prop->length; - ret = of_property_read_u8_array(adapter->dt_node, prop->name, - data, len); - if (ret) - return ret; - mwifiex_dbg(adapter, INFO, - "download cfg_data from device tree: %s\n", - prop->name); - } else if (adapter->cal_data->data && adapter->cal_data->size > 0) { - len = mwifiex_parse_cal_cfg((u8 *)adapter->cal_data->data, - adapter->cal_data->size, data); - mwifiex_dbg(adapter, INFO, - "download cfg_data from config file\n"); - } else { - return -1; - } - - cmd->command = cpu_to_le16(HostCmd_CMD_CFG_DATA); - cmd->size = cpu_to_le16(S_DS_GEN + len); - - return 0; -} - -static int -mwifiex_cmd_set_mc_policy(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_multi_chan_policy *mc_pol = &cmd->params.mc_policy; - const u16 *drcs_info = data_buf; - - mc_pol->action = cpu_to_le16(cmd_action); - mc_pol->policy = cpu_to_le16(*drcs_info); - cmd->command = cpu_to_le16(HostCmd_CMD_MC_POLICY); - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_multi_chan_policy) + - S_DS_GEN); - return 0; -} - -static int mwifiex_cmd_robust_coex(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, bool *is_timeshare) -{ - struct host_cmd_ds_robust_coex *coex = &cmd->params.coex; - struct mwifiex_ie_types_robust_coex *coex_tlv; - - cmd->command = cpu_to_le16(HostCmd_CMD_ROBUST_COEX); - cmd->size = cpu_to_le16(sizeof(*coex) + sizeof(*coex_tlv) + S_DS_GEN); - - coex->action = cpu_to_le16(cmd_action); - coex_tlv = (struct mwifiex_ie_types_robust_coex *) - ((u8 *)coex + sizeof(*coex)); - coex_tlv->header.type = cpu_to_le16(TLV_TYPE_ROBUST_COEX); - coex_tlv->header.len = cpu_to_le16(sizeof(coex_tlv->mode)); - - if (coex->action == HostCmd_ACT_GEN_GET) - return 0; - - if (*is_timeshare) - coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_TIMESHARE); - else - coex_tlv->mode = cpu_to_le32(MWIFIEX_COEX_MODE_SPATIAL); - - return 0; -} - -static int -mwifiex_cmd_coalesce_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_coalesce_cfg *coalesce_cfg = - &cmd->params.coalesce_cfg; - struct mwifiex_ds_coalesce_cfg *cfg = data_buf; - struct coalesce_filt_field_param *param; - u16 cnt, idx, length; - struct coalesce_receive_filt_rule *rule; - - cmd->command = cpu_to_le16(HostCmd_CMD_COALESCE_CFG); - cmd->size = cpu_to_le16(S_DS_GEN); - - coalesce_cfg->action = cpu_to_le16(cmd_action); - coalesce_cfg->num_of_rules = cpu_to_le16(cfg->num_of_rules); - rule = coalesce_cfg->rule; - - for (cnt = 0; cnt < cfg->num_of_rules; cnt++) { - rule->header.type = cpu_to_le16(TLV_TYPE_COALESCE_RULE); - rule->max_coalescing_delay = - cpu_to_le16(cfg->rule[cnt].max_coalescing_delay); - rule->pkt_type = cfg->rule[cnt].pkt_type; - rule->num_of_fields = cfg->rule[cnt].num_of_fields; - - length = 0; - - param = rule->params; - for (idx = 0; idx < cfg->rule[cnt].num_of_fields; idx++) { - param->operation = cfg->rule[cnt].params[idx].operation; - param->operand_len = - cfg->rule[cnt].params[idx].operand_len; - param->offset = - cpu_to_le16(cfg->rule[cnt].params[idx].offset); - memcpy(param->operand_byte_stream, - cfg->rule[cnt].params[idx].operand_byte_stream, - param->operand_len); - - length += sizeof(struct coalesce_filt_field_param); - - param++; - } - - /* Total rule length is sizeof max_coalescing_delay(u16), - * num_of_fields(u8), pkt_type(u8) and total length of the all - * params - */ - rule->header.len = cpu_to_le16(length + sizeof(u16) + - sizeof(u8) + sizeof(u8)); - - /* Add the rule length to the command size*/ - le16_add_cpu(&cmd->size, le16_to_cpu(rule->header.len) + - sizeof(struct mwifiex_ie_types_header)); - - rule = (void *)((u8 *)rule->params + length); - } - - /* Add sizeof action, num_of_rules to total command length */ - le16_add_cpu(&cmd->size, sizeof(u16) + sizeof(u16)); - - return 0; -} - -static int -mwifiex_cmd_tdls_config(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_ds_tdls_config *tdls_config = &cmd->params.tdls_config; - struct mwifiex_tdls_init_cs_params *config; - struct mwifiex_tdls_config *init_config; - u16 len; - - cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_CONFIG); - cmd->size = cpu_to_le16(S_DS_GEN); - tdls_config->tdls_action = cpu_to_le16(cmd_action); - le16_add_cpu(&cmd->size, sizeof(tdls_config->tdls_action)); - - switch (cmd_action) { - case ACT_TDLS_CS_ENABLE_CONFIG: - init_config = data_buf; - len = sizeof(*init_config); - memcpy(tdls_config->tdls_data, init_config, len); - break; - case ACT_TDLS_CS_INIT: - config = data_buf; - len = sizeof(*config); - memcpy(tdls_config->tdls_data, config, len); - break; - case ACT_TDLS_CS_STOP: - len = sizeof(struct mwifiex_tdls_stop_cs_params); - memcpy(tdls_config->tdls_data, data_buf, len); - break; - case ACT_TDLS_CS_PARAMS: - len = sizeof(struct mwifiex_tdls_config_cs_params); - memcpy(tdls_config->tdls_data, data_buf, len); - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "Unknown TDLS configuration\n"); - return -ENOTSUPP; - } - - le16_add_cpu(&cmd->size, len); - return 0; -} - -static int -mwifiex_cmd_tdls_oper(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, - void *data_buf) -{ - struct host_cmd_ds_tdls_oper *tdls_oper = &cmd->params.tdls_oper; - struct mwifiex_ds_tdls_oper *oper = data_buf; - struct mwifiex_sta_node *sta_ptr; - struct host_cmd_tlv_rates *tlv_rates; - struct mwifiex_ie_types_htcap *ht_capab; - struct mwifiex_ie_types_qos_info *wmm_qos_info; - struct mwifiex_ie_types_extcap *extcap; - struct mwifiex_ie_types_vhtcap *vht_capab; - struct mwifiex_ie_types_aid *aid; - struct mwifiex_ie_types_tdls_idle_timeout *timeout; - u8 *pos, qos_info; - u16 config_len = 0; - struct station_parameters *params = priv->sta_params; - - cmd->command = cpu_to_le16(HostCmd_CMD_TDLS_OPER); - cmd->size = cpu_to_le16(S_DS_GEN); - le16_add_cpu(&cmd->size, sizeof(struct host_cmd_ds_tdls_oper)); - - tdls_oper->reason = 0; - memcpy(tdls_oper->peer_mac, oper->peer_mac, ETH_ALEN); - sta_ptr = mwifiex_get_sta_entry(priv, oper->peer_mac); - - pos = (u8 *)tdls_oper + sizeof(struct host_cmd_ds_tdls_oper); - - switch (oper->tdls_action) { - case MWIFIEX_TDLS_DISABLE_LINK: - tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_DELETE); - break; - case MWIFIEX_TDLS_CREATE_LINK: - tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CREATE); - break; - case MWIFIEX_TDLS_CONFIG_LINK: - tdls_oper->tdls_action = cpu_to_le16(ACT_TDLS_CONFIG); - - if (!params) { - mwifiex_dbg(priv->adapter, ERROR, - "TDLS config params not available for %pM\n", - oper->peer_mac); - return -ENODATA; - } - - *(__le16 *)pos = cpu_to_le16(params->capability); - config_len += sizeof(params->capability); - - qos_info = params->uapsd_queues | (params->max_sp << 5); - wmm_qos_info = (struct mwifiex_ie_types_qos_info *)(pos + - config_len); - wmm_qos_info->header.type = cpu_to_le16(WLAN_EID_QOS_CAPA); - wmm_qos_info->header.len = cpu_to_le16(sizeof(qos_info)); - wmm_qos_info->qos_info = qos_info; - config_len += sizeof(struct mwifiex_ie_types_qos_info); - - if (params->ht_capa) { - ht_capab = (struct mwifiex_ie_types_htcap *)(pos + - config_len); - ht_capab->header.type = - cpu_to_le16(WLAN_EID_HT_CAPABILITY); - ht_capab->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - memcpy(&ht_capab->ht_cap, params->ht_capa, - sizeof(struct ieee80211_ht_cap)); - config_len += sizeof(struct mwifiex_ie_types_htcap); - } - - if (params->supported_rates && params->supported_rates_len) { - tlv_rates = (struct host_cmd_tlv_rates *)(pos + - config_len); - tlv_rates->header.type = - cpu_to_le16(WLAN_EID_SUPP_RATES); - tlv_rates->header.len = - cpu_to_le16(params->supported_rates_len); - memcpy(tlv_rates->rates, params->supported_rates, - params->supported_rates_len); - config_len += sizeof(struct host_cmd_tlv_rates) + - params->supported_rates_len; - } - - if (params->ext_capab && params->ext_capab_len) { - extcap = (struct mwifiex_ie_types_extcap *)(pos + - config_len); - extcap->header.type = - cpu_to_le16(WLAN_EID_EXT_CAPABILITY); - extcap->header.len = cpu_to_le16(params->ext_capab_len); - memcpy(extcap->ext_capab, params->ext_capab, - params->ext_capab_len); - config_len += sizeof(struct mwifiex_ie_types_extcap) + - params->ext_capab_len; - } - if (params->vht_capa) { - vht_capab = (struct mwifiex_ie_types_vhtcap *)(pos + - config_len); - vht_capab->header.type = - cpu_to_le16(WLAN_EID_VHT_CAPABILITY); - vht_capab->header.len = - cpu_to_le16(sizeof(struct ieee80211_vht_cap)); - memcpy(&vht_capab->vht_cap, params->vht_capa, - sizeof(struct ieee80211_vht_cap)); - config_len += sizeof(struct mwifiex_ie_types_vhtcap); - } - if (params->aid) { - aid = (struct mwifiex_ie_types_aid *)(pos + config_len); - aid->header.type = cpu_to_le16(WLAN_EID_AID); - aid->header.len = cpu_to_le16(sizeof(params->aid)); - aid->aid = cpu_to_le16(params->aid); - config_len += sizeof(struct mwifiex_ie_types_aid); - } - - timeout = (void *)(pos + config_len); - timeout->header.type = cpu_to_le16(TLV_TYPE_TDLS_IDLE_TIMEOUT); - timeout->header.len = cpu_to_le16(sizeof(timeout->value)); - timeout->value = cpu_to_le16(MWIFIEX_TDLS_IDLE_TIMEOUT_IN_SEC); - config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout); - - break; - default: - mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS operation\n"); - return -ENOTSUPP; - } - - le16_add_cpu(&cmd->size, config_len); - - return 0; -} - -/* This function prepares command of sdio rx aggr info. */ -static int mwifiex_cmd_sdio_rx_aggr_cfg(struct host_cmd_ds_command *cmd, - u16 cmd_action, void *data_buf) -{ - struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = - &cmd->params.sdio_rx_aggr_cfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_SDIO_SP_RX_AGGR_CFG); - cmd->size = - cpu_to_le16(sizeof(struct host_cmd_sdio_sp_rx_aggr_cfg) + - S_DS_GEN); - cfg->action = cmd_action; - if (cmd_action == HostCmd_ACT_GEN_SET) - cfg->enable = *(u8 *)data_buf; - - return 0; -} - -/* - * This function prepares the commands before sending them to the firmware. - * - * This is a generic function which calls specific command preparation - * routines based upon the command number. - */ -int mwifiex_sta_prepare_cmd(struct mwifiex_private *priv, uint16_t cmd_no, - u16 cmd_action, u32 cmd_oid, - void *data_buf, void *cmd_buf) -{ - struct host_cmd_ds_command *cmd_ptr = cmd_buf; - int ret = 0; - - /* Prepare command */ - switch (cmd_no) { - case HostCmd_CMD_GET_HW_SPEC: - ret = mwifiex_cmd_get_hw_spec(priv, cmd_ptr); - break; - case HostCmd_CMD_CFG_DATA: - ret = mwifiex_cmd_cfg_data(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_MAC_CONTROL: - ret = mwifiex_cmd_mac_control(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_802_11_MAC_ADDRESS: - ret = mwifiex_cmd_802_11_mac_address(priv, cmd_ptr, - cmd_action); - break; - case HostCmd_CMD_MAC_MULTICAST_ADR: - ret = mwifiex_cmd_mac_multicast_adr(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_TX_RATE_CFG: - ret = mwifiex_cmd_tx_rate_cfg(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_TXPWR_CFG: - ret = mwifiex_cmd_tx_power_cfg(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_RF_TX_PWR: - ret = mwifiex_cmd_rf_tx_power(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_RF_ANTENNA: - ret = mwifiex_cmd_rf_antenna(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_802_11_PS_MODE_ENH: - ret = mwifiex_cmd_enh_power_mode(priv, cmd_ptr, cmd_action, - (uint16_t)cmd_oid, data_buf); - break; - case HostCmd_CMD_802_11_HS_CFG_ENH: - ret = mwifiex_cmd_802_11_hs_cfg(priv, cmd_ptr, cmd_action, - (struct mwifiex_hs_config_param *) data_buf); - break; - case HostCmd_CMD_802_11_SCAN: - ret = mwifiex_cmd_802_11_scan(cmd_ptr, data_buf); - break; - case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = mwifiex_cmd_802_11_bg_scan_query(cmd_ptr); - break; - case HostCmd_CMD_802_11_ASSOCIATE: - ret = mwifiex_cmd_802_11_associate(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_802_11_DEAUTHENTICATE: - ret = mwifiex_cmd_802_11_deauthenticate(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_802_11_AD_HOC_START: - ret = mwifiex_cmd_802_11_ad_hoc_start(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_802_11_GET_LOG: - ret = mwifiex_cmd_802_11_get_log(cmd_ptr); - break; - case HostCmd_CMD_802_11_AD_HOC_JOIN: - ret = mwifiex_cmd_802_11_ad_hoc_join(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_802_11_AD_HOC_STOP: - ret = mwifiex_cmd_802_11_ad_hoc_stop(cmd_ptr); - break; - case HostCmd_CMD_RSSI_INFO: - ret = mwifiex_cmd_802_11_rssi_info(priv, cmd_ptr, cmd_action); - break; - case HostCmd_CMD_802_11_SNMP_MIB: - ret = mwifiex_cmd_802_11_snmp_mib(priv, cmd_ptr, cmd_action, - cmd_oid, data_buf); - break; - case HostCmd_CMD_802_11_TX_RATE_QUERY: - cmd_ptr->command = - cpu_to_le16(HostCmd_CMD_802_11_TX_RATE_QUERY); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_tx_rate_query) + - S_DS_GEN); - priv->tx_rate = 0; - ret = 0; - break; - case HostCmd_CMD_VERSION_EXT: - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->params.verext.version_str_sel = - (u8) (*((u32 *) data_buf)); - memcpy(&cmd_ptr->params, data_buf, - sizeof(struct host_cmd_ds_version_ext)); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_version_ext) + - S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_MGMT_FRAME_REG: - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->params.reg_mask.action = cpu_to_le16(cmd_action); - cmd_ptr->params.reg_mask.mask = cpu_to_le32(*(u32 *)data_buf); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_mgmt_frame_reg) + - S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_REMAIN_ON_CHAN: - cmd_ptr->command = cpu_to_le16(cmd_no); - memcpy(&cmd_ptr->params, data_buf, - sizeof(struct host_cmd_ds_remain_on_chan)); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_remain_on_chan) + - S_DS_GEN); - break; - case HostCmd_CMD_11AC_CFG: - ret = mwifiex_cmd_11ac_cfg(priv, cmd_ptr, cmd_action, data_buf); - break; - case HostCmd_CMD_P2P_MODE_CFG: - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->params.mode_cfg.action = cpu_to_le16(cmd_action); - cmd_ptr->params.mode_cfg.mode = cpu_to_le16(*(u16 *)data_buf); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_p2p_mode_cfg) + - S_DS_GEN); - break; - case HostCmd_CMD_FUNC_INIT: - if (priv->adapter->hw_status == MWIFIEX_HW_STATUS_RESET) - priv->adapter->hw_status = MWIFIEX_HW_STATUS_READY; - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->size = cpu_to_le16(S_DS_GEN); - break; - case HostCmd_CMD_FUNC_SHUTDOWN: - priv->adapter->hw_status = MWIFIEX_HW_STATUS_RESET; - cmd_ptr->command = cpu_to_le16(cmd_no); - cmd_ptr->size = cpu_to_le16(S_DS_GEN); - break; - case HostCmd_CMD_11N_ADDBA_REQ: - ret = mwifiex_cmd_11n_addba_req(cmd_ptr, data_buf); - break; - case HostCmd_CMD_11N_DELBA: - ret = mwifiex_cmd_11n_delba(cmd_ptr, data_buf); - break; - case HostCmd_CMD_11N_ADDBA_RSP: - ret = mwifiex_cmd_11n_addba_rsp_gen(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_802_11_KEY_MATERIAL: - ret = mwifiex_cmd_802_11_key_material(priv, cmd_ptr, - cmd_action, cmd_oid, - data_buf); - break; - case HostCmd_CMD_802_11D_DOMAIN_INFO: - ret = mwifiex_cmd_802_11d_domain_info(priv, cmd_ptr, - cmd_action); - break; - case HostCmd_CMD_RECONFIGURE_TX_BUFF: - ret = mwifiex_cmd_recfg_tx_buf(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_AMSDU_AGGR_CTRL: - ret = mwifiex_cmd_amsdu_aggr_ctrl(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_11N_CFG: - ret = mwifiex_cmd_11n_cfg(priv, cmd_ptr, cmd_action, data_buf); - break; - case HostCmd_CMD_WMM_GET_STATUS: - mwifiex_dbg(priv->adapter, CMD, - "cmd: WMM: WMM_GET_STATUS cmd sent\n"); - cmd_ptr->command = cpu_to_le16(HostCmd_CMD_WMM_GET_STATUS); - cmd_ptr->size = - cpu_to_le16(sizeof(struct host_cmd_ds_wmm_get_status) + - S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: - ret = mwifiex_cmd_ibss_coalescing_status(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_802_11_SCAN_EXT: - ret = mwifiex_cmd_802_11_scan_ext(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_MEM_ACCESS: - ret = mwifiex_cmd_mem_access(cmd_ptr, cmd_action, data_buf); - break; - case HostCmd_CMD_MAC_REG_ACCESS: - case HostCmd_CMD_BBP_REG_ACCESS: - case HostCmd_CMD_RF_REG_ACCESS: - case HostCmd_CMD_PMIC_REG_ACCESS: - case HostCmd_CMD_CAU_REG_ACCESS: - case HostCmd_CMD_802_11_EEPROM_ACCESS: - ret = mwifiex_cmd_reg_access(cmd_ptr, cmd_action, data_buf); - break; - case HostCmd_CMD_SET_BSS_MODE: - cmd_ptr->command = cpu_to_le16(cmd_no); - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) - cmd_ptr->params.bss_mode.con_type = - CONNECTION_TYPE_ADHOC; - else if (priv->bss_mode == NL80211_IFTYPE_STATION || - priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) - cmd_ptr->params.bss_mode.con_type = - CONNECTION_TYPE_INFRA; - else if (priv->bss_mode == NL80211_IFTYPE_AP || - priv->bss_mode == NL80211_IFTYPE_P2P_GO) - cmd_ptr->params.bss_mode.con_type = CONNECTION_TYPE_AP; - cmd_ptr->size = cpu_to_le16(sizeof(struct - host_cmd_ds_set_bss_mode) + S_DS_GEN); - ret = 0; - break; - case HostCmd_CMD_PCIE_DESC_DETAILS: - ret = mwifiex_cmd_pcie_host_spec(priv, cmd_ptr, cmd_action); - break; - case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: - ret = mwifiex_cmd_802_11_subsc_evt(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_MEF_CFG: - ret = mwifiex_cmd_mef_cfg(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_COALESCE_CFG: - ret = mwifiex_cmd_coalesce_cfg(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_TDLS_OPER: - ret = mwifiex_cmd_tdls_oper(priv, cmd_ptr, data_buf); - break; - case HostCmd_CMD_TDLS_CONFIG: - ret = mwifiex_cmd_tdls_config(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_CHAN_REPORT_REQUEST: - ret = mwifiex_cmd_issue_chan_report_request(priv, cmd_ptr, - data_buf); - break; - case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: - ret = mwifiex_cmd_sdio_rx_aggr_cfg(cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_MC_POLICY: - ret = mwifiex_cmd_set_mc_policy(priv, cmd_ptr, cmd_action, - data_buf); - break; - case HostCmd_CMD_ROBUST_COEX: - ret = mwifiex_cmd_robust_coex(priv, cmd_ptr, cmd_action, - data_buf); - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "PREP_CMD: unknown cmd- %#x\n", cmd_no); - ret = -1; - break; - } - return ret; -} - -/* - * This function issues commands to initialize firmware. - * - * This is called after firmware download to bring the card to - * working state. - * Function is also called during reinitialization of virtual - * interfaces. - * - * The following commands are issued sequentially - - * - Set PCI-Express host buffer configuration (PCIE only) - * - Function init (for first interface only) - * - Read MAC address (for first interface only) - * - Reconfigure Tx buffer size (for first interface only) - * - Enable auto deep sleep (for first interface only) - * - Get Tx rate - * - Get Tx power - * - Set IBSS coalescing status - * - Set AMSDU aggregation control - * - Set 11d control - * - Set MAC control (this must be the last command to initialize firmware) - */ -int mwifiex_sta_init_cmd(struct mwifiex_private *priv, u8 first_sta, bool init) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret; - u16 enable = true; - struct mwifiex_ds_11n_amsdu_aggr_ctrl amsdu_aggr_ctrl; - struct mwifiex_ds_auto_ds auto_ds; - enum state_11d_t state_11d; - struct mwifiex_ds_11n_tx_cfg tx_cfg; - u8 sdio_sp_rx_aggr_enable; - - if (first_sta) { - if (priv->adapter->iface_type == MWIFIEX_PCIE) { - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_PCIE_DESC_DETAILS, - HostCmd_ACT_GEN_SET, 0, NULL, - true); - if (ret) - return -1; - } - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_FUNC_INIT, - HostCmd_ACT_GEN_SET, 0, NULL, true); - if (ret) - return -1; - - /* Download calibration data to firmware. - * The cal-data can be read from device tree and/or - * a configuration file and downloaded to firmware. - */ - adapter->dt_node = - of_find_node_by_name(NULL, "marvell_cfgdata"); - if (adapter->dt_node) { - ret = mwifiex_dnld_dt_cfgdata(priv, adapter->dt_node, - "marvell,caldata"); - if (ret) - return -1; - } - - if (adapter->cal_data) { - ret = mwifiex_send_cmd(priv, HostCmd_CMD_CFG_DATA, - HostCmd_ACT_GEN_SET, 0, NULL, - true); - if (ret) - return -1; - } - - /* Read MAC address from HW */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_GET_HW_SPEC, - HostCmd_ACT_GEN_GET, 0, NULL, true); - if (ret) - return -1; - - /** Set SDIO Single Port RX Aggr Info */ - if (priv->adapter->iface_type == MWIFIEX_SDIO && - ISSUPP_SDIO_SPA_ENABLED(priv->adapter->fw_cap_info) && - !priv->adapter->host_disable_sdio_rx_aggr) { - sdio_sp_rx_aggr_enable = true; - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_SDIO_SP_RX_AGGR_CFG, - HostCmd_ACT_GEN_SET, 0, - &sdio_sp_rx_aggr_enable, - true); - if (ret) { - mwifiex_dbg(priv->adapter, ERROR, - "error while enabling SP aggregation..disable it"); - adapter->sdio_rx_aggr_enable = false; - } - } - - /* Reconfigure tx buf size */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_RECONFIGURE_TX_BUFF, - HostCmd_ACT_GEN_SET, 0, - &priv->adapter->tx_buf_size, true); - if (ret) - return -1; - - if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { - /* Enable IEEE PS by default */ - priv->adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_STA_PS, NULL, - true); - if (ret) - return -1; - } - - if (drcs) { - adapter->drcs_enabled = true; - if (ISSUPP_DRCS_ENABLED(adapter->fw_cap_info)) - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_MC_POLICY, - HostCmd_ACT_GEN_SET, 0, - &adapter->drcs_enabled, - true); - if (ret) - return -1; - } - } - - /* get tx rate */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_TX_RATE_CFG, - HostCmd_ACT_GEN_GET, 0, NULL, true); - if (ret) - return -1; - priv->data_rate = 0; - - /* get tx power */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_RF_TX_PWR, - HostCmd_ACT_GEN_GET, 0, NULL, true); - if (ret) - return -1; - - if (priv->bss_type == MWIFIEX_BSS_TYPE_STA) { - /* set ibss coalescing_status */ - ret = mwifiex_send_cmd( - priv, - HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, - HostCmd_ACT_GEN_SET, 0, &enable, true); - if (ret) - return -1; - } - - memset(&amsdu_aggr_ctrl, 0, sizeof(amsdu_aggr_ctrl)); - amsdu_aggr_ctrl.enable = true; - /* Send request to firmware */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_AMSDU_AGGR_CTRL, - HostCmd_ACT_GEN_SET, 0, - &amsdu_aggr_ctrl, true); - if (ret) - return -1; - /* MAC Control must be the last command in init_fw */ - /* set MAC Control */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter, true); - if (ret) - return -1; - - if (!disable_auto_ds && - first_sta && priv->adapter->iface_type != MWIFIEX_USB && - priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { - /* Enable auto deep sleep */ - auto_ds.auto_ds = DEEP_SLEEP_ON; - auto_ds.idle_time = DEEP_SLEEP_IDLE_TIME; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - EN_AUTO_PS, BITMAP_AUTO_DS, - &auto_ds, true); - if (ret) - return -1; - } - - if (priv->bss_type != MWIFIEX_BSS_TYPE_UAP) { - /* Send cmd to FW to enable/disable 11D function */ - state_11d = ENABLE_11D; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11D_I, - &state_11d, true); - if (ret) - mwifiex_dbg(priv->adapter, ERROR, - "11D: failed to enable 11D\n"); - } - - /* Send cmd to FW to configure 11n specific configuration - * (Short GI, Channel BW, Green field support etc.) for transmit - */ - tx_cfg.tx_htcap = MWIFIEX_FW_DEF_HTTXCFG; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_11N_CFG, - HostCmd_ACT_GEN_SET, 0, &tx_cfg, true); - - if (init) { - /* set last_init_cmd before sending the command */ - priv->adapter->last_init_cmd = HostCmd_CMD_11N_CFG; - ret = -EINPROGRESS; - } - - return ret; -} diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c deleted file mode 100644 index 9ac7aa2431b4..000000000000 --- a/drivers/net/wireless/mwifiex/sta_cmdresp.c +++ /dev/null @@ -1,1249 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station command response handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11ac.h" - - -/* - * This function handles the command response error case. - * - * For scan response error, the function cancels all the pending - * scan commands and generates an event to inform the applications - * of the scan completion. - * - * For Power Save command failure, we do not retry enter PS - * command in case of Ad-hoc mode. - * - * For all other response errors, the current command buffer is freed - * and returned to the free command queue. - */ -static void -mwifiex_process_cmdresp_error(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct cmd_ctrl_node *cmd_node = NULL, *tmp_node; - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_802_11_ps_mode_enh *pm; - unsigned long flags; - - mwifiex_dbg(adapter, ERROR, - "CMD_RESP: cmd %#x error, result=%#x\n", - resp->command, resp->result); - - if (adapter->curr_cmd->wait_q_enabled) - adapter->cmd_wait_q.status = -1; - - switch (le16_to_cpu(resp->command)) { - case HostCmd_CMD_802_11_PS_MODE_ENH: - pm = &resp->params.psmode_enh; - mwifiex_dbg(adapter, ERROR, - "PS_MODE_ENH cmd failed: result=0x%x action=0x%X\n", - resp->result, le16_to_cpu(pm->action)); - /* We do not re-try enter-ps command in ad-hoc mode. */ - if (le16_to_cpu(pm->action) == EN_AUTO_PS && - (le16_to_cpu(pm->params.ps_bitmap) & BITMAP_STA_PS) && - priv->bss_mode == NL80211_IFTYPE_ADHOC) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - - break; - case HostCmd_CMD_802_11_SCAN: - case HostCmd_CMD_802_11_SCAN_EXT: - /* Cancel all pending scan command */ - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - list_for_each_entry_safe(cmd_node, tmp_node, - &adapter->scan_pending_q, list) { - list_del(&cmd_node->list); - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, - flags); - mwifiex_insert_cmd_to_free_q(adapter, cmd_node); - spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); - } - spin_unlock_irqrestore(&adapter->scan_pending_q_lock, flags); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->scan_processing = false; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); - break; - - case HostCmd_CMD_MAC_CONTROL: - break; - - case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: - mwifiex_dbg(adapter, MSG, - "SDIO RX single-port aggregation Not support\n"); - break; - - default: - break; - } - /* Handling errors here */ - mwifiex_recycle_cmd_node(adapter, adapter->curr_cmd); - - spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); - adapter->curr_cmd = NULL; - spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); -} - -/* - * This function handles the command response of get RSSI info. - * - * Handling includes changing the header fields into CPU format - * and saving the following parameters in driver - - * - Last data and beacon RSSI value - * - Average data and beacon RSSI value - * - Last data and beacon NF value - * - Average data and beacon NF value - * - * The parameters are send to the application as well, along with - * calculated SNR values. - */ -static int mwifiex_ret_802_11_rssi_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_rssi_info_rsp *rssi_info_rsp = - &resp->params.rssi_info_rsp; - struct mwifiex_ds_misc_subsc_evt *subsc_evt = - &priv->async_subsc_evt_storage; - - priv->data_rssi_last = le16_to_cpu(rssi_info_rsp->data_rssi_last); - priv->data_nf_last = le16_to_cpu(rssi_info_rsp->data_nf_last); - - priv->data_rssi_avg = le16_to_cpu(rssi_info_rsp->data_rssi_avg); - priv->data_nf_avg = le16_to_cpu(rssi_info_rsp->data_nf_avg); - - priv->bcn_rssi_last = le16_to_cpu(rssi_info_rsp->bcn_rssi_last); - priv->bcn_nf_last = le16_to_cpu(rssi_info_rsp->bcn_nf_last); - - priv->bcn_rssi_avg = le16_to_cpu(rssi_info_rsp->bcn_rssi_avg); - priv->bcn_nf_avg = le16_to_cpu(rssi_info_rsp->bcn_nf_avg); - - if (priv->subsc_evt_rssi_state == EVENT_HANDLED) - return 0; - - memset(subsc_evt, 0x00, sizeof(struct mwifiex_ds_misc_subsc_evt)); - - /* Resubscribe low and high rssi events with new thresholds */ - subsc_evt->events = BITMASK_BCN_RSSI_LOW | BITMASK_BCN_RSSI_HIGH; - subsc_evt->action = HostCmd_ACT_BITWISE_SET; - if (priv->subsc_evt_rssi_state == RSSI_LOW_RECVD) { - subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg - - priv->cqm_rssi_hyst); - subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); - } else if (priv->subsc_evt_rssi_state == RSSI_HIGH_RECVD) { - subsc_evt->bcn_l_rssi_cfg.abs_value = abs(priv->cqm_rssi_thold); - subsc_evt->bcn_h_rssi_cfg.abs_value = abs(priv->bcn_rssi_avg + - priv->cqm_rssi_hyst); - } - subsc_evt->bcn_l_rssi_cfg.evt_freq = 1; - subsc_evt->bcn_h_rssi_cfg.evt_freq = 1; - - priv->subsc_evt_rssi_state = EVENT_HANDLED; - - mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SUBSCRIBE_EVENT, - 0, 0, subsc_evt, false); - - return 0; -} - -/* - * This function handles the command response of set/get SNMP - * MIB parameters. - * - * Handling includes changing the header fields into CPU format - * and saving the parameter in driver. - * - * The following parameters are supported - - * - Fragmentation threshold - * - RTS threshold - * - Short retry limit - */ -static int mwifiex_ret_802_11_snmp_mib(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - u32 *data_buf) -{ - struct host_cmd_ds_802_11_snmp_mib *smib = &resp->params.smib; - u16 oid = le16_to_cpu(smib->oid); - u16 query_type = le16_to_cpu(smib->query_type); - u32 ul_temp; - - mwifiex_dbg(priv->adapter, INFO, - "info: SNMP_RESP: oid value = %#x,\t" - "query_type = %#x, buf size = %#x\n", - oid, query_type, le16_to_cpu(smib->buf_size)); - if (query_type == HostCmd_ACT_GEN_GET) { - ul_temp = le16_to_cpu(*((__le16 *) (smib->value))); - if (data_buf) - *data_buf = ul_temp; - switch (oid) { - case FRAG_THRESH_I: - mwifiex_dbg(priv->adapter, INFO, - "info: SNMP_RESP: FragThsd =%u\n", - ul_temp); - break; - case RTS_THRESH_I: - mwifiex_dbg(priv->adapter, INFO, - "info: SNMP_RESP: RTSThsd =%u\n", - ul_temp); - break; - case SHORT_RETRY_LIM_I: - mwifiex_dbg(priv->adapter, INFO, - "info: SNMP_RESP: TxRetryCount=%u\n", - ul_temp); - break; - case DTIM_PERIOD_I: - mwifiex_dbg(priv->adapter, INFO, - "info: SNMP_RESP: DTIM period=%u\n", - ul_temp); - default: - break; - } - } - - return 0; -} - -/* - * This function handles the command response of get log request - * - * Handling includes changing the header fields into CPU format - * and sending the received parameters to application. - */ -static int mwifiex_ret_get_log(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct mwifiex_ds_get_stats *stats) -{ - struct host_cmd_ds_802_11_get_log *get_log = - &resp->params.get_log; - - if (stats) { - stats->mcast_tx_frame = le32_to_cpu(get_log->mcast_tx_frame); - stats->failed = le32_to_cpu(get_log->failed); - stats->retry = le32_to_cpu(get_log->retry); - stats->multi_retry = le32_to_cpu(get_log->multi_retry); - stats->frame_dup = le32_to_cpu(get_log->frame_dup); - stats->rts_success = le32_to_cpu(get_log->rts_success); - stats->rts_failure = le32_to_cpu(get_log->rts_failure); - stats->ack_failure = le32_to_cpu(get_log->ack_failure); - stats->rx_frag = le32_to_cpu(get_log->rx_frag); - stats->mcast_rx_frame = le32_to_cpu(get_log->mcast_rx_frame); - stats->fcs_error = le32_to_cpu(get_log->fcs_error); - stats->tx_frame = le32_to_cpu(get_log->tx_frame); - stats->wep_icv_error[0] = - le32_to_cpu(get_log->wep_icv_err_cnt[0]); - stats->wep_icv_error[1] = - le32_to_cpu(get_log->wep_icv_err_cnt[1]); - stats->wep_icv_error[2] = - le32_to_cpu(get_log->wep_icv_err_cnt[2]); - stats->wep_icv_error[3] = - le32_to_cpu(get_log->wep_icv_err_cnt[3]); - stats->bcn_rcv_cnt = le32_to_cpu(get_log->bcn_rcv_cnt); - stats->bcn_miss_cnt = le32_to_cpu(get_log->bcn_miss_cnt); - } - - return 0; -} - -/* - * This function handles the command response of set/get Tx rate - * configurations. - * - * Handling includes changing the header fields into CPU format - * and saving the following parameters in driver - - * - DSSS rate bitmap - * - OFDM rate bitmap - * - HT MCS rate bitmaps - * - * Based on the new rate bitmaps, the function re-evaluates if - * auto data rate has been activated. If not, it sends another - * query to the firmware to get the current Tx data rate. - */ -static int mwifiex_ret_tx_rate_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_tx_rate_cfg *rate_cfg = &resp->params.tx_rate_cfg; - struct mwifiex_rate_scope *rate_scope; - struct mwifiex_ie_types_header *head; - u16 tlv, tlv_buf_len, tlv_buf_left; - u8 *tlv_buf; - u32 i; - - tlv_buf = ((u8 *)rate_cfg) + sizeof(struct host_cmd_ds_tx_rate_cfg); - tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*rate_cfg); - - while (tlv_buf_left >= sizeof(*head)) { - head = (struct mwifiex_ie_types_header *)tlv_buf; - tlv = le16_to_cpu(head->type); - tlv_buf_len = le16_to_cpu(head->len); - - if (tlv_buf_left < (sizeof(*head) + tlv_buf_len)) - break; - - switch (tlv) { - case TLV_TYPE_RATE_SCOPE: - rate_scope = (struct mwifiex_rate_scope *) tlv_buf; - priv->bitmap_rates[0] = - le16_to_cpu(rate_scope->hr_dsss_rate_bitmap); - priv->bitmap_rates[1] = - le16_to_cpu(rate_scope->ofdm_rate_bitmap); - for (i = 0; - i < - sizeof(rate_scope->ht_mcs_rate_bitmap) / - sizeof(u16); i++) - priv->bitmap_rates[2 + i] = - le16_to_cpu(rate_scope-> - ht_mcs_rate_bitmap[i]); - - if (priv->adapter->fw_api_ver == MWIFIEX_FW_V15) { - for (i = 0; i < ARRAY_SIZE(rate_scope-> - vht_mcs_rate_bitmap); - i++) - priv->bitmap_rates[10 + i] = - le16_to_cpu(rate_scope-> - vht_mcs_rate_bitmap[i]); - } - break; - /* Add RATE_DROP tlv here */ - } - - tlv_buf += (sizeof(*head) + tlv_buf_len); - tlv_buf_left -= (sizeof(*head) + tlv_buf_len); - } - - priv->is_data_rate_auto = mwifiex_is_rate_auto(priv); - - if (priv->is_data_rate_auto) - priv->data_rate = 0; - else - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL, false); - - return 0; -} - -/* - * This function handles the command response of get Tx power level. - * - * Handling includes saving the maximum and minimum Tx power levels - * in driver, as well as sending the values to user. - */ -static int mwifiex_get_power_level(struct mwifiex_private *priv, void *data_buf) -{ - int length, max_power = -1, min_power = -1; - struct mwifiex_types_power_group *pg_tlv_hdr; - struct mwifiex_power_group *pg; - - if (!data_buf) - return -1; - - pg_tlv_hdr = (struct mwifiex_types_power_group *)((u8 *)data_buf); - pg = (struct mwifiex_power_group *) - ((u8 *) pg_tlv_hdr + sizeof(struct mwifiex_types_power_group)); - length = le16_to_cpu(pg_tlv_hdr->length); - - /* At least one structure required to update power */ - if (length < sizeof(struct mwifiex_power_group)) - return 0; - - max_power = pg->power_max; - min_power = pg->power_min; - length -= sizeof(struct mwifiex_power_group); - - while (length >= sizeof(struct mwifiex_power_group)) { - pg++; - if (max_power < pg->power_max) - max_power = pg->power_max; - - if (min_power > pg->power_min) - min_power = pg->power_min; - - length -= sizeof(struct mwifiex_power_group); - } - priv->min_tx_power_level = (u8) min_power; - priv->max_tx_power_level = (u8) max_power; - - return 0; -} - -/* - * This function handles the command response of set/get Tx power - * configurations. - * - * Handling includes changing the header fields into CPU format - * and saving the current Tx power level in driver. - */ -static int mwifiex_ret_tx_power_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_ds_txpwr_cfg *txp_cfg = &resp->params.txp_cfg; - struct mwifiex_types_power_group *pg_tlv_hdr; - struct mwifiex_power_group *pg; - u16 action = le16_to_cpu(txp_cfg->action); - u16 tlv_buf_left; - - pg_tlv_hdr = (struct mwifiex_types_power_group *) - ((u8 *)txp_cfg + - sizeof(struct host_cmd_ds_txpwr_cfg)); - - pg = (struct mwifiex_power_group *) - ((u8 *)pg_tlv_hdr + - sizeof(struct mwifiex_types_power_group)); - - tlv_buf_left = le16_to_cpu(resp->size) - S_DS_GEN - sizeof(*txp_cfg); - if (tlv_buf_left < - le16_to_cpu(pg_tlv_hdr->length) + sizeof(*pg_tlv_hdr)) - return 0; - - switch (action) { - case HostCmd_ACT_GEN_GET: - if (adapter->hw_status == MWIFIEX_HW_STATUS_INITIALIZING) - mwifiex_get_power_level(priv, pg_tlv_hdr); - - priv->tx_power_level = (u16) pg->power_min; - break; - - case HostCmd_ACT_GEN_SET: - if (!le32_to_cpu(txp_cfg->mode)) - break; - - if (pg->power_max == pg->power_min) - priv->tx_power_level = (u16) pg->power_min; - break; - default: - mwifiex_dbg(adapter, ERROR, - "CMD_RESP: unknown cmd action %d\n", - action); - return 0; - } - mwifiex_dbg(adapter, INFO, - "info: Current TxPower Level = %d, Max Power=%d, Min Power=%d\n", - priv->tx_power_level, priv->max_tx_power_level, - priv->min_tx_power_level); - - return 0; -} - -/* - * This function handles the command response of get RF Tx power. - */ -static int mwifiex_ret_rf_tx_power(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_rf_tx_pwr *txp = &resp->params.txp; - u16 action = le16_to_cpu(txp->action); - - priv->tx_power_level = le16_to_cpu(txp->cur_level); - - if (action == HostCmd_ACT_GEN_GET) { - priv->max_tx_power_level = txp->max_power; - priv->min_tx_power_level = txp->min_power; - } - - mwifiex_dbg(priv->adapter, INFO, - "Current TxPower Level=%d, Max Power=%d, Min Power=%d\n", - priv->tx_power_level, priv->max_tx_power_level, - priv->min_tx_power_level); - - return 0; -} - -/* - * This function handles the command response of set rf antenna - */ -static int mwifiex_ret_rf_antenna(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_rf_ant_mimo *ant_mimo = &resp->params.ant_mimo; - struct host_cmd_ds_rf_ant_siso *ant_siso = &resp->params.ant_siso; - struct mwifiex_adapter *adapter = priv->adapter; - - if (adapter->hw_dev_mcs_support == HT_STREAM_2X2) - mwifiex_dbg(adapter, INFO, - "RF_ANT_RESP: Tx action = 0x%x, Tx Mode = 0x%04x\t" - "Rx action = 0x%x, Rx Mode = 0x%04x\n", - le16_to_cpu(ant_mimo->action_tx), - le16_to_cpu(ant_mimo->tx_ant_mode), - le16_to_cpu(ant_mimo->action_rx), - le16_to_cpu(ant_mimo->rx_ant_mode)); - else - mwifiex_dbg(adapter, INFO, - "RF_ANT_RESP: action = 0x%x, Mode = 0x%04x\n", - le16_to_cpu(ant_siso->action), - le16_to_cpu(ant_siso->ant_mode)); - - return 0; -} - -/* - * This function handles the command response of set/get MAC address. - * - * Handling includes saving the MAC address in driver. - */ -static int mwifiex_ret_802_11_mac_address(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_mac_address *cmd_mac_addr = - &resp->params.mac_addr; - - memcpy(priv->curr_addr, cmd_mac_addr->mac_addr, ETH_ALEN); - - mwifiex_dbg(priv->adapter, INFO, - "info: set mac address: %pM\n", priv->curr_addr); - - return 0; -} - -/* - * This function handles the command response of set/get MAC multicast - * address. - */ -static int mwifiex_ret_mac_multicast_adr(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - return 0; -} - -/* - * This function handles the command response of get Tx rate query. - * - * Handling includes changing the header fields into CPU format - * and saving the Tx rate and HT information parameters in driver. - * - * Both rate configuration and current data rate can be retrieved - * with this request. - */ -static int mwifiex_ret_802_11_tx_rate_query(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - priv->tx_rate = resp->params.tx_rate.tx_rate; - priv->tx_htinfo = resp->params.tx_rate.ht_info; - if (!priv->is_data_rate_auto) - priv->data_rate = - mwifiex_index_to_data_rate(priv, priv->tx_rate, - priv->tx_htinfo); - - return 0; -} - -/* - * This function handles the command response of a deauthenticate - * command. - * - * If the deauthenticated MAC matches the current BSS MAC, the connection - * state is reset. - */ -static int mwifiex_ret_802_11_deauthenticate(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - adapter->dbg.num_cmd_deauth++; - if (!memcmp(resp->params.deauth.mac_addr, - &priv->curr_bss_params.bss_descriptor.mac_address, - sizeof(resp->params.deauth.mac_addr))) - mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING); - - return 0; -} - -/* - * This function handles the command response of ad-hoc stop. - * - * The function resets the connection state in driver. - */ -static int mwifiex_ret_802_11_ad_hoc_stop(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - mwifiex_reset_connect_state(priv, WLAN_REASON_DEAUTH_LEAVING); - return 0; -} - -/* - * This function handles the command response of set/get v1 key material. - * - * Handling includes updating the driver parameters to reflect the - * changes. - */ -static int mwifiex_ret_802_11_key_material_v1(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_key_material *key = - &resp->params.key_material; - - if (le16_to_cpu(key->action) == HostCmd_ACT_GEN_SET) { - if ((le16_to_cpu(key->key_param_set.key_info) & KEY_MCAST)) { - mwifiex_dbg(priv->adapter, INFO, - "info: key: GTK is set\n"); - priv->wpa_is_gtk_set = true; - priv->scan_block = false; - priv->port_open = true; - } - } - - memset(priv->aes_key.key_param_set.key, 0, - sizeof(key->key_param_set.key)); - priv->aes_key.key_param_set.key_len = key->key_param_set.key_len; - memcpy(priv->aes_key.key_param_set.key, key->key_param_set.key, - le16_to_cpu(priv->aes_key.key_param_set.key_len)); - - return 0; -} - -/* - * This function handles the command response of set/get v2 key material. - * - * Handling includes updating the driver parameters to reflect the - * changes. - */ -static int mwifiex_ret_802_11_key_material_v2(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_key_material_v2 *key_v2; - __le16 len; - - key_v2 = &resp->params.key_material_v2; - if (le16_to_cpu(key_v2->action) == HostCmd_ACT_GEN_SET) { - if ((le16_to_cpu(key_v2->key_param_set.key_info) & KEY_MCAST)) { - mwifiex_dbg(priv->adapter, INFO, "info: key: GTK is set\n"); - priv->wpa_is_gtk_set = true; - priv->scan_block = false; - priv->port_open = true; - } - } - - if (key_v2->key_param_set.key_type != KEY_TYPE_ID_AES) - return 0; - - memset(priv->aes_key_v2.key_param_set.key_params.aes.key, 0, - WLAN_KEY_LEN_CCMP); - priv->aes_key_v2.key_param_set.key_params.aes.key_len = - key_v2->key_param_set.key_params.aes.key_len; - len = priv->aes_key_v2.key_param_set.key_params.aes.key_len; - memcpy(priv->aes_key_v2.key_param_set.key_params.aes.key, - key_v2->key_param_set.key_params.aes.key, le16_to_cpu(len)); - - return 0; -} - -/* Wrapper function for processing response of key material command */ -static int mwifiex_ret_802_11_key_material(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - if (priv->adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) - return mwifiex_ret_802_11_key_material_v2(priv, resp); - else - return mwifiex_ret_802_11_key_material_v1(priv, resp); -} - -/* - * This function handles the command response of get 11d domain information. - */ -static int mwifiex_ret_802_11d_domain_info(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11d_domain_info_rsp *domain_info = - &resp->params.domain_info_resp; - struct mwifiex_ietypes_domain_param_set *domain = &domain_info->domain; - u16 action = le16_to_cpu(domain_info->action); - u8 no_of_triplet; - - no_of_triplet = (u8) ((le16_to_cpu(domain->header.len) - - IEEE80211_COUNTRY_STRING_LEN) - / sizeof(struct ieee80211_country_ie_triplet)); - - mwifiex_dbg(priv->adapter, INFO, - "info: 11D Domain Info Resp: no_of_triplet=%d\n", - no_of_triplet); - - if (no_of_triplet > MWIFIEX_MAX_TRIPLET_802_11D) { - mwifiex_dbg(priv->adapter, FATAL, - "11D: invalid number of triplets %d returned\n", - no_of_triplet); - return -1; - } - - switch (action) { - case HostCmd_ACT_GEN_SET: /* Proc Set Action */ - break; - case HostCmd_ACT_GEN_GET: - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "11D: invalid action:%d\n", domain_info->action); - return -1; - } - - return 0; -} - -/* - * This function handles the command response of get extended version. - * - * Handling includes forming the extended version string and sending it - * to application. - */ -static int mwifiex_ret_ver_ext(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct host_cmd_ds_version_ext *version_ext) -{ - struct host_cmd_ds_version_ext *ver_ext = &resp->params.verext; - - if (version_ext) { - version_ext->version_str_sel = ver_ext->version_str_sel; - memcpy(version_ext->version_str, ver_ext->version_str, - sizeof(char) * 128); - memcpy(priv->version_str, ver_ext->version_str, 128); - } - return 0; -} - -/* - * This function handles the command response of remain on channel. - */ -static int -mwifiex_ret_remain_on_chan(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - struct host_cmd_ds_remain_on_chan *roc_cfg) -{ - struct host_cmd_ds_remain_on_chan *resp_cfg = &resp->params.roc_cfg; - - if (roc_cfg) - memcpy(roc_cfg, resp_cfg, sizeof(*roc_cfg)); - - return 0; -} - -/* - * This function handles the command response of P2P mode cfg. - */ -static int -mwifiex_ret_p2p_mode_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct host_cmd_ds_p2p_mode_cfg *mode_cfg = &resp->params.mode_cfg; - - if (data_buf) - *((u16 *)data_buf) = le16_to_cpu(mode_cfg->mode); - - return 0; -} - -/* This function handles the command response of mem_access command - */ -static int -mwifiex_ret_mem_access(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, void *pioctl_buf) -{ - struct host_cmd_ds_mem_access *mem = (void *)&resp->params.mem; - - priv->mem_rw.addr = le32_to_cpu(mem->addr); - priv->mem_rw.value = le32_to_cpu(mem->value); - - return 0; -} -/* - * This function handles the command response of register access. - * - * The register value and offset are returned to the user. For EEPROM - * access, the byte count is also returned. - */ -static int mwifiex_ret_reg_access(u16 type, struct host_cmd_ds_command *resp, - void *data_buf) -{ - struct mwifiex_ds_reg_rw *reg_rw; - struct mwifiex_ds_read_eeprom *eeprom; - union reg { - struct host_cmd_ds_mac_reg_access *mac; - struct host_cmd_ds_bbp_reg_access *bbp; - struct host_cmd_ds_rf_reg_access *rf; - struct host_cmd_ds_pmic_reg_access *pmic; - struct host_cmd_ds_802_11_eeprom_access *eeprom; - } r; - - if (!data_buf) - return 0; - - reg_rw = data_buf; - eeprom = data_buf; - switch (type) { - case HostCmd_CMD_MAC_REG_ACCESS: - r.mac = &resp->params.mac_reg; - reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.mac->offset)); - reg_rw->value = r.mac->value; - break; - case HostCmd_CMD_BBP_REG_ACCESS: - r.bbp = &resp->params.bbp_reg; - reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.bbp->offset)); - reg_rw->value = cpu_to_le32((u32) r.bbp->value); - break; - - case HostCmd_CMD_RF_REG_ACCESS: - r.rf = &resp->params.rf_reg; - reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset)); - reg_rw->value = cpu_to_le32((u32) r.bbp->value); - break; - case HostCmd_CMD_PMIC_REG_ACCESS: - r.pmic = &resp->params.pmic_reg; - reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.pmic->offset)); - reg_rw->value = cpu_to_le32((u32) r.pmic->value); - break; - case HostCmd_CMD_CAU_REG_ACCESS: - r.rf = &resp->params.rf_reg; - reg_rw->offset = cpu_to_le32((u32) le16_to_cpu(r.rf->offset)); - reg_rw->value = cpu_to_le32((u32) r.rf->value); - break; - case HostCmd_CMD_802_11_EEPROM_ACCESS: - r.eeprom = &resp->params.eeprom; - pr_debug("info: EEPROM read len=%x\n", r.eeprom->byte_count); - if (le16_to_cpu(eeprom->byte_count) < - le16_to_cpu(r.eeprom->byte_count)) { - eeprom->byte_count = cpu_to_le16(0); - pr_debug("info: EEPROM read length is too big\n"); - return -1; - } - eeprom->offset = r.eeprom->offset; - eeprom->byte_count = r.eeprom->byte_count; - if (le16_to_cpu(eeprom->byte_count) > 0) - memcpy(&eeprom->value, &r.eeprom->value, - le16_to_cpu(r.eeprom->byte_count)); - - break; - default: - return -1; - } - return 0; -} - -/* - * This function handles the command response of get IBSS coalescing status. - * - * If the received BSSID is different than the current one, the current BSSID, - * beacon interval, ATIM window and ERP information are updated, along with - * changing the ad-hoc state accordingly. - */ -static int mwifiex_ret_ibss_coalescing_status(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_ibss_status *ibss_coal_resp = - &(resp->params.ibss_coalescing); - - if (le16_to_cpu(ibss_coal_resp->action) == HostCmd_ACT_GEN_SET) - return 0; - - mwifiex_dbg(priv->adapter, INFO, - "info: new BSSID %pM\n", ibss_coal_resp->bssid); - - /* If rsp has NULL BSSID, Just return..... No Action */ - if (is_zero_ether_addr(ibss_coal_resp->bssid)) { - mwifiex_dbg(priv->adapter, FATAL, "new BSSID is NULL\n"); - return 0; - } - - /* If BSSID is diff, modify current BSS parameters */ - if (!ether_addr_equal(priv->curr_bss_params.bss_descriptor.mac_address, ibss_coal_resp->bssid)) { - /* BSSID */ - memcpy(priv->curr_bss_params.bss_descriptor.mac_address, - ibss_coal_resp->bssid, ETH_ALEN); - - /* Beacon Interval */ - priv->curr_bss_params.bss_descriptor.beacon_period - = le16_to_cpu(ibss_coal_resp->beacon_interval); - - /* ERP Information */ - priv->curr_bss_params.bss_descriptor.erp_flags = - (u8) le16_to_cpu(ibss_coal_resp->use_g_rate_protect); - - priv->adhoc_state = ADHOC_COALESCED; - } - - return 0; -} -static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_tdls_oper *cmd_tdls_oper = &resp->params.tdls_oper; - u16 reason = le16_to_cpu(cmd_tdls_oper->reason); - u16 action = le16_to_cpu(cmd_tdls_oper->tdls_action); - struct mwifiex_sta_node *node = - mwifiex_get_sta_entry(priv, cmd_tdls_oper->peer_mac); - - switch (action) { - case ACT_TDLS_DELETE: - if (reason) { - if (!node || reason == TDLS_ERR_LINK_NONEXISTENT) - mwifiex_dbg(priv->adapter, MSG, - "TDLS link delete for %pM failed: reason %d\n", - cmd_tdls_oper->peer_mac, reason); - else - mwifiex_dbg(priv->adapter, ERROR, - "TDLS link delete for %pM failed: reason %d\n", - cmd_tdls_oper->peer_mac, reason); - } else { - mwifiex_dbg(priv->adapter, MSG, - "TDLS link delete for %pM successful\n", - cmd_tdls_oper->peer_mac); - } - break; - case ACT_TDLS_CREATE: - if (reason) { - mwifiex_dbg(priv->adapter, ERROR, - "TDLS link creation for %pM failed: reason %d", - cmd_tdls_oper->peer_mac, reason); - if (node && reason != TDLS_ERR_LINK_EXISTS) - node->tdls_status = TDLS_SETUP_FAILURE; - } else { - mwifiex_dbg(priv->adapter, MSG, - "TDLS link creation for %pM successful", - cmd_tdls_oper->peer_mac); - } - break; - case ACT_TDLS_CONFIG: - if (reason) { - mwifiex_dbg(priv->adapter, ERROR, - "TDLS link config for %pM failed, reason %d\n", - cmd_tdls_oper->peer_mac, reason); - if (node) - node->tdls_status = TDLS_SETUP_FAILURE; - } else { - mwifiex_dbg(priv->adapter, MSG, - "TDLS link config for %pM successful\n", - cmd_tdls_oper->peer_mac); - } - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "Unknown TDLS command action response %d", action); - return -1; - } - - return 0; -} -/* - * This function handles the command response for subscribe event command. - */ -static int mwifiex_ret_subsc_evt(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_802_11_subsc_evt *cmd_sub_event = - &resp->params.subsc_evt; - - /* For every subscribe event command (Get/Set/Clear), FW reports the - * current set of subscribed events*/ - mwifiex_dbg(priv->adapter, EVENT, - "Bitmap of currently subscribed events: %16x\n", - le16_to_cpu(cmd_sub_event->events)); - - return 0; -} - -static int mwifiex_ret_uap_sta_list(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct host_cmd_ds_sta_list *sta_list = - &resp->params.sta_list; - struct mwifiex_ie_types_sta_info *sta_info = (void *)&sta_list->tlv; - int i; - struct mwifiex_sta_node *sta_node; - - for (i = 0; i < sta_list->sta_count; i++) { - sta_node = mwifiex_get_sta_entry(priv, sta_info->mac); - if (unlikely(!sta_node)) - continue; - - sta_node->stats.rssi = sta_info->rssi; - sta_info++; - } - - return 0; -} - -/* This function handles the command response of set_cfg_data */ -static int mwifiex_ret_cfg_data(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - if (resp->result != HostCmd_RESULT_OK) { - mwifiex_dbg(priv->adapter, ERROR, "Cal data cmd resp failed\n"); - return -1; - } - - return 0; -} - -/** This Function handles the command response of sdio rx aggr */ -static int mwifiex_ret_sdio_rx_aggr_cfg(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct host_cmd_sdio_sp_rx_aggr_cfg *cfg = - &resp->params.sdio_rx_aggr_cfg; - - adapter->sdio_rx_aggr_enable = cfg->enable; - adapter->sdio_rx_block_size = le16_to_cpu(cfg->block_size); - - return 0; -} - -static int mwifiex_ret_robust_coex(struct mwifiex_private *priv, - struct host_cmd_ds_command *resp, - bool *is_timeshare) -{ - struct host_cmd_ds_robust_coex *coex = &resp->params.coex; - struct mwifiex_ie_types_robust_coex *coex_tlv; - u16 action = le16_to_cpu(coex->action); - u32 mode; - - coex_tlv = (struct mwifiex_ie_types_robust_coex - *)((u8 *)coex + sizeof(struct host_cmd_ds_robust_coex)); - if (action == HostCmd_ACT_GEN_GET) { - mode = le32_to_cpu(coex_tlv->mode); - if (mode == MWIFIEX_COEX_MODE_TIMESHARE) - *is_timeshare = true; - else - *is_timeshare = false; - } - - return 0; -} - -/* - * This function handles the command responses. - * - * This is a generic function, which calls command specific - * response handlers based on the command ID. - */ -int mwifiex_process_sta_cmdresp(struct mwifiex_private *priv, u16 cmdresp_no, - struct host_cmd_ds_command *resp) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - void *data_buf = adapter->curr_cmd->data_buf; - - /* If the command is not successful, cleanup and return failure */ - if (resp->result != HostCmd_RESULT_OK) { - mwifiex_process_cmdresp_error(priv, resp); - return -1; - } - /* Command successful, handle response */ - switch (cmdresp_no) { - case HostCmd_CMD_GET_HW_SPEC: - ret = mwifiex_ret_get_hw_spec(priv, resp); - break; - case HostCmd_CMD_CFG_DATA: - ret = mwifiex_ret_cfg_data(priv, resp); - break; - case HostCmd_CMD_MAC_CONTROL: - break; - case HostCmd_CMD_802_11_MAC_ADDRESS: - ret = mwifiex_ret_802_11_mac_address(priv, resp); - break; - case HostCmd_CMD_MAC_MULTICAST_ADR: - ret = mwifiex_ret_mac_multicast_adr(priv, resp); - break; - case HostCmd_CMD_TX_RATE_CFG: - ret = mwifiex_ret_tx_rate_cfg(priv, resp); - break; - case HostCmd_CMD_802_11_SCAN: - ret = mwifiex_ret_802_11_scan(priv, resp); - adapter->curr_cmd->wait_q_enabled = false; - break; - case HostCmd_CMD_802_11_SCAN_EXT: - ret = mwifiex_ret_802_11_scan_ext(priv, resp); - adapter->curr_cmd->wait_q_enabled = false; - break; - case HostCmd_CMD_802_11_BG_SCAN_QUERY: - ret = mwifiex_ret_802_11_scan(priv, resp); - mwifiex_dbg(adapter, CMD, - "info: CMD_RESP: BG_SCAN result is ready!\n"); - break; - case HostCmd_CMD_TXPWR_CFG: - ret = mwifiex_ret_tx_power_cfg(priv, resp); - break; - case HostCmd_CMD_RF_TX_PWR: - ret = mwifiex_ret_rf_tx_power(priv, resp); - break; - case HostCmd_CMD_RF_ANTENNA: - ret = mwifiex_ret_rf_antenna(priv, resp); - break; - case HostCmd_CMD_802_11_PS_MODE_ENH: - ret = mwifiex_ret_enh_power_mode(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_HS_CFG_ENH: - ret = mwifiex_ret_802_11_hs_cfg(priv, resp); - break; - case HostCmd_CMD_802_11_ASSOCIATE: - ret = mwifiex_ret_802_11_associate(priv, resp); - break; - case HostCmd_CMD_802_11_DEAUTHENTICATE: - ret = mwifiex_ret_802_11_deauthenticate(priv, resp); - break; - case HostCmd_CMD_802_11_AD_HOC_START: - case HostCmd_CMD_802_11_AD_HOC_JOIN: - ret = mwifiex_ret_802_11_ad_hoc(priv, resp); - break; - case HostCmd_CMD_802_11_AD_HOC_STOP: - ret = mwifiex_ret_802_11_ad_hoc_stop(priv, resp); - break; - case HostCmd_CMD_802_11_GET_LOG: - ret = mwifiex_ret_get_log(priv, resp, data_buf); - break; - case HostCmd_CMD_RSSI_INFO: - ret = mwifiex_ret_802_11_rssi_info(priv, resp); - break; - case HostCmd_CMD_802_11_SNMP_MIB: - ret = mwifiex_ret_802_11_snmp_mib(priv, resp, data_buf); - break; - case HostCmd_CMD_802_11_TX_RATE_QUERY: - ret = mwifiex_ret_802_11_tx_rate_query(priv, resp); - break; - case HostCmd_CMD_VERSION_EXT: - ret = mwifiex_ret_ver_ext(priv, resp, data_buf); - break; - case HostCmd_CMD_REMAIN_ON_CHAN: - ret = mwifiex_ret_remain_on_chan(priv, resp, data_buf); - break; - case HostCmd_CMD_11AC_CFG: - break; - case HostCmd_CMD_P2P_MODE_CFG: - ret = mwifiex_ret_p2p_mode_cfg(priv, resp, data_buf); - break; - case HostCmd_CMD_MGMT_FRAME_REG: - case HostCmd_CMD_FUNC_INIT: - case HostCmd_CMD_FUNC_SHUTDOWN: - break; - case HostCmd_CMD_802_11_KEY_MATERIAL: - ret = mwifiex_ret_802_11_key_material(priv, resp); - break; - case HostCmd_CMD_802_11D_DOMAIN_INFO: - ret = mwifiex_ret_802_11d_domain_info(priv, resp); - break; - case HostCmd_CMD_11N_ADDBA_REQ: - ret = mwifiex_ret_11n_addba_req(priv, resp); - break; - case HostCmd_CMD_11N_DELBA: - ret = mwifiex_ret_11n_delba(priv, resp); - break; - case HostCmd_CMD_11N_ADDBA_RSP: - ret = mwifiex_ret_11n_addba_resp(priv, resp); - break; - case HostCmd_CMD_RECONFIGURE_TX_BUFF: - if (0xffff == (u16)le16_to_cpu(resp->params.tx_buf.buff_size)) { - if (adapter->iface_type == MWIFIEX_USB && - adapter->usb_mc_setup) { - if (adapter->if_ops.multi_port_resync) - adapter->if_ops. - multi_port_resync(adapter); - adapter->usb_mc_setup = false; - adapter->tx_lock_flag = false; - } - break; - } - adapter->tx_buf_size = (u16) le16_to_cpu(resp->params. - tx_buf.buff_size); - adapter->tx_buf_size = (adapter->tx_buf_size - / MWIFIEX_SDIO_BLOCK_SIZE) - * MWIFIEX_SDIO_BLOCK_SIZE; - adapter->curr_tx_buf_size = adapter->tx_buf_size; - mwifiex_dbg(adapter, CMD, "cmd: curr_tx_buf_size=%d\n", - adapter->curr_tx_buf_size); - - if (adapter->if_ops.update_mp_end_port) - adapter->if_ops.update_mp_end_port(adapter, - le16_to_cpu(resp->params.tx_buf.mp_end_port)); - break; - case HostCmd_CMD_AMSDU_AGGR_CTRL: - break; - case HostCmd_CMD_WMM_GET_STATUS: - ret = mwifiex_ret_wmm_get_status(priv, resp); - break; - case HostCmd_CMD_802_11_IBSS_COALESCING_STATUS: - ret = mwifiex_ret_ibss_coalescing_status(priv, resp); - break; - case HostCmd_CMD_MEM_ACCESS: - ret = mwifiex_ret_mem_access(priv, resp, data_buf); - break; - case HostCmd_CMD_MAC_REG_ACCESS: - case HostCmd_CMD_BBP_REG_ACCESS: - case HostCmd_CMD_RF_REG_ACCESS: - case HostCmd_CMD_PMIC_REG_ACCESS: - case HostCmd_CMD_CAU_REG_ACCESS: - case HostCmd_CMD_802_11_EEPROM_ACCESS: - ret = mwifiex_ret_reg_access(cmdresp_no, resp, data_buf); - break; - case HostCmd_CMD_SET_BSS_MODE: - break; - case HostCmd_CMD_11N_CFG: - break; - case HostCmd_CMD_PCIE_DESC_DETAILS: - break; - case HostCmd_CMD_802_11_SUBSCRIBE_EVENT: - ret = mwifiex_ret_subsc_evt(priv, resp); - break; - case HostCmd_CMD_UAP_SYS_CONFIG: - break; - case HOST_CMD_APCMD_STA_LIST: - ret = mwifiex_ret_uap_sta_list(priv, resp); - break; - case HostCmd_CMD_UAP_BSS_START: - adapter->tx_lock_flag = false; - adapter->pps_uapsd_mode = false; - adapter->delay_null_pkt = false; - priv->bss_started = 1; - break; - case HostCmd_CMD_UAP_BSS_STOP: - priv->bss_started = 0; - break; - case HostCmd_CMD_UAP_STA_DEAUTH: - break; - case HOST_CMD_APCMD_SYS_RESET: - break; - case HostCmd_CMD_MEF_CFG: - break; - case HostCmd_CMD_COALESCE_CFG: - break; - case HostCmd_CMD_TDLS_OPER: - ret = mwifiex_ret_tdls_oper(priv, resp); - case HostCmd_CMD_MC_POLICY: - break; - case HostCmd_CMD_CHAN_REPORT_REQUEST: - break; - case HostCmd_CMD_SDIO_SP_RX_AGGR_CFG: - ret = mwifiex_ret_sdio_rx_aggr_cfg(priv, resp); - break; - case HostCmd_CMD_TDLS_CONFIG: - break; - case HostCmd_CMD_ROBUST_COEX: - ret = mwifiex_ret_robust_coex(priv, resp, data_buf); - break; - default: - mwifiex_dbg(adapter, ERROR, - "CMD_RESP: unknown cmd response %#x\n", - resp->command); - break; - } - - return ret; -} diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c deleted file mode 100644 index ff3ee9dfbbd5..000000000000 --- a/drivers/net/wireless/mwifiex/sta_event.c +++ /dev/null @@ -1,864 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station event handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -/* - * This function resets the connection state. - * - * The function is invoked after receiving a disconnect event from firmware, - * and performs the following actions - - * - Set media status to disconnected - * - Clean up Tx and Rx packets - * - Resets SNR/NF/RSSI value in driver - * - Resets security configurations in driver - * - Enables auto data rate - * - Saves the previous SSID and BSSID so that they can - * be used for re-association, if required - * - Erases current SSID and BSSID information - * - Sends a disconnect event to upper layers/applications. - */ -void -mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - if (!priv->media_connected) - return; - - mwifiex_dbg(adapter, INFO, - "info: handles disconnect event\n"); - - priv->media_connected = false; - - priv->scan_block = false; - priv->port_open = false; - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) { - mwifiex_disable_all_tdls_links(priv); - - if (priv->adapter->auto_tdls) - mwifiex_clean_auto_tdls(priv); - } - - /* Free Tx and Rx packets, report disconnect to upper layer */ - mwifiex_clean_txrx(priv); - - /* Reset SNR/NF/RSSI values */ - priv->data_rssi_last = 0; - priv->data_nf_last = 0; - priv->data_rssi_avg = 0; - priv->data_nf_avg = 0; - priv->bcn_rssi_last = 0; - priv->bcn_nf_last = 0; - priv->bcn_rssi_avg = 0; - priv->bcn_nf_avg = 0; - priv->rxpd_rate = 0; - priv->rxpd_htinfo = 0; - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - priv->wpa_ie_len = 0; - - priv->sec_info.wapi_enabled = false; - priv->wapi_ie_len = 0; - priv->sec_info.wapi_key_on = false; - - priv->sec_info.encryption_mode = 0; - - /* Enable auto data rate */ - priv->is_data_rate_auto = true; - priv->data_rate = 0; - - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || - GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) && priv->hist_data) - mwifiex_hist_data_reset(priv); - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - priv->adhoc_state = ADHOC_IDLE; - priv->adhoc_is_link_sensed = false; - } - - /* - * Memorize the previous SSID and BSSID so - * it could be used for re-assoc - */ - - mwifiex_dbg(adapter, INFO, - "info: previous SSID=%s, SSID len=%u\n", - priv->prev_ssid.ssid, priv->prev_ssid.ssid_len); - - mwifiex_dbg(adapter, INFO, - "info: current SSID=%s, SSID len=%u\n", - priv->curr_bss_params.bss_descriptor.ssid.ssid, - priv->curr_bss_params.bss_descriptor.ssid.ssid_len); - - memcpy(&priv->prev_ssid, - &priv->curr_bss_params.bss_descriptor.ssid, - sizeof(struct cfg80211_ssid)); - - memcpy(priv->prev_bssid, - priv->curr_bss_params.bss_descriptor.mac_address, ETH_ALEN); - - /* Need to erase the current SSID and BSSID info */ - memset(&priv->curr_bss_params, 0x00, sizeof(priv->curr_bss_params)); - - adapter->tx_lock_flag = false; - adapter->pps_uapsd_mode = false; - - if (adapter->is_cmd_timedout && adapter->curr_cmd) - return; - priv->media_connected = false; - mwifiex_dbg(adapter, MSG, - "info: successfully disconnected from %pM: reason code %d\n", - priv->cfg_bssid, reason_code); - if (priv->bss_mode == NL80211_IFTYPE_STATION || - priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { - cfg80211_disconnected(priv->netdev, reason_code, NULL, 0, - false, GFP_KERNEL); - } - eth_zero_addr(priv->cfg_bssid); - - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); -} - -static int mwifiex_parse_tdls_event(struct mwifiex_private *priv, - struct sk_buff *event_skb) -{ - int ret = 0; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_tdls_generic_event *tdls_evt = - (void *)event_skb->data + sizeof(adapter->event_cause); - u8 *mac = tdls_evt->peer_mac; - - /* reserved 2 bytes are not mandatory in tdls event */ - if (event_skb->len < (sizeof(struct mwifiex_tdls_generic_event) - - sizeof(u16) - sizeof(adapter->event_cause))) { - mwifiex_dbg(adapter, ERROR, "Invalid event length!\n"); - return -1; - } - - sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac); - if (!sta_ptr) { - mwifiex_dbg(adapter, ERROR, "cannot get sta entry!\n"); - return -1; - } - - switch (le16_to_cpu(tdls_evt->type)) { - case TDLS_EVENT_LINK_TEAR_DOWN: - cfg80211_tdls_oper_request(priv->netdev, - tdls_evt->peer_mac, - NL80211_TDLS_TEARDOWN, - le16_to_cpu(tdls_evt->u.reason_code), - GFP_KERNEL); - break; - case TDLS_EVENT_CHAN_SWITCH_RESULT: - mwifiex_dbg(adapter, EVENT, "tdls channel switch result :\n"); - mwifiex_dbg(adapter, EVENT, - "status=0x%x, reason=0x%x cur_chan=%d\n", - tdls_evt->u.switch_result.status, - tdls_evt->u.switch_result.reason, - tdls_evt->u.switch_result.cur_chan); - - /* tdls channel switch failed */ - if (tdls_evt->u.switch_result.status != 0) { - switch (tdls_evt->u.switch_result.cur_chan) { - case TDLS_BASE_CHANNEL: - sta_ptr->tdls_status = TDLS_IN_BASE_CHAN; - break; - case TDLS_OFF_CHANNEL: - sta_ptr->tdls_status = TDLS_IN_OFF_CHAN; - break; - default: - break; - } - return ret; - } - - /* tdls channel switch success */ - switch (tdls_evt->u.switch_result.cur_chan) { - case TDLS_BASE_CHANNEL: - if (sta_ptr->tdls_status == TDLS_IN_BASE_CHAN) - break; - mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac, - false); - sta_ptr->tdls_status = TDLS_IN_BASE_CHAN; - break; - case TDLS_OFF_CHANNEL: - if (sta_ptr->tdls_status == TDLS_IN_OFF_CHAN) - break; - mwifiex_update_ralist_tx_pause_in_tdls_cs(priv, mac, - true); - sta_ptr->tdls_status = TDLS_IN_OFF_CHAN; - break; - default: - break; - } - - break; - case TDLS_EVENT_START_CHAN_SWITCH: - mwifiex_dbg(adapter, EVENT, "tdls start channel switch...\n"); - sta_ptr->tdls_status = TDLS_CHAN_SWITCHING; - break; - case TDLS_EVENT_CHAN_SWITCH_STOPPED: - mwifiex_dbg(adapter, EVENT, - "tdls chan switch stopped, reason=%d\n", - tdls_evt->u.cs_stop_reason); - break; - default: - break; - } - - return ret; -} - -static void mwifiex_process_uap_tx_pause(struct mwifiex_private *priv, - struct mwifiex_ie_types_header *tlv) -{ - struct mwifiex_tx_pause_tlv *tp; - struct mwifiex_sta_node *sta_ptr; - unsigned long flags; - - tp = (void *)tlv; - mwifiex_dbg(priv->adapter, EVENT, - "uap tx_pause: %pM pause=%d, pkts=%d\n", - tp->peermac, tp->tx_pause, - tp->pkt_cnt); - - if (ether_addr_equal(tp->peermac, priv->netdev->dev_addr)) { - if (tp->tx_pause) - priv->port_open = false; - else - priv->port_open = true; - } else if (is_multicast_ether_addr(tp->peermac)) { - mwifiex_update_ralist_tx_pause(priv, tp->peermac, tp->tx_pause); - } else { - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) { - sta_ptr->tx_pause = tp->tx_pause; - mwifiex_update_ralist_tx_pause(priv, tp->peermac, - tp->tx_pause); - } - } -} - -static void mwifiex_process_sta_tx_pause(struct mwifiex_private *priv, - struct mwifiex_ie_types_header *tlv) -{ - struct mwifiex_tx_pause_tlv *tp; - struct mwifiex_sta_node *sta_ptr; - int status; - unsigned long flags; - - tp = (void *)tlv; - mwifiex_dbg(priv->adapter, EVENT, - "sta tx_pause: %pM pause=%d, pkts=%d\n", - tp->peermac, tp->tx_pause, - tp->pkt_cnt); - - if (ether_addr_equal(tp->peermac, priv->cfg_bssid)) { - if (tp->tx_pause) - priv->port_open = false; - else - priv->port_open = true; - } else { - if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) - return; - - status = mwifiex_get_tdls_link_status(priv, tp->peermac); - if (mwifiex_is_tdls_link_setup(status)) { - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - sta_ptr = mwifiex_get_sta_entry(priv, tp->peermac); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - if (sta_ptr && sta_ptr->tx_pause != tp->tx_pause) { - sta_ptr->tx_pause = tp->tx_pause; - mwifiex_update_ralist_tx_pause(priv, - tp->peermac, - tp->tx_pause); - } - } - } -} - -void mwifiex_process_multi_chan_event(struct mwifiex_private *priv, - struct sk_buff *event_skb) -{ - struct mwifiex_ie_types_multi_chan_info *chan_info; - struct mwifiex_ie_types_mc_group_info *grp_info; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_header *tlv; - u16 tlv_buf_left, tlv_type, tlv_len; - int intf_num, bss_type, bss_num, i; - struct mwifiex_private *intf_priv; - - tlv_buf_left = event_skb->len - sizeof(u32); - chan_info = (void *)event_skb->data + sizeof(u32); - - if (le16_to_cpu(chan_info->header.type) != TLV_TYPE_MULTI_CHAN_INFO || - tlv_buf_left < sizeof(struct mwifiex_ie_types_multi_chan_info)) { - mwifiex_dbg(adapter, ERROR, - "unknown TLV in chan_info event\n"); - return; - } - - adapter->usb_mc_status = le16_to_cpu(chan_info->status); - mwifiex_dbg(adapter, EVENT, "multi chan operation %s\n", - adapter->usb_mc_status ? "started" : "over"); - - tlv_buf_left -= sizeof(struct mwifiex_ie_types_multi_chan_info); - tlv = (struct mwifiex_ie_types_header *)chan_info->tlv_buffer; - - while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_len = le16_to_cpu(tlv->len); - if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) > - tlv_buf_left) { - mwifiex_dbg(adapter, ERROR, "wrong tlv: tlvLen=%d,\t" - "tlvBufLeft=%d\n", tlv_len, tlv_buf_left); - break; - } - if (tlv_type != TLV_TYPE_MC_GROUP_INFO) { - mwifiex_dbg(adapter, ERROR, "wrong tlv type: 0x%x\n", - tlv_type); - break; - } - - grp_info = (struct mwifiex_ie_types_mc_group_info *)tlv; - intf_num = grp_info->intf_num; - for (i = 0; i < intf_num; i++) { - bss_type = grp_info->bss_type_numlist[i] >> 4; - bss_num = grp_info->bss_type_numlist[i] & BSS_NUM_MASK; - intf_priv = mwifiex_get_priv_by_id(adapter, bss_num, - bss_type); - if (!intf_priv) { - mwifiex_dbg(adapter, ERROR, - "Invalid bss_type bss_num\t" - "in multi channel event\n"); - continue; - } - if (adapter->iface_type == MWIFIEX_USB) { - u8 ep; - - ep = grp_info->hid_num.usb_ep_num; - if (ep == MWIFIEX_USB_EP_DATA || - ep == MWIFIEX_USB_EP_DATA_CH2) - intf_priv->usb_port = ep; - } - } - - tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) + - tlv_len; - tlv = (void *)((u8 *)tlv + tlv_len + - sizeof(struct mwifiex_ie_types_header)); - } - - if (adapter->iface_type == MWIFIEX_USB) { - adapter->tx_lock_flag = true; - adapter->usb_mc_setup = true; - mwifiex_multi_chan_resync(adapter); - } -} - -void mwifiex_process_tx_pause_event(struct mwifiex_private *priv, - struct sk_buff *event_skb) -{ - struct mwifiex_ie_types_header *tlv; - u16 tlv_type, tlv_len; - int tlv_buf_left; - - if (!priv->media_connected) { - mwifiex_dbg(priv->adapter, ERROR, - "tx_pause event while disconnected; bss_role=%d\n", - priv->bss_role); - return; - } - - tlv_buf_left = event_skb->len - sizeof(u32); - tlv = (void *)event_skb->data + sizeof(u32); - - while (tlv_buf_left >= (int)sizeof(struct mwifiex_ie_types_header)) { - tlv_type = le16_to_cpu(tlv->type); - tlv_len = le16_to_cpu(tlv->len); - if ((sizeof(struct mwifiex_ie_types_header) + tlv_len) > - tlv_buf_left) { - mwifiex_dbg(priv->adapter, ERROR, - "wrong tlv: tlvLen=%d, tlvBufLeft=%d\n", - tlv_len, tlv_buf_left); - break; - } - if (tlv_type == TLV_TYPE_TX_PAUSE) { - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - mwifiex_process_sta_tx_pause(priv, tlv); - else - mwifiex_process_uap_tx_pause(priv, tlv); - } - - tlv_buf_left -= sizeof(struct mwifiex_ie_types_header) + - tlv_len; - tlv = (void *)((u8 *)tlv + tlv_len + - sizeof(struct mwifiex_ie_types_header)); - } - -} - -/* -* This function handles coex events generated by firmware -*/ -void mwifiex_bt_coex_wlan_param_update_event(struct mwifiex_private *priv, - struct sk_buff *event_skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_ie_types_header *tlv; - struct mwifiex_ie_types_btcoex_aggr_win_size *winsizetlv; - struct mwifiex_ie_types_btcoex_scan_time *scantlv; - s32 len = event_skb->len - sizeof(u32); - u8 *cur_ptr = event_skb->data + sizeof(u32); - u16 tlv_type, tlv_len; - - while (len >= sizeof(struct mwifiex_ie_types_header)) { - tlv = (struct mwifiex_ie_types_header *)cur_ptr; - tlv_len = le16_to_cpu(tlv->len); - tlv_type = le16_to_cpu(tlv->type); - - if ((tlv_len + sizeof(struct mwifiex_ie_types_header)) > len) - break; - switch (tlv_type) { - case TLV_BTCOEX_WL_AGGR_WINSIZE: - winsizetlv = - (struct mwifiex_ie_types_btcoex_aggr_win_size *)tlv; - adapter->coex_win_size = winsizetlv->coex_win_size; - adapter->coex_tx_win_size = - winsizetlv->tx_win_size; - adapter->coex_rx_win_size = - winsizetlv->rx_win_size; - mwifiex_coex_ampdu_rxwinsize(adapter); - mwifiex_update_ampdu_txwinsize(adapter); - break; - - case TLV_BTCOEX_WL_SCANTIME: - scantlv = - (struct mwifiex_ie_types_btcoex_scan_time *)tlv; - adapter->coex_scan = scantlv->coex_scan; - adapter->coex_min_scan_time = scantlv->min_scan_time; - adapter->coex_max_scan_time = scantlv->max_scan_time; - break; - - default: - break; - } - - len -= tlv_len + sizeof(struct mwifiex_ie_types_header); - cur_ptr += tlv_len + - sizeof(struct mwifiex_ie_types_header); - } - - dev_dbg(adapter->dev, "coex_scan=%d min_scan=%d coex_win=%d, tx_win=%d rx_win=%d\n", - adapter->coex_scan, adapter->coex_min_scan_time, - adapter->coex_win_size, adapter->coex_tx_win_size, - adapter->coex_rx_win_size); -} - -/* - * This function handles events generated by firmware. - * - * This is a generic function and handles all events. - * - * Event specific routines are called by this function based - * upon the generated event cause. - * - * For the following events, the function just forwards them to upper - * layers, optionally recording the change - - * - EVENT_LINK_SENSED - * - EVENT_MIC_ERR_UNICAST - * - EVENT_MIC_ERR_MULTICAST - * - EVENT_PORT_RELEASE - * - EVENT_RSSI_LOW - * - EVENT_SNR_LOW - * - EVENT_MAX_FAIL - * - EVENT_RSSI_HIGH - * - EVENT_SNR_HIGH - * - EVENT_DATA_RSSI_LOW - * - EVENT_DATA_SNR_LOW - * - EVENT_DATA_RSSI_HIGH - * - EVENT_DATA_SNR_HIGH - * - EVENT_LINK_QUALITY - * - EVENT_PRE_BEACON_LOST - * - EVENT_IBSS_COALESCED - * - EVENT_WEP_ICV_ERR - * - EVENT_BW_CHANGE - * - EVENT_HOSTWAKE_STAIE - * - * For the following events, no action is taken - - * - EVENT_MIB_CHANGED - * - EVENT_INIT_DONE - * - EVENT_DUMMY_HOST_WAKEUP_SIGNAL - * - * Rest of the supported events requires driver handling - - * - EVENT_DEAUTHENTICATED - * - EVENT_DISASSOCIATED - * - EVENT_LINK_LOST - * - EVENT_PS_SLEEP - * - EVENT_PS_AWAKE - * - EVENT_DEEP_SLEEP_AWAKE - * - EVENT_HS_ACT_REQ - * - EVENT_ADHOC_BCN_LOST - * - EVENT_BG_SCAN_REPORT - * - EVENT_WMM_STATUS_CHANGE - * - EVENT_ADDBA - * - EVENT_DELBA - * - EVENT_BA_STREAM_TIEMOUT - * - EVENT_AMSDU_AGGR_CTRL - */ -int mwifiex_process_sta_event(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - u32 eventcause = adapter->event_cause; - u16 ctrl, reason_code; - - switch (eventcause) { - case EVENT_DUMMY_HOST_WAKEUP_SIGNAL: - mwifiex_dbg(adapter, ERROR, - "invalid EVENT: DUMMY_HOST_WAKEUP_SIGNAL, ignore it\n"); - break; - case EVENT_LINK_SENSED: - mwifiex_dbg(adapter, EVENT, "event: LINK_SENSED\n"); - if (!netif_carrier_ok(priv->netdev)) - netif_carrier_on(priv->netdev); - mwifiex_wake_up_net_dev_queue(priv->netdev, adapter); - break; - - case EVENT_DEAUTHENTICATED: - mwifiex_dbg(adapter, EVENT, "event: Deauthenticated\n"); - if (priv->wps.session_enable) { - mwifiex_dbg(adapter, INFO, - "info: receive deauth event in wps session\n"); - break; - } - adapter->dbg.num_event_deauth++; - if (priv->media_connected) { - reason_code = - le16_to_cpu(*(__le16 *)adapter->event_body); - mwifiex_reset_connect_state(priv, reason_code); - } - break; - - case EVENT_DISASSOCIATED: - mwifiex_dbg(adapter, EVENT, "event: Disassociated\n"); - if (priv->wps.session_enable) { - mwifiex_dbg(adapter, INFO, - "info: receive disassoc event in wps session\n"); - break; - } - adapter->dbg.num_event_disassoc++; - if (priv->media_connected) { - reason_code = - le16_to_cpu(*(__le16 *)adapter->event_body); - mwifiex_reset_connect_state(priv, reason_code); - } - break; - - case EVENT_LINK_LOST: - mwifiex_dbg(adapter, EVENT, "event: Link lost\n"); - adapter->dbg.num_event_link_lost++; - if (priv->media_connected) { - reason_code = - le16_to_cpu(*(__le16 *)adapter->event_body); - mwifiex_reset_connect_state(priv, reason_code); - } - break; - - case EVENT_PS_SLEEP: - mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n"); - - adapter->ps_state = PS_STATE_PRE_SLEEP; - - mwifiex_check_ps_cond(adapter); - break; - - case EVENT_PS_AWAKE: - mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n"); - if (!adapter->pps_uapsd_mode && priv->port_open && - priv->media_connected && adapter->sleep_period.period) { - adapter->pps_uapsd_mode = true; - mwifiex_dbg(adapter, EVENT, - "event: PPS/UAPSD mode activated\n"); - } - adapter->tx_lock_flag = false; - if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { - if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent || - (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv))) { - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_card_req = false; - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - break; - } - if (!mwifiex_send_null_packet - (priv, - MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) - adapter->ps_state = - PS_STATE_SLEEP; - return 0; - } - } - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_card_req = false; - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - - break; - - case EVENT_DEEP_SLEEP_AWAKE: - adapter->if_ops.wakeup_complete(adapter); - mwifiex_dbg(adapter, EVENT, "event: DS_AWAKE\n"); - if (adapter->is_deep_sleep) - adapter->is_deep_sleep = false; - break; - - case EVENT_HS_ACT_REQ: - mwifiex_dbg(adapter, EVENT, "event: HS_ACT_REQ\n"); - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_HS_CFG_ENH, - 0, 0, NULL, false); - break; - - case EVENT_MIC_ERR_UNICAST: - mwifiex_dbg(adapter, EVENT, "event: UNICAST MIC ERROR\n"); - cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, - NL80211_KEYTYPE_PAIRWISE, - -1, NULL, GFP_KERNEL); - break; - - case EVENT_MIC_ERR_MULTICAST: - mwifiex_dbg(adapter, EVENT, "event: MULTICAST MIC ERROR\n"); - cfg80211_michael_mic_failure(priv->netdev, priv->cfg_bssid, - NL80211_KEYTYPE_GROUP, - -1, NULL, GFP_KERNEL); - break; - case EVENT_MIB_CHANGED: - case EVENT_INIT_DONE: - break; - - case EVENT_ADHOC_BCN_LOST: - mwifiex_dbg(adapter, EVENT, "event: ADHOC_BCN_LOST\n"); - priv->adhoc_is_link_sensed = false; - mwifiex_clean_txrx(priv); - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - break; - - case EVENT_BG_SCAN_REPORT: - mwifiex_dbg(adapter, EVENT, "event: BGS_REPORT\n"); - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_BG_SCAN_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL, false); - break; - - case EVENT_PORT_RELEASE: - mwifiex_dbg(adapter, EVENT, "event: PORT RELEASE\n"); - priv->port_open = true; - break; - - case EVENT_EXT_SCAN_REPORT: - mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n"); - if (adapter->ext_scan) - ret = mwifiex_handle_event_ext_scan_report(priv, - adapter->event_skb->data); - - break; - - case EVENT_WMM_STATUS_CHANGE: - mwifiex_dbg(adapter, EVENT, "event: WMM status changed\n"); - ret = mwifiex_send_cmd(priv, HostCmd_CMD_WMM_GET_STATUS, - 0, 0, NULL, false); - break; - - case EVENT_RSSI_LOW: - cfg80211_cqm_rssi_notify(priv->netdev, - NL80211_CQM_RSSI_THRESHOLD_EVENT_LOW, - GFP_KERNEL); - mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, - HostCmd_ACT_GEN_GET, 0, NULL, false); - priv->subsc_evt_rssi_state = RSSI_LOW_RECVD; - mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_LOW\n"); - break; - case EVENT_SNR_LOW: - mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_LOW\n"); - break; - case EVENT_MAX_FAIL: - mwifiex_dbg(adapter, EVENT, "event: MAX_FAIL\n"); - break; - case EVENT_RSSI_HIGH: - cfg80211_cqm_rssi_notify(priv->netdev, - NL80211_CQM_RSSI_THRESHOLD_EVENT_HIGH, - GFP_KERNEL); - mwifiex_send_cmd(priv, HostCmd_CMD_RSSI_INFO, - HostCmd_ACT_GEN_GET, 0, NULL, false); - priv->subsc_evt_rssi_state = RSSI_HIGH_RECVD; - mwifiex_dbg(adapter, EVENT, "event: Beacon RSSI_HIGH\n"); - break; - case EVENT_SNR_HIGH: - mwifiex_dbg(adapter, EVENT, "event: Beacon SNR_HIGH\n"); - break; - case EVENT_DATA_RSSI_LOW: - mwifiex_dbg(adapter, EVENT, "event: Data RSSI_LOW\n"); - break; - case EVENT_DATA_SNR_LOW: - mwifiex_dbg(adapter, EVENT, "event: Data SNR_LOW\n"); - break; - case EVENT_DATA_RSSI_HIGH: - mwifiex_dbg(adapter, EVENT, "event: Data RSSI_HIGH\n"); - break; - case EVENT_DATA_SNR_HIGH: - mwifiex_dbg(adapter, EVENT, "event: Data SNR_HIGH\n"); - break; - case EVENT_LINK_QUALITY: - mwifiex_dbg(adapter, EVENT, "event: Link Quality\n"); - break; - case EVENT_PRE_BEACON_LOST: - mwifiex_dbg(adapter, EVENT, "event: Pre-Beacon Lost\n"); - break; - case EVENT_IBSS_COALESCED: - mwifiex_dbg(adapter, EVENT, "event: IBSS_COALESCED\n"); - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_802_11_IBSS_COALESCING_STATUS, - HostCmd_ACT_GEN_GET, 0, NULL, false); - break; - case EVENT_ADDBA: - mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n"); - mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, - HostCmd_ACT_GEN_SET, 0, - adapter->event_body, false); - break; - case EVENT_DELBA: - mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n"); - mwifiex_11n_delete_ba_stream(priv, adapter->event_body); - break; - case EVENT_BA_STREAM_TIEMOUT: - mwifiex_dbg(adapter, EVENT, "event: BA Stream timeout\n"); - mwifiex_11n_ba_stream_timeout(priv, - (struct host_cmd_ds_11n_batimeout - *) - adapter->event_body); - break; - case EVENT_AMSDU_AGGR_CTRL: - ctrl = le16_to_cpu(*(__le16 *)adapter->event_body); - mwifiex_dbg(adapter, EVENT, - "event: AMSDU_AGGR_CTRL %d\n", ctrl); - - adapter->tx_buf_size = - min_t(u16, adapter->curr_tx_buf_size, ctrl); - mwifiex_dbg(adapter, EVENT, "event: tx_buf_size %d\n", - adapter->tx_buf_size); - break; - - case EVENT_WEP_ICV_ERR: - mwifiex_dbg(adapter, EVENT, "event: WEP ICV error\n"); - break; - - case EVENT_BW_CHANGE: - mwifiex_dbg(adapter, EVENT, "event: BW Change\n"); - break; - - case EVENT_HOSTWAKE_STAIE: - mwifiex_dbg(adapter, EVENT, - "event: HOSTWAKE_STAIE %d\n", eventcause); - break; - - case EVENT_REMAIN_ON_CHAN_EXPIRED: - mwifiex_dbg(adapter, EVENT, - "event: Remain on channel expired\n"); - cfg80211_remain_on_channel_expired(&priv->wdev, - priv->roc_cfg.cookie, - &priv->roc_cfg.chan, - GFP_ATOMIC); - - memset(&priv->roc_cfg, 0x00, sizeof(struct mwifiex_roc_cfg)); - - break; - - case EVENT_CHANNEL_SWITCH_ANN: - mwifiex_dbg(adapter, EVENT, "event: Channel Switch Announcement\n"); - priv->csa_expire_time = - jiffies + msecs_to_jiffies(DFS_CHAN_MOVE_TIME); - priv->csa_chan = priv->curr_bss_params.bss_descriptor.channel; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_DEAUTHENTICATE, - HostCmd_ACT_GEN_SET, 0, - priv->curr_bss_params.bss_descriptor.mac_address, - false); - break; - - case EVENT_TDLS_GENERIC_EVENT: - ret = mwifiex_parse_tdls_event(priv, adapter->event_skb); - break; - - case EVENT_TX_DATA_PAUSE: - mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n"); - mwifiex_process_tx_pause_event(priv, adapter->event_skb); - break; - - case EVENT_MULTI_CHAN_INFO: - mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n"); - mwifiex_process_multi_chan_event(priv, adapter->event_skb); - break; - - case EVENT_TX_STATUS_REPORT: - mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n"); - mwifiex_parse_tx_status_event(priv, adapter->event_body); - break; - - case EVENT_CHANNEL_REPORT_RDY: - mwifiex_dbg(adapter, EVENT, "event: Channel Report\n"); - ret = mwifiex_11h_handle_chanrpt_ready(priv, - adapter->event_skb); - break; - case EVENT_RADAR_DETECTED: - mwifiex_dbg(adapter, EVENT, "event: Radar detected\n"); - ret = mwifiex_11h_handle_radar_detected(priv, - adapter->event_skb); - break; - case EVENT_BT_COEX_WLAN_PARA_CHANGE: - dev_dbg(adapter->dev, "EVENT: BT coex wlan param update\n"); - mwifiex_bt_coex_wlan_param_update_event(priv, - adapter->event_skb); - break; - default: - mwifiex_dbg(adapter, ERROR, "event: unknown event id: %#x\n", - eventcause); - break; - } - - return ret; -} diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c deleted file mode 100644 index a6c8a4f7bfe9..000000000000 --- a/drivers/net/wireless/mwifiex/sta_ioctl.c +++ /dev/null @@ -1,1421 +0,0 @@ -/* - * Marvell Wireless LAN device driver: functions for station ioctl - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "cfg80211.h" - -static int disconnect_on_suspend; -module_param(disconnect_on_suspend, int, 0644); - -/* - * Copies the multicast address list from device to driver. - * - * This function does not validate the destination memory for - * size, and the calling function must ensure enough memory is - * available. - */ -int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, - struct net_device *dev) -{ - int i = 0; - struct netdev_hw_addr *ha; - - netdev_for_each_mc_addr(ha, dev) - memcpy(&mlist->mac_list[i++], ha->addr, ETH_ALEN); - - return i; -} - -/* - * Wait queue completion handler. - * - * This function waits on a cmd wait queue. It also cancels the pending - * request after waking up, in case of errors. - */ -int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_queued) -{ - int status; - - /* Wait for completion */ - status = wait_event_interruptible_timeout(adapter->cmd_wait_q.wait, - *(cmd_queued->condition), - (12 * HZ)); - if (status <= 0) { - if (status == 0) - status = -ETIMEDOUT; - mwifiex_dbg(adapter, ERROR, "cmd_wait_q terminated: %d\n", - status); - mwifiex_cancel_all_pending_cmd(adapter); - return status; - } - - status = adapter->cmd_wait_q.status; - adapter->cmd_wait_q.status = 0; - - return status; -} - -/* - * This function prepares the correct firmware command and - * issues it to set the multicast list. - * - * This function can be used to enable promiscuous mode, or enable all - * multicast packets, or to enable selective multicast. - */ -int mwifiex_request_set_multicast_list(struct mwifiex_private *priv, - struct mwifiex_multicast_list *mcast_list) -{ - int ret = 0; - u16 old_pkt_filter; - - old_pkt_filter = priv->curr_pkt_filter; - - if (mcast_list->mode == MWIFIEX_PROMISC_MODE) { - mwifiex_dbg(priv->adapter, INFO, - "info: Enable Promiscuous mode\n"); - priv->curr_pkt_filter |= HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; - priv->curr_pkt_filter &= - ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - } else { - /* Multicast */ - priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_PROMISCUOUS_ENABLE; - if (mcast_list->mode == MWIFIEX_ALL_MULTI_MODE) { - mwifiex_dbg(priv->adapter, INFO, - "info: Enabling All Multicast!\n"); - priv->curr_pkt_filter |= - HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - } else { - priv->curr_pkt_filter &= - ~HostCmd_ACT_MAC_ALL_MULTICAST_ENABLE; - mwifiex_dbg(priv->adapter, INFO, - "info: Set multicast list=%d\n", - mcast_list->num_multicast_addr); - /* Send multicast addresses to firmware */ - ret = mwifiex_send_cmd(priv, - HostCmd_CMD_MAC_MULTICAST_ADR, - HostCmd_ACT_GEN_SET, 0, - mcast_list, false); - } - } - mwifiex_dbg(priv->adapter, INFO, - "info: old_pkt_filter=%#x, curr_pkt_filter=%#x\n", - old_pkt_filter, priv->curr_pkt_filter); - if (old_pkt_filter != priv->curr_pkt_filter) { - ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, - 0, &priv->curr_pkt_filter, false); - } - - return ret; -} - -/* - * This function fills bss descriptor structure using provided - * information. - * beacon_ie buffer is allocated in this function. It is caller's - * responsibility to free the memory. - */ -int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv, - struct cfg80211_bss *bss, - struct mwifiex_bssdescriptor *bss_desc) -{ - u8 *beacon_ie; - size_t beacon_ie_len; - struct mwifiex_bss_priv *bss_priv = (void *)bss->priv; - const struct cfg80211_bss_ies *ies; - - rcu_read_lock(); - ies = rcu_dereference(bss->ies); - beacon_ie = kmemdup(ies->data, ies->len, GFP_ATOMIC); - beacon_ie_len = ies->len; - bss_desc->timestamp = ies->tsf; - rcu_read_unlock(); - - if (!beacon_ie) { - mwifiex_dbg(priv->adapter, ERROR, - " failed to alloc beacon_ie\n"); - return -ENOMEM; - } - - memcpy(bss_desc->mac_address, bss->bssid, ETH_ALEN); - bss_desc->rssi = bss->signal; - /* The caller of this function will free beacon_ie */ - bss_desc->beacon_buf = beacon_ie; - bss_desc->beacon_buf_size = beacon_ie_len; - bss_desc->beacon_period = bss->beacon_interval; - bss_desc->cap_info_bitmap = bss->capability; - bss_desc->bss_band = bss_priv->band; - bss_desc->fw_tsf = bss_priv->fw_tsf; - if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) { - mwifiex_dbg(priv->adapter, INFO, - "info: InterpretIE: AP WEP enabled\n"); - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP; - } else { - bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL; - } - if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS) - bss_desc->bss_mode = NL80211_IFTYPE_ADHOC; - else - bss_desc->bss_mode = NL80211_IFTYPE_STATION; - - /* Disable 11ac by default. Enable it only where there - * exist VHT_CAP IE in AP beacon - */ - bss_desc->disable_11ac = true; - - if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_SPECTRUM_MGMT) - bss_desc->sensed_11h = true; - - return mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc); -} - -void mwifiex_dnld_txpwr_table(struct mwifiex_private *priv) -{ - if (priv->adapter->dt_node) { - char txpwr[] = {"marvell,00_txpwrlimit"}; - - memcpy(&txpwr[8], priv->adapter->country_code, 2); - mwifiex_dnld_dt_cfgdata(priv, priv->adapter->dt_node, txpwr); - } -} - -static int mwifiex_process_country_ie(struct mwifiex_private *priv, - struct cfg80211_bss *bss) -{ - const u8 *country_ie; - u8 country_ie_len; - struct mwifiex_802_11d_domain_reg *domain_info = - &priv->adapter->domain_reg; - - rcu_read_lock(); - country_ie = ieee80211_bss_get_ie(bss, WLAN_EID_COUNTRY); - if (!country_ie) { - rcu_read_unlock(); - return 0; - } - - country_ie_len = country_ie[1]; - if (country_ie_len < IEEE80211_COUNTRY_IE_MIN_LEN) { - rcu_read_unlock(); - return 0; - } - - if (!strncmp(priv->adapter->country_code, &country_ie[2], 2)) { - rcu_read_unlock(); - mwifiex_dbg(priv->adapter, INFO, - "11D: skip setting domain info in FW\n"); - return 0; - } - memcpy(priv->adapter->country_code, &country_ie[2], 2); - - domain_info->country_code[0] = country_ie[2]; - domain_info->country_code[1] = country_ie[3]; - domain_info->country_code[2] = ' '; - - country_ie_len -= IEEE80211_COUNTRY_STRING_LEN; - - domain_info->no_of_triplet = - country_ie_len / sizeof(struct ieee80211_country_ie_triplet); - - memcpy((u8 *)domain_info->triplet, - &country_ie[2] + IEEE80211_COUNTRY_STRING_LEN, country_ie_len); - - rcu_read_unlock(); - - if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11D_DOMAIN_INFO, - HostCmd_ACT_GEN_SET, 0, NULL, false)) { - mwifiex_dbg(priv->adapter, ERROR, - "11D: setting domain info in FW fail\n"); - return -1; - } - - mwifiex_dnld_txpwr_table(priv); - - return 0; -} - -/* - * In Ad-Hoc mode, the IBSS is created if not found in scan list. - * In both Ad-Hoc and infra mode, an deauthentication is performed - * first. - */ -int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss, - struct cfg80211_ssid *req_ssid) -{ - int ret; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *bss_desc = NULL; - - priv->scan_block = false; - - if (bss) { - mwifiex_process_country_ie(priv, bss); - - /* Allocate and fill new bss descriptor */ - bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor), - GFP_KERNEL); - if (!bss_desc) - return -ENOMEM; - - ret = mwifiex_fill_new_bss_desc(priv, bss, bss_desc); - if (ret) - goto done; - } - - if (priv->bss_mode == NL80211_IFTYPE_STATION || - priv->bss_mode == NL80211_IFTYPE_P2P_CLIENT) { - u8 config_bands; - - if (!bss_desc) - return -1; - - if (mwifiex_band_to_radio_type(bss_desc->bss_band) == - HostCmd_SCAN_RADIO_TYPE_BG) { - config_bands = BAND_B | BAND_G | BAND_GN; - } else { - config_bands = BAND_A | BAND_AN; - if (adapter->fw_bands & BAND_AAC) - config_bands |= BAND_AAC; - } - - if (!((config_bands | adapter->fw_bands) & ~adapter->fw_bands)) - adapter->config_bands = config_bands; - - ret = mwifiex_check_network_compatibility(priv, bss_desc); - if (ret) - goto done; - - if (mwifiex_11h_get_csa_closed_channel(priv) == - (u8)bss_desc->channel) { - mwifiex_dbg(adapter, ERROR, - "Attempt to reconnect on csa closed chan(%d)\n", - bss_desc->channel); - goto done; - } - - mwifiex_dbg(adapter, INFO, - "info: SSID found in scan list ...\t" - "associating...\n"); - - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - - /* Clear any past association response stored for - * application retrieval */ - priv->assoc_rsp_size = 0; - ret = mwifiex_associate(priv, bss_desc); - - /* If auth type is auto and association fails using open mode, - * try to connect using shared mode */ - if (ret == WLAN_STATUS_NOT_SUPPORTED_AUTH_ALG && - priv->sec_info.is_authtype_auto && - priv->sec_info.wep_enabled) { - priv->sec_info.authentication_mode = - NL80211_AUTHTYPE_SHARED_KEY; - ret = mwifiex_associate(priv, bss_desc); - } - - if (bss) - cfg80211_put_bss(priv->adapter->wiphy, bss); - } else { - /* Adhoc mode */ - /* If the requested SSID matches current SSID, return */ - if (bss_desc && bss_desc->ssid.ssid_len && - (!mwifiex_ssid_cmp(&priv->curr_bss_params.bss_descriptor. - ssid, &bss_desc->ssid))) { - ret = 0; - goto done; - } - - priv->adhoc_is_link_sensed = false; - - ret = mwifiex_check_network_compatibility(priv, bss_desc); - - mwifiex_stop_net_dev_queue(priv->netdev, adapter); - if (netif_carrier_ok(priv->netdev)) - netif_carrier_off(priv->netdev); - - if (!ret) { - mwifiex_dbg(adapter, INFO, - "info: network found in scan\t" - " list. Joining...\n"); - ret = mwifiex_adhoc_join(priv, bss_desc); - if (bss) - cfg80211_put_bss(priv->adapter->wiphy, bss); - } else { - mwifiex_dbg(adapter, INFO, - "info: Network not found in\t" - "the list, creating adhoc with ssid = %s\n", - req_ssid->ssid); - ret = mwifiex_adhoc_start(priv, req_ssid); - } - } - -done: - /* beacon_ie buffer was allocated in function - * mwifiex_fill_new_bss_desc(). Free it now. - */ - if (bss_desc) - kfree(bss_desc->beacon_buf); - kfree(bss_desc); - return ret; -} - -/* - * IOCTL request handler to set host sleep configuration. - * - * This function prepares the correct firmware command and - * issues it. - */ -int mwifiex_set_hs_params(struct mwifiex_private *priv, u16 action, - int cmd_type, struct mwifiex_ds_hs_cfg *hs_cfg) - -{ - struct mwifiex_adapter *adapter = priv->adapter; - int status = 0; - u32 prev_cond = 0; - - if (!hs_cfg) - return -ENOMEM; - - switch (action) { - case HostCmd_ACT_GEN_SET: - if (adapter->pps_uapsd_mode) { - mwifiex_dbg(adapter, INFO, - "info: Host Sleep IOCTL\t" - "is blocked in UAPSD/PPS mode\n"); - status = -1; - break; - } - if (hs_cfg->is_invoke_hostcmd) { - if (hs_cfg->conditions == HS_CFG_CANCEL) { - if (!adapter->is_hs_configured) - /* Already cancelled */ - break; - /* Save previous condition */ - prev_cond = le32_to_cpu(adapter->hs_cfg - .conditions); - adapter->hs_cfg.conditions = - cpu_to_le32(hs_cfg->conditions); - } else if (hs_cfg->conditions) { - adapter->hs_cfg.conditions = - cpu_to_le32(hs_cfg->conditions); - adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; - if (hs_cfg->gap) - adapter->hs_cfg.gap = (u8)hs_cfg->gap; - } else if (adapter->hs_cfg.conditions == - cpu_to_le32(HS_CFG_CANCEL)) { - /* Return failure if no parameters for HS - enable */ - status = -1; - break; - } - - status = mwifiex_send_cmd(priv, - HostCmd_CMD_802_11_HS_CFG_ENH, - HostCmd_ACT_GEN_SET, 0, - &adapter->hs_cfg, - cmd_type == MWIFIEX_SYNC_CMD); - - if (hs_cfg->conditions == HS_CFG_CANCEL) - /* Restore previous condition */ - adapter->hs_cfg.conditions = - cpu_to_le32(prev_cond); - } else { - adapter->hs_cfg.conditions = - cpu_to_le32(hs_cfg->conditions); - adapter->hs_cfg.gpio = (u8)hs_cfg->gpio; - adapter->hs_cfg.gap = (u8)hs_cfg->gap; - } - break; - case HostCmd_ACT_GEN_GET: - hs_cfg->conditions = le32_to_cpu(adapter->hs_cfg.conditions); - hs_cfg->gpio = adapter->hs_cfg.gpio; - hs_cfg->gap = adapter->hs_cfg.gap; - break; - default: - status = -1; - break; - } - - return status; -} - -/* - * Sends IOCTL request to cancel the existing Host Sleep configuration. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_cancel_hs(struct mwifiex_private *priv, int cmd_type) -{ - struct mwifiex_ds_hs_cfg hscfg; - - hscfg.conditions = HS_CFG_CANCEL; - hscfg.is_invoke_hostcmd = true; - - return mwifiex_set_hs_params(priv, HostCmd_ACT_GEN_SET, - cmd_type, &hscfg); -} -EXPORT_SYMBOL_GPL(mwifiex_cancel_hs); - -/* - * Sends IOCTL request to cancel the existing Host Sleep configuration. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_enable_hs(struct mwifiex_adapter *adapter) -{ - struct mwifiex_ds_hs_cfg hscfg; - struct mwifiex_private *priv; - int i; - - if (disconnect_on_suspend) { - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) - mwifiex_deauthenticate(priv, NULL); - } - } - - if (adapter->hs_activated) { - mwifiex_dbg(adapter, CMD, - "cmd: HS Already activated\n"); - return true; - } - - adapter->hs_activate_wait_q_woken = false; - - memset(&hscfg, 0, sizeof(struct mwifiex_ds_hs_cfg)); - hscfg.is_invoke_hostcmd = true; - - adapter->hs_enabling = true; - mwifiex_cancel_all_pending_cmd(adapter); - - if (mwifiex_set_hs_params(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_STA), - HostCmd_ACT_GEN_SET, MWIFIEX_SYNC_CMD, - &hscfg)) { - mwifiex_dbg(adapter, ERROR, - "IOCTL request HS enable failed\n"); - return false; - } - - if (wait_event_interruptible_timeout(adapter->hs_activate_wait_q, - adapter->hs_activate_wait_q_woken, - (10 * HZ)) <= 0) { - mwifiex_dbg(adapter, ERROR, - "hs_activate_wait_q terminated\n"); - return false; - } - - return true; -} -EXPORT_SYMBOL_GPL(mwifiex_enable_hs); - -/* - * IOCTL request handler to get BSS information. - * - * This function collates the information from different driver structures - * to send to the user. - */ -int mwifiex_get_bss_info(struct mwifiex_private *priv, - struct mwifiex_bss_info *info) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bssdescriptor *bss_desc; - - if (!info) - return -1; - - bss_desc = &priv->curr_bss_params.bss_descriptor; - - info->bss_mode = priv->bss_mode; - - memcpy(&info->ssid, &bss_desc->ssid, sizeof(struct cfg80211_ssid)); - - memcpy(&info->bssid, &bss_desc->mac_address, ETH_ALEN); - - info->bss_chan = bss_desc->channel; - - memcpy(info->country_code, adapter->country_code, - IEEE80211_COUNTRY_STRING_LEN); - - info->media_connected = priv->media_connected; - - info->max_power_level = priv->max_tx_power_level; - info->min_power_level = priv->min_tx_power_level; - - info->adhoc_state = priv->adhoc_state; - - info->bcn_nf_last = priv->bcn_nf_last; - - if (priv->sec_info.wep_enabled) - info->wep_status = true; - else - info->wep_status = false; - - info->is_hs_configured = adapter->is_hs_configured; - info->is_deep_sleep = adapter->is_deep_sleep; - - return 0; -} - -/* - * The function disables auto deep sleep mode. - */ -int mwifiex_disable_auto_ds(struct mwifiex_private *priv) -{ - struct mwifiex_ds_auto_ds auto_ds; - - auto_ds.auto_ds = DEEP_SLEEP_OFF; - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - DIS_AUTO_PS, BITMAP_AUTO_DS, &auto_ds, true); -} -EXPORT_SYMBOL_GPL(mwifiex_disable_auto_ds); - -/* - * Sends IOCTL request to get the data rate. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, u32 *rate) -{ - int ret; - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_TX_RATE_QUERY, - HostCmd_ACT_GEN_GET, 0, NULL, true); - - if (!ret) { - if (priv->is_data_rate_auto) - *rate = mwifiex_index_to_data_rate(priv, priv->tx_rate, - priv->tx_htinfo); - else - *rate = priv->data_rate; - } - - return ret; -} - -/* - * IOCTL request handler to set tx power configuration. - * - * This function prepares the correct firmware command and - * issues it. - * - * For non-auto power mode, all the following power groups are set - - * - Modulation class HR/DSSS - * - Modulation class OFDM - * - Modulation class HTBW20 - * - Modulation class HTBW40 - */ -int mwifiex_set_tx_power(struct mwifiex_private *priv, - struct mwifiex_power_cfg *power_cfg) -{ - int ret; - struct host_cmd_ds_txpwr_cfg *txp_cfg; - struct mwifiex_types_power_group *pg_tlv; - struct mwifiex_power_group *pg; - u8 *buf; - u16 dbm = 0; - - if (!power_cfg->is_power_auto) { - dbm = (u16) power_cfg->power_level; - if ((dbm < priv->min_tx_power_level) || - (dbm > priv->max_tx_power_level)) { - mwifiex_dbg(priv->adapter, ERROR, - "txpower value %d dBm\t" - "is out of range (%d dBm-%d dBm)\n", - dbm, priv->min_tx_power_level, - priv->max_tx_power_level); - return -1; - } - } - buf = kzalloc(MWIFIEX_SIZE_OF_CMD_BUFFER, GFP_KERNEL); - if (!buf) - return -ENOMEM; - - txp_cfg = (struct host_cmd_ds_txpwr_cfg *) buf; - txp_cfg->action = cpu_to_le16(HostCmd_ACT_GEN_SET); - if (!power_cfg->is_power_auto) { - txp_cfg->mode = cpu_to_le32(1); - pg_tlv = (struct mwifiex_types_power_group *) - (buf + sizeof(struct host_cmd_ds_txpwr_cfg)); - pg_tlv->type = cpu_to_le16(TLV_TYPE_POWER_GROUP); - pg_tlv->length = - cpu_to_le16(4 * sizeof(struct mwifiex_power_group)); - pg = (struct mwifiex_power_group *) - (buf + sizeof(struct host_cmd_ds_txpwr_cfg) - + sizeof(struct mwifiex_types_power_group)); - /* Power group for modulation class HR/DSSS */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x03; - pg->modulation_class = MOD_CLASS_HR_DSSS; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg++; - /* Power group for modulation class OFDM */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x07; - pg->modulation_class = MOD_CLASS_OFDM; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg++; - /* Power group for modulation class HTBW20 */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x20; - pg->modulation_class = MOD_CLASS_HT; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg->ht_bandwidth = HT_BW_20; - pg++; - /* Power group for modulation class HTBW40 */ - pg->first_rate_code = 0x00; - pg->last_rate_code = 0x20; - pg->modulation_class = MOD_CLASS_HT; - pg->power_step = 0; - pg->power_min = (s8) dbm; - pg->power_max = (s8) dbm; - pg->ht_bandwidth = HT_BW_40; - } - ret = mwifiex_send_cmd(priv, HostCmd_CMD_TXPWR_CFG, - HostCmd_ACT_GEN_SET, 0, buf, true); - - kfree(buf); - return ret; -} - -/* - * IOCTL request handler to get power save mode. - * - * This function prepares the correct firmware command and - * issues it. - */ -int mwifiex_drv_set_power(struct mwifiex_private *priv, u32 *ps_mode) -{ - int ret; - struct mwifiex_adapter *adapter = priv->adapter; - u16 sub_cmd; - - if (*ps_mode) - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_PSP; - else - adapter->ps_mode = MWIFIEX_802_11_POWER_MODE_CAM; - sub_cmd = (*ps_mode) ? EN_AUTO_PS : DIS_AUTO_PS; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - sub_cmd, BITMAP_STA_PS, NULL, true); - if ((!ret) && (sub_cmd == DIS_AUTO_PS)) - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_PS_MODE_ENH, - GET_PS, 0, NULL, false); - - return ret; -} - -/* - * IOCTL request handler to set/reset WPA IE. - * - * The supplied WPA IE is treated as a opaque buffer. Only the first field - * is checked to determine WPA version. If buffer length is zero, the existing - * WPA IE is reset. - */ -static int mwifiex_set_wpa_ie_helper(struct mwifiex_private *priv, - u8 *ie_data_ptr, u16 ie_len) -{ - if (ie_len) { - if (ie_len > sizeof(priv->wpa_ie)) { - mwifiex_dbg(priv->adapter, ERROR, - "failed to copy WPA IE, too big\n"); - return -1; - } - memcpy(priv->wpa_ie, ie_data_ptr, ie_len); - priv->wpa_ie_len = (u8) ie_len; - mwifiex_dbg(priv->adapter, CMD, - "cmd: Set Wpa_ie_len=%d IE=%#x\n", - priv->wpa_ie_len, priv->wpa_ie[0]); - - if (priv->wpa_ie[0] == WLAN_EID_VENDOR_SPECIFIC) { - priv->sec_info.wpa_enabled = true; - } else if (priv->wpa_ie[0] == WLAN_EID_RSN) { - priv->sec_info.wpa2_enabled = true; - } else { - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - } - } else { - memset(priv->wpa_ie, 0, sizeof(priv->wpa_ie)); - priv->wpa_ie_len = 0; - mwifiex_dbg(priv->adapter, INFO, - "info: reset wpa_ie_len=%d IE=%#x\n", - priv->wpa_ie_len, priv->wpa_ie[0]); - priv->sec_info.wpa_enabled = false; - priv->sec_info.wpa2_enabled = false; - } - - return 0; -} - -/* - * IOCTL request handler to set/reset WAPI IE. - * - * The supplied WAPI IE is treated as a opaque buffer. Only the first field - * is checked to internally enable WAPI. If buffer length is zero, the existing - * WAPI IE is reset. - */ -static int mwifiex_set_wapi_ie(struct mwifiex_private *priv, - u8 *ie_data_ptr, u16 ie_len) -{ - if (ie_len) { - if (ie_len > sizeof(priv->wapi_ie)) { - mwifiex_dbg(priv->adapter, ERROR, - "info: failed to copy WAPI IE, too big\n"); - return -1; - } - memcpy(priv->wapi_ie, ie_data_ptr, ie_len); - priv->wapi_ie_len = ie_len; - mwifiex_dbg(priv->adapter, CMD, - "cmd: Set wapi_ie_len=%d IE=%#x\n", - priv->wapi_ie_len, priv->wapi_ie[0]); - - if (priv->wapi_ie[0] == WLAN_EID_BSS_AC_ACCESS_DELAY) - priv->sec_info.wapi_enabled = true; - } else { - memset(priv->wapi_ie, 0, sizeof(priv->wapi_ie)); - priv->wapi_ie_len = ie_len; - mwifiex_dbg(priv->adapter, INFO, - "info: Reset wapi_ie_len=%d IE=%#x\n", - priv->wapi_ie_len, priv->wapi_ie[0]); - priv->sec_info.wapi_enabled = false; - } - return 0; -} - -/* - * IOCTL request handler to set/reset WPS IE. - * - * The supplied WPS IE is treated as a opaque buffer. Only the first field - * is checked to internally enable WPS. If buffer length is zero, the existing - * WPS IE is reset. - */ -static int mwifiex_set_wps_ie(struct mwifiex_private *priv, - u8 *ie_data_ptr, u16 ie_len) -{ - if (ie_len) { - if (ie_len > MWIFIEX_MAX_VSIE_LEN) { - mwifiex_dbg(priv->adapter, ERROR, - "info: failed to copy WPS IE, too big\n"); - return -1; - } - - priv->wps_ie = kzalloc(MWIFIEX_MAX_VSIE_LEN, GFP_KERNEL); - if (!priv->wps_ie) - return -ENOMEM; - - memcpy(priv->wps_ie, ie_data_ptr, ie_len); - priv->wps_ie_len = ie_len; - mwifiex_dbg(priv->adapter, CMD, - "cmd: Set wps_ie_len=%d IE=%#x\n", - priv->wps_ie_len, priv->wps_ie[0]); - } else { - kfree(priv->wps_ie); - priv->wps_ie_len = ie_len; - mwifiex_dbg(priv->adapter, INFO, - "info: Reset wps_ie_len=%d\n", priv->wps_ie_len); - } - return 0; -} - -/* - * IOCTL request handler to set WAPI key. - * - * This function prepares the correct firmware command and - * issues it. - */ -static int mwifiex_sec_ioctl_set_wapi_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, KEY_INFO_ENABLED, - encrypt_key, true); -} - -/* - * IOCTL request handler to set WEP network key. - * - * This function prepares the correct firmware command and - * issues it, after validation checks. - */ -static int mwifiex_sec_ioctl_set_wep_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret; - struct mwifiex_wep_key *wep_key; - int index; - - if (priv->wep_key_curr_index >= NUM_WEP_KEYS) - priv->wep_key_curr_index = 0; - wep_key = &priv->wep_key[priv->wep_key_curr_index]; - index = encrypt_key->key_index; - if (encrypt_key->key_disable) { - priv->sec_info.wep_enabled = 0; - } else if (!encrypt_key->key_len) { - /* Copy the required key as the current key */ - wep_key = &priv->wep_key[index]; - if (!wep_key->key_length) { - mwifiex_dbg(adapter, ERROR, - "key not set, so cannot enable it\n"); - return -1; - } - - if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) { - memcpy(encrypt_key->key_material, - wep_key->key_material, wep_key->key_length); - encrypt_key->key_len = wep_key->key_length; - } - - priv->wep_key_curr_index = (u16) index; - priv->sec_info.wep_enabled = 1; - } else { - wep_key = &priv->wep_key[index]; - memset(wep_key, 0, sizeof(struct mwifiex_wep_key)); - /* Copy the key in the driver */ - memcpy(wep_key->key_material, - encrypt_key->key_material, - encrypt_key->key_len); - wep_key->key_index = index; - wep_key->key_length = encrypt_key->key_len; - priv->sec_info.wep_enabled = 1; - } - if (wep_key->key_length) { - void *enc_key; - - if (encrypt_key->key_disable) { - memset(&priv->wep_key[index], 0, - sizeof(struct mwifiex_wep_key)); - if (wep_key->key_length) - goto done; - } - - if (adapter->key_api_major_ver == KEY_API_VER_MAJOR_V2) - enc_key = encrypt_key; - else - enc_key = NULL; - - /* Send request to firmware */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, 0, enc_key, false); - if (ret) - return ret; - } - -done: - if (priv->sec_info.wep_enabled) - priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; - else - priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; - - ret = mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter, true); - - return ret; -} - -/* - * IOCTL request handler to set WPA key. - * - * This function prepares the correct firmware command and - * issues it, after validation checks. - * - * Current driver only supports key length of up to 32 bytes. - * - * This function can also be used to disable a currently set key. - */ -static int mwifiex_sec_ioctl_set_wpa_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - int ret; - u8 remove_key = false; - struct host_cmd_ds_802_11_key_material *ibss_key; - - /* Current driver only supports key length of up to 32 bytes */ - if (encrypt_key->key_len > WLAN_MAX_KEY_LEN) { - mwifiex_dbg(priv->adapter, ERROR, - "key length too long\n"); - return -1; - } - - if (priv->bss_mode == NL80211_IFTYPE_ADHOC) { - /* - * IBSS/WPA-None uses only one key (Group) for both receiving - * and sending unicast and multicast packets. - */ - /* Send the key as PTK to firmware */ - encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - KEY_INFO_ENABLED, encrypt_key, false); - if (ret) - return ret; - - ibss_key = &priv->aes_key; - memset(ibss_key, 0, - sizeof(struct host_cmd_ds_802_11_key_material)); - /* Copy the key in the driver */ - memcpy(ibss_key->key_param_set.key, encrypt_key->key_material, - encrypt_key->key_len); - memcpy(&ibss_key->key_param_set.key_len, &encrypt_key->key_len, - sizeof(ibss_key->key_param_set.key_len)); - ibss_key->key_param_set.key_type_id - = cpu_to_le16(KEY_TYPE_ID_TKIP); - ibss_key->key_param_set.key_info = cpu_to_le16(KEY_ENABLED); - - /* Send the key as GTK to firmware */ - encrypt_key->key_index = ~MWIFIEX_KEY_INDEX_UNICAST; - } - - if (!encrypt_key->key_index) - encrypt_key->key_index = MWIFIEX_KEY_INDEX_UNICAST; - - if (remove_key) - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - !KEY_INFO_ENABLED, encrypt_key, true); - else - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_KEY_MATERIAL, - HostCmd_ACT_GEN_SET, - KEY_INFO_ENABLED, encrypt_key, true); - - return ret; -} - -/* - * IOCTL request handler to set/get network keys. - * - * This is a generic key handling function which supports WEP, WPA - * and WAPI. - */ -static int -mwifiex_sec_ioctl_encrypt_key(struct mwifiex_private *priv, - struct mwifiex_ds_encrypt_key *encrypt_key) -{ - int status; - - if (encrypt_key->is_wapi_key) - status = mwifiex_sec_ioctl_set_wapi_key(priv, encrypt_key); - else if (encrypt_key->key_len > WLAN_KEY_LEN_WEP104) - status = mwifiex_sec_ioctl_set_wpa_key(priv, encrypt_key); - else - status = mwifiex_sec_ioctl_set_wep_key(priv, encrypt_key); - return status; -} - -/* - * This function returns the driver version. - */ -int -mwifiex_drv_get_driver_version(struct mwifiex_adapter *adapter, char *version, - int max_len) -{ - union { - __le32 l; - u8 c[4]; - } ver; - char fw_ver[32]; - - ver.l = cpu_to_le32(adapter->fw_release_number); - sprintf(fw_ver, "%u.%u.%u.p%u", ver.c[2], ver.c[1], ver.c[0], ver.c[3]); - - snprintf(version, max_len, driver_version, fw_ver); - - mwifiex_dbg(adapter, MSG, "info: MWIFIEX VERSION: %s\n", version); - - return 0; -} - -/* - * Sends IOCTL request to set encoding parameters. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int mwifiex_set_encode(struct mwifiex_private *priv, struct key_params *kp, - const u8 *key, int key_len, u8 key_index, - const u8 *mac_addr, int disable) -{ - struct mwifiex_ds_encrypt_key encrypt_key; - - memset(&encrypt_key, 0, sizeof(struct mwifiex_ds_encrypt_key)); - encrypt_key.key_len = key_len; - encrypt_key.key_index = key_index; - - if (kp && kp->cipher == WLAN_CIPHER_SUITE_AES_CMAC) - encrypt_key.is_igtk_key = true; - - if (!disable) { - if (key_len) - memcpy(encrypt_key.key_material, key, key_len); - else - encrypt_key.is_current_wep_key = true; - - if (mac_addr) - memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); - if (kp && kp->seq && kp->seq_len) { - memcpy(encrypt_key.pn, kp->seq, kp->seq_len); - encrypt_key.pn_len = kp->seq_len; - encrypt_key.is_rx_seq_valid = true; - } - } else { - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) - return 0; - encrypt_key.key_disable = true; - if (mac_addr) - memcpy(encrypt_key.mac_addr, mac_addr, ETH_ALEN); - } - - return mwifiex_sec_ioctl_encrypt_key(priv, &encrypt_key); -} - -/* - * Sends IOCTL request to get extended version. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_get_ver_ext(struct mwifiex_private *priv) -{ - struct mwifiex_ver_ext ver_ext; - - memset(&ver_ext, 0, sizeof(struct host_cmd_ds_version_ext)); - if (mwifiex_send_cmd(priv, HostCmd_CMD_VERSION_EXT, - HostCmd_ACT_GEN_GET, 0, &ver_ext, true)) - return -1; - - return 0; -} - -int -mwifiex_remain_on_chan_cfg(struct mwifiex_private *priv, u16 action, - struct ieee80211_channel *chan, - unsigned int duration) -{ - struct host_cmd_ds_remain_on_chan roc_cfg; - u8 sc; - - memset(&roc_cfg, 0, sizeof(roc_cfg)); - roc_cfg.action = cpu_to_le16(action); - if (action == HostCmd_ACT_GEN_SET) { - roc_cfg.band_cfg = chan->band; - sc = mwifiex_chan_type_to_sec_chan_offset(NL80211_CHAN_NO_HT); - roc_cfg.band_cfg |= (sc << 2); - - roc_cfg.channel = - ieee80211_frequency_to_channel(chan->center_freq); - roc_cfg.duration = cpu_to_le32(duration); - } - if (mwifiex_send_cmd(priv, HostCmd_CMD_REMAIN_ON_CHAN, - action, 0, &roc_cfg, true)) { - mwifiex_dbg(priv->adapter, ERROR, - "failed to remain on channel\n"); - return -1; - } - - return roc_cfg.status; -} - -/* - * Sends IOCTL request to get statistics information. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_get_stats_info(struct mwifiex_private *priv, - struct mwifiex_ds_get_stats *log) -{ - return mwifiex_send_cmd(priv, HostCmd_CMD_802_11_GET_LOG, - HostCmd_ACT_GEN_GET, 0, log, true); -} - -/* - * IOCTL request handler to read/write register. - * - * This function prepares the correct firmware command and - * issues it. - * - * Access to the following registers are supported - - * - MAC - * - BBP - * - RF - * - PMIC - * - CAU - */ -static int mwifiex_reg_mem_ioctl_reg_rw(struct mwifiex_private *priv, - struct mwifiex_ds_reg_rw *reg_rw, - u16 action) -{ - u16 cmd_no; - - switch (le32_to_cpu(reg_rw->type)) { - case MWIFIEX_REG_MAC: - cmd_no = HostCmd_CMD_MAC_REG_ACCESS; - break; - case MWIFIEX_REG_BBP: - cmd_no = HostCmd_CMD_BBP_REG_ACCESS; - break; - case MWIFIEX_REG_RF: - cmd_no = HostCmd_CMD_RF_REG_ACCESS; - break; - case MWIFIEX_REG_PMIC: - cmd_no = HostCmd_CMD_PMIC_REG_ACCESS; - break; - case MWIFIEX_REG_CAU: - cmd_no = HostCmd_CMD_CAU_REG_ACCESS; - break; - default: - return -1; - } - - return mwifiex_send_cmd(priv, cmd_no, action, 0, reg_rw, true); -} - -/* - * Sends IOCTL request to write to a register. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_reg_write(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 reg_value) -{ - struct mwifiex_ds_reg_rw reg_rw; - - reg_rw.type = cpu_to_le32(reg_type); - reg_rw.offset = cpu_to_le32(reg_offset); - reg_rw.value = cpu_to_le32(reg_value); - - return mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_SET); -} - -/* - * Sends IOCTL request to read from a register. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_reg_read(struct mwifiex_private *priv, u32 reg_type, - u32 reg_offset, u32 *value) -{ - int ret; - struct mwifiex_ds_reg_rw reg_rw; - - reg_rw.type = cpu_to_le32(reg_type); - reg_rw.offset = cpu_to_le32(reg_offset); - ret = mwifiex_reg_mem_ioctl_reg_rw(priv, ®_rw, HostCmd_ACT_GEN_GET); - - if (ret) - goto done; - - *value = le32_to_cpu(reg_rw.value); - -done: - return ret; -} - -/* - * Sends IOCTL request to read from EEPROM. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_eeprom_read(struct mwifiex_private *priv, u16 offset, u16 bytes, - u8 *value) -{ - int ret; - struct mwifiex_ds_read_eeprom rd_eeprom; - - rd_eeprom.offset = cpu_to_le16((u16) offset); - rd_eeprom.byte_count = cpu_to_le16((u16) bytes); - - /* Send request to firmware */ - ret = mwifiex_send_cmd(priv, HostCmd_CMD_802_11_EEPROM_ACCESS, - HostCmd_ACT_GEN_GET, 0, &rd_eeprom, true); - - if (!ret) - memcpy(value, rd_eeprom.value, MAX_EEPROM_DATA); - return ret; -} - -/* - * This function sets a generic IE. In addition to generic IE, it can - * also handle WPA, WPA2 and WAPI IEs. - */ -static int -mwifiex_set_gen_ie_helper(struct mwifiex_private *priv, u8 *ie_data_ptr, - u16 ie_len) -{ - int ret = 0; - struct ieee_types_vendor_header *pvendor_ie; - const u8 wpa_oui[] = { 0x00, 0x50, 0xf2, 0x01 }; - const u8 wps_oui[] = { 0x00, 0x50, 0xf2, 0x04 }; - - /* If the passed length is zero, reset the buffer */ - if (!ie_len) { - priv->gen_ie_buf_len = 0; - priv->wps.session_enable = false; - - return 0; - } else if (!ie_data_ptr) { - return -1; - } - pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; - /* Test to see if it is a WPA IE, if not, then it is a gen IE */ - if (((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && - (!memcmp(pvendor_ie->oui, wpa_oui, sizeof(wpa_oui)))) || - (pvendor_ie->element_id == WLAN_EID_RSN)) { - - /* IE is a WPA/WPA2 IE so call set_wpa function */ - ret = mwifiex_set_wpa_ie_helper(priv, ie_data_ptr, ie_len); - priv->wps.session_enable = false; - - return ret; - } else if (pvendor_ie->element_id == WLAN_EID_BSS_AC_ACCESS_DELAY) { - /* IE is a WAPI IE so call set_wapi function */ - ret = mwifiex_set_wapi_ie(priv, ie_data_ptr, ie_len); - - return ret; - } - /* - * Verify that the passed length is not larger than the - * available space remaining in the buffer - */ - if (ie_len < (sizeof(priv->gen_ie_buf) - priv->gen_ie_buf_len)) { - - /* Test to see if it is a WPS IE, if so, enable - * wps session flag - */ - pvendor_ie = (struct ieee_types_vendor_header *) ie_data_ptr; - if ((pvendor_ie->element_id == WLAN_EID_VENDOR_SPECIFIC) && - (!memcmp(pvendor_ie->oui, wps_oui, sizeof(wps_oui)))) { - priv->wps.session_enable = true; - mwifiex_dbg(priv->adapter, INFO, - "info: WPS Session Enabled.\n"); - ret = mwifiex_set_wps_ie(priv, ie_data_ptr, ie_len); - } - - /* Append the passed data to the end of the - genIeBuffer */ - memcpy(priv->gen_ie_buf + priv->gen_ie_buf_len, ie_data_ptr, - ie_len); - /* Increment the stored buffer length by the - size passed */ - priv->gen_ie_buf_len += ie_len; - } else { - /* Passed data does not fit in the remaining - buffer space */ - ret = -1; - } - - /* Return 0, or -1 for error case */ - return ret; -} - -/* - * IOCTL request handler to set/get generic IE. - * - * In addition to various generic IEs, this function can also be - * used to set the ARP filter. - */ -static int mwifiex_misc_ioctl_gen_ie(struct mwifiex_private *priv, - struct mwifiex_ds_misc_gen_ie *gen_ie, - u16 action) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - switch (gen_ie->type) { - case MWIFIEX_IE_TYPE_GEN_IE: - if (action == HostCmd_ACT_GEN_GET) { - gen_ie->len = priv->wpa_ie_len; - memcpy(gen_ie->ie_data, priv->wpa_ie, gen_ie->len); - } else { - mwifiex_set_gen_ie_helper(priv, gen_ie->ie_data, - (u16) gen_ie->len); - } - break; - case MWIFIEX_IE_TYPE_ARP_FILTER: - memset(adapter->arp_filter, 0, sizeof(adapter->arp_filter)); - if (gen_ie->len > ARP_FILTER_MAX_BUF_SIZE) { - adapter->arp_filter_size = 0; - mwifiex_dbg(adapter, ERROR, - "invalid ARP filter size\n"); - return -1; - } else { - memcpy(adapter->arp_filter, gen_ie->ie_data, - gen_ie->len); - adapter->arp_filter_size = gen_ie->len; - } - break; - default: - mwifiex_dbg(adapter, ERROR, "invalid IE type\n"); - return -1; - } - return 0; -} - -/* - * Sends IOCTL request to set a generic IE. - * - * This function allocates the IOCTL request buffer, fills it - * with requisite parameters and calls the IOCTL handler. - */ -int -mwifiex_set_gen_ie(struct mwifiex_private *priv, const u8 *ie, int ie_len) -{ - struct mwifiex_ds_misc_gen_ie gen_ie; - - if (ie_len > IEEE_MAX_IE_SIZE) - return -EFAULT; - - gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE; - gen_ie.len = ie_len; - memcpy(gen_ie.ie_data, ie, ie_len); - if (mwifiex_misc_ioctl_gen_ie(priv, &gen_ie, HostCmd_ACT_GEN_SET)) - return -EFAULT; - - return 0; -} diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c deleted file mode 100644 index d4d4cb1ce95b..000000000000 --- a/drivers/net/wireless/mwifiex/sta_rx.c +++ /dev/null @@ -1,267 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station RX data handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include <uapi/linux/ipv6.h> -#include <net/ndisc.h> -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "11n_aggr.h" -#include "11n_rxreorder.h" - -/* This function checks if a frame is IPv4 ARP or IPv6 Neighbour advertisement - * frame. If frame has both source and destination mac address as same, this - * function drops such gratuitous frames. - */ -static bool -mwifiex_discard_gratuitous_arp(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - const struct mwifiex_arp_eth_header *arp; - struct ethhdr *eth; - struct ipv6hdr *ipv6; - struct icmp6hdr *icmpv6; - - eth = (struct ethhdr *)skb->data; - switch (ntohs(eth->h_proto)) { - case ETH_P_ARP: - arp = (void *)(skb->data + sizeof(struct ethhdr)); - if (arp->hdr.ar_op == htons(ARPOP_REPLY) || - arp->hdr.ar_op == htons(ARPOP_REQUEST)) { - if (!memcmp(arp->ar_sip, arp->ar_tip, 4)) - return true; - } - break; - case ETH_P_IPV6: - ipv6 = (void *)(skb->data + sizeof(struct ethhdr)); - icmpv6 = (void *)(skb->data + sizeof(struct ethhdr) + - sizeof(struct ipv6hdr)); - if (NDISC_NEIGHBOUR_ADVERTISEMENT == icmpv6->icmp6_type) { - if (!memcmp(&ipv6->saddr, &ipv6->daddr, - sizeof(struct in6_addr))) - return true; - } - break; - default: - break; - } - - return false; -} - -/* - * This function processes the received packet and forwards it - * to kernel/upper layer. - * - * This function parses through the received packet and determines - * if it is a debug packet or normal packet. - * - * For non-debug packets, the function chops off unnecessary leading - * header bytes, reconstructs the packet as an ethernet frame or - * 802.2/llc/snap frame as required, and sends it to kernel/upper layer. - * - * The completion callback is called after processing in complete. - */ -int mwifiex_process_rx_packet(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - int ret; - struct rx_packet_hdr *rx_pkt_hdr; - struct rxpd *local_rx_pd; - int hdr_chop; - struct ethhdr *eth; - u16 rx_pkt_off, rx_pkt_len; - u8 *offset; - u8 adj_rx_rate = 0; - - local_rx_pd = (struct rxpd *) (skb->data); - - rx_pkt_off = le16_to_cpu(local_rx_pd->rx_pkt_offset); - rx_pkt_len = le16_to_cpu(local_rx_pd->rx_pkt_length); - rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_off; - - if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, - sizeof(bridge_tunnel_header))) || - (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, - sizeof(rfc1042_header)) && - ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && - ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { - /* - * Replace the 803 header and rfc1042 header (llc/snap) with an - * EthernetII header, keep the src/dst and snap_type - * (ethertype). - * The firmware only passes up SNAP frames converting - * all RX Data from 802.11 to 802.2/LLC/SNAP frames. - * To create the Ethernet II, just move the src, dst address - * right before the snap_type. - */ - eth = (struct ethhdr *) - ((u8 *) &rx_pkt_hdr->eth803_hdr - + sizeof(rx_pkt_hdr->eth803_hdr) + - sizeof(rx_pkt_hdr->rfc1042_hdr) - - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) - - sizeof(rx_pkt_hdr->eth803_hdr.h_source) - - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); - - memcpy(eth->h_source, rx_pkt_hdr->eth803_hdr.h_source, - sizeof(eth->h_source)); - memcpy(eth->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, - sizeof(eth->h_dest)); - - /* Chop off the rxpd + the excess memory from the 802.2/llc/snap - header that was removed. */ - hdr_chop = (u8 *) eth - (u8 *) local_rx_pd; - } else { - /* Chop off the rxpd */ - hdr_chop = (u8 *) &rx_pkt_hdr->eth803_hdr - - (u8 *) local_rx_pd; - } - - /* Chop off the leading header bytes so the it points to the start of - either the reconstructed EthII frame or the 802.2/llc/snap frame */ - skb_pull(skb, hdr_chop); - - if (priv->hs2_enabled && - mwifiex_discard_gratuitous_arp(priv, skb)) { - mwifiex_dbg(priv->adapter, INFO, "Bypassed Gratuitous ARP\n"); - dev_kfree_skb_any(skb); - return 0; - } - - if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - ntohs(rx_pkt_hdr->eth803_hdr.h_proto) == ETH_P_TDLS) { - offset = (u8 *)local_rx_pd + rx_pkt_off; - mwifiex_process_tdls_action_frame(priv, offset, rx_pkt_len); - } - - priv->rxpd_rate = local_rx_pd->rx_rate; - - priv->rxpd_htinfo = local_rx_pd->ht_info; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA || - GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - adj_rx_rate = mwifiex_adjust_data_rate(priv, priv->rxpd_rate, - priv->rxpd_htinfo); - mwifiex_hist_data_add(priv, adj_rx_rate, local_rx_pd->snr, - local_rx_pd->nf); - } - - ret = mwifiex_recv_packet(priv, skb); - if (ret == -1) - mwifiex_dbg(priv->adapter, ERROR, - "recv packet failed\n"); - - return ret; -} - -/* - * This function processes the received buffer. - * - * The function looks into the RxPD and performs sanity tests on the - * received buffer to ensure its a valid packet, before processing it - * further. If the packet is determined to be aggregated, it is - * de-aggregated accordingly. Non-unicast packets are sent directly to - * the kernel/upper layers. Unicast packets are handed over to the - * Rx reordering routine if 11n is enabled. - * - * The completion callback is called after processing in complete. - */ -int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret = 0; - struct rxpd *local_rx_pd; - struct rx_packet_hdr *rx_pkt_hdr; - u8 ta[ETH_ALEN]; - u16 rx_pkt_type, rx_pkt_offset, rx_pkt_length, seq_num; - struct mwifiex_sta_node *sta_ptr; - - local_rx_pd = (struct rxpd *) (skb->data); - rx_pkt_type = le16_to_cpu(local_rx_pd->rx_pkt_type); - rx_pkt_offset = le16_to_cpu(local_rx_pd->rx_pkt_offset); - rx_pkt_length = le16_to_cpu(local_rx_pd->rx_pkt_length); - seq_num = le16_to_cpu(local_rx_pd->seq_num); - - rx_pkt_hdr = (void *)local_rx_pd + rx_pkt_offset; - - if ((rx_pkt_offset + rx_pkt_length) > (u16) skb->len) { - mwifiex_dbg(adapter, ERROR, - "wrong rx packet: len=%d, rx_pkt_offset=%d, rx_pkt_length=%d\n", - skb->len, rx_pkt_offset, rx_pkt_length); - priv->stats.rx_dropped++; - dev_kfree_skb_any(skb); - return ret; - } - - if (rx_pkt_type == PKT_TYPE_MGMT) { - ret = mwifiex_process_mgmt_packet(priv, skb); - if (ret) - mwifiex_dbg(adapter, ERROR, "Rx of mgmt packet failed"); - dev_kfree_skb_any(skb); - return ret; - } - - /* - * If the packet is not an unicast packet then send the packet - * directly to os. Don't pass thru rx reordering - */ - if ((!IS_11N_ENABLED(priv) && - !(ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - !(local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET))) || - !ether_addr_equal_unaligned(priv->curr_addr, rx_pkt_hdr->eth803_hdr.h_dest)) { - mwifiex_process_rx_packet(priv, skb); - return ret; - } - - if (mwifiex_queuing_ra_based(priv) || - (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET)) { - memcpy(ta, rx_pkt_hdr->eth803_hdr.h_source, ETH_ALEN); - if (local_rx_pd->flags & MWIFIEX_RXPD_FLAGS_TDLS_PACKET && - local_rx_pd->priority < MAX_NUM_TID) { - sta_ptr = mwifiex_get_sta_entry(priv, ta); - if (sta_ptr) - sta_ptr->rx_seq[local_rx_pd->priority] = - le16_to_cpu(local_rx_pd->seq_num); - mwifiex_auto_tdls_update_peer_signal(priv, ta, - local_rx_pd->snr, - local_rx_pd->nf); - } - } else { - if (rx_pkt_type != PKT_TYPE_BAR) - priv->rx_seq[local_rx_pd->priority] = seq_num; - memcpy(ta, priv->curr_bss_params.bss_descriptor.mac_address, - ETH_ALEN); - } - - /* Reorder and send to OS */ - ret = mwifiex_11n_rx_reorder_pkt(priv, seq_num, local_rx_pd->priority, - ta, (u8) rx_pkt_type, skb); - - if (ret || (rx_pkt_type == PKT_TYPE_BAR)) - dev_kfree_skb_any(skb); - - if (ret) - priv->stats.rx_dropped++; - - return ret; -} diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c deleted file mode 100644 index f6683ea6bd5d..000000000000 --- a/drivers/net/wireless/mwifiex/sta_tx.c +++ /dev/null @@ -1,244 +0,0 @@ -/* - * Marvell Wireless LAN device driver: station TX data handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" - -/* - * This function fills the TxPD for tx packets. - * - * The Tx buffer received by this function should already have the - * header space allocated for TxPD. - * - * This function inserts the TxPD in between interface header and actual - * data and adjusts the buffer pointers accordingly. - * - * The following TxPD fields are set by this function, as required - - * - BSS number - * - Tx packet length and offset - * - Priority - * - Packet delay - * - Priority specific Tx control - * - Flags - */ -void *mwifiex_process_sta_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct txpd *local_tx_pd; - struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - unsigned int pad; - u16 pkt_type, pkt_offset; - int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 : - INTF_HEADER_LEN; - - if (!skb->len) { - mwifiex_dbg(adapter, ERROR, - "Tx: bad packet length: %d\n", skb->len); - tx_info->status_code = -1; - return skb->data; - } - - BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN); - - pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; - - pad = ((void *)skb->data - (sizeof(*local_tx_pd) + hroom)- - NULL) & (MWIFIEX_DMA_ALIGN_SZ - 1); - skb_push(skb, sizeof(*local_tx_pd) + pad); - - local_tx_pd = (struct txpd *) skb->data; - memset(local_tx_pd, 0, sizeof(struct txpd)); - local_tx_pd->bss_num = priv->bss_num; - local_tx_pd->bss_type = priv->bss_type; - local_tx_pd->tx_pkt_length = cpu_to_le16((u16)(skb->len - - (sizeof(struct txpd) + - pad))); - - local_tx_pd->priority = (u8) skb->priority; - local_tx_pd->pkt_delay_2ms = - mwifiex_wmm_compute_drv_pkt_delay(priv, skb); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS || - tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) { - local_tx_pd->tx_token_id = tx_info->ack_frame_id; - local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS; - } - - if (local_tx_pd->priority < - ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) - /* - * Set the priority specific tx_control field, setting of 0 will - * cause the default value to be used later in this function - */ - local_tx_pd->tx_control = - cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[local_tx_pd-> - priority]); - - if (adapter->pps_uapsd_mode) { - if (mwifiex_check_last_packet_indication(priv)) { - adapter->tx_lock_flag = true; - local_tx_pd->flags = - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET; - } - } - - if (tx_info->flags & MWIFIEX_BUF_FLAG_TDLS_PKT) - local_tx_pd->flags |= MWIFIEX_TXPD_FLAGS_TDLS_PACKET; - - /* Offset of actual data */ - pkt_offset = sizeof(struct txpd) + pad; - if (pkt_type == PKT_TYPE_MGMT) { - /* Set the packet type and add header for management frame */ - local_tx_pd->tx_pkt_type = cpu_to_le16(pkt_type); - pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE; - } - - local_tx_pd->tx_pkt_offset = cpu_to_le16(pkt_offset); - - /* make space for INTF_HEADER_LEN */ - skb_push(skb, hroom); - - if (!local_tx_pd->tx_control) - /* TxCtrl set by user or default */ - local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - return skb->data; -} - -/* - * This function tells firmware to send a NULL data packet. - * - * The function creates a NULL data packet with TxPD and sends to the - * firmware for transmission, with highest priority setting. - */ -int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct txpd *local_tx_pd; - struct mwifiex_tx_param tx_param; -/* sizeof(struct txpd) + Interface specific header */ -#define NULL_PACKET_HDR 64 - u32 data_len = NULL_PACKET_HDR; - struct sk_buff *skb; - int ret; - struct mwifiex_txinfo *tx_info = NULL; - - if (adapter->surprise_removed) - return -1; - - if (!priv->media_connected) - return -1; - - if (adapter->data_sent) - return -1; - - if (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv)) - return -1; - - skb = dev_alloc_skb(data_len); - if (!skb) - return -1; - - tx_info = MWIFIEX_SKB_TXCB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->bss_num = priv->bss_num; - tx_info->bss_type = priv->bss_type; - tx_info->pkt_len = data_len - (sizeof(struct txpd) + INTF_HEADER_LEN); - skb_reserve(skb, sizeof(struct txpd) + INTF_HEADER_LEN); - skb_push(skb, sizeof(struct txpd)); - - local_tx_pd = (struct txpd *) skb->data; - local_tx_pd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - local_tx_pd->flags = flags; - local_tx_pd->priority = WMM_HIGHEST_PRIORITY; - local_tx_pd->tx_pkt_offset = cpu_to_le16(sizeof(struct txpd)); - local_tx_pd->bss_num = priv->bss_num; - local_tx_pd->bss_type = priv->bss_type; - - if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, - skb, NULL); - } else { - skb_push(skb, INTF_HEADER_LEN); - tx_param.next_pkt_len = 0; - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb, &tx_param); - } - switch (ret) { - case -EBUSY: - dev_kfree_skb_any(skb); - mwifiex_dbg(adapter, ERROR, - "%s: host_to_card failed: ret=%d\n", - __func__, ret); - adapter->dbg.num_tx_host_to_card_failure++; - break; - case -1: - dev_kfree_skb_any(skb); - mwifiex_dbg(adapter, ERROR, - "%s: host_to_card failed: ret=%d\n", - __func__, ret); - adapter->dbg.num_tx_host_to_card_failure++; - break; - case 0: - dev_kfree_skb_any(skb); - mwifiex_dbg(adapter, DATA, - "data: %s: host_to_card succeeded\n", - __func__); - adapter->tx_lock_flag = true; - break; - case -EINPROGRESS: - adapter->tx_lock_flag = true; - break; - default: - break; - } - - return ret; -} - -/* - * This function checks if we need to send last packet indication. - */ -u8 -mwifiex_check_last_packet_indication(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u8 ret = false; - - if (!adapter->sleep_period.period) - return ret; - if (mwifiex_wmm_lists_empty(adapter)) - ret = true; - - if (ret && !adapter->cmd_sent && !adapter->curr_cmd && - !is_command_pending(adapter)) { - adapter->delay_null_pkt = false; - ret = true; - } else { - ret = false; - adapter->delay_null_pkt = true; - } - return ret; -} diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c deleted file mode 100644 index 9275f9c3f869..000000000000 --- a/drivers/net/wireless/mwifiex/tdls.c +++ /dev/null @@ -1,1500 +0,0 @@ -/* Marvell Wireless LAN device driver: TDLS handling - * - * Copyright (C) 2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available on the worldwide web at - * http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" -#include "wmm.h" -#include "11n.h" -#include "11n_rxreorder.h" -#include "11ac.h" - -#define TDLS_REQ_FIX_LEN 6 -#define TDLS_RESP_FIX_LEN 8 -#define TDLS_CONFIRM_FIX_LEN 6 -#define MWIFIEX_TDLS_WMM_INFO_SIZE 7 - -static void mwifiex_restore_tdls_packets(struct mwifiex_private *priv, - const u8 *mac, u8 status) -{ - struct mwifiex_ra_list_tbl *ra_list; - struct list_head *tid_list; - struct sk_buff *skb, *tmp; - struct mwifiex_txinfo *tx_info; - unsigned long flags; - u32 tid; - u8 tid_down; - - mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) { - if (!ether_addr_equal(mac, skb->data)) - continue; - - __skb_unlink(skb, &priv->tdls_txq); - tx_info = MWIFIEX_SKB_TXCB(skb); - tid = skb->priority; - tid_down = mwifiex_wmm_downgrade_tid(priv, tid); - - if (mwifiex_is_tdls_link_setup(status)) { - ra_list = mwifiex_wmm_get_queue_raptr(priv, tid, mac); - ra_list->tdls_link = true; - tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; - } else { - tid_list = &priv->wmm.tid_tbl_ptr[tid_down].ra_list; - if (!list_empty(tid_list)) - ra_list = list_first_entry(tid_list, - struct mwifiex_ra_list_tbl, list); - else - ra_list = NULL; - tx_info->flags &= ~MWIFIEX_BUF_FLAG_TDLS_PKT; - } - - if (!ra_list) { - mwifiex_write_data_complete(priv->adapter, skb, 0, -1); - continue; - } - - skb_queue_tail(&ra_list->skb_head, skb); - - ra_list->ba_pkt_count++; - ra_list->total_pkt_count++; - - if (atomic_read(&priv->wmm.highest_queued_prio) < - tos_to_tid_inv[tid_down]) - atomic_set(&priv->wmm.highest_queued_prio, - tos_to_tid_inv[tid_down]); - - atomic_inc(&priv->wmm.tx_pkts_queued); - } - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - return; -} - -static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, - const u8 *mac) -{ - struct mwifiex_ra_list_tbl *ra_list; - struct list_head *ra_list_head; - struct sk_buff *skb, *tmp; - unsigned long flags; - int i; - - mwifiex_dbg(priv->adapter, DATA, "%s: %pM\n", __func__, mac); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - for (i = 0; i < MAX_NUM_TID; i++) { - if (!list_empty(&priv->wmm.tid_tbl_ptr[i].ra_list)) { - ra_list_head = &priv->wmm.tid_tbl_ptr[i].ra_list; - list_for_each_entry(ra_list, ra_list_head, list) { - skb_queue_walk_safe(&ra_list->skb_head, skb, - tmp) { - if (!ether_addr_equal(mac, skb->data)) - continue; - __skb_unlink(skb, &ra_list->skb_head); - atomic_dec(&priv->wmm.tx_pkts_queued); - ra_list->total_pkt_count--; - skb_queue_tail(&priv->tdls_txq, skb); - } - } - } - } - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - return; -} - -/* This function appends rate TLV to scan config command. */ -static int -mwifiex_tdls_append_rates_ie(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - u8 rates[MWIFIEX_SUPPORTED_RATES], *pos; - u16 rates_size, supp_rates_size, ext_rates_size; - - memset(rates, 0, sizeof(rates)); - rates_size = mwifiex_get_supported_rates(priv, rates); - - supp_rates_size = min_t(u16, rates_size, MWIFIEX_TDLS_SUPPORTED_RATES); - - if (skb_tailroom(skb) < rates_size + 4) { - mwifiex_dbg(priv->adapter, ERROR, - "Insuffient space while adding rates\n"); - return -ENOMEM; - } - - pos = skb_put(skb, supp_rates_size + 2); - *pos++ = WLAN_EID_SUPP_RATES; - *pos++ = supp_rates_size; - memcpy(pos, rates, supp_rates_size); - - if (rates_size > MWIFIEX_TDLS_SUPPORTED_RATES) { - ext_rates_size = rates_size - MWIFIEX_TDLS_SUPPORTED_RATES; - pos = skb_put(skb, ext_rates_size + 2); - *pos++ = WLAN_EID_EXT_SUPP_RATES; - *pos++ = ext_rates_size; - memcpy(pos, rates + MWIFIEX_TDLS_SUPPORTED_RATES, - ext_rates_size); - } - - return 0; -} - -static void mwifiex_tdls_add_aid(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct ieee_types_assoc_rsp *assoc_rsp; - u8 *pos; - - assoc_rsp = (struct ieee_types_assoc_rsp *)&priv->assoc_rsp_buf; - pos = (void *)skb_put(skb, 4); - *pos++ = WLAN_EID_AID; - *pos++ = 2; - memcpy(pos, &assoc_rsp->a_id, sizeof(assoc_rsp->a_id)); - - return; -} - -static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct ieee80211_vht_cap vht_cap; - u8 *pos; - - pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_cap) + 2); - *pos++ = WLAN_EID_VHT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_vht_cap); - - memset(&vht_cap, 0, sizeof(struct ieee80211_vht_cap)); - - mwifiex_fill_vht_cap_tlv(priv, &vht_cap, priv->curr_bss_params.band); - memcpy(pos, &vht_cap, sizeof(vht_cap)); - - return 0; -} - -static int -mwifiex_tdls_add_ht_oper(struct mwifiex_private *priv, const u8 *mac, - u8 vht_enabled, struct sk_buff *skb) -{ - struct ieee80211_ht_operation *ht_oper; - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_bssdescriptor *bss_desc = - &priv->curr_bss_params.bss_descriptor; - u8 *pos; - - sta_ptr = mwifiex_get_sta_entry(priv, mac); - if (unlikely(!sta_ptr)) { - mwifiex_dbg(priv->adapter, ERROR, - "TDLS peer station not found in list\n"); - return -1; - } - - if (!(le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info))) { - mwifiex_dbg(priv->adapter, WARN, - "TDLS peer doesn't support ht capabilities\n"); - return 0; - } - - pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_operation) + 2); - *pos++ = WLAN_EID_HT_OPERATION; - *pos++ = sizeof(struct ieee80211_ht_operation); - ht_oper = (void *)pos; - - ht_oper->primary_chan = bss_desc->channel; - - /* follow AP's channel bandwidth */ - if (ISSUPP_CHANWIDTH40(priv->adapter->hw_dot_11n_dev_cap) && - bss_desc->bcn_ht_cap && - ISALLOWED_CHANWIDTH40(bss_desc->bcn_ht_oper->ht_param)) - ht_oper->ht_param = bss_desc->bcn_ht_oper->ht_param; - - if (vht_enabled) { - ht_oper->ht_param = - mwifiex_get_sec_chan_offset(bss_desc->channel); - ht_oper->ht_param |= BIT(2); - } - - memcpy(&sta_ptr->tdls_cap.ht_oper, ht_oper, - sizeof(struct ieee80211_ht_operation)); - - return 0; -} - -static int mwifiex_tdls_add_vht_oper(struct mwifiex_private *priv, - const u8 *mac, struct sk_buff *skb) -{ - struct mwifiex_bssdescriptor *bss_desc; - struct ieee80211_vht_operation *vht_oper; - struct ieee80211_vht_cap *vht_cap, *ap_vht_cap = NULL; - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_adapter *adapter = priv->adapter; - u8 supp_chwd_set, peer_supp_chwd_set; - u8 *pos, ap_supp_chwd_set, chan_bw; - u16 mcs_map_user, mcs_map_resp, mcs_map_result; - u16 mcs_user, mcs_resp, nss; - u32 usr_vht_cap_info; - - bss_desc = &priv->curr_bss_params.bss_descriptor; - - sta_ptr = mwifiex_get_sta_entry(priv, mac); - if (unlikely(!sta_ptr)) { - mwifiex_dbg(adapter, ERROR, - "TDLS peer station not found in list\n"); - return -1; - } - - if (!(le32_to_cpu(sta_ptr->tdls_cap.vhtcap.vht_cap_info))) { - mwifiex_dbg(adapter, WARN, - "TDLS peer doesn't support vht capabilities\n"); - return 0; - } - - if (!mwifiex_is_bss_in_11ac_mode(priv)) { - if (sta_ptr->tdls_cap.extcap.ext_capab[7] & - WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) { - mwifiex_dbg(adapter, WARN, - "TDLS peer doesn't support wider bandwidth\n"); - return 0; - } - } else { - ap_vht_cap = bss_desc->bcn_vht_cap; - } - - pos = (void *)skb_put(skb, sizeof(struct ieee80211_vht_operation) + 2); - *pos++ = WLAN_EID_VHT_OPERATION; - *pos++ = sizeof(struct ieee80211_vht_operation); - vht_oper = (struct ieee80211_vht_operation *)pos; - - if (bss_desc->bss_band & BAND_A) - usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_a; - else - usr_vht_cap_info = adapter->usr_dot_11ac_dev_cap_bg; - - /* find the minmum bandwith between AP/TDLS peers */ - vht_cap = &sta_ptr->tdls_cap.vhtcap; - supp_chwd_set = GET_VHTCAP_CHWDSET(usr_vht_cap_info); - peer_supp_chwd_set = - GET_VHTCAP_CHWDSET(le32_to_cpu(vht_cap->vht_cap_info)); - supp_chwd_set = min_t(u8, supp_chwd_set, peer_supp_chwd_set); - - /* We need check AP's bandwidth when TDLS_WIDER_BANDWIDTH is off */ - - if (ap_vht_cap && sta_ptr->tdls_cap.extcap.ext_capab[7] & - WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED) { - ap_supp_chwd_set = - GET_VHTCAP_CHWDSET(le32_to_cpu(ap_vht_cap->vht_cap_info)); - supp_chwd_set = min_t(u8, supp_chwd_set, ap_supp_chwd_set); - } - - switch (supp_chwd_set) { - case IEEE80211_VHT_CHANWIDTH_80MHZ: - vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80MHZ; - break; - case IEEE80211_VHT_CHANWIDTH_160MHZ: - vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_160MHZ; - break; - case IEEE80211_VHT_CHANWIDTH_80P80MHZ: - vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_80P80MHZ; - break; - default: - vht_oper->chan_width = IEEE80211_VHT_CHANWIDTH_USE_HT; - break; - } - - mcs_map_user = GET_DEVRXMCSMAP(adapter->usr_dot_11ac_mcs_support); - mcs_map_resp = le16_to_cpu(vht_cap->supp_mcs.rx_mcs_map); - mcs_map_result = 0; - - for (nss = 1; nss <= 8; nss++) { - mcs_user = GET_VHTNSSMCS(mcs_map_user, nss); - mcs_resp = GET_VHTNSSMCS(mcs_map_resp, nss); - - if ((mcs_user == IEEE80211_VHT_MCS_NOT_SUPPORTED) || - (mcs_resp == IEEE80211_VHT_MCS_NOT_SUPPORTED)) - SET_VHTNSSMCS(mcs_map_result, nss, - IEEE80211_VHT_MCS_NOT_SUPPORTED); - else - SET_VHTNSSMCS(mcs_map_result, nss, - min_t(u16, mcs_user, mcs_resp)); - } - - vht_oper->basic_mcs_set = cpu_to_le16(mcs_map_result); - - switch (vht_oper->chan_width) { - case IEEE80211_VHT_CHANWIDTH_80MHZ: - chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ; - break; - case IEEE80211_VHT_CHANWIDTH_160MHZ: - chan_bw = IEEE80211_VHT_CHANWIDTH_160MHZ; - break; - case IEEE80211_VHT_CHANWIDTH_80P80MHZ: - chan_bw = IEEE80211_VHT_CHANWIDTH_80MHZ; - break; - default: - chan_bw = IEEE80211_VHT_CHANWIDTH_USE_HT; - break; - } - vht_oper->center_freq_seg1_idx = - mwifiex_get_center_freq_index(priv, BAND_AAC, - bss_desc->channel, - chan_bw); - - return 0; -} - -static void mwifiex_tdls_add_ext_capab(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct ieee_types_extcap *extcap; - - extcap = (void *)skb_put(skb, sizeof(struct ieee_types_extcap)); - extcap->ieee_hdr.element_id = WLAN_EID_EXT_CAPABILITY; - extcap->ieee_hdr.len = 8; - memset(extcap->ext_capab, 0, 8); - extcap->ext_capab[4] |= WLAN_EXT_CAPA5_TDLS_ENABLED; - extcap->ext_capab[3] |= WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH; - - if (priv->adapter->is_hw_11ac_capable) - extcap->ext_capab[7] |= WLAN_EXT_CAPA8_TDLS_WIDE_BW_ENABLED; -} - -static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb) -{ - u8 *pos = (void *)skb_put(skb, 3); - - *pos++ = WLAN_EID_QOS_CAPA; - *pos++ = 1; - *pos++ = MWIFIEX_TDLS_DEF_QOS_CAPAB; -} - -static void -mwifiex_tdls_add_wmm_param_ie(struct mwifiex_private *priv, struct sk_buff *skb) -{ - struct ieee80211_wmm_param_ie *wmm; - u8 ac_vi[] = {0x42, 0x43, 0x5e, 0x00}; - u8 ac_vo[] = {0x62, 0x32, 0x2f, 0x00}; - u8 ac_be[] = {0x03, 0xa4, 0x00, 0x00}; - u8 ac_bk[] = {0x27, 0xa4, 0x00, 0x00}; - - wmm = (void *)skb_put(skb, sizeof(*wmm)); - memset(wmm, 0, sizeof(*wmm)); - - wmm->element_id = WLAN_EID_VENDOR_SPECIFIC; - wmm->len = sizeof(*wmm) - 2; - wmm->oui[0] = 0x00; /* Microsoft OUI 00:50:F2 */ - wmm->oui[1] = 0x50; - wmm->oui[2] = 0xf2; - wmm->oui_type = 2; /* WME */ - wmm->oui_subtype = 1; /* WME param */ - wmm->version = 1; /* WME ver */ - wmm->qos_info = 0; /* U-APSD not in use */ - - /* use default WMM AC parameters for TDLS link*/ - memcpy(&wmm->ac[0], ac_be, sizeof(ac_be)); - memcpy(&wmm->ac[1], ac_bk, sizeof(ac_bk)); - memcpy(&wmm->ac[2], ac_vi, sizeof(ac_vi)); - memcpy(&wmm->ac[3], ac_vo, sizeof(ac_vo)); -} - -static void -mwifiex_add_wmm_info_ie(struct mwifiex_private *priv, struct sk_buff *skb, - u8 qosinfo) -{ - u8 *buf; - - buf = (void *)skb_put(skb, MWIFIEX_TDLS_WMM_INFO_SIZE + - sizeof(struct ieee_types_header)); - - *buf++ = WLAN_EID_VENDOR_SPECIFIC; - *buf++ = 7; /* len */ - *buf++ = 0x00; /* Microsoft OUI 00:50:F2 */ - *buf++ = 0x50; - *buf++ = 0xf2; - *buf++ = 2; /* WME */ - *buf++ = 0; /* WME info */ - *buf++ = 1; /* WME ver */ - *buf++ = qosinfo; /* U-APSD no in use */ -} - -static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv, - const u8 *peer, u8 action_code, - u8 dialog_token, - u16 status_code, struct sk_buff *skb) -{ - struct ieee80211_tdls_data *tf; - int ret; - u16 capab; - struct ieee80211_ht_cap *ht_cap; - u8 radio, *pos; - - capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap; - - tf = (void *)skb_put(skb, offsetof(struct ieee80211_tdls_data, u)); - memcpy(tf->da, peer, ETH_ALEN); - memcpy(tf->sa, priv->curr_addr, ETH_ALEN); - tf->ether_type = cpu_to_be16(ETH_P_TDLS); - tf->payload_type = WLAN_TDLS_SNAP_RFTYPE; - - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_SETUP_REQUEST; - skb_put(skb, sizeof(tf->u.setup_req)); - tf->u.setup_req.dialog_token = dialog_token; - tf->u.setup_req.capability = cpu_to_le16(capab); - ret = mwifiex_tdls_append_rates_ie(priv, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - - pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (void *)pos; - radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - ret = mwifiex_fill_cap_info(priv, radio, ht_cap); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - - if (priv->adapter->is_hw_11ac_capable) { - ret = mwifiex_tdls_add_vht_capab(priv, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - mwifiex_tdls_add_aid(priv, skb); - } - - mwifiex_tdls_add_ext_capab(priv, skb); - mwifiex_tdls_add_qos_capab(skb); - mwifiex_add_wmm_info_ie(priv, skb, 0); - break; - - case WLAN_TDLS_SETUP_RESPONSE: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_SETUP_RESPONSE; - skb_put(skb, sizeof(tf->u.setup_resp)); - tf->u.setup_resp.status_code = cpu_to_le16(status_code); - tf->u.setup_resp.dialog_token = dialog_token; - tf->u.setup_resp.capability = cpu_to_le16(capab); - ret = mwifiex_tdls_append_rates_ie(priv, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - - pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (void *)pos; - radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - ret = mwifiex_fill_cap_info(priv, radio, ht_cap); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - - if (priv->adapter->is_hw_11ac_capable) { - ret = mwifiex_tdls_add_vht_capab(priv, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - mwifiex_tdls_add_aid(priv, skb); - } - - mwifiex_tdls_add_ext_capab(priv, skb); - mwifiex_tdls_add_qos_capab(skb); - mwifiex_add_wmm_info_ie(priv, skb, 0); - break; - - case WLAN_TDLS_SETUP_CONFIRM: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_SETUP_CONFIRM; - skb_put(skb, sizeof(tf->u.setup_cfm)); - tf->u.setup_cfm.status_code = cpu_to_le16(status_code); - tf->u.setup_cfm.dialog_token = dialog_token; - - mwifiex_tdls_add_wmm_param_ie(priv, skb); - if (priv->adapter->is_hw_11ac_capable) { - ret = mwifiex_tdls_add_vht_oper(priv, peer, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - ret = mwifiex_tdls_add_ht_oper(priv, peer, 1, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - } else { - ret = mwifiex_tdls_add_ht_oper(priv, peer, 0, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - } - break; - - case WLAN_TDLS_TEARDOWN: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_TEARDOWN; - skb_put(skb, sizeof(tf->u.teardown)); - tf->u.teardown.reason_code = cpu_to_le16(status_code); - break; - - case WLAN_TDLS_DISCOVERY_REQUEST: - tf->category = WLAN_CATEGORY_TDLS; - tf->action_code = WLAN_TDLS_DISCOVERY_REQUEST; - skb_put(skb, sizeof(tf->u.discover_req)); - tf->u.discover_req.dialog_token = dialog_token; - break; - default: - mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n"); - return -EINVAL; - } - - return 0; -} - -static void -mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr, - const u8 *peer, const u8 *bssid) -{ - struct ieee80211_tdls_lnkie *lnkid; - - lnkid = (void *)skb_put(skb, sizeof(struct ieee80211_tdls_lnkie)); - lnkid->ie_type = WLAN_EID_LINK_ID; - lnkid->ie_len = sizeof(struct ieee80211_tdls_lnkie) - - sizeof(struct ieee_types_header); - - memcpy(lnkid->bssid, bssid, ETH_ALEN); - memcpy(lnkid->init_sta, src_addr, ETH_ALEN); - memcpy(lnkid->resp_sta, peer, ETH_ALEN); -} - -int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len) -{ - struct sk_buff *skb; - struct mwifiex_txinfo *tx_info; - int ret; - u16 skb_len; - - skb_len = MWIFIEX_MIN_DATA_HEADER_LEN + - max(sizeof(struct ieee80211_mgmt), - sizeof(struct ieee80211_tdls_data)) + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + - MWIFIEX_SUPPORTED_RATES + - 3 + /* Qos Info */ - sizeof(struct ieee_types_extcap) + - sizeof(struct ieee80211_ht_cap) + - sizeof(struct ieee_types_bss_co_2040) + - sizeof(struct ieee80211_ht_operation) + - sizeof(struct ieee80211_tdls_lnkie) + - sizeof(struct ieee80211_wmm_param_ie) + - extra_ies_len; - - if (priv->adapter->is_hw_11ac_capable) - skb_len += sizeof(struct ieee_types_vht_cap) + - sizeof(struct ieee_types_vht_oper) + - sizeof(struct ieee_types_aid); - - skb = dev_alloc_skb(skb_len); - if (!skb) { - mwifiex_dbg(priv->adapter, ERROR, - "allocate skb failed for management frame\n"); - return -ENOMEM; - } - skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN); - - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - case WLAN_TDLS_SETUP_CONFIRM: - case WLAN_TDLS_TEARDOWN: - case WLAN_TDLS_DISCOVERY_REQUEST: - ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code, - dialog_token, status_code, - skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - if (extra_ies_len) - memcpy(skb_put(skb, extra_ies_len), extra_ies, - extra_ies_len); - mwifiex_tdls_add_link_ie(skb, priv->curr_addr, peer, - priv->cfg_bssid); - break; - case WLAN_TDLS_SETUP_RESPONSE: - ret = mwifiex_prep_tdls_encap_data(priv, peer, action_code, - dialog_token, status_code, - skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - if (extra_ies_len) - memcpy(skb_put(skb, extra_ies_len), extra_ies, - extra_ies_len); - mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr, - priv->cfg_bssid); - break; - } - - switch (action_code) { - case WLAN_TDLS_SETUP_REQUEST: - case WLAN_TDLS_SETUP_RESPONSE: - skb->priority = MWIFIEX_PRIO_BK; - break; - default: - skb->priority = MWIFIEX_PRIO_VI; - break; - } - - tx_info = MWIFIEX_SKB_TXCB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->bss_num = priv->bss_num; - tx_info->bss_type = priv->bss_type; - - __net_timestamp(skb); - mwifiex_queue_tx_pkt(priv, skb); - - return 0; -} - -static int -mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, - const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, struct sk_buff *skb) -{ - struct ieee80211_mgmt *mgmt; - u8 bc_addr[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - int ret; - u16 capab; - struct ieee80211_ht_cap *ht_cap; - u8 radio, *pos; - - capab = priv->curr_bss_params.bss_descriptor.cap_info_bitmap; - - mgmt = (void *)skb_put(skb, offsetof(struct ieee80211_mgmt, u)); - - memset(mgmt, 0, 24); - memcpy(mgmt->da, peer, ETH_ALEN); - memcpy(mgmt->sa, priv->curr_addr, ETH_ALEN); - memcpy(mgmt->bssid, priv->cfg_bssid, ETH_ALEN); - mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | - IEEE80211_STYPE_ACTION); - - /* add address 4 */ - pos = skb_put(skb, ETH_ALEN); - - switch (action_code) { - case WLAN_PUB_ACTION_TDLS_DISCOVER_RES: - skb_put(skb, sizeof(mgmt->u.action.u.tdls_discover_resp) + 1); - mgmt->u.action.category = WLAN_CATEGORY_PUBLIC; - mgmt->u.action.u.tdls_discover_resp.action_code = - WLAN_PUB_ACTION_TDLS_DISCOVER_RES; - mgmt->u.action.u.tdls_discover_resp.dialog_token = - dialog_token; - mgmt->u.action.u.tdls_discover_resp.capability = - cpu_to_le16(capab); - /* move back for addr4 */ - memmove(pos + ETH_ALEN, &mgmt->u.action.category, - sizeof(mgmt->u.action.u.tdls_discover_resp)); - /* init address 4 */ - memcpy(pos, bc_addr, ETH_ALEN); - - ret = mwifiex_tdls_append_rates_ie(priv, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - - pos = (void *)skb_put(skb, sizeof(struct ieee80211_ht_cap) + 2); - *pos++ = WLAN_EID_HT_CAPABILITY; - *pos++ = sizeof(struct ieee80211_ht_cap); - ht_cap = (void *)pos; - radio = mwifiex_band_to_radio_type(priv->curr_bss_params.band); - ret = mwifiex_fill_cap_info(priv, radio, ht_cap); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - - if (priv->adapter->is_hw_11ac_capable) { - ret = mwifiex_tdls_add_vht_capab(priv, skb); - if (ret) { - dev_kfree_skb_any(skb); - return ret; - } - mwifiex_tdls_add_aid(priv, skb); - } - - mwifiex_tdls_add_ext_capab(priv, skb); - mwifiex_tdls_add_qos_capab(skb); - break; - default: - mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS action frame type\n"); - return -EINVAL; - } - - return 0; -} - -int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv, const u8 *peer, - u8 action_code, u8 dialog_token, - u16 status_code, const u8 *extra_ies, - size_t extra_ies_len) -{ - struct sk_buff *skb; - struct mwifiex_txinfo *tx_info; - u8 *pos; - u32 pkt_type, tx_control; - u16 pkt_len, skb_len; - - skb_len = MWIFIEX_MIN_DATA_HEADER_LEN + - max(sizeof(struct ieee80211_mgmt), - sizeof(struct ieee80211_tdls_data)) + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + - MWIFIEX_SUPPORTED_RATES + - sizeof(struct ieee_types_extcap) + - sizeof(struct ieee80211_ht_cap) + - sizeof(struct ieee_types_bss_co_2040) + - sizeof(struct ieee80211_ht_operation) + - sizeof(struct ieee80211_tdls_lnkie) + - extra_ies_len + - 3 + /* Qos Info */ - ETH_ALEN; /* Address4 */ - - if (priv->adapter->is_hw_11ac_capable) - skb_len += sizeof(struct ieee_types_vht_cap) + - sizeof(struct ieee_types_vht_oper) + - sizeof(struct ieee_types_aid); - - skb = dev_alloc_skb(skb_len); - if (!skb) { - mwifiex_dbg(priv->adapter, ERROR, - "allocate skb failed for management frame\n"); - return -ENOMEM; - } - - skb_reserve(skb, MWIFIEX_MIN_DATA_HEADER_LEN); - - pkt_type = PKT_TYPE_MGMT; - tx_control = 0; - pos = skb_put(skb, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); - memset(pos, 0, MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(pkt_len)); - memcpy(pos, &pkt_type, sizeof(pkt_type)); - memcpy(pos + sizeof(pkt_type), &tx_control, sizeof(tx_control)); - - if (mwifiex_construct_tdls_action_frame(priv, peer, action_code, - dialog_token, status_code, - skb)) { - dev_kfree_skb_any(skb); - return -EINVAL; - } - - if (extra_ies_len) - memcpy(skb_put(skb, extra_ies_len), extra_ies, extra_ies_len); - - /* the TDLS link IE is always added last we are the responder */ - - mwifiex_tdls_add_link_ie(skb, peer, priv->curr_addr, - priv->cfg_bssid); - - skb->priority = MWIFIEX_PRIO_VI; - - tx_info = MWIFIEX_SKB_TXCB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->bss_num = priv->bss_num; - tx_info->bss_type = priv->bss_type; - tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; - - pkt_len = skb->len - MWIFIEX_MGMT_FRAME_HEADER_SIZE - sizeof(pkt_len); - memcpy(skb->data + MWIFIEX_MGMT_FRAME_HEADER_SIZE, &pkt_len, - sizeof(pkt_len)); - __net_timestamp(skb); - mwifiex_queue_tx_pkt(priv, skb); - - return 0; -} - -/* This function process tdls action frame from peer. - * Peer capabilities are stored into station node structure. - */ -void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv, - u8 *buf, int len) -{ - struct mwifiex_sta_node *sta_ptr; - u8 *peer, *pos, *end; - u8 i, action, basic; - __le16 cap = 0; - int ie_len = 0; - - if (len < (sizeof(struct ethhdr) + 3)) - return; - if (*(buf + sizeof(struct ethhdr)) != WLAN_TDLS_SNAP_RFTYPE) - return; - if (*(buf + sizeof(struct ethhdr) + 1) != WLAN_CATEGORY_TDLS) - return; - - peer = buf + ETH_ALEN; - action = *(buf + sizeof(struct ethhdr) + 2); - mwifiex_dbg(priv->adapter, DATA, - "rx:tdls action: peer=%pM, action=%d\n", peer, action); - - switch (action) { - case WLAN_TDLS_SETUP_REQUEST: - if (len < (sizeof(struct ethhdr) + TDLS_REQ_FIX_LEN)) - return; - - pos = buf + sizeof(struct ethhdr) + 4; - /* payload 1+ category 1 + action 1 + dialog 1 */ - cap = cpu_to_le16(*(u16 *)pos); - ie_len = len - sizeof(struct ethhdr) - TDLS_REQ_FIX_LEN; - pos += 2; - break; - - case WLAN_TDLS_SETUP_RESPONSE: - if (len < (sizeof(struct ethhdr) + TDLS_RESP_FIX_LEN)) - return; - /* payload 1+ category 1 + action 1 + dialog 1 + status code 2*/ - pos = buf + sizeof(struct ethhdr) + 6; - cap = cpu_to_le16(*(u16 *)pos); - ie_len = len - sizeof(struct ethhdr) - TDLS_RESP_FIX_LEN; - pos += 2; - break; - - case WLAN_TDLS_SETUP_CONFIRM: - if (len < (sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN)) - return; - pos = buf + sizeof(struct ethhdr) + TDLS_CONFIRM_FIX_LEN; - ie_len = len - sizeof(struct ethhdr) - TDLS_CONFIRM_FIX_LEN; - break; - default: - mwifiex_dbg(priv->adapter, ERROR, "Unknown TDLS frame type.\n"); - return; - } - - sta_ptr = mwifiex_add_sta_entry(priv, peer); - if (!sta_ptr) - return; - - sta_ptr->tdls_cap.capab = cap; - - for (end = pos + ie_len; pos + 1 < end; pos += 2 + pos[1]) { - if (pos + 2 + pos[1] > end) - break; - - switch (*pos) { - case WLAN_EID_SUPP_RATES: - sta_ptr->tdls_cap.rates_len = pos[1]; - for (i = 0; i < pos[1]; i++) - sta_ptr->tdls_cap.rates[i] = pos[i + 2]; - break; - - case WLAN_EID_EXT_SUPP_RATES: - basic = sta_ptr->tdls_cap.rates_len; - for (i = 0; i < pos[1]; i++) - sta_ptr->tdls_cap.rates[basic + i] = pos[i + 2]; - sta_ptr->tdls_cap.rates_len += pos[1]; - break; - case WLAN_EID_HT_CAPABILITY: - memcpy((u8 *)&sta_ptr->tdls_cap.ht_capb, pos, - sizeof(struct ieee80211_ht_cap)); - sta_ptr->is_11n_enabled = 1; - break; - case WLAN_EID_HT_OPERATION: - memcpy(&sta_ptr->tdls_cap.ht_oper, pos, - sizeof(struct ieee80211_ht_operation)); - break; - case WLAN_EID_BSS_COEX_2040: - sta_ptr->tdls_cap.coex_2040 = pos[2]; - break; - case WLAN_EID_EXT_CAPABILITY: - memcpy((u8 *)&sta_ptr->tdls_cap.extcap, pos, - sizeof(struct ieee_types_header) + - min_t(u8, pos[1], 8)); - break; - case WLAN_EID_RSN: - memcpy((u8 *)&sta_ptr->tdls_cap.rsn_ie, pos, - sizeof(struct ieee_types_header) + - min_t(u8, pos[1], IEEE_MAX_IE_SIZE - - sizeof(struct ieee_types_header))); - break; - case WLAN_EID_QOS_CAPA: - sta_ptr->tdls_cap.qos_info = pos[2]; - break; - case WLAN_EID_VHT_OPERATION: - if (priv->adapter->is_hw_11ac_capable) - memcpy(&sta_ptr->tdls_cap.vhtoper, pos, - sizeof(struct ieee80211_vht_operation)); - break; - case WLAN_EID_VHT_CAPABILITY: - if (priv->adapter->is_hw_11ac_capable) { - memcpy((u8 *)&sta_ptr->tdls_cap.vhtcap, pos, - sizeof(struct ieee80211_vht_cap)); - sta_ptr->is_11ac_enabled = 1; - } - break; - case WLAN_EID_AID: - if (priv->adapter->is_hw_11ac_capable) - sta_ptr->tdls_cap.aid = - le16_to_cpu(*(__le16 *)(pos + 2)); - default: - break; - } - } - - return; -} - -static int -mwifiex_tdls_process_config_link(struct mwifiex_private *priv, const u8 *peer) -{ - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; - - memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); - sta_ptr = mwifiex_get_sta_entry(priv, peer); - - if (!sta_ptr || sta_ptr->tdls_status == TDLS_SETUP_FAILURE) { - mwifiex_dbg(priv->adapter, ERROR, - "link absent for peer %pM; cannot config\n", peer); - return -EINVAL; - } - - memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); - tdls_oper.tdls_action = MWIFIEX_TDLS_CONFIG_LINK; - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, - HostCmd_ACT_GEN_SET, 0, &tdls_oper, true); -} - -static int -mwifiex_tdls_process_create_link(struct mwifiex_private *priv, const u8 *peer) -{ - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; - - memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); - sta_ptr = mwifiex_get_sta_entry(priv, peer); - - if (sta_ptr && sta_ptr->tdls_status == TDLS_SETUP_INPROGRESS) { - mwifiex_dbg(priv->adapter, WARN, - "Setup already in progress for peer %pM\n", peer); - return 0; - } - - sta_ptr = mwifiex_add_sta_entry(priv, peer); - if (!sta_ptr) - return -ENOMEM; - - sta_ptr->tdls_status = TDLS_SETUP_INPROGRESS; - mwifiex_hold_tdls_packets(priv, peer); - memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); - tdls_oper.tdls_action = MWIFIEX_TDLS_CREATE_LINK; - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, - HostCmd_ACT_GEN_SET, 0, &tdls_oper, true); -} - -static int -mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, const u8 *peer) -{ - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; - unsigned long flags; - - memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); - sta_ptr = mwifiex_get_sta_entry(priv, peer); - - if (sta_ptr) { - if (sta_ptr->is_11n_enabled) { - mwifiex_11n_cleanup_reorder_tbl(priv); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, - flags); - mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - flags); - } - mwifiex_del_sta_entry(priv, peer); - } - - mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); - mwifiex_auto_tdls_update_peer_status(priv, peer, TDLS_NOT_SETUP); - memcpy(&tdls_oper.peer_mac, peer, ETH_ALEN); - tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, - HostCmd_ACT_GEN_SET, 0, &tdls_oper, true); -} - -static int -mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer) -{ - struct mwifiex_sta_node *sta_ptr; - struct ieee80211_mcs_info mcs; - unsigned long flags; - int i; - - sta_ptr = mwifiex_get_sta_entry(priv, peer); - - if (sta_ptr && (sta_ptr->tdls_status != TDLS_SETUP_FAILURE)) { - mwifiex_dbg(priv->adapter, MSG, - "tdls: enable link %pM success\n", peer); - - sta_ptr->tdls_status = TDLS_SETUP_COMPLETE; - - mcs = sta_ptr->tdls_cap.ht_capb.mcs; - if (mcs.rx_mask[0] != 0xff) - sta_ptr->is_11n_enabled = true; - if (sta_ptr->is_11n_enabled) { - if (le16_to_cpu(sta_ptr->tdls_cap.ht_capb.cap_info) & - IEEE80211_HT_CAP_MAX_AMSDU) - sta_ptr->max_amsdu = - MWIFIEX_TX_DATA_BUF_SIZE_8K; - else - sta_ptr->max_amsdu = - MWIFIEX_TX_DATA_BUF_SIZE_4K; - - for (i = 0; i < MAX_NUM_TID; i++) - sta_ptr->ampdu_sta[i] = - priv->aggr_prio_tbl[i].ampdu_user; - } else { - for (i = 0; i < MAX_NUM_TID; i++) - sta_ptr->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; - } - if (sta_ptr->tdls_cap.extcap.ext_capab[3] & - WLAN_EXT_CAPA4_TDLS_CHAN_SWITCH) { - mwifiex_config_tdls_enable(priv); - mwifiex_config_tdls_cs_params(priv); - } - - memset(sta_ptr->rx_seq, 0xff, sizeof(sta_ptr->rx_seq)); - mwifiex_restore_tdls_packets(priv, peer, TDLS_SETUP_COMPLETE); - mwifiex_auto_tdls_update_peer_status(priv, peer, - TDLS_SETUP_COMPLETE); - } else { - mwifiex_dbg(priv->adapter, ERROR, - "tdls: enable link %pM failed\n", peer); - if (sta_ptr) { - mwifiex_11n_cleanup_reorder_tbl(priv); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, - flags); - mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - flags); - mwifiex_del_sta_entry(priv, peer); - } - mwifiex_restore_tdls_packets(priv, peer, TDLS_LINK_TEARDOWN); - mwifiex_auto_tdls_update_peer_status(priv, peer, - TDLS_NOT_SETUP); - - return -1; - } - - return 0; -} - -int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action) -{ - switch (action) { - case MWIFIEX_TDLS_ENABLE_LINK: - return mwifiex_tdls_process_enable_link(priv, peer); - case MWIFIEX_TDLS_DISABLE_LINK: - return mwifiex_tdls_process_disable_link(priv, peer); - case MWIFIEX_TDLS_CREATE_LINK: - return mwifiex_tdls_process_create_link(priv, peer); - case MWIFIEX_TDLS_CONFIG_LINK: - return mwifiex_tdls_process_config_link(priv, peer); - } - return 0; -} - -int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac) -{ - struct mwifiex_sta_node *sta_ptr; - - sta_ptr = mwifiex_get_sta_entry(priv, mac); - if (sta_ptr) - return sta_ptr->tdls_status; - - return TDLS_NOT_SETUP; -} - -int mwifiex_get_tdls_list(struct mwifiex_private *priv, - struct tdls_peer_info *buf) -{ - struct mwifiex_sta_node *sta_ptr; - struct tdls_peer_info *peer = buf; - int count = 0; - unsigned long flags; - - if (!ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) - return 0; - - /* make sure we are in station mode and connected */ - if (!(priv->bss_type == MWIFIEX_BSS_TYPE_STA && priv->media_connected)) - return 0; - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - list_for_each_entry(sta_ptr, &priv->sta_list, list) { - if (mwifiex_is_tdls_link_setup(sta_ptr->tdls_status)) { - ether_addr_copy(peer->peer_addr, sta_ptr->mac_addr); - peer++; - count++; - if (count >= MWIFIEX_MAX_TDLS_PEER_SUPPORTED) - break; - } - } - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - - return count; -} - -void mwifiex_disable_all_tdls_links(struct mwifiex_private *priv) -{ - struct mwifiex_sta_node *sta_ptr; - struct mwifiex_ds_tdls_oper tdls_oper; - unsigned long flags; - - if (list_empty(&priv->sta_list)) - return; - - list_for_each_entry(sta_ptr, &priv->sta_list, list) { - memset(&tdls_oper, 0, sizeof(struct mwifiex_ds_tdls_oper)); - - if (sta_ptr->is_11n_enabled) { - mwifiex_11n_cleanup_reorder_tbl(priv); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, - flags); - mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - flags); - } - - mwifiex_restore_tdls_packets(priv, sta_ptr->mac_addr, - TDLS_LINK_TEARDOWN); - memcpy(&tdls_oper.peer_mac, sta_ptr->mac_addr, ETH_ALEN); - tdls_oper.tdls_action = MWIFIEX_TDLS_DISABLE_LINK; - if (mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_OPER, - HostCmd_ACT_GEN_SET, 0, &tdls_oper, false)) - mwifiex_dbg(priv->adapter, ERROR, - "Disable link failed for TDLS peer %pM", - sta_ptr->mac_addr); - } - - mwifiex_del_all_sta_list(priv); -} - -int mwifiex_tdls_check_tx(struct mwifiex_private *priv, struct sk_buff *skb) -{ - struct mwifiex_auto_tdls_peer *peer; - unsigned long flags; - u8 mac[ETH_ALEN]; - - ether_addr_copy(mac, skb->data); - - spin_lock_irqsave(&priv->auto_tdls_lock, flags); - list_for_each_entry(peer, &priv->auto_tdls_list, list) { - if (!memcmp(mac, peer->mac_addr, ETH_ALEN)) { - if (peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH && - peer->tdls_status == TDLS_NOT_SETUP && - (peer->failure_count < - MWIFIEX_TDLS_MAX_FAIL_COUNT)) { - peer->tdls_status = TDLS_SETUP_INPROGRESS; - mwifiex_dbg(priv->adapter, INFO, - "setup TDLS link, peer=%pM rssi=%d\n", - peer->mac_addr, peer->rssi); - - cfg80211_tdls_oper_request(priv->netdev, - peer->mac_addr, - NL80211_TDLS_SETUP, - 0, GFP_ATOMIC); - peer->do_setup = false; - priv->check_tdls_tx = false; - } else if (peer->failure_count < - MWIFIEX_TDLS_MAX_FAIL_COUNT && - peer->do_discover) { - mwifiex_send_tdls_data_frame(priv, - peer->mac_addr, - WLAN_TDLS_DISCOVERY_REQUEST, - 1, 0, NULL, 0); - peer->do_discover = false; - } - } - } - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); - - return 0; -} - -void mwifiex_flush_auto_tdls_list(struct mwifiex_private *priv) -{ - struct mwifiex_auto_tdls_peer *peer, *tmp_node; - unsigned long flags; - - spin_lock_irqsave(&priv->auto_tdls_lock, flags); - list_for_each_entry_safe(peer, tmp_node, &priv->auto_tdls_list, list) { - list_del(&peer->list); - kfree(peer); - } - - INIT_LIST_HEAD(&priv->auto_tdls_list); - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); - priv->check_tdls_tx = false; -} - -void mwifiex_add_auto_tdls_peer(struct mwifiex_private *priv, const u8 *mac) -{ - struct mwifiex_auto_tdls_peer *tdls_peer; - unsigned long flags; - - if (!priv->adapter->auto_tdls) - return; - - spin_lock_irqsave(&priv->auto_tdls_lock, flags); - list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) { - if (!memcmp(tdls_peer->mac_addr, mac, ETH_ALEN)) { - tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS; - tdls_peer->rssi_jiffies = jiffies; - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); - return; - } - } - - /* create new TDLS peer */ - tdls_peer = kzalloc(sizeof(*tdls_peer), GFP_ATOMIC); - if (tdls_peer) { - ether_addr_copy(tdls_peer->mac_addr, mac); - tdls_peer->tdls_status = TDLS_SETUP_INPROGRESS; - tdls_peer->rssi_jiffies = jiffies; - INIT_LIST_HEAD(&tdls_peer->list); - list_add_tail(&tdls_peer->list, &priv->auto_tdls_list); - mwifiex_dbg(priv->adapter, INFO, - "Add auto TDLS peer= %pM to list\n", mac); - } - - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); -} - -void mwifiex_auto_tdls_update_peer_status(struct mwifiex_private *priv, - const u8 *mac, u8 link_status) -{ - struct mwifiex_auto_tdls_peer *peer; - unsigned long flags; - - if (!priv->adapter->auto_tdls) - return; - - spin_lock_irqsave(&priv->auto_tdls_lock, flags); - list_for_each_entry(peer, &priv->auto_tdls_list, list) { - if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) { - if ((link_status == TDLS_NOT_SETUP) && - (peer->tdls_status == TDLS_SETUP_INPROGRESS)) - peer->failure_count++; - else if (mwifiex_is_tdls_link_setup(link_status)) - peer->failure_count = 0; - - peer->tdls_status = link_status; - break; - } - } - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); -} - -void mwifiex_auto_tdls_update_peer_signal(struct mwifiex_private *priv, - u8 *mac, s8 snr, s8 nflr) -{ - struct mwifiex_auto_tdls_peer *peer; - unsigned long flags; - - if (!priv->adapter->auto_tdls) - return; - - spin_lock_irqsave(&priv->auto_tdls_lock, flags); - list_for_each_entry(peer, &priv->auto_tdls_list, list) { - if (!memcmp(peer->mac_addr, mac, ETH_ALEN)) { - peer->rssi = nflr - snr; - peer->rssi_jiffies = jiffies; - break; - } - } - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); -} - -void mwifiex_check_auto_tdls(unsigned long context) -{ - struct mwifiex_private *priv = (struct mwifiex_private *)context; - struct mwifiex_auto_tdls_peer *tdls_peer; - unsigned long flags; - u16 reason = WLAN_REASON_TDLS_TEARDOWN_UNSPECIFIED; - - if (WARN_ON_ONCE(!priv || !priv->adapter)) { - pr_err("mwifiex: %s: adapter or private structure is NULL\n", - __func__); - return; - } - - if (unlikely(!priv->adapter->auto_tdls)) - return; - - if (!priv->auto_tdls_timer_active) { - mwifiex_dbg(priv->adapter, INFO, - "auto TDLS timer inactive; return"); - return; - } - - priv->check_tdls_tx = false; - - if (list_empty(&priv->auto_tdls_list)) { - mod_timer(&priv->auto_tdls_timer, - jiffies + - msecs_to_jiffies(MWIFIEX_TIMER_10S)); - return; - } - - spin_lock_irqsave(&priv->auto_tdls_lock, flags); - list_for_each_entry(tdls_peer, &priv->auto_tdls_list, list) { - if ((jiffies - tdls_peer->rssi_jiffies) > - (MWIFIEX_AUTO_TDLS_IDLE_TIME * HZ)) { - tdls_peer->rssi = 0; - tdls_peer->do_discover = true; - priv->check_tdls_tx = true; - } - - if (((tdls_peer->rssi >= MWIFIEX_TDLS_RSSI_LOW) || - !tdls_peer->rssi) && - mwifiex_is_tdls_link_setup(tdls_peer->tdls_status)) { - tdls_peer->tdls_status = TDLS_LINK_TEARDOWN; - mwifiex_dbg(priv->adapter, MSG, - "teardown TDLS link,peer=%pM rssi=%d\n", - tdls_peer->mac_addr, -tdls_peer->rssi); - tdls_peer->do_discover = true; - priv->check_tdls_tx = true; - cfg80211_tdls_oper_request(priv->netdev, - tdls_peer->mac_addr, - NL80211_TDLS_TEARDOWN, - reason, GFP_ATOMIC); - } else if (tdls_peer->rssi && - tdls_peer->rssi <= MWIFIEX_TDLS_RSSI_HIGH && - tdls_peer->tdls_status == TDLS_NOT_SETUP && - tdls_peer->failure_count < - MWIFIEX_TDLS_MAX_FAIL_COUNT) { - priv->check_tdls_tx = true; - tdls_peer->do_setup = true; - mwifiex_dbg(priv->adapter, INFO, - "check TDLS with peer=%pM\t" - "rssi=%d\n", tdls_peer->mac_addr, - tdls_peer->rssi); - } - } - spin_unlock_irqrestore(&priv->auto_tdls_lock, flags); - - mod_timer(&priv->auto_tdls_timer, - jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); -} - -void mwifiex_setup_auto_tdls_timer(struct mwifiex_private *priv) -{ - setup_timer(&priv->auto_tdls_timer, mwifiex_check_auto_tdls, - (unsigned long)priv); - priv->auto_tdls_timer_active = true; - mod_timer(&priv->auto_tdls_timer, - jiffies + msecs_to_jiffies(MWIFIEX_TIMER_10S)); -} - -void mwifiex_clean_auto_tdls(struct mwifiex_private *priv) -{ - if (ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info) && - priv->adapter->auto_tdls && - priv->bss_type == MWIFIEX_BSS_TYPE_STA) { - priv->auto_tdls_timer_active = false; - del_timer(&priv->auto_tdls_timer); - mwifiex_flush_auto_tdls_list(priv); - } -} - -static int mwifiex_config_tdls(struct mwifiex_private *priv, u8 enable) -{ - struct mwifiex_tdls_config config; - - config.enable = cpu_to_le16(enable); - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG, - ACT_TDLS_CS_ENABLE_CONFIG, 0, &config, true); -} - -int mwifiex_config_tdls_enable(struct mwifiex_private *priv) -{ - return mwifiex_config_tdls(priv, true); -} - -int mwifiex_config_tdls_disable(struct mwifiex_private *priv) -{ - return mwifiex_config_tdls(priv, false); -} - -int mwifiex_config_tdls_cs_params(struct mwifiex_private *priv) -{ - struct mwifiex_tdls_config_cs_params config_tdls_cs_params; - - config_tdls_cs_params.unit_time = MWIFIEX_DEF_CS_UNIT_TIME; - config_tdls_cs_params.thr_otherlink = MWIFIEX_DEF_CS_THR_OTHERLINK; - config_tdls_cs_params.thr_directlink = MWIFIEX_DEF_THR_DIRECTLINK; - - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG, - ACT_TDLS_CS_PARAMS, 0, - &config_tdls_cs_params, true); -} - -int mwifiex_stop_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac) -{ - struct mwifiex_tdls_stop_cs_params stop_tdls_cs_params; - - ether_addr_copy(stop_tdls_cs_params.peer_mac, peer_mac); - - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG, - ACT_TDLS_CS_STOP, 0, - &stop_tdls_cs_params, true); -} - -int mwifiex_start_tdls_cs(struct mwifiex_private *priv, const u8 *peer_mac, - u8 primary_chan, u8 second_chan_offset, u8 band) -{ - struct mwifiex_tdls_init_cs_params start_tdls_cs_params; - - ether_addr_copy(start_tdls_cs_params.peer_mac, peer_mac); - start_tdls_cs_params.primary_chan = primary_chan; - start_tdls_cs_params.second_chan_offset = second_chan_offset; - start_tdls_cs_params.band = band; - - start_tdls_cs_params.switch_time = cpu_to_le16(MWIFIEX_DEF_CS_TIME); - start_tdls_cs_params.switch_timeout = - cpu_to_le16(MWIFIEX_DEF_CS_TIMEOUT); - start_tdls_cs_params.reg_class = MWIFIEX_DEF_CS_REG_CLASS; - start_tdls_cs_params.periodicity = MWIFIEX_DEF_CS_PERIODICITY; - - return mwifiex_send_cmd(priv, HostCmd_CMD_TDLS_CONFIG, - ACT_TDLS_CS_INIT, 0, - &start_tdls_cs_params, true); -} diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c deleted file mode 100644 index bf6182b646a5..000000000000 --- a/drivers/net/wireless/mwifiex/txrx.c +++ /dev/null @@ -1,386 +0,0 @@ -/* - * Marvell Wireless LAN device driver: generic TX/RX data handling - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" - -/* - * This function processes the received buffer. - * - * Main responsibility of this function is to parse the RxPD to - * identify the correct interface this packet is headed for and - * forwarding it to the associated handling function, where the - * packet will be further processed and sent to kernel/upper layer - * if required. - */ -int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - struct mwifiex_private *priv = - mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - struct rxpd *local_rx_pd; - struct mwifiex_rxinfo *rx_info = MWIFIEX_SKB_RXCB(skb); - int ret; - - local_rx_pd = (struct rxpd *) (skb->data); - /* Get the BSS number from rxpd, get corresponding priv */ - priv = mwifiex_get_priv_by_id(adapter, local_rx_pd->bss_num & - BSS_NUM_MASK, local_rx_pd->bss_type); - if (!priv) - priv = mwifiex_get_priv(adapter, MWIFIEX_BSS_ROLE_ANY); - - if (!priv) { - mwifiex_dbg(adapter, ERROR, - "data: priv not found. Drop RX packet\n"); - dev_kfree_skb_any(skb); - return -1; - } - - mwifiex_dbg_dump(adapter, DAT_D, "rx pkt:", skb->data, - min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN)); - - memset(rx_info, 0, sizeof(*rx_info)); - rx_info->bss_num = priv->bss_num; - rx_info->bss_type = priv->bss_type; - - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) - ret = mwifiex_process_uap_rx_packet(priv, skb); - else - ret = mwifiex_process_sta_rx_packet(priv, skb); - - return ret; -} -EXPORT_SYMBOL_GPL(mwifiex_handle_rx_packet); - -/* - * This function sends a packet to device. - * - * It processes the packet to add the TxPD, checks condition and - * sends the processed packet to firmware for transmission. - * - * On successful completion, the function calls the completion callback - * and logs the time. - */ -int mwifiex_process_tx(struct mwifiex_private *priv, struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - int hroom, ret = -1; - struct mwifiex_adapter *adapter = priv->adapter; - u8 *head_ptr; - struct txpd *local_tx_pd = NULL; - struct mwifiex_sta_node *dest_node; - struct ethhdr *hdr = (void *)skb->data; - - hroom = (adapter->iface_type == MWIFIEX_USB) ? 0 : INTF_HEADER_LEN; - - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP) { - dest_node = mwifiex_get_sta_entry(priv, hdr->h_dest); - if (dest_node) { - dest_node->stats.tx_bytes += skb->len; - dest_node->stats.tx_packets++; - } - - head_ptr = mwifiex_process_uap_txpd(priv, skb); - } else { - head_ptr = mwifiex_process_sta_txpd(priv, skb); - } - - if ((adapter->data_sent || adapter->tx_lock_flag) && head_ptr) { - skb_queue_tail(&adapter->tx_data_q, skb); - atomic_inc(&adapter->tx_queued); - return 0; - } - - if (head_ptr) { - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) - local_tx_pd = (struct txpd *)(head_ptr + hroom); - if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, - priv->usb_port, - skb, NULL); - } else { - ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_TYPE_DATA, - skb, tx_param); - } - } - mwifiex_dbg_dump(adapter, DAT_D, "tx pkt:", skb->data, - min_t(size_t, skb->len, DEBUG_DUMP_DATA_MAX_LEN)); - - switch (ret) { - case -ENOSR: - mwifiex_dbg(adapter, DATA, "data: -ENOSR is returned\n"); - break; - case -EBUSY: - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - (adapter->pps_uapsd_mode) && (adapter->tx_lock_flag)) { - priv->adapter->tx_lock_flag = false; - if (local_tx_pd) - local_tx_pd->flags = 0; - } - mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); - break; - case -1: - mwifiex_dbg(adapter, ERROR, - "mwifiex_write_data_async failed: 0x%X\n", - ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb, 0, ret); - break; - case -EINPROGRESS: - break; - case 0: - mwifiex_write_data_complete(adapter, skb, 0, ret); - break; - default: - break; - } - - return ret; -} - -static int mwifiex_host_to_card(struct mwifiex_adapter *adapter, - struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - struct txpd *local_tx_pd = NULL; - u8 *head_ptr = skb->data; - int ret = 0; - struct mwifiex_private *priv; - struct mwifiex_txinfo *tx_info; - - tx_info = MWIFIEX_SKB_TXCB(skb); - priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num, - tx_info->bss_type); - if (!priv) { - mwifiex_dbg(adapter, ERROR, - "data: priv not found. Drop TX packet\n"); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb, 0, 0); - return ret; - } - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) { - if (adapter->iface_type == MWIFIEX_USB) - local_tx_pd = (struct txpd *)head_ptr; - else - local_tx_pd = (struct txpd *) (head_ptr + - INTF_HEADER_LEN); - } - - if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, - priv->usb_port, - skb, NULL); - } else { - ret = adapter->if_ops.host_to_card(adapter, - MWIFIEX_TYPE_DATA, - skb, tx_param); - } - switch (ret) { - case -ENOSR: - mwifiex_dbg(adapter, ERROR, "data: -ENOSR is returned\n"); - break; - case -EBUSY: - if ((GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA) && - (adapter->pps_uapsd_mode) && - (adapter->tx_lock_flag)) { - priv->adapter->tx_lock_flag = false; - if (local_tx_pd) - local_tx_pd->flags = 0; - } - skb_queue_head(&adapter->tx_data_q, skb); - if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) - atomic_add(tx_info->aggr_num, &adapter->tx_queued); - else - atomic_inc(&adapter->tx_queued); - mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); - break; - case -1: - mwifiex_dbg(adapter, ERROR, - "mwifiex_write_data_async failed: 0x%X\n", ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb, 0, ret); - break; - case -EINPROGRESS: - break; - case 0: - mwifiex_write_data_complete(adapter, skb, 0, ret); - break; - default: - break; - } - return ret; -} - -static int -mwifiex_dequeue_tx_queue(struct mwifiex_adapter *adapter) -{ - struct sk_buff *skb, *skb_next; - struct mwifiex_txinfo *tx_info; - struct mwifiex_tx_param tx_param; - - skb = skb_dequeue(&adapter->tx_data_q); - if (!skb) - return -1; - - tx_info = MWIFIEX_SKB_TXCB(skb); - if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) - atomic_sub(tx_info->aggr_num, &adapter->tx_queued); - else - atomic_dec(&adapter->tx_queued); - - if (!skb_queue_empty(&adapter->tx_data_q)) - skb_next = skb_peek(&adapter->tx_data_q); - else - skb_next = NULL; - tx_param.next_pkt_len = ((skb_next) ? skb_next->len : 0); - if (!tx_param.next_pkt_len) { - if (!mwifiex_wmm_lists_empty(adapter)) - tx_param.next_pkt_len = 1; - } - return mwifiex_host_to_card(adapter, skb, &tx_param); -} - -void -mwifiex_process_tx_queue(struct mwifiex_adapter *adapter) -{ - do { - if (adapter->data_sent || adapter->tx_lock_flag) - break; - if (mwifiex_dequeue_tx_queue(adapter)) - break; - } while (!skb_queue_empty(&adapter->tx_data_q)); -} - -/* - * Packet send completion callback handler. - * - * It either frees the buffer directly or forwards it to another - * completion callback which checks conditions, updates statistics, - * wakes up stalled traffic queue if required, and then frees the buffer. - */ -int mwifiex_write_data_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb, int aggr, int status) -{ - struct mwifiex_private *priv; - struct mwifiex_txinfo *tx_info; - struct netdev_queue *txq; - int index; - - if (!skb) - return 0; - - tx_info = MWIFIEX_SKB_TXCB(skb); - priv = mwifiex_get_priv_by_id(adapter, tx_info->bss_num, - tx_info->bss_type); - if (!priv) - goto done; - - mwifiex_set_trans_start(priv->netdev); - if (!status) { - priv->stats.tx_packets++; - priv->stats.tx_bytes += tx_info->pkt_len; - if (priv->tx_timeout_cnt) - priv->tx_timeout_cnt = 0; - } else { - priv->stats.tx_errors++; - } - - if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) - atomic_dec_return(&adapter->pending_bridged_pkts); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_AGGR_PKT) - goto done; - - if (aggr) - /* For skb_aggr, do not wake up tx queue */ - goto done; - - atomic_dec(&adapter->tx_pending); - - index = mwifiex_1d_to_wmm_queue[skb->priority]; - if (atomic_dec_return(&priv->wmm_tx_pending[index]) < LOW_TX_PENDING) { - txq = netdev_get_tx_queue(priv->netdev, index); - if (netif_tx_queue_stopped(txq)) { - netif_tx_wake_queue(txq); - mwifiex_dbg(adapter, DATA, "wake queue: %d\n", index); - } - } -done: - dev_kfree_skb_any(skb); - - return 0; -} -EXPORT_SYMBOL_GPL(mwifiex_write_data_complete); - -void mwifiex_parse_tx_status_event(struct mwifiex_private *priv, - void *event_body) -{ - struct tx_status_event *tx_status = (void *)priv->adapter->event_body; - struct sk_buff *ack_skb; - unsigned long flags; - struct mwifiex_txinfo *tx_info; - - if (!tx_status->tx_token_id) - return; - - spin_lock_irqsave(&priv->ack_status_lock, flags); - ack_skb = idr_find(&priv->ack_status_frames, tx_status->tx_token_id); - if (ack_skb) - idr_remove(&priv->ack_status_frames, tx_status->tx_token_id); - spin_unlock_irqrestore(&priv->ack_status_lock, flags); - - if (ack_skb) { - tx_info = MWIFIEX_SKB_TXCB(ack_skb); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS) { - /* consumes ack_skb */ - skb_complete_wifi_ack(ack_skb, !tx_status->status); - } else { - /* Remove broadcast address which was added by driver */ - memmove(ack_skb->data + - sizeof(struct ieee80211_hdr_3addr) + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16), - ack_skb->data + - sizeof(struct ieee80211_hdr_3addr) + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) + - ETH_ALEN, ack_skb->len - - (sizeof(struct ieee80211_hdr_3addr) + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + sizeof(u16) + - ETH_ALEN)); - ack_skb->len = ack_skb->len - ETH_ALEN; - /* Remove driver's proprietary header including 2 bytes - * of packet length and pass actual management frame buffer - * to cfg80211. - */ - cfg80211_mgmt_tx_status(&priv->wdev, tx_info->cookie, - ack_skb->data + - MWIFIEX_MGMT_FRAME_HEADER_SIZE + - sizeof(u16), ack_skb->len - - (MWIFIEX_MGMT_FRAME_HEADER_SIZE - + sizeof(u16)), - !tx_status->status, GFP_ATOMIC); - dev_kfree_skb_any(ack_skb); - } - } -} diff --git a/drivers/net/wireless/mwifiex/uap_cmd.c b/drivers/net/wireless/mwifiex/uap_cmd.c deleted file mode 100644 index 759a6ada5b0f..000000000000 --- a/drivers/net/wireless/mwifiex/uap_cmd.c +++ /dev/null @@ -1,885 +0,0 @@ -/* - * Marvell Wireless LAN device driver: AP specific command handling - * - * Copyright (C) 2012-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" -#include "11ac.h" - -/* This function parses security related parameters from cfg80211_ap_settings - * and sets into FW understandable bss_config structure. - */ -int mwifiex_set_secure_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_config, - struct cfg80211_ap_settings *params) { - int i; - struct mwifiex_wep_key wep_key; - - if (!params->privacy) { - bss_config->protocol = PROTOCOL_NO_SECURITY; - bss_config->key_mgmt = KEY_MGMT_NONE; - bss_config->wpa_cfg.length = 0; - priv->sec_info.wep_enabled = 0; - priv->sec_info.wpa_enabled = 0; - priv->sec_info.wpa2_enabled = 0; - - return 0; - } - - switch (params->auth_type) { - case NL80211_AUTHTYPE_OPEN_SYSTEM: - bss_config->auth_mode = WLAN_AUTH_OPEN; - break; - case NL80211_AUTHTYPE_SHARED_KEY: - bss_config->auth_mode = WLAN_AUTH_SHARED_KEY; - break; - case NL80211_AUTHTYPE_NETWORK_EAP: - bss_config->auth_mode = WLAN_AUTH_LEAP; - break; - default: - bss_config->auth_mode = MWIFIEX_AUTH_MODE_AUTO; - break; - } - - bss_config->key_mgmt_operation |= KEY_MGMT_ON_HOST; - - for (i = 0; i < params->crypto.n_akm_suites; i++) { - switch (params->crypto.akm_suites[i]) { - case WLAN_AKM_SUITE_8021X: - if (params->crypto.wpa_versions & - NL80211_WPA_VERSION_1) { - bss_config->protocol = PROTOCOL_WPA; - bss_config->key_mgmt = KEY_MGMT_EAP; - } - if (params->crypto.wpa_versions & - NL80211_WPA_VERSION_2) { - bss_config->protocol |= PROTOCOL_WPA2; - bss_config->key_mgmt = KEY_MGMT_EAP; - } - break; - case WLAN_AKM_SUITE_PSK: - if (params->crypto.wpa_versions & - NL80211_WPA_VERSION_1) { - bss_config->protocol = PROTOCOL_WPA; - bss_config->key_mgmt = KEY_MGMT_PSK; - } - if (params->crypto.wpa_versions & - NL80211_WPA_VERSION_2) { - bss_config->protocol |= PROTOCOL_WPA2; - bss_config->key_mgmt = KEY_MGMT_PSK; - } - break; - default: - break; - } - } - for (i = 0; i < params->crypto.n_ciphers_pairwise; i++) { - switch (params->crypto.ciphers_pairwise[i]) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - break; - case WLAN_CIPHER_SUITE_TKIP: - if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) - bss_config->wpa_cfg.pairwise_cipher_wpa |= - CIPHER_TKIP; - if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) - bss_config->wpa_cfg.pairwise_cipher_wpa2 |= - CIPHER_TKIP; - break; - case WLAN_CIPHER_SUITE_CCMP: - if (params->crypto.wpa_versions & NL80211_WPA_VERSION_1) - bss_config->wpa_cfg.pairwise_cipher_wpa |= - CIPHER_AES_CCMP; - if (params->crypto.wpa_versions & NL80211_WPA_VERSION_2) - bss_config->wpa_cfg.pairwise_cipher_wpa2 |= - CIPHER_AES_CCMP; - default: - break; - } - } - - switch (params->crypto.cipher_group) { - case WLAN_CIPHER_SUITE_WEP40: - case WLAN_CIPHER_SUITE_WEP104: - if (priv->sec_info.wep_enabled) { - bss_config->protocol = PROTOCOL_STATIC_WEP; - bss_config->key_mgmt = KEY_MGMT_NONE; - bss_config->wpa_cfg.length = 0; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - wep_key = priv->wep_key[i]; - bss_config->wep_cfg[i].key_index = i; - - if (priv->wep_key_curr_index == i) - bss_config->wep_cfg[i].is_default = 1; - else - bss_config->wep_cfg[i].is_default = 0; - - bss_config->wep_cfg[i].length = - wep_key.key_length; - memcpy(&bss_config->wep_cfg[i].key, - &wep_key.key_material, - wep_key.key_length); - } - } - break; - case WLAN_CIPHER_SUITE_TKIP: - bss_config->wpa_cfg.group_cipher = CIPHER_TKIP; - break; - case WLAN_CIPHER_SUITE_CCMP: - bss_config->wpa_cfg.group_cipher = CIPHER_AES_CCMP; - break; - default: - break; - } - - return 0; -} - -/* This function updates 11n related parameters from IE and sets them into - * bss_config structure. - */ -void -mwifiex_set_ht_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params) -{ - const u8 *ht_ie; - u16 cap_info; - - if (!ISSUPP_11NENABLED(priv->adapter->fw_cap_info)) - return; - - ht_ie = cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, params->beacon.tail, - params->beacon.tail_len); - if (ht_ie) { - memcpy(&bss_cfg->ht_cap, ht_ie + 2, - sizeof(struct ieee80211_ht_cap)); - cap_info = le16_to_cpu(bss_cfg->ht_cap.cap_info); - memset(&bss_cfg->ht_cap.mcs, 0, - priv->adapter->number_of_antenna); - switch (GET_RXSTBC(cap_info)) { - case MWIFIEX_RX_STBC1: - /* HT_CAP 1X1 mode */ - bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff; - break; - case MWIFIEX_RX_STBC12: /* fall through */ - case MWIFIEX_RX_STBC123: - /* HT_CAP 2X2 mode */ - bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff; - bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff; - break; - default: - mwifiex_dbg(priv->adapter, WARN, - "Unsupported RX-STBC, default to 2x2\n"); - bss_cfg->ht_cap.mcs.rx_mask[0] = 0xff; - bss_cfg->ht_cap.mcs.rx_mask[1] = 0xff; - break; - } - priv->ap_11n_enabled = 1; - } else { - memset(&bss_cfg->ht_cap , 0, sizeof(struct ieee80211_ht_cap)); - bss_cfg->ht_cap.cap_info = cpu_to_le16(MWIFIEX_DEF_HT_CAP); - bss_cfg->ht_cap.ampdu_params_info = MWIFIEX_DEF_AMPDU; - } - - return; -} - -/* This function updates 11ac related parameters from IE - * and sets them into bss_config structure. - */ -void mwifiex_set_vht_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params) -{ - const u8 *vht_ie; - - vht_ie = cfg80211_find_ie(WLAN_EID_VHT_CAPABILITY, params->beacon.tail, - params->beacon.tail_len); - if (vht_ie) { - memcpy(&bss_cfg->vht_cap, vht_ie + 2, - sizeof(struct ieee80211_vht_cap)); - priv->ap_11ac_enabled = 1; - } else { - priv->ap_11ac_enabled = 0; - } - - return; -} - -/* This function updates 11ac related parameters from IE - * and sets them into bss_config structure. - */ -void mwifiex_set_tpc_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params) -{ - const u8 *tpc_ie; - - tpc_ie = cfg80211_find_ie(WLAN_EID_TPC_REQUEST, params->beacon.tail, - params->beacon.tail_len); - if (tpc_ie) - bss_cfg->power_constraint = *(tpc_ie + 2); - else - bss_cfg->power_constraint = 0; -} - -/* Enable VHT only when cfg80211_ap_settings has VHT IE. - * Otherwise disable VHT. - */ -void mwifiex_set_vht_width(struct mwifiex_private *priv, - enum nl80211_chan_width width, - bool ap_11ac_enable) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_11ac_vht_cfg vht_cfg; - - vht_cfg.band_config = VHT_CFG_5GHZ; - vht_cfg.cap_info = adapter->hw_dot_11ac_dev_cap; - - if (!ap_11ac_enable) { - vht_cfg.mcs_tx_set = DISABLE_VHT_MCS_SET; - vht_cfg.mcs_rx_set = DISABLE_VHT_MCS_SET; - } else { - vht_cfg.mcs_tx_set = DEFAULT_VHT_MCS_SET; - vht_cfg.mcs_rx_set = DEFAULT_VHT_MCS_SET; - } - - vht_cfg.misc_config = VHT_CAP_UAP_ONLY; - - if (ap_11ac_enable && width >= NL80211_CHAN_WIDTH_80) - vht_cfg.misc_config |= VHT_BW_80_160_80P80; - - mwifiex_send_cmd(priv, HostCmd_CMD_11AC_CFG, - HostCmd_ACT_GEN_SET, 0, &vht_cfg, true); - - return; -} - -/* This function finds supported rates IE from beacon parameter and sets - * these rates into bss_config structure. - */ -void -mwifiex_set_uap_rates(struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params) -{ - struct ieee_types_header *rate_ie; - int var_offset = offsetof(struct ieee80211_mgmt, u.beacon.variable); - const u8 *var_pos = params->beacon.head + var_offset; - int len = params->beacon.head_len - var_offset; - u8 rate_len = 0; - - rate_ie = (void *)cfg80211_find_ie(WLAN_EID_SUPP_RATES, var_pos, len); - if (rate_ie) { - memcpy(bss_cfg->rates, rate_ie + 1, rate_ie->len); - rate_len = rate_ie->len; - } - - rate_ie = (void *)cfg80211_find_ie(WLAN_EID_EXT_SUPP_RATES, - params->beacon.tail, - params->beacon.tail_len); - if (rate_ie) - memcpy(bss_cfg->rates + rate_len, rate_ie + 1, rate_ie->len); - - return; -} - -/* This function initializes some of mwifiex_uap_bss_param variables. - * This helps FW in ignoring invalid values. These values may or may not - * be get updated to valid ones at later stage. - */ -void mwifiex_set_sys_config_invalid_data(struct mwifiex_uap_bss_param *config) -{ - config->bcast_ssid_ctl = 0x7F; - config->radio_ctl = 0x7F; - config->dtim_period = 0x7F; - config->beacon_period = 0x7FFF; - config->auth_mode = 0x7F; - config->rts_threshold = 0x7FFF; - config->frag_threshold = 0x7FFF; - config->retry_limit = 0x7F; - config->qos_info = 0xFF; -} - -/* This function parses BSS related parameters from structure - * and prepares TLVs specific to WPA/WPA2 security. - * These TLVs are appended to command buffer. - */ -static void -mwifiex_uap_bss_wpa(u8 **tlv_buf, void *cmd_buf, u16 *param_size) -{ - struct host_cmd_tlv_pwk_cipher *pwk_cipher; - struct host_cmd_tlv_gwk_cipher *gwk_cipher; - struct host_cmd_tlv_passphrase *passphrase; - struct host_cmd_tlv_akmp *tlv_akmp; - struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; - u16 cmd_size = *param_size; - u8 *tlv = *tlv_buf; - - tlv_akmp = (struct host_cmd_tlv_akmp *)tlv; - tlv_akmp->header.type = cpu_to_le16(TLV_TYPE_UAP_AKMP); - tlv_akmp->header.len = cpu_to_le16(sizeof(struct host_cmd_tlv_akmp) - - sizeof(struct mwifiex_ie_types_header)); - tlv_akmp->key_mgmt_operation = cpu_to_le16(bss_cfg->key_mgmt_operation); - tlv_akmp->key_mgmt = cpu_to_le16(bss_cfg->key_mgmt); - cmd_size += sizeof(struct host_cmd_tlv_akmp); - tlv += sizeof(struct host_cmd_tlv_akmp); - - if (bss_cfg->wpa_cfg.pairwise_cipher_wpa & VALID_CIPHER_BITMAP) { - pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; - pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); - pwk_cipher->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - - sizeof(struct mwifiex_ie_types_header)); - pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA); - pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa; - cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); - tlv += sizeof(struct host_cmd_tlv_pwk_cipher); - } - - if (bss_cfg->wpa_cfg.pairwise_cipher_wpa2 & VALID_CIPHER_BITMAP) { - pwk_cipher = (struct host_cmd_tlv_pwk_cipher *)tlv; - pwk_cipher->header.type = cpu_to_le16(TLV_TYPE_PWK_CIPHER); - pwk_cipher->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_pwk_cipher) - - sizeof(struct mwifiex_ie_types_header)); - pwk_cipher->proto = cpu_to_le16(PROTOCOL_WPA2); - pwk_cipher->cipher = bss_cfg->wpa_cfg.pairwise_cipher_wpa2; - cmd_size += sizeof(struct host_cmd_tlv_pwk_cipher); - tlv += sizeof(struct host_cmd_tlv_pwk_cipher); - } - - if (bss_cfg->wpa_cfg.group_cipher & VALID_CIPHER_BITMAP) { - gwk_cipher = (struct host_cmd_tlv_gwk_cipher *)tlv; - gwk_cipher->header.type = cpu_to_le16(TLV_TYPE_GWK_CIPHER); - gwk_cipher->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_gwk_cipher) - - sizeof(struct mwifiex_ie_types_header)); - gwk_cipher->cipher = bss_cfg->wpa_cfg.group_cipher; - cmd_size += sizeof(struct host_cmd_tlv_gwk_cipher); - tlv += sizeof(struct host_cmd_tlv_gwk_cipher); - } - - if (bss_cfg->wpa_cfg.length) { - passphrase = (struct host_cmd_tlv_passphrase *)tlv; - passphrase->header.type = - cpu_to_le16(TLV_TYPE_UAP_WPA_PASSPHRASE); - passphrase->header.len = cpu_to_le16(bss_cfg->wpa_cfg.length); - memcpy(passphrase->passphrase, bss_cfg->wpa_cfg.passphrase, - bss_cfg->wpa_cfg.length); - cmd_size += sizeof(struct mwifiex_ie_types_header) + - bss_cfg->wpa_cfg.length; - tlv += sizeof(struct mwifiex_ie_types_header) + - bss_cfg->wpa_cfg.length; - } - - *param_size = cmd_size; - *tlv_buf = tlv; - - return; -} - -/* This function parses WMM related parameters from cfg80211_ap_settings - * structure and updates bss_config structure. - */ -void -mwifiex_set_wmm_params(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_ap_settings *params) -{ - const u8 *vendor_ie; - struct ieee_types_header *wmm_ie; - u8 wmm_oui[] = {0x00, 0x50, 0xf2, 0x02}; - - vendor_ie = cfg80211_find_vendor_ie(WLAN_OUI_MICROSOFT, - WLAN_OUI_TYPE_MICROSOFT_WMM, - params->beacon.tail, - params->beacon.tail_len); - if (vendor_ie) { - wmm_ie = (struct ieee_types_header *)vendor_ie; - memcpy(&bss_cfg->wmm_info, wmm_ie + 1, - sizeof(bss_cfg->wmm_info)); - priv->wmm_enabled = 1; - } else { - memset(&bss_cfg->wmm_info, 0, sizeof(bss_cfg->wmm_info)); - memcpy(&bss_cfg->wmm_info.oui, wmm_oui, sizeof(wmm_oui)); - bss_cfg->wmm_info.subtype = MWIFIEX_WMM_SUBTYPE; - bss_cfg->wmm_info.version = MWIFIEX_WMM_VERSION; - priv->wmm_enabled = 0; - } - - bss_cfg->qos_info = 0x00; - return; -} -/* This function parses BSS related parameters from structure - * and prepares TLVs specific to WEP encryption. - * These TLVs are appended to command buffer. - */ -static void -mwifiex_uap_bss_wep(u8 **tlv_buf, void *cmd_buf, u16 *param_size) -{ - struct host_cmd_tlv_wep_key *wep_key; - u16 cmd_size = *param_size; - int i; - u8 *tlv = *tlv_buf; - struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; - - for (i = 0; i < NUM_WEP_KEYS; i++) { - if (bss_cfg->wep_cfg[i].length && - (bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP40 || - bss_cfg->wep_cfg[i].length == WLAN_KEY_LEN_WEP104)) { - wep_key = (struct host_cmd_tlv_wep_key *)tlv; - wep_key->header.type = - cpu_to_le16(TLV_TYPE_UAP_WEP_KEY); - wep_key->header.len = - cpu_to_le16(bss_cfg->wep_cfg[i].length + 2); - wep_key->key_index = bss_cfg->wep_cfg[i].key_index; - wep_key->is_default = bss_cfg->wep_cfg[i].is_default; - memcpy(wep_key->key, bss_cfg->wep_cfg[i].key, - bss_cfg->wep_cfg[i].length); - cmd_size += sizeof(struct mwifiex_ie_types_header) + 2 + - bss_cfg->wep_cfg[i].length; - tlv += sizeof(struct mwifiex_ie_types_header) + 2 + - bss_cfg->wep_cfg[i].length; - } - } - - *param_size = cmd_size; - *tlv_buf = tlv; - - return; -} - -/* This function parses BSS related parameters from structure - * and prepares TLVs. These TLVs are appended to command buffer. -*/ -static int -mwifiex_uap_bss_param_prepare(u8 *tlv, void *cmd_buf, u16 *param_size) -{ - struct host_cmd_tlv_dtim_period *dtim_period; - struct host_cmd_tlv_beacon_period *beacon_period; - struct host_cmd_tlv_ssid *ssid; - struct host_cmd_tlv_bcast_ssid *bcast_ssid; - struct host_cmd_tlv_channel_band *chan_band; - struct host_cmd_tlv_frag_threshold *frag_threshold; - struct host_cmd_tlv_rts_threshold *rts_threshold; - struct host_cmd_tlv_retry_limit *retry_limit; - struct host_cmd_tlv_encrypt_protocol *encrypt_protocol; - struct host_cmd_tlv_auth_type *auth_type; - struct host_cmd_tlv_rates *tlv_rates; - struct host_cmd_tlv_ageout_timer *ao_timer, *ps_ao_timer; - struct host_cmd_tlv_power_constraint *pwr_ct; - struct mwifiex_ie_types_htcap *htcap; - struct mwifiex_ie_types_wmmcap *wmm_cap; - struct mwifiex_uap_bss_param *bss_cfg = cmd_buf; - int i; - u16 cmd_size = *param_size; - - if (bss_cfg->ssid.ssid_len) { - ssid = (struct host_cmd_tlv_ssid *)tlv; - ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_SSID); - ssid->header.len = cpu_to_le16((u16)bss_cfg->ssid.ssid_len); - memcpy(ssid->ssid, bss_cfg->ssid.ssid, bss_cfg->ssid.ssid_len); - cmd_size += sizeof(struct mwifiex_ie_types_header) + - bss_cfg->ssid.ssid_len; - tlv += sizeof(struct mwifiex_ie_types_header) + - bss_cfg->ssid.ssid_len; - - bcast_ssid = (struct host_cmd_tlv_bcast_ssid *)tlv; - bcast_ssid->header.type = cpu_to_le16(TLV_TYPE_UAP_BCAST_SSID); - bcast_ssid->header.len = - cpu_to_le16(sizeof(bcast_ssid->bcast_ctl)); - bcast_ssid->bcast_ctl = bss_cfg->bcast_ssid_ctl; - cmd_size += sizeof(struct host_cmd_tlv_bcast_ssid); - tlv += sizeof(struct host_cmd_tlv_bcast_ssid); - } - if (bss_cfg->rates[0]) { - tlv_rates = (struct host_cmd_tlv_rates *)tlv; - tlv_rates->header.type = cpu_to_le16(TLV_TYPE_UAP_RATES); - - for (i = 0; i < MWIFIEX_SUPPORTED_RATES && bss_cfg->rates[i]; - i++) - tlv_rates->rates[i] = bss_cfg->rates[i]; - - tlv_rates->header.len = cpu_to_le16(i); - cmd_size += sizeof(struct host_cmd_tlv_rates) + i; - tlv += sizeof(struct host_cmd_tlv_rates) + i; - } - if (bss_cfg->channel && - ((bss_cfg->band_cfg == BAND_CONFIG_BG && - bss_cfg->channel <= MAX_CHANNEL_BAND_BG) || - (bss_cfg->band_cfg == BAND_CONFIG_A && - bss_cfg->channel <= MAX_CHANNEL_BAND_A))) { - chan_band = (struct host_cmd_tlv_channel_band *)tlv; - chan_band->header.type = cpu_to_le16(TLV_TYPE_CHANNELBANDLIST); - chan_band->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_channel_band) - - sizeof(struct mwifiex_ie_types_header)); - chan_band->band_config = bss_cfg->band_cfg; - chan_band->channel = bss_cfg->channel; - cmd_size += sizeof(struct host_cmd_tlv_channel_band); - tlv += sizeof(struct host_cmd_tlv_channel_band); - } - if (bss_cfg->beacon_period >= MIN_BEACON_PERIOD && - bss_cfg->beacon_period <= MAX_BEACON_PERIOD) { - beacon_period = (struct host_cmd_tlv_beacon_period *)tlv; - beacon_period->header.type = - cpu_to_le16(TLV_TYPE_UAP_BEACON_PERIOD); - beacon_period->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_beacon_period) - - sizeof(struct mwifiex_ie_types_header)); - beacon_period->period = cpu_to_le16(bss_cfg->beacon_period); - cmd_size += sizeof(struct host_cmd_tlv_beacon_period); - tlv += sizeof(struct host_cmd_tlv_beacon_period); - } - if (bss_cfg->dtim_period >= MIN_DTIM_PERIOD && - bss_cfg->dtim_period <= MAX_DTIM_PERIOD) { - dtim_period = (struct host_cmd_tlv_dtim_period *)tlv; - dtim_period->header.type = - cpu_to_le16(TLV_TYPE_UAP_DTIM_PERIOD); - dtim_period->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_dtim_period) - - sizeof(struct mwifiex_ie_types_header)); - dtim_period->period = bss_cfg->dtim_period; - cmd_size += sizeof(struct host_cmd_tlv_dtim_period); - tlv += sizeof(struct host_cmd_tlv_dtim_period); - } - if (bss_cfg->rts_threshold <= MWIFIEX_RTS_MAX_VALUE) { - rts_threshold = (struct host_cmd_tlv_rts_threshold *)tlv; - rts_threshold->header.type = - cpu_to_le16(TLV_TYPE_UAP_RTS_THRESHOLD); - rts_threshold->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_rts_threshold) - - sizeof(struct mwifiex_ie_types_header)); - rts_threshold->rts_thr = cpu_to_le16(bss_cfg->rts_threshold); - cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); - tlv += sizeof(struct host_cmd_tlv_frag_threshold); - } - if ((bss_cfg->frag_threshold >= MWIFIEX_FRAG_MIN_VALUE) && - (bss_cfg->frag_threshold <= MWIFIEX_FRAG_MAX_VALUE)) { - frag_threshold = (struct host_cmd_tlv_frag_threshold *)tlv; - frag_threshold->header.type = - cpu_to_le16(TLV_TYPE_UAP_FRAG_THRESHOLD); - frag_threshold->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_frag_threshold) - - sizeof(struct mwifiex_ie_types_header)); - frag_threshold->frag_thr = cpu_to_le16(bss_cfg->frag_threshold); - cmd_size += sizeof(struct host_cmd_tlv_frag_threshold); - tlv += sizeof(struct host_cmd_tlv_frag_threshold); - } - if (bss_cfg->retry_limit <= MWIFIEX_RETRY_LIMIT) { - retry_limit = (struct host_cmd_tlv_retry_limit *)tlv; - retry_limit->header.type = - cpu_to_le16(TLV_TYPE_UAP_RETRY_LIMIT); - retry_limit->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_retry_limit) - - sizeof(struct mwifiex_ie_types_header)); - retry_limit->limit = (u8)bss_cfg->retry_limit; - cmd_size += sizeof(struct host_cmd_tlv_retry_limit); - tlv += sizeof(struct host_cmd_tlv_retry_limit); - } - if ((bss_cfg->protocol & PROTOCOL_WPA) || - (bss_cfg->protocol & PROTOCOL_WPA2) || - (bss_cfg->protocol & PROTOCOL_EAP)) - mwifiex_uap_bss_wpa(&tlv, cmd_buf, &cmd_size); - else - mwifiex_uap_bss_wep(&tlv, cmd_buf, &cmd_size); - - if ((bss_cfg->auth_mode <= WLAN_AUTH_SHARED_KEY) || - (bss_cfg->auth_mode == MWIFIEX_AUTH_MODE_AUTO)) { - auth_type = (struct host_cmd_tlv_auth_type *)tlv; - auth_type->header.type = cpu_to_le16(TLV_TYPE_AUTH_TYPE); - auth_type->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_auth_type) - - sizeof(struct mwifiex_ie_types_header)); - auth_type->auth_type = (u8)bss_cfg->auth_mode; - cmd_size += sizeof(struct host_cmd_tlv_auth_type); - tlv += sizeof(struct host_cmd_tlv_auth_type); - } - if (bss_cfg->protocol) { - encrypt_protocol = (struct host_cmd_tlv_encrypt_protocol *)tlv; - encrypt_protocol->header.type = - cpu_to_le16(TLV_TYPE_UAP_ENCRY_PROTOCOL); - encrypt_protocol->header.len = - cpu_to_le16(sizeof(struct host_cmd_tlv_encrypt_protocol) - - sizeof(struct mwifiex_ie_types_header)); - encrypt_protocol->proto = cpu_to_le16(bss_cfg->protocol); - cmd_size += sizeof(struct host_cmd_tlv_encrypt_protocol); - tlv += sizeof(struct host_cmd_tlv_encrypt_protocol); - } - - if (bss_cfg->ht_cap.cap_info) { - htcap = (struct mwifiex_ie_types_htcap *)tlv; - htcap->header.type = cpu_to_le16(WLAN_EID_HT_CAPABILITY); - htcap->header.len = - cpu_to_le16(sizeof(struct ieee80211_ht_cap)); - htcap->ht_cap.cap_info = bss_cfg->ht_cap.cap_info; - htcap->ht_cap.ampdu_params_info = - bss_cfg->ht_cap.ampdu_params_info; - memcpy(&htcap->ht_cap.mcs, &bss_cfg->ht_cap.mcs, - sizeof(struct ieee80211_mcs_info)); - htcap->ht_cap.extended_ht_cap_info = - bss_cfg->ht_cap.extended_ht_cap_info; - htcap->ht_cap.tx_BF_cap_info = bss_cfg->ht_cap.tx_BF_cap_info; - htcap->ht_cap.antenna_selection_info = - bss_cfg->ht_cap.antenna_selection_info; - cmd_size += sizeof(struct mwifiex_ie_types_htcap); - tlv += sizeof(struct mwifiex_ie_types_htcap); - } - - if (bss_cfg->wmm_info.qos_info != 0xFF) { - wmm_cap = (struct mwifiex_ie_types_wmmcap *)tlv; - wmm_cap->header.type = cpu_to_le16(WLAN_EID_VENDOR_SPECIFIC); - wmm_cap->header.len = cpu_to_le16(sizeof(wmm_cap->wmm_info)); - memcpy(&wmm_cap->wmm_info, &bss_cfg->wmm_info, - sizeof(wmm_cap->wmm_info)); - cmd_size += sizeof(struct mwifiex_ie_types_wmmcap); - tlv += sizeof(struct mwifiex_ie_types_wmmcap); - } - - if (bss_cfg->sta_ao_timer) { - ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; - ao_timer->header.type = cpu_to_le16(TLV_TYPE_UAP_AO_TIMER); - ao_timer->header.len = cpu_to_le16(sizeof(*ao_timer) - - sizeof(struct mwifiex_ie_types_header)); - ao_timer->sta_ao_timer = cpu_to_le32(bss_cfg->sta_ao_timer); - cmd_size += sizeof(*ao_timer); - tlv += sizeof(*ao_timer); - } - - if (bss_cfg->power_constraint) { - pwr_ct = (void *)tlv; - pwr_ct->header.type = cpu_to_le16(TLV_TYPE_PWR_CONSTRAINT); - pwr_ct->header.len = cpu_to_le16(sizeof(u8)); - pwr_ct->constraint = bss_cfg->power_constraint; - cmd_size += sizeof(*pwr_ct); - tlv += sizeof(*pwr_ct); - } - - if (bss_cfg->ps_sta_ao_timer) { - ps_ao_timer = (struct host_cmd_tlv_ageout_timer *)tlv; - ps_ao_timer->header.type = - cpu_to_le16(TLV_TYPE_UAP_PS_AO_TIMER); - ps_ao_timer->header.len = cpu_to_le16(sizeof(*ps_ao_timer) - - sizeof(struct mwifiex_ie_types_header)); - ps_ao_timer->sta_ao_timer = - cpu_to_le32(bss_cfg->ps_sta_ao_timer); - cmd_size += sizeof(*ps_ao_timer); - tlv += sizeof(*ps_ao_timer); - } - - *param_size = cmd_size; - - return 0; -} - -/* This function parses custom IEs from IE list and prepares command buffer */ -static int mwifiex_uap_custom_ie_prepare(u8 *tlv, void *cmd_buf, u16 *ie_size) -{ - struct mwifiex_ie_list *ap_ie = cmd_buf; - struct mwifiex_ie_types_header *tlv_ie = (void *)tlv; - - if (!ap_ie || !ap_ie->len || !ap_ie->ie_list) - return -1; - - *ie_size += le16_to_cpu(ap_ie->len) + - sizeof(struct mwifiex_ie_types_header); - - tlv_ie->type = cpu_to_le16(TLV_TYPE_MGMT_IE); - tlv_ie->len = ap_ie->len; - tlv += sizeof(struct mwifiex_ie_types_header); - - memcpy(tlv, ap_ie->ie_list, le16_to_cpu(ap_ie->len)); - - return 0; -} - -/* Parse AP config structure and prepare TLV based command structure - * to be sent to FW for uAP configuration - */ -static int -mwifiex_cmd_uap_sys_config(struct host_cmd_ds_command *cmd, u16 cmd_action, - u32 type, void *cmd_buf) -{ - u8 *tlv; - u16 cmd_size, param_size, ie_size; - struct host_cmd_ds_sys_config *sys_cfg; - - cmd->command = cpu_to_le16(HostCmd_CMD_UAP_SYS_CONFIG); - cmd_size = (u16)(sizeof(struct host_cmd_ds_sys_config) + S_DS_GEN); - sys_cfg = (struct host_cmd_ds_sys_config *)&cmd->params.uap_sys_config; - sys_cfg->action = cpu_to_le16(cmd_action); - tlv = sys_cfg->tlv; - - switch (type) { - case UAP_BSS_PARAMS_I: - param_size = cmd_size; - if (mwifiex_uap_bss_param_prepare(tlv, cmd_buf, ¶m_size)) - return -1; - cmd->size = cpu_to_le16(param_size); - break; - case UAP_CUSTOM_IE_I: - ie_size = cmd_size; - if (mwifiex_uap_custom_ie_prepare(tlv, cmd_buf, &ie_size)) - return -1; - cmd->size = cpu_to_le16(ie_size); - break; - default: - return -1; - } - - return 0; -} - -/* This function prepares AP specific deauth command with mac supplied in - * function parameter. - */ -static int mwifiex_cmd_uap_sta_deauth(struct mwifiex_private *priv, - struct host_cmd_ds_command *cmd, u8 *mac) -{ - struct host_cmd_ds_sta_deauth *sta_deauth = &cmd->params.sta_deauth; - - cmd->command = cpu_to_le16(HostCmd_CMD_UAP_STA_DEAUTH); - memcpy(sta_deauth->mac, mac, ETH_ALEN); - sta_deauth->reason = cpu_to_le16(WLAN_REASON_DEAUTH_LEAVING); - - cmd->size = cpu_to_le16(sizeof(struct host_cmd_ds_sta_deauth) + - S_DS_GEN); - return 0; -} - -/* This function prepares the AP specific commands before sending them - * to the firmware. - * This is a generic function which calls specific command preparation - * routines based upon the command number. - */ -int mwifiex_uap_prepare_cmd(struct mwifiex_private *priv, u16 cmd_no, - u16 cmd_action, u32 type, - void *data_buf, void *cmd_buf) -{ - struct host_cmd_ds_command *cmd = cmd_buf; - - switch (cmd_no) { - case HostCmd_CMD_UAP_SYS_CONFIG: - if (mwifiex_cmd_uap_sys_config(cmd, cmd_action, type, data_buf)) - return -1; - break; - case HostCmd_CMD_UAP_BSS_START: - case HostCmd_CMD_UAP_BSS_STOP: - case HOST_CMD_APCMD_SYS_RESET: - case HOST_CMD_APCMD_STA_LIST: - cmd->command = cpu_to_le16(cmd_no); - cmd->size = cpu_to_le16(S_DS_GEN); - break; - case HostCmd_CMD_UAP_STA_DEAUTH: - if (mwifiex_cmd_uap_sta_deauth(priv, cmd, data_buf)) - return -1; - break; - case HostCmd_CMD_CHAN_REPORT_REQUEST: - if (mwifiex_cmd_issue_chan_report_request(priv, cmd_buf, - data_buf)) - return -1; - break; - default: - mwifiex_dbg(priv->adapter, ERROR, - "PREP_CMD: unknown cmd %#x\n", cmd_no); - return -1; - } - - return 0; -} - -void mwifiex_uap_set_channel(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg, - struct cfg80211_chan_def chandef) -{ - u8 config_bands = 0, old_bands = priv->adapter->config_bands; - - priv->bss_chandef = chandef; - - bss_cfg->channel = ieee80211_frequency_to_channel( - chandef.chan->center_freq); - - /* Set appropriate bands */ - if (chandef.chan->band == IEEE80211_BAND_2GHZ) { - bss_cfg->band_cfg = BAND_CONFIG_BG; - config_bands = BAND_B | BAND_G; - - if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) - config_bands |= BAND_GN; - } else { - bss_cfg->band_cfg = BAND_CONFIG_A; - config_bands = BAND_A; - - if (chandef.width > NL80211_CHAN_WIDTH_20_NOHT) - config_bands |= BAND_AN; - - if (chandef.width > NL80211_CHAN_WIDTH_40) - config_bands |= BAND_AAC; - } - - priv->adapter->config_bands = config_bands; - - if (old_bands != config_bands) { - mwifiex_send_domain_info_cmd_fw(priv->adapter->wiphy); - mwifiex_dnld_txpwr_table(priv); - } -} - -int mwifiex_config_start_uap(struct mwifiex_private *priv, - struct mwifiex_uap_bss_param *bss_cfg) -{ - enum state_11d_t state_11d; - - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_SYS_CONFIG, - HostCmd_ACT_GEN_SET, - UAP_BSS_PARAMS_I, bss_cfg, false)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to set the SSID\n"); - return -1; - } - - /* Send cmd to FW to enable 11D function */ - state_11d = ENABLE_11D; - if (mwifiex_send_cmd(priv, HostCmd_CMD_802_11_SNMP_MIB, - HostCmd_ACT_GEN_SET, DOT11D_I, - &state_11d, true)) { - mwifiex_dbg(priv->adapter, ERROR, - "11D: failed to enable 11D\n"); - return -1; - } - - if (mwifiex_send_cmd(priv, HostCmd_CMD_UAP_BSS_START, - HostCmd_ACT_GEN_SET, 0, NULL, false)) { - mwifiex_dbg(priv->adapter, ERROR, - "Failed to start the BSS\n"); - return -1; - } - - if (priv->sec_info.wep_enabled) - priv->curr_pkt_filter |= HostCmd_ACT_MAC_WEP_ENABLE; - else - priv->curr_pkt_filter &= ~HostCmd_ACT_MAC_WEP_ENABLE; - - if (mwifiex_send_cmd(priv, HostCmd_CMD_MAC_CONTROL, - HostCmd_ACT_GEN_SET, 0, - &priv->curr_pkt_filter, true)) - return -1; - - return 0; -} diff --git a/drivers/net/wireless/mwifiex/uap_event.c b/drivers/net/wireless/mwifiex/uap_event.c deleted file mode 100644 index 86ff54296f39..000000000000 --- a/drivers/net/wireless/mwifiex/uap_event.c +++ /dev/null @@ -1,333 +0,0 @@ -/* - * Marvell Wireless LAN device driver: AP event handling - * - * Copyright (C) 2012-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "main.h" -#include "11n.h" - -#define MWIFIEX_BSS_START_EVT_FIX_SIZE 12 - -static int mwifiex_check_uap_capabilties(struct mwifiex_private *priv, - struct sk_buff *event) -{ - int evt_len; - u8 *curr; - u16 tlv_len; - struct mwifiex_ie_types_data *tlv_hdr; - struct ieee_types_wmm_parameter *wmm_param_ie = NULL; - int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK; - - priv->wmm_enabled = false; - skb_pull(event, MWIFIEX_BSS_START_EVT_FIX_SIZE); - evt_len = event->len; - curr = event->data; - - mwifiex_dbg_dump(priv->adapter, EVT_D, "uap capabilties:", - event->data, event->len); - - skb_push(event, MWIFIEX_BSS_START_EVT_FIX_SIZE); - - while ((evt_len >= sizeof(tlv_hdr->header))) { - tlv_hdr = (struct mwifiex_ie_types_data *)curr; - tlv_len = le16_to_cpu(tlv_hdr->header.len); - - if (evt_len < tlv_len + sizeof(tlv_hdr->header)) - break; - - switch (le16_to_cpu(tlv_hdr->header.type)) { - case WLAN_EID_HT_CAPABILITY: - priv->ap_11n_enabled = true; - break; - - case WLAN_EID_VHT_CAPABILITY: - priv->ap_11ac_enabled = true; - break; - - case WLAN_EID_VENDOR_SPECIFIC: - /* Point the regular IEEE IE 2 bytes into the Marvell IE - * and setup the IEEE IE type and length byte fields - */ - wmm_param_ie = (void *)(curr + 2); - wmm_param_ie->vend_hdr.len = (u8)tlv_len; - wmm_param_ie->vend_hdr.element_id = - WLAN_EID_VENDOR_SPECIFIC; - mwifiex_dbg(priv->adapter, EVENT, - "info: check uap capabilities:\t" - "wmm parameter set count: %d\n", - wmm_param_ie->qos_info_bitmap & mask); - - mwifiex_wmm_setup_ac_downgrade(priv); - priv->wmm_enabled = true; - mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); - break; - - default: - break; - } - - curr += (tlv_len + sizeof(tlv_hdr->header)); - evt_len -= (tlv_len + sizeof(tlv_hdr->header)); - } - - return 0; -} - -/* - * This function handles AP interface specific events generated by firmware. - * - * Event specific routines are called by this function based - * upon the generated event cause. - * - * - * Events supported for AP - - * - EVENT_UAP_STA_ASSOC - * - EVENT_UAP_STA_DEAUTH - * - EVENT_UAP_BSS_ACTIVE - * - EVENT_UAP_BSS_START - * - EVENT_UAP_BSS_IDLE - * - EVENT_UAP_MIC_COUNTERMEASURES: - */ -int mwifiex_process_uap_event(struct mwifiex_private *priv) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int len, i; - u32 eventcause = adapter->event_cause; - struct station_info sinfo; - struct mwifiex_assoc_event *event; - struct mwifiex_sta_node *node; - u8 *deauth_mac; - struct host_cmd_ds_11n_batimeout *ba_timeout; - u16 ctrl; - - switch (eventcause) { - case EVENT_UAP_STA_ASSOC: - memset(&sinfo, 0, sizeof(sinfo)); - event = (struct mwifiex_assoc_event *) - (adapter->event_body + MWIFIEX_UAP_EVENT_EXTRA_HEADER); - if (le16_to_cpu(event->type) == TLV_TYPE_UAP_MGMT_FRAME) { - len = -1; - - if (ieee80211_is_assoc_req(event->frame_control)) - len = 0; - else if (ieee80211_is_reassoc_req(event->frame_control)) - /* There will be ETH_ALEN bytes of - * current_ap_addr before the re-assoc ies. - */ - len = ETH_ALEN; - - if (len != -1) { - sinfo.assoc_req_ies = &event->data[len]; - len = (u8 *)sinfo.assoc_req_ies - - (u8 *)&event->frame_control; - sinfo.assoc_req_ies_len = - le16_to_cpu(event->len) - (u16)len; - } - } - cfg80211_new_sta(priv->netdev, event->sta_addr, &sinfo, - GFP_KERNEL); - - node = mwifiex_add_sta_entry(priv, event->sta_addr); - if (!node) { - mwifiex_dbg(adapter, ERROR, - "could not create station entry!\n"); - return -1; - } - - if (!priv->ap_11n_enabled) - break; - - mwifiex_set_sta_ht_cap(priv, sinfo.assoc_req_ies, - sinfo.assoc_req_ies_len, node); - - for (i = 0; i < MAX_NUM_TID; i++) { - if (node->is_11n_enabled) - node->ampdu_sta[i] = - priv->aggr_prio_tbl[i].ampdu_user; - else - node->ampdu_sta[i] = BA_STREAM_NOT_ALLOWED; - } - memset(node->rx_seq, 0xff, sizeof(node->rx_seq)); - break; - case EVENT_UAP_STA_DEAUTH: - deauth_mac = adapter->event_body + - MWIFIEX_UAP_EVENT_EXTRA_HEADER; - cfg80211_del_sta(priv->netdev, deauth_mac, GFP_KERNEL); - - if (priv->ap_11n_enabled) { - mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, deauth_mac); - mwifiex_del_tx_ba_stream_tbl_by_ra(priv, deauth_mac); - } - mwifiex_wmm_del_peer_ra_list(priv, deauth_mac); - mwifiex_del_sta_entry(priv, deauth_mac); - break; - case EVENT_UAP_BSS_IDLE: - priv->media_connected = false; - priv->port_open = false; - mwifiex_clean_txrx(priv); - mwifiex_del_all_sta_list(priv); - break; - case EVENT_UAP_BSS_ACTIVE: - priv->media_connected = true; - priv->port_open = true; - break; - case EVENT_UAP_BSS_START: - mwifiex_dbg(adapter, EVENT, - "AP EVENT: event id: %#x\n", eventcause); - priv->port_open = false; - memcpy(priv->netdev->dev_addr, adapter->event_body + 2, - ETH_ALEN); - if (priv->hist_data) - mwifiex_hist_data_reset(priv); - mwifiex_check_uap_capabilties(priv, adapter->event_skb); - break; - case EVENT_UAP_MIC_COUNTERMEASURES: - /* For future development */ - mwifiex_dbg(adapter, EVENT, - "AP EVENT: event id: %#x\n", eventcause); - break; - case EVENT_AMSDU_AGGR_CTRL: - ctrl = le16_to_cpu(*(__le16 *)adapter->event_body); - mwifiex_dbg(adapter, EVENT, - "event: AMSDU_AGGR_CTRL %d\n", ctrl); - - if (priv->media_connected) { - adapter->tx_buf_size = - min_t(u16, adapter->curr_tx_buf_size, ctrl); - mwifiex_dbg(adapter, EVENT, - "event: tx_buf_size %d\n", - adapter->tx_buf_size); - } - break; - case EVENT_ADDBA: - mwifiex_dbg(adapter, EVENT, "event: ADDBA Request\n"); - if (priv->media_connected) - mwifiex_send_cmd(priv, HostCmd_CMD_11N_ADDBA_RSP, - HostCmd_ACT_GEN_SET, 0, - adapter->event_body, false); - break; - case EVENT_DELBA: - mwifiex_dbg(adapter, EVENT, "event: DELBA Request\n"); - if (priv->media_connected) - mwifiex_11n_delete_ba_stream(priv, adapter->event_body); - break; - case EVENT_BA_STREAM_TIEMOUT: - mwifiex_dbg(adapter, EVENT, "event: BA Stream timeout\n"); - if (priv->media_connected) { - ba_timeout = (void *)adapter->event_body; - mwifiex_11n_ba_stream_timeout(priv, ba_timeout); - } - break; - case EVENT_EXT_SCAN_REPORT: - mwifiex_dbg(adapter, EVENT, "event: EXT_SCAN Report\n"); - if (adapter->ext_scan) - return mwifiex_handle_event_ext_scan_report(priv, - adapter->event_skb->data); - break; - case EVENT_TX_STATUS_REPORT: - mwifiex_dbg(adapter, EVENT, "event: TX_STATUS Report\n"); - mwifiex_parse_tx_status_event(priv, adapter->event_body); - break; - case EVENT_PS_SLEEP: - mwifiex_dbg(adapter, EVENT, "info: EVENT: SLEEP\n"); - - adapter->ps_state = PS_STATE_PRE_SLEEP; - - mwifiex_check_ps_cond(adapter); - break; - - case EVENT_PS_AWAKE: - mwifiex_dbg(adapter, EVENT, "info: EVENT: AWAKE\n"); - if (!adapter->pps_uapsd_mode && - priv->media_connected && adapter->sleep_period.period) { - adapter->pps_uapsd_mode = true; - mwifiex_dbg(adapter, EVENT, - "event: PPS/UAPSD mode activated\n"); - } - adapter->tx_lock_flag = false; - if (adapter->pps_uapsd_mode && adapter->gen_null_pkt) { - if (mwifiex_check_last_packet_indication(priv)) { - if (adapter->data_sent || - (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv))) { - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_card_req = false; - adapter->pm_wakeup_fw_try = false; - break; - } - if (!mwifiex_send_null_packet - (priv, - MWIFIEX_TxPD_POWER_MGMT_NULL_PACKET | - MWIFIEX_TxPD_POWER_MGMT_LAST_PACKET)) - adapter->ps_state = - PS_STATE_SLEEP; - return 0; - } - } - adapter->ps_state = PS_STATE_AWAKE; - adapter->pm_wakeup_card_req = false; - adapter->pm_wakeup_fw_try = false; - break; - - case EVENT_CHANNEL_REPORT_RDY: - mwifiex_dbg(adapter, EVENT, "event: Channel Report\n"); - mwifiex_11h_handle_chanrpt_ready(priv, adapter->event_skb); - break; - case EVENT_RADAR_DETECTED: - mwifiex_dbg(adapter, EVENT, "event: Radar detected\n"); - mwifiex_11h_handle_radar_detected(priv, adapter->event_skb); - break; - case EVENT_BT_COEX_WLAN_PARA_CHANGE: - dev_err(adapter->dev, "EVENT: BT coex wlan param update\n"); - mwifiex_bt_coex_wlan_param_update_event(priv, - adapter->event_skb); - break; - case EVENT_TX_DATA_PAUSE: - mwifiex_dbg(adapter, EVENT, "event: TX DATA PAUSE\n"); - mwifiex_process_tx_pause_event(priv, adapter->event_skb); - break; - - case EVENT_MULTI_CHAN_INFO: - mwifiex_dbg(adapter, EVENT, "event: multi-chan info\n"); - mwifiex_process_multi_chan_event(priv, adapter->event_skb); - break; - - default: - mwifiex_dbg(adapter, EVENT, - "event: unknown event id: %#x\n", eventcause); - break; - } - - return 0; -} - -/* This function deletes station entry from associated station list. - * Also if both AP and STA are 11n enabled, RxReorder tables and TxBA stream - * tables created for this station are deleted. - */ -void mwifiex_uap_del_sta_data(struct mwifiex_private *priv, - struct mwifiex_sta_node *node) -{ - if (priv->ap_11n_enabled && node->is_11n_enabled) { - mwifiex_11n_del_rx_reorder_tbl_by_ta(priv, node->mac_addr); - mwifiex_del_tx_ba_stream_tbl_by_ra(priv, node->mac_addr); - } - mwifiex_del_sta_entry(priv, node->mac_addr); - - return; -} diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c deleted file mode 100644 index 74d5d7238633..000000000000 --- a/drivers/net/wireless/mwifiex/uap_txrx.c +++ /dev/null @@ -1,437 +0,0 @@ -/* - * Marvell Wireless LAN device driver: AP TX and RX data handling - * - * Copyright (C) 2012-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "main.h" -#include "wmm.h" -#include "11n_aggr.h" -#include "11n_rxreorder.h" - -/* This function checks if particular RA list has packets more than low bridge - * packet threshold and then deletes packet from this RA list. - * Function deletes packets from such RA list and returns true. If no such list - * is found, false is returned. - */ -static bool -mwifiex_uap_del_tx_pkts_in_ralist(struct mwifiex_private *priv, - struct list_head *ra_list_head, - int tid) -{ - struct mwifiex_ra_list_tbl *ra_list; - struct sk_buff *skb, *tmp; - bool pkt_deleted = false; - struct mwifiex_txinfo *tx_info; - struct mwifiex_adapter *adapter = priv->adapter; - - list_for_each_entry(ra_list, ra_list_head, list) { - if (skb_queue_empty(&ra_list->skb_head)) - continue; - - skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) { - tx_info = MWIFIEX_SKB_TXCB(skb); - if (tx_info->flags & MWIFIEX_BUF_FLAG_BRIDGED_PKT) { - __skb_unlink(skb, &ra_list->skb_head); - mwifiex_write_data_complete(adapter, skb, 0, - -1); - if (ra_list->tx_paused) - priv->wmm.pkts_paused[tid]--; - else - atomic_dec(&priv->wmm.tx_pkts_queued); - pkt_deleted = true; - } - if ((atomic_read(&adapter->pending_bridged_pkts) <= - MWIFIEX_BRIDGED_PKTS_THR_LOW)) - break; - } - } - - return pkt_deleted; -} - -/* This function deletes packets from particular RA List. RA list index - * from which packets are deleted is preserved so that packets from next RA - * list are deleted upon subsequent call thus maintaining fairness. - */ -static void mwifiex_uap_cleanup_tx_queues(struct mwifiex_private *priv) -{ - unsigned long flags; - struct list_head *ra_list; - int i; - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - for (i = 0; i < MAX_NUM_TID; i++, priv->del_list_idx++) { - if (priv->del_list_idx == MAX_NUM_TID) - priv->del_list_idx = 0; - ra_list = &priv->wmm.tid_tbl_ptr[priv->del_list_idx].ra_list; - if (mwifiex_uap_del_tx_pkts_in_ralist(priv, ra_list, i)) { - priv->del_list_idx++; - break; - } - } - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - - -static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct uap_rxpd *uap_rx_pd; - struct rx_packet_hdr *rx_pkt_hdr; - struct sk_buff *new_skb; - struct mwifiex_txinfo *tx_info; - int hdr_chop; - struct ethhdr *p_ethhdr; - struct mwifiex_sta_node *src_node; - - uap_rx_pd = (struct uap_rxpd *)(skb->data); - rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); - - if ((atomic_read(&adapter->pending_bridged_pkts) >= - MWIFIEX_BRIDGED_PKTS_THR_HIGH)) { - mwifiex_dbg(priv->adapter, ERROR, - "Tx: Bridge packet limit reached. Drop packet!\n"); - kfree_skb(skb); - mwifiex_uap_cleanup_tx_queues(priv); - return; - } - - if ((!memcmp(&rx_pkt_hdr->rfc1042_hdr, bridge_tunnel_header, - sizeof(bridge_tunnel_header))) || - (!memcmp(&rx_pkt_hdr->rfc1042_hdr, rfc1042_header, - sizeof(rfc1042_header)) && - ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_AARP && - ntohs(rx_pkt_hdr->rfc1042_hdr.snap_type) != ETH_P_IPX)) { - /* Replace the 803 header and rfc1042 header (llc/snap) with - * an Ethernet II header, keep the src/dst and snap_type - * (ethertype). - * - * The firmware only passes up SNAP frames converting all RX - * data from 802.11 to 802.2/LLC/SNAP frames. - * - * To create the Ethernet II, just move the src, dst address - * right before the snap_type. - */ - p_ethhdr = (struct ethhdr *) - ((u8 *)(&rx_pkt_hdr->eth803_hdr) - + sizeof(rx_pkt_hdr->eth803_hdr) - + sizeof(rx_pkt_hdr->rfc1042_hdr) - - sizeof(rx_pkt_hdr->eth803_hdr.h_dest) - - sizeof(rx_pkt_hdr->eth803_hdr.h_source) - - sizeof(rx_pkt_hdr->rfc1042_hdr.snap_type)); - memcpy(p_ethhdr->h_source, rx_pkt_hdr->eth803_hdr.h_source, - sizeof(p_ethhdr->h_source)); - memcpy(p_ethhdr->h_dest, rx_pkt_hdr->eth803_hdr.h_dest, - sizeof(p_ethhdr->h_dest)); - /* Chop off the rxpd + the excess memory from - * 802.2/llc/snap header that was removed. - */ - hdr_chop = (u8 *)p_ethhdr - (u8 *)uap_rx_pd; - } else { - /* Chop off the rxpd */ - hdr_chop = (u8 *)&rx_pkt_hdr->eth803_hdr - (u8 *)uap_rx_pd; - } - - /* Chop off the leading header bytes so that it points - * to the start of either the reconstructed EthII frame - * or the 802.2/llc/snap frame. - */ - skb_pull(skb, hdr_chop); - - if (skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN) { - mwifiex_dbg(priv->adapter, ERROR, - "data: Tx: insufficient skb headroom %d\n", - skb_headroom(skb)); - /* Insufficient skb headroom - allocate a new skb */ - new_skb = - skb_realloc_headroom(skb, MWIFIEX_MIN_DATA_HEADER_LEN); - if (unlikely(!new_skb)) { - mwifiex_dbg(priv->adapter, ERROR, - "Tx: cannot allocate new_skb\n"); - kfree_skb(skb); - priv->stats.tx_dropped++; - return; - } - - kfree_skb(skb); - skb = new_skb; - mwifiex_dbg(priv->adapter, INFO, - "info: new skb headroom %d\n", - skb_headroom(skb)); - } - - tx_info = MWIFIEX_SKB_TXCB(skb); - memset(tx_info, 0, sizeof(*tx_info)); - tx_info->bss_num = priv->bss_num; - tx_info->bss_type = priv->bss_type; - tx_info->flags |= MWIFIEX_BUF_FLAG_BRIDGED_PKT; - - src_node = mwifiex_get_sta_entry(priv, rx_pkt_hdr->eth803_hdr.h_source); - if (src_node) { - src_node->stats.last_rx = jiffies; - src_node->stats.rx_bytes += skb->len; - src_node->stats.rx_packets++; - src_node->stats.last_tx_rate = uap_rx_pd->rx_rate; - src_node->stats.last_tx_htinfo = uap_rx_pd->ht_info; - } - - if (is_unicast_ether_addr(rx_pkt_hdr->eth803_hdr.h_dest)) { - /* Update bridge packet statistics as the - * packet is not going to kernel/upper layer. - */ - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; - - /* Sending bridge packet to TX queue, so save the packet - * length in TXCB to update statistics in TX complete. - */ - tx_info->pkt_len = skb->len; - } - - __net_timestamp(skb); - mwifiex_wmm_add_buf_txqueue(priv, skb); - atomic_inc(&adapter->tx_pending); - atomic_inc(&adapter->pending_bridged_pkts); - - return; -} - -/* - * This function contains logic for AP packet forwarding. - * - * If a packet is multicast/broadcast, it is sent to kernel/upper layer - * as well as queued back to AP TX queue so that it can be sent to other - * associated stations. - * If a packet is unicast and RA is present in associated station list, - * it is again requeued into AP TX queue. - * If a packet is unicast and RA is not in associated station list, - * packet is forwarded to kernel to handle routing logic. - */ -int mwifiex_handle_uap_rx_forward(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct uap_rxpd *uap_rx_pd; - struct rx_packet_hdr *rx_pkt_hdr; - u8 ra[ETH_ALEN]; - struct sk_buff *skb_uap; - - uap_rx_pd = (struct uap_rxpd *)(skb->data); - rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); - - /* don't do packet forwarding in disconnected state */ - if (!priv->media_connected) { - mwifiex_dbg(adapter, ERROR, - "drop packet in disconnected state.\n"); - dev_kfree_skb_any(skb); - return 0; - } - - memcpy(ra, rx_pkt_hdr->eth803_hdr.h_dest, ETH_ALEN); - - if (is_multicast_ether_addr(ra)) { - skb_uap = skb_copy(skb, GFP_ATOMIC); - mwifiex_uap_queue_bridged_pkt(priv, skb_uap); - } else { - if (mwifiex_get_sta_entry(priv, ra)) { - /* Requeue Intra-BSS packet */ - mwifiex_uap_queue_bridged_pkt(priv, skb); - return 0; - } - } - - /* Forward unicat/Inter-BSS packets to kernel. */ - return mwifiex_process_rx_packet(priv, skb); -} - -/* - * This function processes the packet received on AP interface. - * - * The function looks into the RxPD and performs sanity tests on the - * received buffer to ensure its a valid packet before processing it - * further. If the packet is determined to be aggregated, it is - * de-aggregated accordingly. Then skb is passed to AP packet forwarding logic. - * - * The completion callback is called after processing is complete. - */ -int mwifiex_process_uap_rx_packet(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - int ret; - struct uap_rxpd *uap_rx_pd; - struct rx_packet_hdr *rx_pkt_hdr; - u16 rx_pkt_type; - u8 ta[ETH_ALEN], pkt_type; - unsigned long flags; - struct mwifiex_sta_node *node; - - uap_rx_pd = (struct uap_rxpd *)(skb->data); - rx_pkt_type = le16_to_cpu(uap_rx_pd->rx_pkt_type); - rx_pkt_hdr = (void *)uap_rx_pd + le16_to_cpu(uap_rx_pd->rx_pkt_offset); - - ether_addr_copy(ta, rx_pkt_hdr->eth803_hdr.h_source); - - if ((le16_to_cpu(uap_rx_pd->rx_pkt_offset) + - le16_to_cpu(uap_rx_pd->rx_pkt_length)) > (u16) skb->len) { - mwifiex_dbg(adapter, ERROR, - "wrong rx packet: len=%d, offset=%d, length=%d\n", - skb->len, le16_to_cpu(uap_rx_pd->rx_pkt_offset), - le16_to_cpu(uap_rx_pd->rx_pkt_length)); - priv->stats.rx_dropped++; - - node = mwifiex_get_sta_entry(priv, ta); - if (node) - node->stats.tx_failed++; - - dev_kfree_skb_any(skb); - return 0; - } - - if (rx_pkt_type == PKT_TYPE_MGMT) { - ret = mwifiex_process_mgmt_packet(priv, skb); - if (ret) - mwifiex_dbg(adapter, ERROR, - "Rx of mgmt packet failed"); - dev_kfree_skb_any(skb); - return ret; - } - - - if (rx_pkt_type != PKT_TYPE_BAR && uap_rx_pd->priority < MAX_NUM_TID) { - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - node = mwifiex_get_sta_entry(priv, ta); - if (node) - node->rx_seq[uap_rx_pd->priority] = - le16_to_cpu(uap_rx_pd->seq_num); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - } - - if (!priv->ap_11n_enabled || - (!mwifiex_11n_get_rx_reorder_tbl(priv, uap_rx_pd->priority, ta) && - (le16_to_cpu(uap_rx_pd->rx_pkt_type) != PKT_TYPE_AMSDU))) { - ret = mwifiex_handle_uap_rx_forward(priv, skb); - return ret; - } - - /* Reorder and send to kernel */ - pkt_type = (u8)le16_to_cpu(uap_rx_pd->rx_pkt_type); - ret = mwifiex_11n_rx_reorder_pkt(priv, le16_to_cpu(uap_rx_pd->seq_num), - uap_rx_pd->priority, ta, pkt_type, - skb); - - if (ret || (rx_pkt_type == PKT_TYPE_BAR)) - dev_kfree_skb_any(skb); - - if (ret) - priv->stats.rx_dropped++; - - return ret; -} - -/* - * This function fills the TxPD for AP tx packets. - * - * The Tx buffer received by this function should already have the - * header space allocated for TxPD. - * - * This function inserts the TxPD in between interface header and actual - * data and adjusts the buffer pointers accordingly. - * - * The following TxPD fields are set by this function, as required - - * - BSS number - * - Tx packet length and offset - * - Priority - * - Packet delay - * - Priority specific Tx control - * - Flags - */ -void *mwifiex_process_uap_txpd(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct uap_txpd *txpd; - struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - int pad; - u16 pkt_type, pkt_offset; - int hroom = (priv->adapter->iface_type == MWIFIEX_USB) ? 0 : - INTF_HEADER_LEN; - - if (!skb->len) { - mwifiex_dbg(adapter, ERROR, - "Tx: bad packet length: %d\n", skb->len); - tx_info->status_code = -1; - return skb->data; - } - - BUG_ON(skb_headroom(skb) < MWIFIEX_MIN_DATA_HEADER_LEN); - - pkt_type = mwifiex_is_skb_mgmt_frame(skb) ? PKT_TYPE_MGMT : 0; - - pad = ((void *)skb->data - (sizeof(*txpd) + hroom) - NULL) & - (MWIFIEX_DMA_ALIGN_SZ - 1); - - skb_push(skb, sizeof(*txpd) + pad); - - txpd = (struct uap_txpd *)skb->data; - memset(txpd, 0, sizeof(*txpd)); - txpd->bss_num = priv->bss_num; - txpd->bss_type = priv->bss_type; - txpd->tx_pkt_length = cpu_to_le16((u16)(skb->len - (sizeof(*txpd) + - pad))); - txpd->priority = (u8)skb->priority; - - txpd->pkt_delay_2ms = mwifiex_wmm_compute_drv_pkt_delay(priv, skb); - - if (tx_info->flags & MWIFIEX_BUF_FLAG_EAPOL_TX_STATUS || - tx_info->flags & MWIFIEX_BUF_FLAG_ACTION_TX_STATUS) { - txpd->tx_token_id = tx_info->ack_frame_id; - txpd->flags |= MWIFIEX_TXPD_FLAGS_REQ_TX_STATUS; - } - - if (txpd->priority < ARRAY_SIZE(priv->wmm.user_pri_pkt_tx_ctrl)) - /* - * Set the priority specific tx_control field, setting of 0 will - * cause the default value to be used later in this function. - */ - txpd->tx_control = - cpu_to_le32(priv->wmm.user_pri_pkt_tx_ctrl[txpd->priority]); - - /* Offset of actual data */ - pkt_offset = sizeof(*txpd) + pad; - if (pkt_type == PKT_TYPE_MGMT) { - /* Set the packet type and add header for management frame */ - txpd->tx_pkt_type = cpu_to_le16(pkt_type); - pkt_offset += MWIFIEX_MGMT_FRAME_HEADER_SIZE; - } - - txpd->tx_pkt_offset = cpu_to_le16(pkt_offset); - - /* make space for INTF_HEADER_LEN */ - skb_push(skb, hroom); - - if (!txpd->tx_control) - /* TxCtrl set by user or default */ - txpd->tx_control = cpu_to_le32(priv->pkt_tx_ctrl); - - return skb->data; -} diff --git a/drivers/net/wireless/mwifiex/usb.c b/drivers/net/wireless/mwifiex/usb.c deleted file mode 100644 index e43aff932360..000000000000 --- a/drivers/net/wireless/mwifiex/usb.c +++ /dev/null @@ -1,1267 +0,0 @@ -/* - * Marvell Wireless LAN device driver: USB specific handling - * - * Copyright (C) 2012-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "main.h" -#include "usb.h" - -#define USB_VERSION "1.0" - -static u8 user_rmmod; -static struct mwifiex_if_ops usb_ops; -static struct semaphore add_remove_card_sem; - -static struct usb_device_id mwifiex_usb_table[] = { - /* 8766 */ - {USB_DEVICE(USB8XXX_VID, USB8766_PID_1)}, - {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8766_PID_2, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0xff)}, - /* 8797 */ - {USB_DEVICE(USB8XXX_VID, USB8797_PID_1)}, - {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8797_PID_2, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0xff)}, - /* 8801 */ - {USB_DEVICE(USB8XXX_VID, USB8801_PID_1)}, - {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8801_PID_2, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0xff)}, - /* 8997 */ - {USB_DEVICE(USB8XXX_VID, USB8997_PID_1)}, - {USB_DEVICE_AND_INTERFACE_INFO(USB8XXX_VID, USB8997_PID_2, - USB_CLASS_VENDOR_SPEC, - USB_SUBCLASS_VENDOR_SPEC, 0xff)}, - { } /* Terminating entry */ -}; - -MODULE_DEVICE_TABLE(usb, mwifiex_usb_table); - -static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size); - -/* This function handles received packet. Necessary action is taken based on - * cmd/event/data. - */ -static int mwifiex_usb_recv(struct mwifiex_adapter *adapter, - struct sk_buff *skb, u8 ep) -{ - u32 recv_type; - __le32 tmp; - int ret; - - if (adapter->hs_activated) - mwifiex_process_hs_config(adapter); - - if (skb->len < INTF_HEADER_LEN) { - mwifiex_dbg(adapter, ERROR, - "%s: invalid skb->len\n", __func__); - return -1; - } - - switch (ep) { - case MWIFIEX_USB_EP_CMD_EVENT: - mwifiex_dbg(adapter, EVENT, - "%s: EP_CMD_EVENT\n", __func__); - skb_copy_from_linear_data(skb, &tmp, INTF_HEADER_LEN); - recv_type = le32_to_cpu(tmp); - skb_pull(skb, INTF_HEADER_LEN); - - switch (recv_type) { - case MWIFIEX_USB_TYPE_CMD: - if (skb->len > MWIFIEX_SIZE_OF_CMD_BUFFER) { - mwifiex_dbg(adapter, ERROR, - "CMD: skb->len too large\n"); - ret = -1; - goto exit_restore_skb; - } else if (!adapter->curr_cmd) { - mwifiex_dbg(adapter, WARN, "CMD: no curr_cmd\n"); - if (adapter->ps_state == PS_STATE_SLEEP_CFM) { - mwifiex_process_sleep_confirm_resp( - adapter, skb->data, - skb->len); - ret = 0; - goto exit_restore_skb; - } - ret = -1; - goto exit_restore_skb; - } - - adapter->curr_cmd->resp_skb = skb; - adapter->cmd_resp_received = true; - break; - case MWIFIEX_USB_TYPE_EVENT: - if (skb->len < sizeof(u32)) { - mwifiex_dbg(adapter, ERROR, - "EVENT: skb->len too small\n"); - ret = -1; - goto exit_restore_skb; - } - skb_copy_from_linear_data(skb, &tmp, sizeof(u32)); - adapter->event_cause = le32_to_cpu(tmp); - mwifiex_dbg(adapter, EVENT, - "event_cause %#x\n", adapter->event_cause); - - if (skb->len > MAX_EVENT_SIZE) { - mwifiex_dbg(adapter, ERROR, - "EVENT: event body too large\n"); - ret = -1; - goto exit_restore_skb; - } - - memcpy(adapter->event_body, skb->data + - MWIFIEX_EVENT_HEADER_LEN, skb->len); - - adapter->event_received = true; - adapter->event_skb = skb; - break; - default: - mwifiex_dbg(adapter, ERROR, - "unknown recv_type %#x\n", recv_type); - return -1; - } - break; - case MWIFIEX_USB_EP_DATA: - mwifiex_dbg(adapter, DATA, "%s: EP_DATA\n", __func__); - if (skb->len > MWIFIEX_RX_DATA_BUF_SIZE) { - mwifiex_dbg(adapter, ERROR, - "DATA: skb->len too large\n"); - return -1; - } - - skb_queue_tail(&adapter->rx_data_q, skb); - adapter->data_received = true; - atomic_inc(&adapter->rx_pending); - break; - default: - mwifiex_dbg(adapter, ERROR, - "%s: unknown endport %#x\n", __func__, ep); - return -1; - } - - return -EINPROGRESS; - -exit_restore_skb: - /* The buffer will be reused for further cmds/events */ - skb_push(skb, INTF_HEADER_LEN); - - return ret; -} - -static void mwifiex_usb_rx_complete(struct urb *urb) -{ - struct urb_context *context = (struct urb_context *)urb->context; - struct mwifiex_adapter *adapter = context->adapter; - struct sk_buff *skb = context->skb; - struct usb_card_rec *card; - int recv_length = urb->actual_length; - int size, status; - - if (!adapter || !adapter->card) { - pr_err("mwifiex adapter or card structure is not valid\n"); - return; - } - - card = (struct usb_card_rec *)adapter->card; - if (card->rx_cmd_ep == context->ep) - atomic_dec(&card->rx_cmd_urb_pending); - else - atomic_dec(&card->rx_data_urb_pending); - - if (recv_length) { - if (urb->status || (adapter->surprise_removed)) { - mwifiex_dbg(adapter, ERROR, - "URB status is failed: %d\n", urb->status); - /* Do not free skb in case of command ep */ - if (card->rx_cmd_ep != context->ep) - dev_kfree_skb_any(skb); - goto setup_for_next; - } - if (skb->len > recv_length) - skb_trim(skb, recv_length); - else - skb_put(skb, recv_length - skb->len); - - status = mwifiex_usb_recv(adapter, skb, context->ep); - - mwifiex_dbg(adapter, INFO, - "info: recv_length=%d, status=%d\n", - recv_length, status); - if (status == -EINPROGRESS) { - mwifiex_queue_main_work(adapter); - - /* urb for data_ep is re-submitted now; - * urb for cmd_ep will be re-submitted in callback - * mwifiex_usb_recv_complete - */ - if (card->rx_cmd_ep == context->ep) - return; - } else { - if (status == -1) - mwifiex_dbg(adapter, ERROR, - "received data processing failed!\n"); - - /* Do not free skb in case of command ep */ - if (card->rx_cmd_ep != context->ep) - dev_kfree_skb_any(skb); - } - } else if (urb->status) { - if (!adapter->is_suspended) { - mwifiex_dbg(adapter, FATAL, - "Card is removed: %d\n", urb->status); - adapter->surprise_removed = true; - } - dev_kfree_skb_any(skb); - return; - } else { - /* Do not free skb in case of command ep */ - if (card->rx_cmd_ep != context->ep) - dev_kfree_skb_any(skb); - - /* fall through setup_for_next */ - } - -setup_for_next: - if (card->rx_cmd_ep == context->ep) - size = MWIFIEX_RX_CMD_BUF_SIZE; - else - size = MWIFIEX_RX_DATA_BUF_SIZE; - - if (card->rx_cmd_ep == context->ep) { - mwifiex_usb_submit_rx_urb(context, size); - } else { - if (atomic_read(&adapter->rx_pending) <= HIGH_RX_PENDING){ - mwifiex_usb_submit_rx_urb(context, size); - }else{ - context->skb = NULL; - } - } - - return; -} - -static void mwifiex_usb_tx_complete(struct urb *urb) -{ - struct urb_context *context = (struct urb_context *)(urb->context); - struct mwifiex_adapter *adapter = context->adapter; - struct usb_card_rec *card = adapter->card; - struct usb_tx_data_port *port; - int i; - - mwifiex_dbg(adapter, INFO, - "%s: status: %d\n", __func__, urb->status); - - if (context->ep == card->tx_cmd_ep) { - mwifiex_dbg(adapter, CMD, - "%s: CMD\n", __func__); - atomic_dec(&card->tx_cmd_urb_pending); - adapter->cmd_sent = false; - } else { - mwifiex_dbg(adapter, DATA, - "%s: DATA\n", __func__); - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { - port = &card->port[i]; - if (context->ep == port->tx_data_ep) { - atomic_dec(&port->tx_data_urb_pending); - port->block_status = false; - break; - } - } - adapter->data_sent = false; - mwifiex_write_data_complete(adapter, context->skb, 0, - urb->status ? -1 : 0); - } - - if (card->mc_resync_flag) - mwifiex_multi_chan_resync(adapter); - - mwifiex_queue_main_work(adapter); - - return; -} - -static int mwifiex_usb_submit_rx_urb(struct urb_context *ctx, int size) -{ - struct mwifiex_adapter *adapter = ctx->adapter; - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - - if (card->rx_cmd_ep != ctx->ep) { - ctx->skb = dev_alloc_skb(size); - if (!ctx->skb) { - mwifiex_dbg(adapter, ERROR, - "%s: dev_alloc_skb failed\n", __func__); - return -ENOMEM; - } - } - - usb_fill_bulk_urb(ctx->urb, card->udev, - usb_rcvbulkpipe(card->udev, ctx->ep), ctx->skb->data, - size, mwifiex_usb_rx_complete, (void *)ctx); - - if (card->rx_cmd_ep == ctx->ep) - atomic_inc(&card->rx_cmd_urb_pending); - else - atomic_inc(&card->rx_data_urb_pending); - - if (usb_submit_urb(ctx->urb, GFP_ATOMIC)) { - mwifiex_dbg(adapter, ERROR, "usb_submit_urb failed\n"); - dev_kfree_skb_any(ctx->skb); - ctx->skb = NULL; - - if (card->rx_cmd_ep == ctx->ep) - atomic_dec(&card->rx_cmd_urb_pending); - else - atomic_dec(&card->rx_data_urb_pending); - - return -1; - } - - return 0; -} - -static void mwifiex_usb_free(struct usb_card_rec *card) -{ - struct usb_tx_data_port *port; - int i, j; - - if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) - usb_kill_urb(card->rx_cmd.urb); - - usb_free_urb(card->rx_cmd.urb); - card->rx_cmd.urb = NULL; - - if (atomic_read(&card->rx_data_urb_pending)) - for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) - if (card->rx_data_list[i].urb) - usb_kill_urb(card->rx_data_list[i].urb); - - for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) { - usb_free_urb(card->rx_data_list[i].urb); - card->rx_data_list[i].urb = NULL; - } - - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { - port = &card->port[i]; - for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { - usb_free_urb(port->tx_data_list[j].urb); - port->tx_data_list[j].urb = NULL; - } - } - - usb_free_urb(card->tx_cmd.urb); - card->tx_cmd.urb = NULL; - - return; -} - -/* This function probes an mwifiex device and registers it. It allocates - * the card structure, initiates the device registration and initialization - * procedure by adding a logical interface. - */ -static int mwifiex_usb_probe(struct usb_interface *intf, - const struct usb_device_id *id) -{ - struct usb_device *udev = interface_to_usbdev(intf); - struct usb_host_interface *iface_desc = intf->cur_altsetting; - struct usb_endpoint_descriptor *epd; - int ret, i; - struct usb_card_rec *card; - u16 id_vendor, id_product, bcd_device, bcd_usb; - - card = kzalloc(sizeof(struct usb_card_rec), GFP_KERNEL); - if (!card) - return -ENOMEM; - - id_vendor = le16_to_cpu(udev->descriptor.idVendor); - id_product = le16_to_cpu(udev->descriptor.idProduct); - bcd_device = le16_to_cpu(udev->descriptor.bcdDevice); - bcd_usb = le16_to_cpu(udev->descriptor.bcdUSB); - pr_debug("info: VID/PID = %X/%X, Boot2 version = %X\n", - id_vendor, id_product, bcd_device); - - /* PID_1 is used for firmware downloading only */ - switch (id_product) { - case USB8766_PID_1: - case USB8797_PID_1: - case USB8801_PID_1: - case USB8997_PID_1: - card->usb_boot_state = USB8XXX_FW_DNLD; - break; - case USB8766_PID_2: - case USB8797_PID_2: - case USB8801_PID_2: - case USB8997_PID_2: - card->usb_boot_state = USB8XXX_FW_READY; - break; - default: - pr_warn("unknown id_product %#x\n", id_product); - card->usb_boot_state = USB8XXX_FW_DNLD; - break; - } - - card->udev = udev; - card->intf = intf; - - pr_debug("info: bcdUSB=%#x Device Class=%#x SubClass=%#x Protocol=%#x\n", - udev->descriptor.bcdUSB, udev->descriptor.bDeviceClass, - udev->descriptor.bDeviceSubClass, - udev->descriptor.bDeviceProtocol); - - for (i = 0; i < iface_desc->desc.bNumEndpoints; ++i) { - epd = &iface_desc->endpoint[i].desc; - if (usb_endpoint_dir_in(epd) && - usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT && - usb_endpoint_xfer_bulk(epd)) { - pr_debug("info: bulk IN: max pkt size: %d, addr: %d\n", - le16_to_cpu(epd->wMaxPacketSize), - epd->bEndpointAddress); - card->rx_cmd_ep = usb_endpoint_num(epd); - atomic_set(&card->rx_cmd_urb_pending, 0); - } - if (usb_endpoint_dir_in(epd) && - usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA && - usb_endpoint_xfer_bulk(epd)) { - pr_debug("info: bulk IN: max pkt size: %d, addr: %d\n", - le16_to_cpu(epd->wMaxPacketSize), - epd->bEndpointAddress); - card->rx_data_ep = usb_endpoint_num(epd); - atomic_set(&card->rx_data_urb_pending, 0); - } - if (usb_endpoint_dir_out(epd) && - usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA && - usb_endpoint_xfer_bulk(epd)) { - pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n", - le16_to_cpu(epd->wMaxPacketSize), - epd->bEndpointAddress); - card->port[0].tx_data_ep = usb_endpoint_num(epd); - atomic_set(&card->port[0].tx_data_urb_pending, 0); - } - if (usb_endpoint_dir_out(epd) && - usb_endpoint_num(epd) == MWIFIEX_USB_EP_DATA_CH2 && - usb_endpoint_xfer_bulk(epd)) { - pr_debug("info: bulk OUT chan2:\t" - "max pkt size: %d, addr: %d\n", - le16_to_cpu(epd->wMaxPacketSize), - epd->bEndpointAddress); - card->port[1].tx_data_ep = usb_endpoint_num(epd); - atomic_set(&card->port[1].tx_data_urb_pending, 0); - } - if (usb_endpoint_dir_out(epd) && - usb_endpoint_num(epd) == MWIFIEX_USB_EP_CMD_EVENT && - usb_endpoint_xfer_bulk(epd)) { - pr_debug("info: bulk OUT: max pkt size: %d, addr: %d\n", - le16_to_cpu(epd->wMaxPacketSize), - epd->bEndpointAddress); - card->tx_cmd_ep = usb_endpoint_num(epd); - atomic_set(&card->tx_cmd_urb_pending, 0); - card->bulk_out_maxpktsize = - le16_to_cpu(epd->wMaxPacketSize); - } - } - - usb_set_intfdata(intf, card); - - ret = mwifiex_add_card(card, &add_remove_card_sem, &usb_ops, - MWIFIEX_USB); - if (ret) { - pr_err("%s: mwifiex_add_card failed: %d\n", __func__, ret); - usb_reset_device(udev); - kfree(card); - return ret; - } - - usb_get_dev(udev); - - return 0; -} - -/* Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not suspended, this function allocates and sends a - * 'host sleep activate' request to the firmware and turns off the traffic. - */ -static int mwifiex_usb_suspend(struct usb_interface *intf, pm_message_t message) -{ - struct usb_card_rec *card = usb_get_intfdata(intf); - struct mwifiex_adapter *adapter; - struct usb_tx_data_port *port; - int i, j; - - if (!card || !card->adapter) { - pr_err("%s: card or card->adapter is NULL\n", __func__); - return 0; - } - adapter = card->adapter; - - if (unlikely(adapter->is_suspended)) - mwifiex_dbg(adapter, WARN, - "Device already suspended\n"); - - mwifiex_enable_hs(adapter); - - /* 'is_suspended' flag indicates device is suspended. - * It must be set here before the usb_kill_urb() calls. Reason - * is in the complete handlers, urb->status(= -ENOENT) and - * this flag is used in combination to distinguish between a - * 'suspended' state and a 'disconnect' one. - */ - adapter->is_suspended = true; - adapter->hs_enabling = false; - - if (atomic_read(&card->rx_cmd_urb_pending) && card->rx_cmd.urb) - usb_kill_urb(card->rx_cmd.urb); - - if (atomic_read(&card->rx_data_urb_pending)) - for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) - if (card->rx_data_list[i].urb) - usb_kill_urb(card->rx_data_list[i].urb); - - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { - port = &card->port[i]; - for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { - if (port->tx_data_list[j].urb) - usb_kill_urb(port->tx_data_list[j].urb); - } - } - - if (card->tx_cmd.urb) - usb_kill_urb(card->tx_cmd.urb); - - return 0; -} - -/* Kernel needs to suspend all functions separately. Therefore all - * registered functions must have drivers with suspend and resume - * methods. Failing that the kernel simply removes the whole card. - * - * If already not resumed, this function turns on the traffic and - * sends a 'host sleep cancel' request to the firmware. - */ -static int mwifiex_usb_resume(struct usb_interface *intf) -{ - struct usb_card_rec *card = usb_get_intfdata(intf); - struct mwifiex_adapter *adapter; - int i; - - if (!card || !card->adapter) { - pr_err("%s: card or card->adapter is NULL\n", __func__); - return 0; - } - adapter = card->adapter; - - if (unlikely(!adapter->is_suspended)) { - mwifiex_dbg(adapter, WARN, - "Device already resumed\n"); - return 0; - } - - /* Indicate device resumed. The netdev queue will be resumed only - * after the urbs have been re-submitted - */ - adapter->is_suspended = false; - - if (!atomic_read(&card->rx_data_urb_pending)) - for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) - mwifiex_usb_submit_rx_urb(&card->rx_data_list[i], - MWIFIEX_RX_DATA_BUF_SIZE); - - if (!atomic_read(&card->rx_cmd_urb_pending)) { - card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE); - if (card->rx_cmd.skb) - mwifiex_usb_submit_rx_urb(&card->rx_cmd, - MWIFIEX_RX_CMD_BUF_SIZE); - } - - /* Disable Host Sleep */ - if (adapter->hs_activated) - mwifiex_cancel_hs(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY), - MWIFIEX_ASYNC_CMD); - - return 0; -} - -static void mwifiex_usb_disconnect(struct usb_interface *intf) -{ - struct usb_card_rec *card = usb_get_intfdata(intf); - struct mwifiex_adapter *adapter; - - if (!card || !card->adapter) { - pr_err("%s: card or card->adapter is NULL\n", __func__); - return; - } - - adapter = card->adapter; - if (!adapter->priv_num) - return; - - if (user_rmmod) { -#ifdef CONFIG_PM - if (adapter->is_suspended) - mwifiex_usb_resume(intf); -#endif - - mwifiex_deauthenticate_all(adapter); - - mwifiex_init_shutdown_fw(mwifiex_get_priv(adapter, - MWIFIEX_BSS_ROLE_ANY), - MWIFIEX_FUNC_SHUTDOWN); - } - - mwifiex_usb_free(card); - - mwifiex_dbg(adapter, FATAL, - "%s: removing card\n", __func__); - mwifiex_remove_card(adapter, &add_remove_card_sem); - - usb_set_intfdata(intf, NULL); - usb_put_dev(interface_to_usbdev(intf)); - kfree(card); - - return; -} - -static struct usb_driver mwifiex_usb_driver = { - .name = "mwifiex_usb", - .probe = mwifiex_usb_probe, - .disconnect = mwifiex_usb_disconnect, - .id_table = mwifiex_usb_table, - .suspend = mwifiex_usb_suspend, - .resume = mwifiex_usb_resume, - .soft_unbind = 1, -}; - -static int mwifiex_usb_tx_init(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - struct usb_tx_data_port *port; - int i, j; - - card->tx_cmd.adapter = adapter; - card->tx_cmd.ep = card->tx_cmd_ep; - - card->tx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL); - if (!card->tx_cmd.urb) { - mwifiex_dbg(adapter, ERROR, - "tx_cmd.urb allocation failed\n"); - return -ENOMEM; - } - - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { - port = &card->port[i]; - if (!port->tx_data_ep) - continue; - port->tx_data_ix = 0; - if (port->tx_data_ep == MWIFIEX_USB_EP_DATA) - port->block_status = false; - else - port->block_status = true; - for (j = 0; j < MWIFIEX_TX_DATA_URB; j++) { - port->tx_data_list[j].adapter = adapter; - port->tx_data_list[j].ep = port->tx_data_ep; - port->tx_data_list[j].urb = - usb_alloc_urb(0, GFP_KERNEL); - if (!port->tx_data_list[j].urb) { - mwifiex_dbg(adapter, ERROR, - "urb allocation failed\n"); - return -ENOMEM; - } - } - } - - return 0; -} - -static int mwifiex_usb_rx_init(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - int i; - - card->rx_cmd.adapter = adapter; - card->rx_cmd.ep = card->rx_cmd_ep; - - card->rx_cmd.urb = usb_alloc_urb(0, GFP_KERNEL); - if (!card->rx_cmd.urb) { - mwifiex_dbg(adapter, ERROR, "rx_cmd.urb allocation failed\n"); - return -ENOMEM; - } - - card->rx_cmd.skb = dev_alloc_skb(MWIFIEX_RX_CMD_BUF_SIZE); - if (!card->rx_cmd.skb) - return -ENOMEM; - - if (mwifiex_usb_submit_rx_urb(&card->rx_cmd, MWIFIEX_RX_CMD_BUF_SIZE)) - return -1; - - for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) { - card->rx_data_list[i].adapter = adapter; - card->rx_data_list[i].ep = card->rx_data_ep; - - card->rx_data_list[i].urb = usb_alloc_urb(0, GFP_KERNEL); - if (!card->rx_data_list[i].urb) { - mwifiex_dbg(adapter, ERROR, - "rx_data_list[] urb allocation failed\n"); - return -1; - } - if (mwifiex_usb_submit_rx_urb(&card->rx_data_list[i], - MWIFIEX_RX_DATA_BUF_SIZE)) - return -1; - } - - return 0; -} - -static int mwifiex_write_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf, - u32 *len, u8 ep, u32 timeout) -{ - struct usb_card_rec *card = adapter->card; - int actual_length, ret; - - if (!(*len % card->bulk_out_maxpktsize)) - (*len)++; - - /* Send the data block */ - ret = usb_bulk_msg(card->udev, usb_sndbulkpipe(card->udev, ep), pbuf, - *len, &actual_length, timeout); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "usb_bulk_msg for tx failed: %d\n", ret); - return ret; - } - - *len = actual_length; - - return ret; -} - -static int mwifiex_read_data_sync(struct mwifiex_adapter *adapter, u8 *pbuf, - u32 *len, u8 ep, u32 timeout) -{ - struct usb_card_rec *card = adapter->card; - int actual_length, ret; - - /* Receive the data response */ - ret = usb_bulk_msg(card->udev, usb_rcvbulkpipe(card->udev, ep), pbuf, - *len, &actual_length, timeout); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "usb_bulk_msg for rx failed: %d\n", ret); - return ret; - } - - *len = actual_length; - - return ret; -} - -static void mwifiex_usb_port_resync(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = adapter->card; - u8 active_port = MWIFIEX_USB_EP_DATA; - struct mwifiex_private *priv = NULL; - int i; - - if (adapter->usb_mc_status) { - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP && - !priv->bss_started) || - (priv->bss_role == MWIFIEX_BSS_ROLE_STA && - !priv->media_connected)) - priv->usb_port = MWIFIEX_USB_EP_DATA; - } - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) - card->port[i].block_status = false; - } else { - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - if ((priv->bss_role == MWIFIEX_BSS_ROLE_UAP && - priv->bss_started) || - (priv->bss_role == MWIFIEX_BSS_ROLE_STA && - priv->media_connected)) { - active_port = priv->usb_port; - break; - } - } - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (priv) - priv->usb_port = active_port; - } - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) { - if (active_port == card->port[i].tx_data_ep) - card->port[i].block_status = false; - else - card->port[i].block_status = true; - } - } -} - -static bool mwifiex_usb_is_port_ready(struct mwifiex_private *priv) -{ - struct usb_card_rec *card = priv->adapter->card; - int idx; - - for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { - if (priv->usb_port == card->port[idx].tx_data_ep) - return !card->port[idx].block_status; - } - - return false; -} - -static inline u8 mwifiex_usb_data_sent(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = adapter->card; - int i; - - for (i = 0; i < MWIFIEX_TX_DATA_PORT; i++) - if (!card->port[i].block_status) - return false; - - return true; -} - -/* This function write a command/data packet to card. */ -static int mwifiex_usb_host_to_card(struct mwifiex_adapter *adapter, u8 ep, - struct sk_buff *skb, - struct mwifiex_tx_param *tx_param) -{ - struct usb_card_rec *card = adapter->card; - struct urb_context *context = NULL; - struct usb_tx_data_port *port = NULL; - u8 *data = (u8 *)skb->data; - struct urb *tx_urb; - int idx, ret; - - if (adapter->is_suspended) { - mwifiex_dbg(adapter, ERROR, - "%s: not allowed while suspended\n", __func__); - return -1; - } - - if (adapter->surprise_removed) { - mwifiex_dbg(adapter, ERROR, "%s: device removed\n", __func__); - return -1; - } - - mwifiex_dbg(adapter, INFO, "%s: ep=%d\n", __func__, ep); - - if (ep == card->tx_cmd_ep) { - context = &card->tx_cmd; - } else { - for (idx = 0; idx < MWIFIEX_TX_DATA_PORT; idx++) { - if (ep == card->port[idx].tx_data_ep) { - port = &card->port[idx]; - if (atomic_read(&port->tx_data_urb_pending) - >= MWIFIEX_TX_DATA_URB) { - port->block_status = true; - ret = -EBUSY; - goto done; - } - if (port->tx_data_ix >= MWIFIEX_TX_DATA_URB) - port->tx_data_ix = 0; - context = - &port->tx_data_list[port->tx_data_ix++]; - break; - } - } - if (!port) { - mwifiex_dbg(adapter, ERROR, "Wrong usb tx data port\n"); - return -1; - } - } - - context->adapter = adapter; - context->ep = ep; - context->skb = skb; - tx_urb = context->urb; - - usb_fill_bulk_urb(tx_urb, card->udev, usb_sndbulkpipe(card->udev, ep), - data, skb->len, mwifiex_usb_tx_complete, - (void *)context); - - tx_urb->transfer_flags |= URB_ZERO_PACKET; - - if (ep == card->tx_cmd_ep) - atomic_inc(&card->tx_cmd_urb_pending); - else - atomic_inc(&port->tx_data_urb_pending); - - if (usb_submit_urb(tx_urb, GFP_ATOMIC)) { - mwifiex_dbg(adapter, ERROR, - "%s: usb_submit_urb failed\n", __func__); - if (ep == card->tx_cmd_ep) { - atomic_dec(&card->tx_cmd_urb_pending); - } else { - atomic_dec(&port->tx_data_urb_pending); - port->block_status = false; - if (port->tx_data_ix) - port->tx_data_ix--; - else - port->tx_data_ix = MWIFIEX_TX_DATA_URB; - } - - return -1; - } else { - if (ep != card->tx_cmd_ep && - atomic_read(&port->tx_data_urb_pending) == - MWIFIEX_TX_DATA_URB) { - port->block_status = true; - ret = -ENOSR; - goto done; - } - } - - return -EINPROGRESS; - -done: - if (ep != card->tx_cmd_ep) - adapter->data_sent = mwifiex_usb_data_sent(adapter); - - return ret; -} - -/* This function register usb device and initialize parameter. */ -static int mwifiex_register_dev(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - - card->adapter = adapter; - adapter->dev = &card->udev->dev; - - switch (le16_to_cpu(card->udev->descriptor.idProduct)) { - case USB8997_PID_1: - case USB8997_PID_2: - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_4K; - strcpy(adapter->fw_name, USB8997_DEFAULT_FW_NAME); - adapter->ext_scan = true; - break; - case USB8766_PID_1: - case USB8766_PID_2: - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - strcpy(adapter->fw_name, USB8766_DEFAULT_FW_NAME); - adapter->ext_scan = true; - break; - case USB8801_PID_1: - case USB8801_PID_2: - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - strcpy(adapter->fw_name, USB8801_DEFAULT_FW_NAME); - adapter->ext_scan = false; - break; - case USB8797_PID_1: - case USB8797_PID_2: - default: - adapter->tx_buf_size = MWIFIEX_TX_DATA_BUF_SIZE_2K; - strcpy(adapter->fw_name, USB8797_DEFAULT_FW_NAME); - break; - } - - adapter->usb_mc_status = false; - adapter->usb_mc_setup = false; - - return 0; -} - -static void mwifiex_unregister_dev(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - - card->adapter = NULL; -} - -static int mwifiex_prog_fw_w_helper(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *fw) -{ - int ret = 0; - u8 *firmware = fw->fw_buf, *recv_buff; - u32 retries = USB8XXX_FW_MAX_RETRY, dlen; - u32 fw_seqnum = 0, tlen = 0, dnld_cmd = 0; - struct fw_data *fwdata; - struct fw_sync_header sync_fw; - u8 check_winner = 1; - - if (!firmware) { - mwifiex_dbg(adapter, ERROR, - "No firmware image found! Terminating download\n"); - ret = -1; - goto fw_exit; - } - - /* Allocate memory for transmit */ - fwdata = kzalloc(FW_DNLD_TX_BUF_SIZE, GFP_KERNEL); - if (!fwdata) { - ret = -ENOMEM; - goto fw_exit; - } - - /* Allocate memory for receive */ - recv_buff = kzalloc(FW_DNLD_RX_BUF_SIZE, GFP_KERNEL); - if (!recv_buff) - goto cleanup; - - do { - /* Send pseudo data to check winner status first */ - if (check_winner) { - memset(&fwdata->fw_hdr, 0, sizeof(struct fw_header)); - dlen = 0; - } else { - /* copy the header of the fw_data to get the length */ - memcpy(&fwdata->fw_hdr, &firmware[tlen], - sizeof(struct fw_header)); - - dlen = le32_to_cpu(fwdata->fw_hdr.data_len); - dnld_cmd = le32_to_cpu(fwdata->fw_hdr.dnld_cmd); - tlen += sizeof(struct fw_header); - - memcpy(fwdata->data, &firmware[tlen], dlen); - - fwdata->seq_num = cpu_to_le32(fw_seqnum); - tlen += dlen; - } - - /* If the send/receive fails or CRC occurs then retry */ - while (retries--) { - u8 *buf = (u8 *)fwdata; - u32 len = FW_DATA_XMIT_SIZE; - - /* send the firmware block */ - ret = mwifiex_write_data_sync(adapter, buf, &len, - MWIFIEX_USB_EP_CMD_EVENT, - MWIFIEX_USB_TIMEOUT); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "write_data_sync: failed: %d\n", - ret); - continue; - } - - buf = recv_buff; - len = FW_DNLD_RX_BUF_SIZE; - - /* Receive the firmware block response */ - ret = mwifiex_read_data_sync(adapter, buf, &len, - MWIFIEX_USB_EP_CMD_EVENT, - MWIFIEX_USB_TIMEOUT); - if (ret) { - mwifiex_dbg(adapter, ERROR, - "read_data_sync: failed: %d\n", - ret); - continue; - } - - memcpy(&sync_fw, recv_buff, - sizeof(struct fw_sync_header)); - - /* check 1st firmware block resp for highest bit set */ - if (check_winner) { - if (le32_to_cpu(sync_fw.cmd) & 0x80000000) { - mwifiex_dbg(adapter, WARN, - "USB is not the winner %#x\n", - sync_fw.cmd); - - /* returning success */ - ret = 0; - goto cleanup; - } - - mwifiex_dbg(adapter, MSG, - "start to download FW...\n"); - - check_winner = 0; - break; - } - - /* check the firmware block response for CRC errors */ - if (sync_fw.cmd) { - mwifiex_dbg(adapter, ERROR, - "FW received block with CRC %#x\n", - sync_fw.cmd); - ret = -1; - continue; - } - - retries = USB8XXX_FW_MAX_RETRY; - break; - } - fw_seqnum++; - } while ((dnld_cmd != FW_HAS_LAST_BLOCK) && retries); - -cleanup: - mwifiex_dbg(adapter, MSG, - "info: FW download over, size %d bytes\n", tlen); - - kfree(recv_buff); - kfree(fwdata); - - if (retries) - ret = 0; -fw_exit: - return ret; -} - -static int mwifiex_usb_dnld_fw(struct mwifiex_adapter *adapter, - struct mwifiex_fw_image *fw) -{ - int ret; - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - - if (card->usb_boot_state == USB8XXX_FW_DNLD) { - ret = mwifiex_prog_fw_w_helper(adapter, fw); - if (ret) - return -1; - - /* Boot state changes after successful firmware download */ - if (card->usb_boot_state == USB8XXX_FW_DNLD) - return -1; - } - - ret = mwifiex_usb_rx_init(adapter); - if (!ret) - ret = mwifiex_usb_tx_init(adapter); - - return ret; -} - -static void mwifiex_submit_rx_urb(struct mwifiex_adapter *adapter, u8 ep) -{ - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - - skb_push(card->rx_cmd.skb, INTF_HEADER_LEN); - if ((ep == card->rx_cmd_ep) && - (!atomic_read(&card->rx_cmd_urb_pending))) - mwifiex_usb_submit_rx_urb(&card->rx_cmd, - MWIFIEX_RX_CMD_BUF_SIZE); - - return; -} - -static int mwifiex_usb_cmd_event_complete(struct mwifiex_adapter *adapter, - struct sk_buff *skb) -{ - mwifiex_submit_rx_urb(adapter, MWIFIEX_USB_EP_CMD_EVENT); - - return 0; -} - -/* This function wakes up the card. */ -static int mwifiex_pm_wakeup_card(struct mwifiex_adapter *adapter) -{ - /* Simulation of HS_AWAKE event */ - adapter->pm_wakeup_fw_try = false; - del_timer(&adapter->wakeup_timer); - adapter->pm_wakeup_card_req = false; - adapter->ps_state = PS_STATE_AWAKE; - - return 0; -} - -static void mwifiex_usb_submit_rem_rx_urbs(struct mwifiex_adapter *adapter) -{ - struct usb_card_rec *card = (struct usb_card_rec *)adapter->card; - int i; - struct urb_context *ctx; - - for (i = 0; i < MWIFIEX_RX_DATA_URB; i++) { - if (card->rx_data_list[i].skb) - continue; - ctx = &card->rx_data_list[i]; - mwifiex_usb_submit_rx_urb(ctx, MWIFIEX_RX_DATA_BUF_SIZE); - } -} - -/* This function is called after the card has woken up. */ -static inline int -mwifiex_pm_wakeup_card_complete(struct mwifiex_adapter *adapter) -{ - return 0; -} - -static struct mwifiex_if_ops usb_ops = { - .register_dev = mwifiex_register_dev, - .unregister_dev = mwifiex_unregister_dev, - .wakeup = mwifiex_pm_wakeup_card, - .wakeup_complete = mwifiex_pm_wakeup_card_complete, - - /* USB specific */ - .dnld_fw = mwifiex_usb_dnld_fw, - .cmdrsp_complete = mwifiex_usb_cmd_event_complete, - .event_complete = mwifiex_usb_cmd_event_complete, - .host_to_card = mwifiex_usb_host_to_card, - .submit_rem_rx_urbs = mwifiex_usb_submit_rem_rx_urbs, - .multi_port_resync = mwifiex_usb_port_resync, - .is_port_ready = mwifiex_usb_is_port_ready, -}; - -/* This function initializes the USB driver module. - * - * This initiates the semaphore and registers the device with - * USB bus. - */ -static int mwifiex_usb_init_module(void) -{ - int ret; - - pr_debug("Marvell USB8797 Driver\n"); - - sema_init(&add_remove_card_sem, 1); - - ret = usb_register(&mwifiex_usb_driver); - if (ret) - pr_err("Driver register failed!\n"); - else - pr_debug("info: Driver registered successfully!\n"); - - return ret; -} - -/* This function cleans up the USB driver. - * - * The following major steps are followed in .disconnect for cleanup: - * - Resume the device if its suspended - * - Disconnect the device if connected - * - Shutdown the firmware - * - Unregister the device from USB bus. - */ -static void mwifiex_usb_cleanup_module(void) -{ - if (!down_interruptible(&add_remove_card_sem)) - up(&add_remove_card_sem); - - /* set the flag as user is removing this module */ - user_rmmod = 1; - - usb_deregister(&mwifiex_usb_driver); -} - -module_init(mwifiex_usb_init_module); -module_exit(mwifiex_usb_cleanup_module); - -MODULE_AUTHOR("Marvell International Ltd."); -MODULE_DESCRIPTION("Marvell WiFi-Ex USB Driver version" USB_VERSION); -MODULE_VERSION(USB_VERSION); -MODULE_LICENSE("GPL v2"); -MODULE_FIRMWARE(USB8766_DEFAULT_FW_NAME); -MODULE_FIRMWARE(USB8797_DEFAULT_FW_NAME); -MODULE_FIRMWARE(USB8801_DEFAULT_FW_NAME); -MODULE_FIRMWARE(USB8997_DEFAULT_FW_NAME); diff --git a/drivers/net/wireless/mwifiex/usb.h b/drivers/net/wireless/mwifiex/usb.h deleted file mode 100644 index b4e9246bbcdc..000000000000 --- a/drivers/net/wireless/mwifiex/usb.h +++ /dev/null @@ -1,110 +0,0 @@ -/* - * This file contains definitions for mwifiex USB interface driver. - * - * Copyright (C) 2012-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_USB_H -#define _MWIFIEX_USB_H - -#include <linux/usb.h> - -#define USB8XXX_VID 0x1286 - -#define USB8766_PID_1 0x2041 -#define USB8766_PID_2 0x2042 -#define USB8797_PID_1 0x2043 -#define USB8797_PID_2 0x2044 -#define USB8801_PID_1 0x2049 -#define USB8801_PID_2 0x204a -#define USB8997_PID_1 0x2052 -#define USB8997_PID_2 0x204e - - -#define USB8XXX_FW_DNLD 1 -#define USB8XXX_FW_READY 2 -#define USB8XXX_FW_MAX_RETRY 3 - -#define MWIFIEX_TX_DATA_PORT 2 -#define MWIFIEX_TX_DATA_URB 6 -#define MWIFIEX_RX_DATA_URB 6 -#define MWIFIEX_USB_TIMEOUT 100 - -#define USB8766_DEFAULT_FW_NAME "mrvl/usb8766_uapsta.bin" -#define USB8797_DEFAULT_FW_NAME "mrvl/usb8797_uapsta.bin" -#define USB8801_DEFAULT_FW_NAME "mrvl/usb8801_uapsta.bin" -#define USB8997_DEFAULT_FW_NAME "mrvl/usb8997_uapsta.bin" - -#define FW_DNLD_TX_BUF_SIZE 620 -#define FW_DNLD_RX_BUF_SIZE 2048 -#define FW_HAS_LAST_BLOCK 0x00000004 - -#define FW_DATA_XMIT_SIZE \ - (sizeof(struct fw_header) + dlen + sizeof(u32)) - -struct urb_context { - struct mwifiex_adapter *adapter; - struct sk_buff *skb; - struct urb *urb; - u8 ep; -}; - -struct usb_tx_data_port { - u8 tx_data_ep; - u8 block_status; - atomic_t tx_data_urb_pending; - int tx_data_ix; - struct urb_context tx_data_list[MWIFIEX_TX_DATA_URB]; -}; - -struct usb_card_rec { - struct mwifiex_adapter *adapter; - struct usb_device *udev; - struct usb_interface *intf; - u8 rx_cmd_ep; - struct urb_context rx_cmd; - atomic_t rx_cmd_urb_pending; - struct urb_context rx_data_list[MWIFIEX_RX_DATA_URB]; - u8 usb_boot_state; - u8 rx_data_ep; - atomic_t rx_data_urb_pending; - u8 tx_cmd_ep; - atomic_t tx_cmd_urb_pending; - int bulk_out_maxpktsize; - struct urb_context tx_cmd; - u8 mc_resync_flag; - struct usb_tx_data_port port[MWIFIEX_TX_DATA_PORT]; -}; - -struct fw_header { - __le32 dnld_cmd; - __le32 base_addr; - __le32 data_len; - __le32 crc; -}; - -struct fw_sync_header { - __le32 cmd; - __le32 seq_num; -}; - -struct fw_data { - struct fw_header fw_hdr; - __le32 seq_num; - u8 data[1]; -}; - -#endif /*_MWIFIEX_USB_H */ diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c deleted file mode 100644 index 0cec8a64473e..000000000000 --- a/drivers/net/wireless/mwifiex/util.c +++ /dev/null @@ -1,751 +0,0 @@ -/* - * Marvell Wireless LAN device driver: utility functions - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - -static struct mwifiex_debug_data items[] = { - {"debug_mask", item_size(debug_mask), - item_addr(debug_mask), 1}, - {"int_counter", item_size(int_counter), - item_addr(int_counter), 1}, - {"wmm_ac_vo", item_size(packets_out[WMM_AC_VO]), - item_addr(packets_out[WMM_AC_VO]), 1}, - {"wmm_ac_vi", item_size(packets_out[WMM_AC_VI]), - item_addr(packets_out[WMM_AC_VI]), 1}, - {"wmm_ac_be", item_size(packets_out[WMM_AC_BE]), - item_addr(packets_out[WMM_AC_BE]), 1}, - {"wmm_ac_bk", item_size(packets_out[WMM_AC_BK]), - item_addr(packets_out[WMM_AC_BK]), 1}, - {"tx_buf_size", item_size(tx_buf_size), - item_addr(tx_buf_size), 1}, - {"curr_tx_buf_size", item_size(curr_tx_buf_size), - item_addr(curr_tx_buf_size), 1}, - {"ps_mode", item_size(ps_mode), - item_addr(ps_mode), 1}, - {"ps_state", item_size(ps_state), - item_addr(ps_state), 1}, - {"is_deep_sleep", item_size(is_deep_sleep), - item_addr(is_deep_sleep), 1}, - {"wakeup_dev_req", item_size(pm_wakeup_card_req), - item_addr(pm_wakeup_card_req), 1}, - {"wakeup_tries", item_size(pm_wakeup_fw_try), - item_addr(pm_wakeup_fw_try), 1}, - {"hs_configured", item_size(is_hs_configured), - item_addr(is_hs_configured), 1}, - {"hs_activated", item_size(hs_activated), - item_addr(hs_activated), 1}, - {"num_tx_timeout", item_size(num_tx_timeout), - item_addr(num_tx_timeout), 1}, - {"is_cmd_timedout", item_size(is_cmd_timedout), - item_addr(is_cmd_timedout), 1}, - {"timeout_cmd_id", item_size(timeout_cmd_id), - item_addr(timeout_cmd_id), 1}, - {"timeout_cmd_act", item_size(timeout_cmd_act), - item_addr(timeout_cmd_act), 1}, - {"last_cmd_id", item_size(last_cmd_id), - item_addr(last_cmd_id), DBG_CMD_NUM}, - {"last_cmd_act", item_size(last_cmd_act), - item_addr(last_cmd_act), DBG_CMD_NUM}, - {"last_cmd_index", item_size(last_cmd_index), - item_addr(last_cmd_index), 1}, - {"last_cmd_resp_id", item_size(last_cmd_resp_id), - item_addr(last_cmd_resp_id), DBG_CMD_NUM}, - {"last_cmd_resp_index", item_size(last_cmd_resp_index), - item_addr(last_cmd_resp_index), 1}, - {"last_event", item_size(last_event), - item_addr(last_event), DBG_CMD_NUM}, - {"last_event_index", item_size(last_event_index), - item_addr(last_event_index), 1}, - {"num_cmd_h2c_fail", item_size(num_cmd_host_to_card_failure), - item_addr(num_cmd_host_to_card_failure), 1}, - {"num_cmd_sleep_cfm_fail", - item_size(num_cmd_sleep_cfm_host_to_card_failure), - item_addr(num_cmd_sleep_cfm_host_to_card_failure), 1}, - {"num_tx_h2c_fail", item_size(num_tx_host_to_card_failure), - item_addr(num_tx_host_to_card_failure), 1}, - {"num_evt_deauth", item_size(num_event_deauth), - item_addr(num_event_deauth), 1}, - {"num_evt_disassoc", item_size(num_event_disassoc), - item_addr(num_event_disassoc), 1}, - {"num_evt_link_lost", item_size(num_event_link_lost), - item_addr(num_event_link_lost), 1}, - {"num_cmd_deauth", item_size(num_cmd_deauth), - item_addr(num_cmd_deauth), 1}, - {"num_cmd_assoc_ok", item_size(num_cmd_assoc_success), - item_addr(num_cmd_assoc_success), 1}, - {"num_cmd_assoc_fail", item_size(num_cmd_assoc_failure), - item_addr(num_cmd_assoc_failure), 1}, - {"cmd_sent", item_size(cmd_sent), - item_addr(cmd_sent), 1}, - {"data_sent", item_size(data_sent), - item_addr(data_sent), 1}, - {"cmd_resp_received", item_size(cmd_resp_received), - item_addr(cmd_resp_received), 1}, - {"event_received", item_size(event_received), - item_addr(event_received), 1}, - - /* variables defined in struct mwifiex_adapter */ - {"cmd_pending", adapter_item_size(cmd_pending), - adapter_item_addr(cmd_pending), 1}, - {"tx_pending", adapter_item_size(tx_pending), - adapter_item_addr(tx_pending), 1}, - {"rx_pending", adapter_item_size(rx_pending), - adapter_item_addr(rx_pending), 1}, -}; - -static int num_of_items = ARRAY_SIZE(items); - -/* - * Firmware initialization complete callback handler. - * - * This function wakes up the function waiting on the init - * wait queue for the firmware initialization to complete. - */ -int mwifiex_init_fw_complete(struct mwifiex_adapter *adapter) -{ - - if (adapter->hw_status == MWIFIEX_HW_STATUS_READY) - if (adapter->if_ops.init_fw_port) - adapter->if_ops.init_fw_port(adapter); - - adapter->init_wait_q_woken = true; - wake_up_interruptible(&adapter->init_wait_q); - return 0; -} - -/* - * Firmware shutdown complete callback handler. - * - * This function sets the hardware status to not ready and wakes up - * the function waiting on the init wait queue for the firmware - * shutdown to complete. - */ -int mwifiex_shutdown_fw_complete(struct mwifiex_adapter *adapter) -{ - adapter->hw_status = MWIFIEX_HW_STATUS_NOT_READY; - adapter->init_wait_q_woken = true; - wake_up_interruptible(&adapter->init_wait_q); - return 0; -} - -/* - * This function sends init/shutdown command - * to firmware. - */ -int mwifiex_init_shutdown_fw(struct mwifiex_private *priv, - u32 func_init_shutdown) -{ - u16 cmd; - - if (func_init_shutdown == MWIFIEX_FUNC_INIT) { - cmd = HostCmd_CMD_FUNC_INIT; - } else if (func_init_shutdown == MWIFIEX_FUNC_SHUTDOWN) { - cmd = HostCmd_CMD_FUNC_SHUTDOWN; - } else { - mwifiex_dbg(priv->adapter, ERROR, - "unsupported parameter\n"); - return -1; - } - - return mwifiex_send_cmd(priv, cmd, HostCmd_ACT_GEN_SET, 0, NULL, true); -} -EXPORT_SYMBOL_GPL(mwifiex_init_shutdown_fw); - -/* - * IOCTL request handler to set/get debug information. - * - * This function collates/sets the information from/to different driver - * structures. - */ -int mwifiex_get_debug_info(struct mwifiex_private *priv, - struct mwifiex_debug_info *info) -{ - struct mwifiex_adapter *adapter = priv->adapter; - - if (info) { - info->debug_mask = adapter->debug_mask; - memcpy(info->packets_out, - priv->wmm.packets_out, - sizeof(priv->wmm.packets_out)); - info->curr_tx_buf_size = (u32) adapter->curr_tx_buf_size; - info->tx_buf_size = (u32) adapter->tx_buf_size; - info->rx_tbl_num = mwifiex_get_rx_reorder_tbl(priv, - info->rx_tbl); - info->tx_tbl_num = mwifiex_get_tx_ba_stream_tbl(priv, - info->tx_tbl); - info->tdls_peer_num = mwifiex_get_tdls_list(priv, - info->tdls_list); - info->ps_mode = adapter->ps_mode; - info->ps_state = adapter->ps_state; - info->is_deep_sleep = adapter->is_deep_sleep; - info->pm_wakeup_card_req = adapter->pm_wakeup_card_req; - info->pm_wakeup_fw_try = adapter->pm_wakeup_fw_try; - info->is_hs_configured = adapter->is_hs_configured; - info->hs_activated = adapter->hs_activated; - info->is_cmd_timedout = adapter->is_cmd_timedout; - info->num_cmd_host_to_card_failure - = adapter->dbg.num_cmd_host_to_card_failure; - info->num_cmd_sleep_cfm_host_to_card_failure - = adapter->dbg.num_cmd_sleep_cfm_host_to_card_failure; - info->num_tx_host_to_card_failure - = adapter->dbg.num_tx_host_to_card_failure; - info->num_event_deauth = adapter->dbg.num_event_deauth; - info->num_event_disassoc = adapter->dbg.num_event_disassoc; - info->num_event_link_lost = adapter->dbg.num_event_link_lost; - info->num_cmd_deauth = adapter->dbg.num_cmd_deauth; - info->num_cmd_assoc_success = - adapter->dbg.num_cmd_assoc_success; - info->num_cmd_assoc_failure = - adapter->dbg.num_cmd_assoc_failure; - info->num_tx_timeout = adapter->dbg.num_tx_timeout; - info->timeout_cmd_id = adapter->dbg.timeout_cmd_id; - info->timeout_cmd_act = adapter->dbg.timeout_cmd_act; - memcpy(info->last_cmd_id, adapter->dbg.last_cmd_id, - sizeof(adapter->dbg.last_cmd_id)); - memcpy(info->last_cmd_act, adapter->dbg.last_cmd_act, - sizeof(adapter->dbg.last_cmd_act)); - info->last_cmd_index = adapter->dbg.last_cmd_index; - memcpy(info->last_cmd_resp_id, adapter->dbg.last_cmd_resp_id, - sizeof(adapter->dbg.last_cmd_resp_id)); - info->last_cmd_resp_index = adapter->dbg.last_cmd_resp_index; - memcpy(info->last_event, adapter->dbg.last_event, - sizeof(adapter->dbg.last_event)); - info->last_event_index = adapter->dbg.last_event_index; - info->data_sent = adapter->data_sent; - info->cmd_sent = adapter->cmd_sent; - info->cmd_resp_received = adapter->cmd_resp_received; - } - - return 0; -} - -int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf, - struct mwifiex_debug_info *info) -{ - char *p = buf; - struct mwifiex_debug_data *d = &items[0]; - size_t size, addr; - long val; - int i, j; - - if (!info) - return 0; - - for (i = 0; i < num_of_items; i++) { - p += sprintf(p, "%s=", d[i].name); - - size = d[i].size / d[i].num; - - if (i < (num_of_items - 3)) - addr = d[i].addr + (size_t)info; - else /* The last 3 items are struct mwifiex_adapter variables */ - addr = d[i].addr + (size_t)priv->adapter; - - for (j = 0; j < d[i].num; j++) { - switch (size) { - case 1: - val = *((u8 *)addr); - break; - case 2: - val = *((u16 *)addr); - break; - case 4: - val = *((u32 *)addr); - break; - case 8: - val = *((long long *)addr); - break; - default: - val = -1; - break; - } - - p += sprintf(p, "%#lx ", val); - addr += size; - } - - p += sprintf(p, "\n"); - } - - if (info->tx_tbl_num) { - p += sprintf(p, "Tx BA stream table:\n"); - for (i = 0; i < info->tx_tbl_num; i++) - p += sprintf(p, "tid = %d, ra = %pM\n", - info->tx_tbl[i].tid, info->tx_tbl[i].ra); - } - - if (info->rx_tbl_num) { - p += sprintf(p, "Rx reorder table:\n"); - for (i = 0; i < info->rx_tbl_num; i++) { - p += sprintf(p, "tid = %d, ta = %pM, ", - info->rx_tbl[i].tid, - info->rx_tbl[i].ta); - p += sprintf(p, "start_win = %d, ", - info->rx_tbl[i].start_win); - p += sprintf(p, "win_size = %d, buffer: ", - info->rx_tbl[i].win_size); - - for (j = 0; j < info->rx_tbl[i].win_size; j++) - p += sprintf(p, "%c ", - info->rx_tbl[i].buffer[j] ? - '1' : '0'); - - p += sprintf(p, "\n"); - } - } - - if (info->tdls_peer_num) { - p += sprintf(p, "TDLS peer table:\n"); - for (i = 0; i < info->tdls_peer_num; i++) { - p += sprintf(p, "peer = %pM", - info->tdls_list[i].peer_addr); - p += sprintf(p, "\n"); - } - } - - return p - buf; -} - -static int -mwifiex_parse_mgmt_packet(struct mwifiex_private *priv, u8 *payload, u16 len, - struct rxpd *rx_pd) -{ - u16 stype; - u8 category, action_code, *addr2; - struct ieee80211_hdr *ieee_hdr = (void *)payload; - - stype = (le16_to_cpu(ieee_hdr->frame_control) & IEEE80211_FCTL_STYPE); - - switch (stype) { - case IEEE80211_STYPE_ACTION: - category = *(payload + sizeof(struct ieee80211_hdr)); - switch (category) { - case WLAN_CATEGORY_PUBLIC: - action_code = *(payload + sizeof(struct ieee80211_hdr) - + 1); - if (action_code == WLAN_PUB_ACTION_TDLS_DISCOVER_RES) { - addr2 = ieee_hdr->addr2; - mwifiex_dbg(priv->adapter, INFO, - "TDLS discovery response %pM nf=%d, snr=%d\n", - addr2, rx_pd->nf, rx_pd->snr); - mwifiex_auto_tdls_update_peer_signal(priv, - addr2, - rx_pd->snr, - rx_pd->nf); - } - break; - case WLAN_CATEGORY_BACK: - /*we dont indicate BACK action frames to cfg80211*/ - mwifiex_dbg(priv->adapter, INFO, - "drop BACK action frames"); - return -1; - default: - mwifiex_dbg(priv->adapter, INFO, - "unknown public action frame category %d\n", - category); - } - default: - mwifiex_dbg(priv->adapter, INFO, - "unknown mgmt frame subtype %#x\n", stype); - return 0; - } - - return 0; -} -/* - * This function processes the received management packet and send it - * to the kernel. - */ -int -mwifiex_process_mgmt_packet(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct rxpd *rx_pd; - u16 pkt_len; - struct ieee80211_hdr *ieee_hdr; - - if (!skb) - return -1; - - if (!priv->mgmt_frame_mask || - priv->wdev.iftype == NL80211_IFTYPE_UNSPECIFIED) { - mwifiex_dbg(priv->adapter, ERROR, - "do not receive mgmt frames on uninitialized intf"); - return -1; - } - - rx_pd = (struct rxpd *)skb->data; - - skb_pull(skb, le16_to_cpu(rx_pd->rx_pkt_offset)); - skb_pull(skb, sizeof(pkt_len)); - - pkt_len = le16_to_cpu(rx_pd->rx_pkt_length); - - ieee_hdr = (void *)skb->data; - if (ieee80211_is_mgmt(ieee_hdr->frame_control)) { - if (mwifiex_parse_mgmt_packet(priv, (u8 *)ieee_hdr, - pkt_len, rx_pd)) - return -1; - } - /* Remove address4 */ - memmove(skb->data + sizeof(struct ieee80211_hdr_3addr), - skb->data + sizeof(struct ieee80211_hdr), - pkt_len - sizeof(struct ieee80211_hdr)); - - pkt_len -= ETH_ALEN + sizeof(pkt_len); - rx_pd->rx_pkt_length = cpu_to_le16(pkt_len); - - cfg80211_rx_mgmt(&priv->wdev, priv->roc_cfg.chan.center_freq, - CAL_RSSI(rx_pd->snr, rx_pd->nf), skb->data, pkt_len, - 0); - - return 0; -} - -/* - * This function processes the received packet before sending it to the - * kernel. - * - * It extracts the SKB from the received buffer and sends it to kernel. - * In case the received buffer does not contain the data in SKB format, - * the function creates a blank SKB, fills it with the data from the - * received buffer and then sends this new SKB to the kernel. - */ -int mwifiex_recv_packet(struct mwifiex_private *priv, struct sk_buff *skb) -{ - struct mwifiex_sta_node *src_node; - struct ethhdr *p_ethhdr; - - if (!skb) - return -1; - - priv->stats.rx_bytes += skb->len; - priv->stats.rx_packets++; - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_UAP) { - p_ethhdr = (void *)skb->data; - src_node = mwifiex_get_sta_entry(priv, p_ethhdr->h_source); - if (src_node) { - src_node->stats.last_rx = jiffies; - src_node->stats.rx_bytes += skb->len; - src_node->stats.rx_packets++; - } - } - - skb->dev = priv->netdev; - skb->protocol = eth_type_trans(skb, priv->netdev); - skb->ip_summed = CHECKSUM_NONE; - - /* This is required only in case of 11n and USB/PCIE as we alloc - * a buffer of 4K only if its 11N (to be able to receive 4K - * AMSDU packets). In case of SD we allocate buffers based - * on the size of packet and hence this is not needed. - * - * Modifying the truesize here as our allocation for each - * skb is 4K but we only receive 2K packets and this cause - * the kernel to start dropping packets in case where - * application has allocated buffer based on 2K size i.e. - * if there a 64K packet received (in IP fragments and - * application allocates 64K to receive this packet but - * this packet would almost double up because we allocate - * each 1.5K fragment in 4K and pass it up. As soon as the - * 64K limit hits kernel will start to drop rest of the - * fragments. Currently we fail the Filesndl-ht.scr script - * for UDP, hence this fix - */ - if ((priv->adapter->iface_type == MWIFIEX_USB || - priv->adapter->iface_type == MWIFIEX_PCIE) && - (skb->truesize > MWIFIEX_RX_DATA_BUF_SIZE)) - skb->truesize += (skb->len - MWIFIEX_RX_DATA_BUF_SIZE); - - if (in_interrupt()) - netif_rx(skb); - else - netif_rx_ni(skb); - - return 0; -} - -/* - * IOCTL completion callback handler. - * - * This function is called when a pending IOCTL is completed. - * - * If work queue support is enabled, the function wakes up the - * corresponding waiting function. Otherwise, it processes the - * IOCTL response and frees the response buffer. - */ -int mwifiex_complete_cmd(struct mwifiex_adapter *adapter, - struct cmd_ctrl_node *cmd_node) -{ - WARN_ON(!cmd_node->wait_q_enabled); - mwifiex_dbg(adapter, CMD, "cmd completed: status=%d\n", - adapter->cmd_wait_q.status); - - *cmd_node->condition = true; - wake_up_interruptible(&adapter->cmd_wait_q.wait); - - return 0; -} - -/* This function will return the pointer to station entry in station list - * table which matches specified mac address. - * This function should be called after acquiring RA list spinlock. - * NULL is returned if station entry is not found in associated STA list. - */ -struct mwifiex_sta_node * -mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac) -{ - struct mwifiex_sta_node *node; - - if (!mac) - return NULL; - - list_for_each_entry(node, &priv->sta_list, list) { - if (!memcmp(node->mac_addr, mac, ETH_ALEN)) - return node; - } - - return NULL; -} - -static struct mwifiex_sta_node * -mwifiex_get_tdls_sta_entry(struct mwifiex_private *priv, u8 status) -{ - struct mwifiex_sta_node *node; - - list_for_each_entry(node, &priv->sta_list, list) { - if (node->tdls_status == status) - return node; - } - - return NULL; -} - -/* If tdls channel switching is on-going, tx data traffic should be - * blocked until the switching stage completed. - */ -u8 mwifiex_is_tdls_chan_switching(struct mwifiex_private *priv) -{ - struct mwifiex_sta_node *sta_ptr; - - if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) - return false; - - sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_CHAN_SWITCHING); - if (sta_ptr) - return true; - - return false; -} - -u8 mwifiex_is_tdls_off_chan(struct mwifiex_private *priv) -{ - struct mwifiex_sta_node *sta_ptr; - - if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) - return false; - - sta_ptr = mwifiex_get_tdls_sta_entry(priv, TDLS_IN_OFF_CHAN); - if (sta_ptr) - return true; - - return false; -} - -/* If tdls channel switching is on-going or tdls operate on off-channel, - * cmd path should be blocked until tdls switched to base-channel. - */ -u8 mwifiex_is_send_cmd_allowed(struct mwifiex_private *priv) -{ - if (!priv || !ISSUPP_TDLS_ENABLED(priv->adapter->fw_cap_info)) - return true; - - if (mwifiex_is_tdls_chan_switching(priv) || - mwifiex_is_tdls_off_chan(priv)) - return false; - - return true; -} - -/* This function will add a sta_node entry to associated station list - * table with the given mac address. - * If entry exist already, existing entry is returned. - * If received mac address is NULL, NULL is returned. - */ -struct mwifiex_sta_node * -mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac) -{ - struct mwifiex_sta_node *node; - unsigned long flags; - - if (!mac) - return NULL; - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - node = mwifiex_get_sta_entry(priv, mac); - if (node) - goto done; - - node = kzalloc(sizeof(*node), GFP_ATOMIC); - if (!node) - goto done; - - memcpy(node->mac_addr, mac, ETH_ALEN); - list_add_tail(&node->list, &priv->sta_list); - -done: - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - return node; -} - -/* This function will search for HT IE in association request IEs - * and set station HT parameters accordingly. - */ -void -mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies, - int ies_len, struct mwifiex_sta_node *node) -{ - struct ieee_types_header *ht_cap_ie; - const struct ieee80211_ht_cap *ht_cap; - - if (!ies) - return; - - ht_cap_ie = (void *)cfg80211_find_ie(WLAN_EID_HT_CAPABILITY, ies, - ies_len); - if (ht_cap_ie) { - ht_cap = (void *)(ht_cap_ie + 1); - node->is_11n_enabled = 1; - node->max_amsdu = le16_to_cpu(ht_cap->cap_info) & - IEEE80211_HT_CAP_MAX_AMSDU ? - MWIFIEX_TX_DATA_BUF_SIZE_8K : - MWIFIEX_TX_DATA_BUF_SIZE_4K; - } else { - node->is_11n_enabled = 0; - } - - return; -} - -/* This function will delete a station entry from station list */ -void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac) -{ - struct mwifiex_sta_node *node; - unsigned long flags; - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - - node = mwifiex_get_sta_entry(priv, mac); - if (node) { - list_del(&node->list); - kfree(node); - } - - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - return; -} - -/* This function will delete all stations from associated station list. */ -void mwifiex_del_all_sta_list(struct mwifiex_private *priv) -{ - struct mwifiex_sta_node *node, *tmp; - unsigned long flags; - - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - - list_for_each_entry_safe(node, tmp, &priv->sta_list, list) { - list_del(&node->list); - kfree(node); - } - - INIT_LIST_HEAD(&priv->sta_list); - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - return; -} - -/* This function adds histogram data to histogram array*/ -void mwifiex_hist_data_add(struct mwifiex_private *priv, - u8 rx_rate, s8 snr, s8 nflr) -{ - struct mwifiex_histogram_data *phist_data = priv->hist_data; - - if (atomic_read(&phist_data->num_samples) > MWIFIEX_HIST_MAX_SAMPLES) - mwifiex_hist_data_reset(priv); - mwifiex_hist_data_set(priv, rx_rate, snr, nflr); -} - -/* function to add histogram record */ -void mwifiex_hist_data_set(struct mwifiex_private *priv, u8 rx_rate, s8 snr, - s8 nflr) -{ - struct mwifiex_histogram_data *phist_data = priv->hist_data; - - atomic_inc(&phist_data->num_samples); - atomic_inc(&phist_data->rx_rate[rx_rate]); - atomic_inc(&phist_data->snr[snr]); - atomic_inc(&phist_data->noise_flr[128 + nflr]); - atomic_inc(&phist_data->sig_str[nflr - snr]); -} - -/* function to reset histogram data during init/reset */ -void mwifiex_hist_data_reset(struct mwifiex_private *priv) -{ - int ix; - struct mwifiex_histogram_data *phist_data = priv->hist_data; - - atomic_set(&phist_data->num_samples, 0); - for (ix = 0; ix < MWIFIEX_MAX_AC_RX_RATES; ix++) - atomic_set(&phist_data->rx_rate[ix], 0); - for (ix = 0; ix < MWIFIEX_MAX_SNR; ix++) - atomic_set(&phist_data->snr[ix], 0); - for (ix = 0; ix < MWIFIEX_MAX_NOISE_FLR; ix++) - atomic_set(&phist_data->noise_flr[ix], 0); - for (ix = 0; ix < MWIFIEX_MAX_SIG_STRENGTH; ix++) - atomic_set(&phist_data->sig_str[ix], 0); -} - -void *mwifiex_alloc_dma_align_buf(int rx_len, gfp_t flags) -{ - struct sk_buff *skb; - int buf_len, pad; - - buf_len = rx_len + MWIFIEX_RX_HEADROOM + MWIFIEX_DMA_ALIGN_SZ; - - skb = __dev_alloc_skb(buf_len, flags); - - if (!skb) - return NULL; - - skb_reserve(skb, MWIFIEX_RX_HEADROOM); - - pad = MWIFIEX_ALIGN_ADDR(skb->data, MWIFIEX_DMA_ALIGN_SZ) - - (long)skb->data; - - skb_reserve(skb, pad); - - return skb; -} -EXPORT_SYMBOL_GPL(mwifiex_alloc_dma_align_buf); diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h deleted file mode 100644 index b541d66c01eb..000000000000 --- a/drivers/net/wireless/mwifiex/util.h +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Marvell Wireless LAN device driver: utility functions - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_UTIL_H_ -#define _MWIFIEX_UTIL_H_ - -struct mwifiex_private; - -struct mwifiex_dma_mapping { - dma_addr_t addr; - size_t len; -}; - -struct mwifiex_cb { - struct mwifiex_dma_mapping dma_mapping; - union { - struct mwifiex_rxinfo rx_info; - struct mwifiex_txinfo tx_info; - }; -}; - -/* size/addr for mwifiex_debug_info */ -#define item_size(n) (FIELD_SIZEOF(struct mwifiex_debug_info, n)) -#define item_addr(n) (offsetof(struct mwifiex_debug_info, n)) - -/* size/addr for struct mwifiex_adapter */ -#define adapter_item_size(n) (FIELD_SIZEOF(struct mwifiex_adapter, n)) -#define adapter_item_addr(n) (offsetof(struct mwifiex_adapter, n)) - -struct mwifiex_debug_data { - char name[32]; /* variable/array name */ - u32 size; /* size of the variable/array */ - size_t addr; /* address of the variable/array */ - int num; /* number of variables in an array */ -}; - -static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb) -{ - struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; - - BUILD_BUG_ON(sizeof(struct mwifiex_cb) > sizeof(skb->cb)); - return &cb->rx_info; -} - -static inline struct mwifiex_txinfo *MWIFIEX_SKB_TXCB(struct sk_buff *skb) -{ - struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; - - return &cb->tx_info; -} - -static inline void mwifiex_store_mapping(struct sk_buff *skb, - struct mwifiex_dma_mapping *mapping) -{ - struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; - - memcpy(&cb->dma_mapping, mapping, sizeof(*mapping)); -} - -static inline void mwifiex_get_mapping(struct sk_buff *skb, - struct mwifiex_dma_mapping *mapping) -{ - struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb; - - memcpy(mapping, &cb->dma_mapping, sizeof(*mapping)); -} - -static inline dma_addr_t MWIFIEX_SKB_DMA_ADDR(struct sk_buff *skb) -{ - struct mwifiex_dma_mapping mapping; - - mwifiex_get_mapping(skb, &mapping); - - return mapping.addr; -} - -int mwifiex_debug_info_to_buffer(struct mwifiex_private *priv, char *buf, - struct mwifiex_debug_info *info); - -#endif /* !_MWIFIEX_UTIL_H_ */ diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c deleted file mode 100644 index acccd6734e3b..000000000000 --- a/drivers/net/wireless/mwifiex/wmm.c +++ /dev/null @@ -1,1531 +0,0 @@ -/* - * Marvell Wireless LAN device driver: WMM - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#include "decl.h" -#include "ioctl.h" -#include "util.h" -#include "fw.h" -#include "main.h" -#include "wmm.h" -#include "11n.h" - - -/* Maximum value FW can accept for driver delay in packet transmission */ -#define DRV_PKT_DELAY_TO_FW_MAX 512 - - -#define WMM_QUEUED_PACKET_LOWER_LIMIT 180 - -#define WMM_QUEUED_PACKET_UPPER_LIMIT 200 - -/* Offset for TOS field in the IP header */ -#define IPTOS_OFFSET 5 - -static bool disable_tx_amsdu; -module_param(disable_tx_amsdu, bool, 0644); - -/* WMM information IE */ -static const u8 wmm_info_ie[] = { WLAN_EID_VENDOR_SPECIFIC, 0x07, - 0x00, 0x50, 0xf2, 0x02, - 0x00, 0x01, 0x00 -}; - -static const u8 wmm_aci_to_qidx_map[] = { WMM_AC_BE, - WMM_AC_BK, - WMM_AC_VI, - WMM_AC_VO -}; - -static u8 tos_to_tid[] = { - /* TID DSCP_P2 DSCP_P1 DSCP_P0 WMM_AC */ - 0x01, /* 0 1 0 AC_BK */ - 0x02, /* 0 0 0 AC_BK */ - 0x00, /* 0 0 1 AC_BE */ - 0x03, /* 0 1 1 AC_BE */ - 0x04, /* 1 0 0 AC_VI */ - 0x05, /* 1 0 1 AC_VI */ - 0x06, /* 1 1 0 AC_VO */ - 0x07 /* 1 1 1 AC_VO */ -}; - -static u8 ac_to_tid[4][2] = { {1, 2}, {0, 3}, {4, 5}, {6, 7} }; - -/* - * This function debug prints the priority parameters for a WMM AC. - */ -static void -mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param) -{ - const char *ac_str[] = { "BK", "BE", "VI", "VO" }; - - pr_debug("info: WMM AC_%s: ACI=%d, ACM=%d, Aifsn=%d, " - "EcwMin=%d, EcwMax=%d, TxopLimit=%d\n", - ac_str[wmm_aci_to_qidx_map[(ac_param->aci_aifsn_bitmap - & MWIFIEX_ACI) >> 5]], - (ac_param->aci_aifsn_bitmap & MWIFIEX_ACI) >> 5, - (ac_param->aci_aifsn_bitmap & MWIFIEX_ACM) >> 4, - ac_param->aci_aifsn_bitmap & MWIFIEX_AIFSN, - ac_param->ecw_bitmap & MWIFIEX_ECW_MIN, - (ac_param->ecw_bitmap & MWIFIEX_ECW_MAX) >> 4, - le16_to_cpu(ac_param->tx_op_limit)); -} - -/* - * This function allocates a route address list. - * - * The function also initializes the list with the provided RA. - */ -static struct mwifiex_ra_list_tbl * -mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra) -{ - struct mwifiex_ra_list_tbl *ra_list; - - ra_list = kzalloc(sizeof(struct mwifiex_ra_list_tbl), GFP_ATOMIC); - if (!ra_list) - return NULL; - - INIT_LIST_HEAD(&ra_list->list); - skb_queue_head_init(&ra_list->skb_head); - - memcpy(ra_list->ra, ra, ETH_ALEN); - - ra_list->total_pkt_count = 0; - - mwifiex_dbg(adapter, INFO, "info: allocated ra_list %p\n", ra_list); - - return ra_list; -} - -/* This function returns random no between 16 and 32 to be used as threshold - * for no of packets after which BA setup is initiated. - */ -static u8 mwifiex_get_random_ba_threshold(void) -{ - u64 ns; - /* setup ba_packet_threshold here random number between - * [BA_SETUP_PACKET_OFFSET, - * BA_SETUP_PACKET_OFFSET+BA_SETUP_MAX_PACKET_THRESHOLD-1] - */ - ns = ktime_get_ns(); - ns += (ns >> 32) + (ns >> 16); - - return ((u8)ns % BA_SETUP_MAX_PACKET_THRESHOLD) + BA_SETUP_PACKET_OFFSET; -} - -/* - * This function allocates and adds a RA list for all TIDs - * with the given RA. - */ -void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra) -{ - int i; - struct mwifiex_ra_list_tbl *ra_list; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_sta_node *node; - unsigned long flags; - - - for (i = 0; i < MAX_NUM_TID; ++i) { - ra_list = mwifiex_wmm_allocate_ralist_node(adapter, ra); - mwifiex_dbg(adapter, INFO, - "info: created ra_list %p\n", ra_list); - - if (!ra_list) - break; - - ra_list->is_11n_enabled = 0; - ra_list->tdls_link = false; - ra_list->ba_status = BA_SETUP_NONE; - ra_list->amsdu_in_ampdu = false; - if (!mwifiex_queuing_ra_based(priv)) { - if (mwifiex_is_tdls_link_setup - (mwifiex_get_tdls_link_status(priv, ra))) { - ra_list->tdls_link = true; - ra_list->is_11n_enabled = - mwifiex_tdls_peer_11n_enabled(priv, ra); - } else { - ra_list->is_11n_enabled = IS_11N_ENABLED(priv); - } - } else { - spin_lock_irqsave(&priv->sta_list_spinlock, flags); - node = mwifiex_get_sta_entry(priv, ra); - if (node) - ra_list->tx_paused = node->tx_pause; - ra_list->is_11n_enabled = - mwifiex_is_sta_11n_enabled(priv, node); - if (ra_list->is_11n_enabled) - ra_list->max_amsdu = node->max_amsdu; - spin_unlock_irqrestore(&priv->sta_list_spinlock, flags); - } - - mwifiex_dbg(adapter, DATA, "data: ralist %p: is_11n_enabled=%d\n", - ra_list, ra_list->is_11n_enabled); - - if (ra_list->is_11n_enabled) { - ra_list->ba_pkt_count = 0; - ra_list->ba_packet_thr = - mwifiex_get_random_ba_threshold(); - } - list_add_tail(&ra_list->list, - &priv->wmm.tid_tbl_ptr[i].ra_list); - } -} - -/* - * This function sets the WMM queue priorities to their default values. - */ -static void mwifiex_wmm_default_queue_priorities(struct mwifiex_private *priv) -{ - /* Default queue priorities: VO->VI->BE->BK */ - priv->wmm.queue_priority[0] = WMM_AC_VO; - priv->wmm.queue_priority[1] = WMM_AC_VI; - priv->wmm.queue_priority[2] = WMM_AC_BE; - priv->wmm.queue_priority[3] = WMM_AC_BK; -} - -/* - * This function map ACs to TIDs. - */ -static void -mwifiex_wmm_queue_priorities_tid(struct mwifiex_private *priv) -{ - struct mwifiex_wmm_desc *wmm = &priv->wmm; - u8 *queue_priority = wmm->queue_priority; - int i; - - for (i = 0; i < 4; ++i) { - tos_to_tid[7 - (i * 2)] = ac_to_tid[queue_priority[i]][1]; - tos_to_tid[6 - (i * 2)] = ac_to_tid[queue_priority[i]][0]; - } - - for (i = 0; i < MAX_NUM_TID; ++i) - priv->tos_to_tid_inv[tos_to_tid[i]] = (u8)i; - - atomic_set(&wmm->highest_queued_prio, HIGH_PRIO_TID); -} - -/* - * This function initializes WMM priority queues. - */ -void -mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, - struct ieee_types_wmm_parameter *wmm_ie) -{ - u16 cw_min, avg_back_off, tmp[4]; - u32 i, j, num_ac; - u8 ac_idx; - - if (!wmm_ie || !priv->wmm_enabled) { - /* WMM is not enabled, just set the defaults and return */ - mwifiex_wmm_default_queue_priorities(priv); - return; - } - - mwifiex_dbg(priv->adapter, INFO, - "info: WMM Parameter IE: version=%d,\t" - "qos_info Parameter Set Count=%d, Reserved=%#x\n", - wmm_ie->vend_hdr.version, wmm_ie->qos_info_bitmap & - IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK, - wmm_ie->reserved); - - for (num_ac = 0; num_ac < ARRAY_SIZE(wmm_ie->ac_params); num_ac++) { - u8 ecw = wmm_ie->ac_params[num_ac].ecw_bitmap; - u8 aci_aifsn = wmm_ie->ac_params[num_ac].aci_aifsn_bitmap; - cw_min = (1 << (ecw & MWIFIEX_ECW_MIN)) - 1; - avg_back_off = (cw_min >> 1) + (aci_aifsn & MWIFIEX_AIFSN); - - ac_idx = wmm_aci_to_qidx_map[(aci_aifsn & MWIFIEX_ACI) >> 5]; - priv->wmm.queue_priority[ac_idx] = ac_idx; - tmp[ac_idx] = avg_back_off; - - mwifiex_dbg(priv->adapter, INFO, - "info: WMM: CWmax=%d CWmin=%d Avg Back-off=%d\n", - (1 << ((ecw & MWIFIEX_ECW_MAX) >> 4)) - 1, - cw_min, avg_back_off); - mwifiex_wmm_ac_debug_print(&wmm_ie->ac_params[num_ac]); - } - - /* Bubble sort */ - for (i = 0; i < num_ac; i++) { - for (j = 1; j < num_ac - i; j++) { - if (tmp[j - 1] > tmp[j]) { - swap(tmp[j - 1], tmp[j]); - swap(priv->wmm.queue_priority[j - 1], - priv->wmm.queue_priority[j]); - } else if (tmp[j - 1] == tmp[j]) { - if (priv->wmm.queue_priority[j - 1] - < priv->wmm.queue_priority[j]) - swap(priv->wmm.queue_priority[j - 1], - priv->wmm.queue_priority[j]); - } - } - } - - mwifiex_wmm_queue_priorities_tid(priv); -} - -/* - * This function evaluates whether or not an AC is to be downgraded. - * - * In case the AC is not enabled, the highest AC is returned that is - * enabled and does not require admission control. - */ -static enum mwifiex_wmm_ac_e -mwifiex_wmm_eval_downgrade_ac(struct mwifiex_private *priv, - enum mwifiex_wmm_ac_e eval_ac) -{ - int down_ac; - enum mwifiex_wmm_ac_e ret_ac; - struct mwifiex_wmm_ac_status *ac_status; - - ac_status = &priv->wmm.ac_status[eval_ac]; - - if (!ac_status->disabled) - /* Okay to use this AC, its enabled */ - return eval_ac; - - /* Setup a default return value of the lowest priority */ - ret_ac = WMM_AC_BK; - - /* - * Find the highest AC that is enabled and does not require - * admission control. The spec disallows downgrading to an AC, - * which is enabled due to a completed admission control. - * Unadmitted traffic is not to be sent on an AC with admitted - * traffic. - */ - for (down_ac = WMM_AC_BK; down_ac < eval_ac; down_ac++) { - ac_status = &priv->wmm.ac_status[down_ac]; - - if (!ac_status->disabled && !ac_status->flow_required) - /* AC is enabled and does not require admission - control */ - ret_ac = (enum mwifiex_wmm_ac_e) down_ac; - } - - return ret_ac; -} - -/* - * This function downgrades WMM priority queue. - */ -void -mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv) -{ - int ac_val; - - mwifiex_dbg(priv->adapter, INFO, "info: WMM: AC Priorities:\t" - "BK(0), BE(1), VI(2), VO(3)\n"); - - if (!priv->wmm_enabled) { - /* WMM is not enabled, default priorities */ - for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) - priv->wmm.ac_down_graded_vals[ac_val] = - (enum mwifiex_wmm_ac_e) ac_val; - } else { - for (ac_val = WMM_AC_BK; ac_val <= WMM_AC_VO; ac_val++) { - priv->wmm.ac_down_graded_vals[ac_val] - = mwifiex_wmm_eval_downgrade_ac(priv, - (enum mwifiex_wmm_ac_e) ac_val); - mwifiex_dbg(priv->adapter, INFO, - "info: WMM: AC PRIO %d maps to %d\n", - ac_val, - priv->wmm.ac_down_graded_vals[ac_val]); - } - } -} - -/* - * This function converts the IP TOS field to an WMM AC - * Queue assignment. - */ -static enum mwifiex_wmm_ac_e -mwifiex_wmm_convert_tos_to_ac(struct mwifiex_adapter *adapter, u32 tos) -{ - /* Map of TOS UP values to WMM AC */ - const enum mwifiex_wmm_ac_e tos_to_ac[] = { WMM_AC_BE, - WMM_AC_BK, - WMM_AC_BK, - WMM_AC_BE, - WMM_AC_VI, - WMM_AC_VI, - WMM_AC_VO, - WMM_AC_VO - }; - - if (tos >= ARRAY_SIZE(tos_to_ac)) - return WMM_AC_BE; - - return tos_to_ac[tos]; -} - -/* - * This function evaluates a given TID and downgrades it to a lower - * TID if the WMM Parameter IE received from the AP indicates that the - * AP is disabled (due to call admission control (ACM bit). Mapping - * of TID to AC is taken care of internally. - */ -u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid) -{ - enum mwifiex_wmm_ac_e ac, ac_down; - u8 new_tid; - - ac = mwifiex_wmm_convert_tos_to_ac(priv->adapter, tid); - ac_down = priv->wmm.ac_down_graded_vals[ac]; - - /* Send the index to tid array, picking from the array will be - * taken care by dequeuing function - */ - new_tid = ac_to_tid[ac_down][tid % 2]; - - return new_tid; -} - -/* - * This function initializes the WMM state information and the - * WMM data path queues. - */ -void -mwifiex_wmm_init(struct mwifiex_adapter *adapter) -{ - int i, j; - struct mwifiex_private *priv; - - for (j = 0; j < adapter->priv_num; ++j) { - priv = adapter->priv[j]; - if (!priv) - continue; - - for (i = 0; i < MAX_NUM_TID; ++i) { - if (!disable_tx_amsdu && - adapter->tx_buf_size > MWIFIEX_TX_DATA_BUF_SIZE_2K) - priv->aggr_prio_tbl[i].amsdu = - priv->tos_to_tid_inv[i]; - else - priv->aggr_prio_tbl[i].amsdu = - BA_STREAM_NOT_ALLOWED; - priv->aggr_prio_tbl[i].ampdu_ap = - priv->tos_to_tid_inv[i]; - priv->aggr_prio_tbl[i].ampdu_user = - priv->tos_to_tid_inv[i]; - } - - priv->aggr_prio_tbl[6].amsdu - = priv->aggr_prio_tbl[6].ampdu_ap - = priv->aggr_prio_tbl[6].ampdu_user - = BA_STREAM_NOT_ALLOWED; - - priv->aggr_prio_tbl[7].amsdu = priv->aggr_prio_tbl[7].ampdu_ap - = priv->aggr_prio_tbl[7].ampdu_user - = BA_STREAM_NOT_ALLOWED; - - mwifiex_set_ba_params(priv); - mwifiex_reset_11n_rx_seq_num(priv); - - atomic_set(&priv->wmm.tx_pkts_queued, 0); - atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); - } -} - -int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter) -{ - struct mwifiex_private *priv; - int i; - - for (i = 0; i < adapter->priv_num; i++) { - priv = adapter->priv[i]; - if (!priv) - continue; - if (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv)) - continue; - if (!skb_queue_empty(&priv->bypass_txq)) - return false; - } - - return true; -} - -/* - * This function checks if WMM Tx queue is empty. - */ -int -mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter) -{ - int i; - struct mwifiex_private *priv; - - for (i = 0; i < adapter->priv_num; ++i) { - priv = adapter->priv[i]; - if (!priv) - continue; - if (!priv->port_open) - continue; - if (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv)) - continue; - if (atomic_read(&priv->wmm.tx_pkts_queued)) - return false; - } - - return true; -} - -/* - * This function deletes all packets in an RA list node. - * - * The packet sent completion callback handler are called with - * status failure, after they are dequeued to ensure proper - * cleanup. The RA list node itself is freed at the end. - */ -static void -mwifiex_wmm_del_pkts_in_ralist_node(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra_list) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct sk_buff *skb, *tmp; - - skb_queue_walk_safe(&ra_list->skb_head, skb, tmp) - mwifiex_write_data_complete(adapter, skb, 0, -1); -} - -/* - * This function deletes all packets in an RA list. - * - * Each nodes in the RA list are freed individually first, and then - * the RA list itself is freed. - */ -static void -mwifiex_wmm_del_pkts_in_ralist(struct mwifiex_private *priv, - struct list_head *ra_list_head) -{ - struct mwifiex_ra_list_tbl *ra_list; - - list_for_each_entry(ra_list, ra_list_head, list) - mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); -} - -/* - * This function deletes all packets in all RA lists. - */ -static void mwifiex_wmm_cleanup_queues(struct mwifiex_private *priv) -{ - int i; - - for (i = 0; i < MAX_NUM_TID; i++) - mwifiex_wmm_del_pkts_in_ralist(priv, &priv->wmm.tid_tbl_ptr[i]. - ra_list); - - atomic_set(&priv->wmm.tx_pkts_queued, 0); - atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); -} - -/* - * This function deletes all route addresses from all RA lists. - */ -static void mwifiex_wmm_delete_all_ralist(struct mwifiex_private *priv) -{ - struct mwifiex_ra_list_tbl *ra_list, *tmp_node; - int i; - - for (i = 0; i < MAX_NUM_TID; ++i) { - mwifiex_dbg(priv->adapter, INFO, - "info: ra_list: freeing buf for tid %d\n", i); - list_for_each_entry_safe(ra_list, tmp_node, - &priv->wmm.tid_tbl_ptr[i].ra_list, - list) { - list_del(&ra_list->list); - kfree(ra_list); - } - - INIT_LIST_HEAD(&priv->wmm.tid_tbl_ptr[i].ra_list); - } -} - -static int mwifiex_free_ack_frame(int id, void *p, void *data) -{ - pr_warn("Have pending ack frames!\n"); - kfree_skb(p); - return 0; -} - -/* - * This function cleans up the Tx and Rx queues. - * - * Cleanup includes - - * - All packets in RA lists - * - All entries in Rx reorder table - * - All entries in Tx BA stream table - * - MPA buffer (if required) - * - All RA lists - */ -void -mwifiex_clean_txrx(struct mwifiex_private *priv) -{ - unsigned long flags; - struct sk_buff *skb, *tmp; - - mwifiex_11n_cleanup_reorder_tbl(priv); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - mwifiex_wmm_cleanup_queues(priv); - mwifiex_11n_delete_all_tx_ba_stream_tbl(priv); - - if (priv->adapter->if_ops.cleanup_mpa_buf) - priv->adapter->if_ops.cleanup_mpa_buf(priv->adapter); - - mwifiex_wmm_delete_all_ralist(priv); - memcpy(tos_to_tid, ac_to_tid, sizeof(tos_to_tid)); - - if (priv->adapter->if_ops.clean_pcie_ring && - !priv->adapter->surprise_removed) - priv->adapter->if_ops.clean_pcie_ring(priv->adapter); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - - skb_queue_walk_safe(&priv->tdls_txq, skb, tmp) - mwifiex_write_data_complete(priv->adapter, skb, 0, -1); - - skb_queue_walk_safe(&priv->bypass_txq, skb, tmp) - mwifiex_write_data_complete(priv->adapter, skb, 0, -1); - atomic_set(&priv->adapter->bypass_tx_pending, 0); - - idr_for_each(&priv->ack_status_frames, mwifiex_free_ack_frame, NULL); - idr_destroy(&priv->ack_status_frames); -} - -/* - * This function retrieves a particular RA list node, matching with the - * given TID and RA address. - */ -struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid, - const u8 *ra_addr) -{ - struct mwifiex_ra_list_tbl *ra_list; - - list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[tid].ra_list, - list) { - if (!memcmp(ra_list->ra, ra_addr, ETH_ALEN)) - return ra_list; - } - - return NULL; -} - -void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac, - u8 tx_pause) -{ - struct mwifiex_ra_list_tbl *ra_list; - u32 pkt_cnt = 0, tx_pkts_queued; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - for (i = 0; i < MAX_NUM_TID; ++i) { - ra_list = mwifiex_wmm_get_ralist_node(priv, i, mac); - if (ra_list && ra_list->tx_paused != tx_pause) { - pkt_cnt += ra_list->total_pkt_count; - ra_list->tx_paused = tx_pause; - if (tx_pause) - priv->wmm.pkts_paused[i] += - ra_list->total_pkt_count; - else - priv->wmm.pkts_paused[i] -= - ra_list->total_pkt_count; - } - } - - if (pkt_cnt) { - tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued); - if (tx_pause) - tx_pkts_queued -= pkt_cnt; - else - tx_pkts_queued += pkt_cnt; - - atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued); - atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); - } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* This function update non-tdls peer ralist tx_pause while - * tdls channel swithing - */ -void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv, - u8 *mac, u8 tx_pause) -{ - struct mwifiex_ra_list_tbl *ra_list; - u32 pkt_cnt = 0, tx_pkts_queued; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - for (i = 0; i < MAX_NUM_TID; ++i) { - list_for_each_entry(ra_list, &priv->wmm.tid_tbl_ptr[i].ra_list, - list) { - if (!memcmp(ra_list->ra, mac, ETH_ALEN)) - continue; - - if (ra_list->tx_paused != tx_pause) { - pkt_cnt += ra_list->total_pkt_count; - ra_list->tx_paused = tx_pause; - if (tx_pause) - priv->wmm.pkts_paused[i] += - ra_list->total_pkt_count; - else - priv->wmm.pkts_paused[i] -= - ra_list->total_pkt_count; - } - } - } - - if (pkt_cnt) { - tx_pkts_queued = atomic_read(&priv->wmm.tx_pkts_queued); - if (tx_pause) - tx_pkts_queued -= pkt_cnt; - else - tx_pkts_queued += pkt_cnt; - - atomic_set(&priv->wmm.tx_pkts_queued, tx_pkts_queued); - atomic_set(&priv->wmm.highest_queued_prio, HIGH_PRIO_TID); - } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* - * This function retrieves an RA list node for a given TID and - * RA address pair. - * - * If no such node is found, a new node is added first and then - * retrieved. - */ -struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, - const u8 *ra_addr) -{ - struct mwifiex_ra_list_tbl *ra_list; - - ra_list = mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); - if (ra_list) - return ra_list; - mwifiex_ralist_add(priv, ra_addr); - - return mwifiex_wmm_get_ralist_node(priv, tid, ra_addr); -} - -/* - * This function deletes RA list nodes for given mac for all TIDs. - * Function also decrements TX pending count accordingly. - */ -void -mwifiex_wmm_del_peer_ra_list(struct mwifiex_private *priv, const u8 *ra_addr) -{ - struct mwifiex_ra_list_tbl *ra_list; - unsigned long flags; - int i; - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - for (i = 0; i < MAX_NUM_TID; ++i) { - ra_list = mwifiex_wmm_get_ralist_node(priv, i, ra_addr); - - if (!ra_list) - continue; - mwifiex_wmm_del_pkts_in_ralist_node(priv, ra_list); - if (ra_list->tx_paused) - priv->wmm.pkts_paused[i] -= ra_list->total_pkt_count; - else - atomic_sub(ra_list->total_pkt_count, - &priv->wmm.tx_pkts_queued); - list_del(&ra_list->list); - kfree(ra_list); - } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* - * This function checks if a particular RA list node exists in a given TID - * table index. - */ -int -mwifiex_is_ralist_valid(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra_list, int ptr_index) -{ - struct mwifiex_ra_list_tbl *rlist; - - list_for_each_entry(rlist, &priv->wmm.tid_tbl_ptr[ptr_index].ra_list, - list) { - if (rlist == ra_list) - return true; - } - - return false; -} - -/* - * This function adds a packet to bypass TX queue. - * This is special TX queue for packets which can be sent even when port_open - * is false. - */ -void -mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - skb_queue_tail(&priv->bypass_txq, skb); -} - -/* - * This function adds a packet to WMM queue. - * - * In disconnected state the packet is immediately dropped and the - * packet send completion callback is called with status failure. - * - * Otherwise, the correct RA list node is located and the packet - * is queued at the list tail. - */ -void -mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, - struct sk_buff *skb) -{ - struct mwifiex_adapter *adapter = priv->adapter; - u32 tid; - struct mwifiex_ra_list_tbl *ra_list; - u8 ra[ETH_ALEN], tid_down; - unsigned long flags; - struct list_head list_head; - int tdls_status = TDLS_NOT_SETUP; - struct ethhdr *eth_hdr = (struct ethhdr *)skb->data; - struct mwifiex_txinfo *tx_info = MWIFIEX_SKB_TXCB(skb); - - memcpy(ra, eth_hdr->h_dest, ETH_ALEN); - - if (GET_BSS_ROLE(priv) == MWIFIEX_BSS_ROLE_STA && - ISSUPP_TDLS_ENABLED(adapter->fw_cap_info)) { - if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS) - mwifiex_dbg(adapter, DATA, - "TDLS setup packet for %pM.\t" - "Don't block\n", ra); - else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN)) - tdls_status = mwifiex_get_tdls_link_status(priv, ra); - } - - if (!priv->media_connected && !mwifiex_is_skb_mgmt_frame(skb)) { - mwifiex_dbg(adapter, DATA, "data: drop packet in disconnect\n"); - mwifiex_write_data_complete(adapter, skb, 0, -1); - return; - } - - tid = skb->priority; - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - - tid_down = mwifiex_wmm_downgrade_tid(priv, tid); - - /* In case of infra as we have already created the list during - association we just don't have to call get_queue_raptr, we will - have only 1 raptr for a tid in case of infra */ - if (!mwifiex_queuing_ra_based(priv) && - !mwifiex_is_skb_mgmt_frame(skb)) { - switch (tdls_status) { - case TDLS_SETUP_COMPLETE: - case TDLS_CHAN_SWITCHING: - case TDLS_IN_BASE_CHAN: - case TDLS_IN_OFF_CHAN: - ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, - ra); - tx_info->flags |= MWIFIEX_BUF_FLAG_TDLS_PKT; - break; - case TDLS_SETUP_INPROGRESS: - skb_queue_tail(&priv->tdls_txq, skb); - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - flags); - return; - default: - list_head = priv->wmm.tid_tbl_ptr[tid_down].ra_list; - if (!list_empty(&list_head)) - ra_list = list_first_entry( - &list_head, struct mwifiex_ra_list_tbl, - list); - else - ra_list = NULL; - break; - } - } else { - memcpy(ra, skb->data, ETH_ALEN); - if (ra[0] & 0x01 || mwifiex_is_skb_mgmt_frame(skb)) - eth_broadcast_addr(ra); - ra_list = mwifiex_wmm_get_queue_raptr(priv, tid_down, ra); - } - - if (!ra_list) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - mwifiex_write_data_complete(adapter, skb, 0, -1); - return; - } - - skb_queue_tail(&ra_list->skb_head, skb); - - ra_list->ba_pkt_count++; - ra_list->total_pkt_count++; - - if (atomic_read(&priv->wmm.highest_queued_prio) < - priv->tos_to_tid_inv[tid_down]) - atomic_set(&priv->wmm.highest_queued_prio, - priv->tos_to_tid_inv[tid_down]); - - if (ra_list->tx_paused) - priv->wmm.pkts_paused[tid_down]++; - else - atomic_inc(&priv->wmm.tx_pkts_queued); - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* - * This function processes the get WMM status command response from firmware. - * - * The response may contain multiple TLVs - - * - AC Queue status TLVs - * - Current WMM Parameter IE TLV - * - Admission Control action frame TLVs - * - * This function parses the TLVs and then calls further specific functions - * to process any changes in the queue prioritize or state. - */ -int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, - const struct host_cmd_ds_command *resp) -{ - u8 *curr = (u8 *) &resp->params.get_wmm_status; - uint16_t resp_len = le16_to_cpu(resp->size), tlv_len; - int mask = IEEE80211_WMM_IE_AP_QOSINFO_PARAM_SET_CNT_MASK; - bool valid = true; - - struct mwifiex_ie_types_data *tlv_hdr; - struct mwifiex_ie_types_wmm_queue_status *tlv_wmm_qstatus; - struct ieee_types_wmm_parameter *wmm_param_ie = NULL; - struct mwifiex_wmm_ac_status *ac_status; - - mwifiex_dbg(priv->adapter, INFO, - "info: WMM: WMM_GET_STATUS cmdresp received: %d\n", - resp_len); - - while ((resp_len >= sizeof(tlv_hdr->header)) && valid) { - tlv_hdr = (struct mwifiex_ie_types_data *) curr; - tlv_len = le16_to_cpu(tlv_hdr->header.len); - - if (resp_len < tlv_len + sizeof(tlv_hdr->header)) - break; - - switch (le16_to_cpu(tlv_hdr->header.type)) { - case TLV_TYPE_WMMQSTATUS: - tlv_wmm_qstatus = - (struct mwifiex_ie_types_wmm_queue_status *) - tlv_hdr; - mwifiex_dbg(priv->adapter, CMD, - "info: CMD_RESP: WMM_GET_STATUS:\t" - "QSTATUS TLV: %d, %d, %d\n", - tlv_wmm_qstatus->queue_index, - tlv_wmm_qstatus->flow_required, - tlv_wmm_qstatus->disabled); - - ac_status = &priv->wmm.ac_status[tlv_wmm_qstatus-> - queue_index]; - ac_status->disabled = tlv_wmm_qstatus->disabled; - ac_status->flow_required = - tlv_wmm_qstatus->flow_required; - ac_status->flow_created = tlv_wmm_qstatus->flow_created; - break; - - case WLAN_EID_VENDOR_SPECIFIC: - /* - * Point the regular IEEE IE 2 bytes into the Marvell IE - * and setup the IEEE IE type and length byte fields - */ - - wmm_param_ie = - (struct ieee_types_wmm_parameter *) (curr + - 2); - wmm_param_ie->vend_hdr.len = (u8) tlv_len; - wmm_param_ie->vend_hdr.element_id = - WLAN_EID_VENDOR_SPECIFIC; - - mwifiex_dbg(priv->adapter, CMD, - "info: CMD_RESP: WMM_GET_STATUS:\t" - "WMM Parameter Set Count: %d\n", - wmm_param_ie->qos_info_bitmap & mask); - - memcpy((u8 *) &priv->curr_bss_params.bss_descriptor. - wmm_ie, wmm_param_ie, - wmm_param_ie->vend_hdr.len + 2); - - break; - - default: - valid = false; - break; - } - - curr += (tlv_len + sizeof(tlv_hdr->header)); - resp_len -= (tlv_len + sizeof(tlv_hdr->header)); - } - - mwifiex_wmm_setup_queue_priorities(priv, wmm_param_ie); - mwifiex_wmm_setup_ac_downgrade(priv); - - return 0; -} - -/* - * Callback handler from the command module to allow insertion of a WMM TLV. - * - * If the BSS we are associating to supports WMM, this function adds the - * required WMM Information IE to the association request command buffer in - * the form of a Marvell extended IEEE IE. - */ -u32 -mwifiex_wmm_process_association_req(struct mwifiex_private *priv, - u8 **assoc_buf, - struct ieee_types_wmm_parameter *wmm_ie, - struct ieee80211_ht_cap *ht_cap) -{ - struct mwifiex_ie_types_wmm_param_set *wmm_tlv; - u32 ret_len = 0; - - /* Null checks */ - if (!assoc_buf) - return 0; - if (!(*assoc_buf)) - return 0; - - if (!wmm_ie) - return 0; - - mwifiex_dbg(priv->adapter, INFO, - "info: WMM: process assoc req: bss->wmm_ie=%#x\n", - wmm_ie->vend_hdr.element_id); - - if ((priv->wmm_required || - (ht_cap && (priv->adapter->config_bands & BAND_GN || - priv->adapter->config_bands & BAND_AN))) && - wmm_ie->vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) { - wmm_tlv = (struct mwifiex_ie_types_wmm_param_set *) *assoc_buf; - wmm_tlv->header.type = cpu_to_le16((u16) wmm_info_ie[0]); - wmm_tlv->header.len = cpu_to_le16((u16) wmm_info_ie[1]); - memcpy(wmm_tlv->wmm_ie, &wmm_info_ie[2], - le16_to_cpu(wmm_tlv->header.len)); - if (wmm_ie->qos_info_bitmap & IEEE80211_WMM_IE_AP_QOSINFO_UAPSD) - memcpy((u8 *) (wmm_tlv->wmm_ie - + le16_to_cpu(wmm_tlv->header.len) - - sizeof(priv->wmm_qosinfo)), - &priv->wmm_qosinfo, sizeof(priv->wmm_qosinfo)); - - ret_len = sizeof(wmm_tlv->header) - + le16_to_cpu(wmm_tlv->header.len); - - *assoc_buf += ret_len; - } - - return ret_len; -} - -/* - * This function computes the time delay in the driver queues for a - * given packet. - * - * When the packet is received at the OS/Driver interface, the current - * time is set in the packet structure. The difference between the present - * time and that received time is computed in this function and limited - * based on pre-compiled limits in the driver. - */ -u8 -mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, - const struct sk_buff *skb) -{ - u32 queue_delay = ktime_to_ms(net_timedelta(skb->tstamp)); - u8 ret_val; - - /* - * Queue delay is passed as a uint8 in units of 2ms (ms shifted - * by 1). Min value (other than 0) is therefore 2ms, max is 510ms. - * - * Pass max value if queue_delay is beyond the uint8 range - */ - ret_val = (u8) (min(queue_delay, priv->wmm.drv_pkt_delay_max) >> 1); - - mwifiex_dbg(priv->adapter, DATA, "data: WMM: Pkt Delay: %d ms,\t" - "%d ms sent to FW\n", queue_delay, ret_val); - - return ret_val; -} - -/* - * This function retrieves the highest priority RA list table pointer. - */ -static struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_highest_priolist_ptr(struct mwifiex_adapter *adapter, - struct mwifiex_private **priv, int *tid) -{ - struct mwifiex_private *priv_tmp; - struct mwifiex_ra_list_tbl *ptr; - struct mwifiex_tid_tbl *tid_ptr; - atomic_t *hqp; - unsigned long flags_ra; - int i, j; - - /* check the BSS with highest priority first */ - for (j = adapter->priv_num - 1; j >= 0; --j) { - /* iterate over BSS with the equal priority */ - list_for_each_entry(adapter->bss_prio_tbl[j].bss_prio_cur, - &adapter->bss_prio_tbl[j].bss_prio_head, - list) { - - priv_tmp = adapter->bss_prio_tbl[j].bss_prio_cur->priv; - - if (!priv_tmp->port_open || - (atomic_read(&priv_tmp->wmm.tx_pkts_queued) == 0)) - continue; - - if (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv_tmp)) - continue; - - /* iterate over the WMM queues of the BSS */ - hqp = &priv_tmp->wmm.highest_queued_prio; - for (i = atomic_read(hqp); i >= LOW_PRIO_TID; --i) { - - spin_lock_irqsave(&priv_tmp->wmm. - ra_list_spinlock, flags_ra); - - tid_ptr = &(priv_tmp)->wmm. - tid_tbl_ptr[tos_to_tid[i]]; - - /* iterate over receiver addresses */ - list_for_each_entry(ptr, &tid_ptr->ra_list, - list) { - - if (!ptr->tx_paused && - !skb_queue_empty(&ptr->skb_head)) - /* holds both locks */ - goto found; - } - - spin_unlock_irqrestore(&priv_tmp->wmm. - ra_list_spinlock, - flags_ra); - } - } - - } - - return NULL; - -found: - /* holds ra_list_spinlock */ - if (atomic_read(hqp) > i) - atomic_set(hqp, i); - spin_unlock_irqrestore(&priv_tmp->wmm.ra_list_spinlock, flags_ra); - - *priv = priv_tmp; - *tid = tos_to_tid[i]; - - return ptr; -} - -/* This functions rotates ra and bss lists so packets are picked round robin. - * - * After a packet is successfully transmitted, rotate the ra list, so the ra - * next to the one transmitted, will come first in the list. This way we pick - * the ra' in a round robin fashion. Same applies to bss nodes of equal - * priority. - * - * Function also increments wmm.packets_out counter. - */ -void mwifiex_rotate_priolists(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra, - int tid) -{ - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_bss_prio_tbl *tbl = adapter->bss_prio_tbl; - struct mwifiex_tid_tbl *tid_ptr = &priv->wmm.tid_tbl_ptr[tid]; - unsigned long flags; - - spin_lock_irqsave(&tbl[priv->bss_priority].bss_prio_lock, flags); - /* - * dirty trick: we remove 'head' temporarily and reinsert it after - * curr bss node. imagine list to stay fixed while head is moved - */ - list_move(&tbl[priv->bss_priority].bss_prio_head, - &tbl[priv->bss_priority].bss_prio_cur->list); - spin_unlock_irqrestore(&tbl[priv->bss_priority].bss_prio_lock, flags); - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - if (mwifiex_is_ralist_valid(priv, ra, tid)) { - priv->wmm.packets_out[tid]++; - /* same as above */ - list_move(&tid_ptr->ra_list, &ra->list); - } - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); -} - -/* - * This function checks if 11n aggregation is possible. - */ -static int -mwifiex_is_11n_aggragation_possible(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, - int max_buf_size) -{ - int count = 0, total_size = 0; - struct sk_buff *skb, *tmp; - int max_amsdu_size; - - if (priv->bss_role == MWIFIEX_BSS_ROLE_UAP && priv->ap_11n_enabled && - ptr->is_11n_enabled) - max_amsdu_size = min_t(int, ptr->max_amsdu, max_buf_size); - else - max_amsdu_size = max_buf_size; - - skb_queue_walk_safe(&ptr->skb_head, skb, tmp) { - total_size += skb->len; - if (total_size >= max_amsdu_size) - break; - if (++count >= MIN_NUM_AMSDU) - return true; - } - - return false; -} - -/* - * This function sends a single packet to firmware for transmission. - */ -static void -mwifiex_send_single_packet(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_index, - unsigned long ra_list_flags) - __releases(&priv->wmm.ra_list_spinlock) -{ - struct sk_buff *skb, *skb_next; - struct mwifiex_tx_param tx_param; - struct mwifiex_adapter *adapter = priv->adapter; - struct mwifiex_txinfo *tx_info; - - if (skb_queue_empty(&ptr->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_dbg(adapter, DATA, "data: nothing to send\n"); - return; - } - - skb = skb_dequeue(&ptr->skb_head); - - tx_info = MWIFIEX_SKB_TXCB(skb); - mwifiex_dbg(adapter, DATA, - "data: dequeuing the packet %p %p\n", ptr, skb); - - ptr->total_pkt_count--; - - if (!skb_queue_empty(&ptr->skb_head)) - skb_next = skb_peek(&ptr->skb_head); - else - skb_next = NULL; - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - - tx_param.next_pkt_len = ((skb_next) ? skb_next->len + - sizeof(struct txpd) : 0); - - if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { - /* Queue the packet back at the head */ - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_write_data_complete(adapter, skb, 0, -1); - return; - } - - skb_queue_tail(&ptr->skb_head, skb); - - ptr->total_pkt_count++; - ptr->ba_pkt_count++; - tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - } else { - mwifiex_rotate_priolists(priv, ptr, ptr_index); - atomic_dec(&priv->wmm.tx_pkts_queued); - } -} - -/* - * This function checks if the first packet in the given RA list - * is already processed or not. - */ -static int -mwifiex_is_ptr_processed(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr) -{ - struct sk_buff *skb; - struct mwifiex_txinfo *tx_info; - - if (skb_queue_empty(&ptr->skb_head)) - return false; - - skb = skb_peek(&ptr->skb_head); - - tx_info = MWIFIEX_SKB_TXCB(skb); - if (tx_info->flags & MWIFIEX_BUF_FLAG_REQUEUED_PKT) - return true; - - return false; -} - -/* - * This function sends a single processed packet to firmware for - * transmission. - */ -static void -mwifiex_send_processed_packet(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ptr, int ptr_index, - unsigned long ra_list_flags) - __releases(&priv->wmm.ra_list_spinlock) -{ - struct mwifiex_tx_param tx_param; - struct mwifiex_adapter *adapter = priv->adapter; - int ret = -1; - struct sk_buff *skb, *skb_next; - struct mwifiex_txinfo *tx_info; - - if (skb_queue_empty(&ptr->skb_head)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - return; - } - - skb = skb_dequeue(&ptr->skb_head); - - if (adapter->data_sent || adapter->tx_lock_flag) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - skb_queue_tail(&adapter->tx_data_q, skb); - atomic_inc(&adapter->tx_queued); - return; - } - - if (!skb_queue_empty(&ptr->skb_head)) - skb_next = skb_peek(&ptr->skb_head); - else - skb_next = NULL; - - tx_info = MWIFIEX_SKB_TXCB(skb); - - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (adapter->iface_type == MWIFIEX_USB) { - ret = adapter->if_ops.host_to_card(adapter, priv->usb_port, - skb, NULL); - } else { - tx_param.next_pkt_len = - ((skb_next) ? skb_next->len + - sizeof(struct txpd) : 0); - ret = adapter->if_ops.host_to_card(adapter, MWIFIEX_TYPE_DATA, - skb, &tx_param); - } - - switch (ret) { - case -EBUSY: - mwifiex_dbg(adapter, ERROR, "data: -EBUSY is returned\n"); - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, ra_list_flags); - - if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - mwifiex_write_data_complete(adapter, skb, 0, -1); - return; - } - - skb_queue_tail(&ptr->skb_head, skb); - - tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, - ra_list_flags); - break; - case -1: - mwifiex_dbg(adapter, ERROR, "host_to_card failed: %#x\n", ret); - adapter->dbg.num_tx_host_to_card_failure++; - mwifiex_write_data_complete(adapter, skb, 0, ret); - break; - case -EINPROGRESS: - break; - case 0: - mwifiex_write_data_complete(adapter, skb, 0, ret); - default: - break; - } - if (ret != -EBUSY) { - mwifiex_rotate_priolists(priv, ptr, ptr_index); - atomic_dec(&priv->wmm.tx_pkts_queued); - } -} - -/* - * This function dequeues a packet from the highest priority list - * and transmits it. - */ -static int -mwifiex_dequeue_tx_packet(struct mwifiex_adapter *adapter) -{ - struct mwifiex_ra_list_tbl *ptr; - struct mwifiex_private *priv = NULL; - int ptr_index = 0; - u8 ra[ETH_ALEN]; - int tid_del = 0, tid = 0; - unsigned long flags; - - ptr = mwifiex_wmm_get_highest_priolist_ptr(adapter, &priv, &ptr_index); - if (!ptr) - return -1; - - tid = mwifiex_get_tid(ptr); - - mwifiex_dbg(adapter, DATA, "data: tid=%d\n", tid); - - spin_lock_irqsave(&priv->wmm.ra_list_spinlock, flags); - if (!mwifiex_is_ralist_valid(priv, ptr, ptr_index)) { - spin_unlock_irqrestore(&priv->wmm.ra_list_spinlock, flags); - return -1; - } - - if (mwifiex_is_ptr_processed(priv, ptr)) { - mwifiex_send_processed_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_send_processed_packet() */ - return 0; - } - - if (!ptr->is_11n_enabled || - ptr->ba_status || - priv->wps.session_enable) { - if (ptr->is_11n_enabled && - ptr->ba_status && - ptr->amsdu_in_ampdu && - mwifiex_is_amsdu_allowed(priv, tid) && - mwifiex_is_11n_aggragation_possible(priv, ptr, - adapter->tx_buf_size)) - mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - * mwifiex_11n_aggregate_pkt() - */ - else - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - * mwifiex_send_single_packet() - */ - } else { - if (mwifiex_is_ampdu_allowed(priv, ptr, tid) && - ptr->ba_pkt_count > ptr->ba_packet_thr) { - if (mwifiex_space_avail_for_new_ba_stream(adapter)) { - mwifiex_create_ba_tbl(priv, ptr->ra, tid, - BA_SETUP_INPROGRESS); - mwifiex_send_addba(priv, tid, ptr->ra); - } else if (mwifiex_find_stream_to_delete - (priv, tid, &tid_del, ra)) { - mwifiex_create_ba_tbl(priv, ptr->ra, tid, - BA_SETUP_INPROGRESS); - mwifiex_send_delba(priv, tid_del, ra, 1); - } - } - if (mwifiex_is_amsdu_allowed(priv, tid) && - mwifiex_is_11n_aggragation_possible(priv, ptr, - adapter->tx_buf_size)) - mwifiex_11n_aggregate_pkt(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_11n_aggregate_pkt() */ - else - mwifiex_send_single_packet(priv, ptr, ptr_index, flags); - /* ra_list_spinlock has been freed in - mwifiex_send_single_packet() */ - } - return 0; -} - -void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter) -{ - struct mwifiex_tx_param tx_param; - struct sk_buff *skb; - struct mwifiex_txinfo *tx_info; - struct mwifiex_private *priv; - int i; - - if (adapter->data_sent || adapter->tx_lock_flag) - return; - - for (i = 0; i < adapter->priv_num; ++i) { - priv = adapter->priv[i]; - - if (!priv) - continue; - - if (adapter->if_ops.is_port_ready && - !adapter->if_ops.is_port_ready(priv)) - continue; - - if (skb_queue_empty(&priv->bypass_txq)) - continue; - - skb = skb_dequeue(&priv->bypass_txq); - tx_info = MWIFIEX_SKB_TXCB(skb); - - /* no aggregation for bypass packets */ - tx_param.next_pkt_len = 0; - - if (mwifiex_process_tx(priv, skb, &tx_param) == -EBUSY) { - skb_queue_head(&priv->bypass_txq, skb); - tx_info->flags |= MWIFIEX_BUF_FLAG_REQUEUED_PKT; - } else { - atomic_dec(&adapter->bypass_tx_pending); - } - } -} - -/* - * This function transmits the highest priority packet awaiting in the - * WMM Queues. - */ -void -mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter) -{ - do { - if (mwifiex_dequeue_tx_packet(adapter)) - break; - if (adapter->iface_type != MWIFIEX_SDIO) { - if (adapter->data_sent || - adapter->tx_lock_flag) - break; - } else { - if (atomic_read(&adapter->tx_queued) >= - MWIFIEX_MAX_PKTS_TXQ) - break; - } - } while (!mwifiex_wmm_lists_empty(adapter)); -} diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h deleted file mode 100644 index 38f09762bd2f..000000000000 --- a/drivers/net/wireless/mwifiex/wmm.h +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Marvell Wireless LAN device driver: WMM - * - * Copyright (C) 2011-2014, Marvell International Ltd. - * - * This software file (the "File") is distributed by Marvell International - * Ltd. under the terms of the GNU General Public License Version 2, June 1991 - * (the "License"). You may use, redistribute and/or modify this File in - * accordance with the terms and conditions of the License, a copy of which - * is available by writing to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA or on the - * worldwide web at http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt. - * - * THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE - * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE - * ARE EXPRESSLY DISCLAIMED. The License provides additional details about - * this warranty disclaimer. - */ - -#ifndef _MWIFIEX_WMM_H_ -#define _MWIFIEX_WMM_H_ - -enum ieee_types_wmm_aciaifsn_bitmasks { - MWIFIEX_AIFSN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), - MWIFIEX_ACM = BIT(4), - MWIFIEX_ACI = (BIT(5) | BIT(6)), -}; - -enum ieee_types_wmm_ecw_bitmasks { - MWIFIEX_ECW_MIN = (BIT(0) | BIT(1) | BIT(2) | BIT(3)), - MWIFIEX_ECW_MAX = (BIT(4) | BIT(5) | BIT(6) | BIT(7)), -}; - -static const u16 mwifiex_1d_to_wmm_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; - -/* - * This table inverses the tos_to_tid operation to get a priority - * which is in sequential order, and can be compared. - * Use this to compare the priority of two different TIDs. - */ -static const u8 tos_to_tid_inv[] = { - 0x02, /* from tos_to_tid[2] = 0 */ - 0x00, /* from tos_to_tid[0] = 1 */ - 0x01, /* from tos_to_tid[1] = 2 */ - 0x03, - 0x04, - 0x05, - 0x06, - 0x07}; - -/* - * This function retrieves the TID of the given RA list. - */ -static inline int -mwifiex_get_tid(struct mwifiex_ra_list_tbl *ptr) -{ - struct sk_buff *skb; - - if (skb_queue_empty(&ptr->skb_head)) - return 0; - - skb = skb_peek(&ptr->skb_head); - - return skb->priority; -} - -/* - * This function gets the length of a list. - */ -static inline int -mwifiex_wmm_list_len(struct list_head *head) -{ - struct list_head *pos; - int count = 0; - - list_for_each(pos, head) - ++count; - - return count; -} - -/* - * This function checks if a RA list is empty or not. - */ -static inline u8 -mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead) -{ - struct mwifiex_ra_list_tbl *ra_list; - int is_list_empty; - - list_for_each_entry(ra_list, ra_list_hhead, list) { - is_list_empty = skb_queue_empty(&ra_list->skb_head); - if (!is_list_empty) - return false; - } - - return true; -} - -void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv, - struct sk_buff *skb); -void mwifiex_wmm_add_buf_bypass_txqueue(struct mwifiex_private *priv, - struct sk_buff *skb); -void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra); -void mwifiex_rotate_priolists(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra, int tid); - -int mwifiex_wmm_lists_empty(struct mwifiex_adapter *adapter); -int mwifiex_bypass_txlist_empty(struct mwifiex_adapter *adapter); -void mwifiex_wmm_process_tx(struct mwifiex_adapter *adapter); -void mwifiex_process_bypass_tx(struct mwifiex_adapter *adapter); -int mwifiex_is_ralist_valid(struct mwifiex_private *priv, - struct mwifiex_ra_list_tbl *ra_list, int tid); - -u8 mwifiex_wmm_compute_drv_pkt_delay(struct mwifiex_private *priv, - const struct sk_buff *skb); -void mwifiex_wmm_init(struct mwifiex_adapter *adapter); - -u32 mwifiex_wmm_process_association_req(struct mwifiex_private *priv, - u8 **assoc_buf, - struct ieee_types_wmm_parameter *wmmie, - struct ieee80211_ht_cap *htcap); - -void mwifiex_wmm_setup_queue_priorities(struct mwifiex_private *priv, - struct ieee_types_wmm_parameter *wmm_ie); -void mwifiex_wmm_setup_ac_downgrade(struct mwifiex_private *priv); -int mwifiex_ret_wmm_get_status(struct mwifiex_private *priv, - const struct host_cmd_ds_command *resp); -struct mwifiex_ra_list_tbl * -mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, - const u8 *ra_addr); -u8 mwifiex_wmm_downgrade_tid(struct mwifiex_private *priv, u32 tid); -void mwifiex_update_ralist_tx_pause(struct mwifiex_private *priv, u8 *mac, - u8 tx_pause); -void mwifiex_update_ralist_tx_pause_in_tdls_cs(struct mwifiex_private *priv, - u8 *mac, u8 tx_pause); - -struct mwifiex_ra_list_tbl *mwifiex_wmm_get_ralist_node(struct mwifiex_private - *priv, u8 tid, const u8 *ra_addr); -#endif /* !_MWIFIEX_WMM_H_ */ |