diff options
author | Bjørn Mork <bjorn@mork.no> | 2016-08-22 14:05:07 +0200 |
---|---|---|
committer | Bjørn Mork <bjorn@mork.no> | 2016-08-22 14:05:07 +0200 |
commit | 40fae1ddc3d847a5a2be28c0a67ea07ec77e16c7 (patch) | |
tree | 259a54d866037cd200a48d9089ceca21b5618b4a | |
parent | a602e201b4401fb722d5b3e53424f794d523290e (diff) | |
parent | d48847cc83954930fdcd98818bbf33e75707b8e1 (diff) |
Merge remote-tracking branch 'origin/master'10.3.0.18-20160804
33 files changed, 556 insertions, 393 deletions
diff --git a/Makefile.external b/Makefile.external deleted file mode 100644 index 11cbf8e..0000000 --- a/Makefile.external +++ /dev/null @@ -1,39 +0,0 @@ -obj-m += mwlwifi.o - -mwlwifi-objs += main.o -mwlwifi-objs += mac80211.o -mwlwifi-objs += fwdl.o -mwlwifi-objs += fwcmd.o -mwlwifi-objs += tx.o -mwlwifi-objs += rx.o -mwlwifi-objs += isr.o -mwlwifi-$(CONFIG_THERMAL) += thermal.o -mwlwifi-$(CONFIG_DEBUG_FS) += debugfs.o -ifeq (1, $(BUILD_MFG)) -mwlwifi-objs += mfg.o -endif - -AS = $(CROSS_COMPILE)as -LD = $(CROSS_COMPILE)ld -CC = $(CROSS_COMPILE)gcc - -EXTRA_CFLAGS+= -I${KDIR} -EXTRA_CFLAGS+= -O2 -funroll-loops -D__CHECK_ENDIAN__ - -ifeq (1, $(BUILD_MFG)) -EXTRA_CFLAGS+= -DSUPPORT_MFG -endif - -ifeq (1, $(BUILD_BG4CT_A0)) -EXTRA_CFLAGS+= -DBG4CT_A0_WORKAROUND -endif - -EXTRA_CFLAGS+= -I${PWD} - -all: - $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules - -clean: - rm -f *.o *.a *.s *.ko *.ko.cmd *.o.cmd *.mod.* .mwlwifi.* - rm -rf modules.order Module.symvers .tmp_versions - find . -name ".*.o.cmd" -exec rm -f {} \; diff --git a/README.md b/README.md new file mode 100644 index 0000000..5f8896f --- /dev/null +++ b/README.md @@ -0,0 +1,20 @@ +# mwlwifi +mac80211 driver for the Marvell 88W8864 802.11ac chip + +* How to build mwlwifi with OpenWrt: + +10.3.0.17-20160601 had been modified to be built with latest backports package "compat-wireless-2016-01-10" without patches. + +a. Modify package/kernel/mwlwifi/Makefile: + +PKG_VERSION:=10.3.0.17-20160601 +& +PKG_SOURCE_VERSION:=4bb95ba1aeccce506a95499b49b9b844ecfae8a1 + +b. Rename package/kernel/mwlwifi/patches to package/kernel/mwlwifi/patches.tmp + +c. make package/kernel/mwlwifi/clean + +d. make V=s (-jx) + +* For driver 10.3.0.17-20160603, [MAX-MPDU-7991] should be removed from vht_capab command of hostapd. diff --git a/bin/firmware/88W8864.bin b/bin/firmware/88W8864.bin Binary files differindex 21bd0c0..e6d12b9 100755 --- a/bin/firmware/88W8864.bin +++ b/bin/firmware/88W8864.bin diff --git a/bin/firmware/88W8897.bin b/bin/firmware/88W8897.bin Binary files differindex 021a9ee..a3b10c5 100755 --- a/bin/firmware/88W8897.bin +++ b/bin/firmware/88W8897.bin @@ -99,6 +99,11 @@ static ssize_t mwl_debugfs_info_read(struct file *file, char __user *ubuf, len += scnprintf(p + len, size - len, "firmware version: 0x%08x\n", priv->hw_data.fw_release_num); len += scnprintf(p + len, size - len, + "power table loaded from dts: %s\n", + priv->forbidden_setting ? "no" : "yes"); + len += scnprintf(p + len, size - len, "firmware region code: 0x%x\n", + priv->fw_region_code); + len += scnprintf(p + len, size - len, "mac address: %pM\n", priv->hw_data.mac_addr); len += scnprintf(p + len, size - len, "2g: %s\n", priv->disable_2g ? "disable" : "enable"); @@ -122,8 +127,6 @@ static ssize_t mwl_debugfs_info_read(struct file *file, char __user *ubuf, "macid used: %08x\n", priv->macids_used); len += scnprintf(p + len, size - len, "qe trigger number: %d\n", priv->qe_trigger_num); - len += scnprintf(p + len, size - len, - "mfg mode: %s\n", priv->mfg_mode ? "true" : "false"); len += scnprintf(p + len, size - len, "\n"); ret = simple_read_from_buffer(ubuf, count, ppos, p, len); @@ -165,11 +168,6 @@ static ssize_t mwl_debugfs_vif_read(struct file *file, char __user *ubuf, len += scnprintf(p + len, size - len, "mac address: %pM\n", mwl_vif->bssid); break; - case NL80211_IFTYPE_MESH_POINT: - len += scnprintf(p + len, size - len, "type: mesh\n"); - len += scnprintf(p + len, size - len, - "mac address: %pM\n", mwl_vif->bssid); - break; case NL80211_IFTYPE_STATION: len += scnprintf(p + len, size - len, "type: sta\n"); len += scnprintf(p + len, size - len, @@ -262,7 +260,8 @@ static ssize_t mwl_debugfs_sta_read(struct file *file, char __user *ubuf, } len += scnprintf(p + len, size - len, "rx_bw: %d, rx_nss: %d\n", sta->bandwidth, sta->rx_nss); - len += scnprintf(p + len, size - len, "tdls: %d, tdls_init: %d\n", + len += scnprintf(p + len, size - len, + "tdls: %d, tdls_init: %d\n", sta->tdls, sta->tdls_initiator); len += scnprintf(p + len, size - len, "wme: %d, mfp: %d\n", sta->wme, sta->mfp); @@ -334,6 +333,49 @@ static ssize_t mwl_debugfs_ampdu_read(struct file *file, char __user *ubuf, return ret; } +static ssize_t mwl_debugfs_device_pwrtbl_read(struct file *file, + char __user *ubuf, + size_t count, loff_t *ppos) +{ + struct mwl_priv *priv = (struct mwl_priv *)file->private_data; + unsigned long page = get_zeroed_page(GFP_KERNEL); + char *p = (char *)page; + int len = 0, size = PAGE_SIZE; + int i, j; + ssize_t ret; + + if (!p) + return -ENOMEM; + + len += scnprintf(p + len, size - len, "\n"); + len += scnprintf(p + len, size - len, + "power table loaded from dts: %s\n", + priv->forbidden_setting ? "no" : "yes"); + len += scnprintf(p + len, size - len, "firmware region code: 0x%x\n", + priv->fw_region_code); + len += scnprintf(p + len, size - len, "number of channel: %d\n", + priv->number_of_channels); + for (i = 0; i < priv->number_of_channels; i++) { + len += scnprintf(p + len, size - len, "%3d ", + priv->device_pwr_tbl[i].channel); + for (j = 0; j < SYSADPT_TX_POWER_LEVEL_TOTAL; j++) + len += scnprintf(p + len, size - len, "%3d ", + priv->device_pwr_tbl[i].tx_pwr[j]); + len += scnprintf(p + len, size - len, "%3d ", + priv->device_pwr_tbl[i].dfs_capable); + len += scnprintf(p + len, size - len, "%3d ", + priv->device_pwr_tbl[i].ax_ant); + len += scnprintf(p + len, size - len, "%3d\n", + priv->device_pwr_tbl[i].cdd); + } + len += scnprintf(p + len, size - len, "\n"); + + ret = simple_read_from_buffer(ubuf, count, ppos, p, len); + free_page(page); + + return ret; +} + static ssize_t mwl_debugfs_tx_desc_read(struct file *file, char __user *ubuf, size_t count, loff_t *ppos) @@ -389,9 +431,7 @@ static ssize_t mwl_debugfs_tx_desc_write(struct file *file, goto err; } - ret = sscanf(buf, "%d", &tx_desc_num); - - if (ret != 1) { + if (kstrtoint(buf, 0, &tx_desc_num)) { ret = -EINVAL; goto err; } @@ -438,11 +478,9 @@ static ssize_t mwl_debugfs_dfs_channel_read(struct file *file, channel->hw_value, channel->center_freq, channel->flags, channel->dfs_state); -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) len += scnprintf(p + len, size - len, "cac timer: %d ms\n", channel->dfs_cac_ms); -#endif } } len += scnprintf(p + len, size - len, "\n"); @@ -493,10 +531,8 @@ static ssize_t mwl_debugfs_dfs_channel_write(struct file *file, channel = &sband->channels[i]; if (channel->flags & IEEE80211_CHAN_RADAR) { channel->dfs_state = dfs_state; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) if (cac_time != -1) channel->dfs_cac_ms = cac_time * 1000; -#endif } } ret = count; @@ -758,6 +794,7 @@ MWLWIFI_DEBUGFS_FILE_READ_OPS(info); MWLWIFI_DEBUGFS_FILE_READ_OPS(vif); MWLWIFI_DEBUGFS_FILE_READ_OPS(sta); MWLWIFI_DEBUGFS_FILE_READ_OPS(ampdu); +MWLWIFI_DEBUGFS_FILE_READ_OPS(device_pwrtbl); MWLWIFI_DEBUGFS_FILE_OPS(tx_desc); MWLWIFI_DEBUGFS_FILE_OPS(dfs_channel); MWLWIFI_DEBUGFS_FILE_OPS(dfs_radar); @@ -779,6 +816,7 @@ void mwl_debugfs_init(struct ieee80211_hw *hw) MWLWIFI_DEBUGFS_ADD_FILE(vif); MWLWIFI_DEBUGFS_ADD_FILE(sta); MWLWIFI_DEBUGFS_ADD_FILE(ampdu); + MWLWIFI_DEBUGFS_ADD_FILE(device_pwrtbl); MWLWIFI_DEBUGFS_ADD_FILE(tx_desc); MWLWIFI_DEBUGFS_ADD_FILE(dfs_channel); MWLWIFI_DEBUGFS_ADD_FILE(dfs_radar); @@ -27,7 +27,7 @@ #include <net/mac80211.h> #define MWL_DRV_NAME KBUILD_MODNAME -#define MWL_DRV_VERSION "10.3.0.17-20160531-1" +#define MWL_DRV_VERSION "10.3.0.18-20160804" /* Map to 0x80000000 (Bus control) on BAR0 */ #define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */ @@ -147,6 +147,14 @@ struct mwl_chip_info { int antenna_rx; }; +struct mwl_device_pwr_tbl { + u8 channel; + u8 tx_pwr[SYSADPT_TX_POWER_LEVEL_TOTAL]; + u8 dfs_capable; + u8 ax_ant; + u8 cdd; +}; + struct mwl_tx_pwr_tbl { u8 channel; u8 setcap; @@ -278,6 +286,13 @@ struct mwl_ampdu_stream { struct mwl_priv { struct ieee80211_hw *hw; struct firmware *fw_ucode; + bool fw_device_pwrtbl; + bool forbidden_setting; + bool regulatory_set; + u32 fw_region_code; + char fw_alpha2[2]; + u8 number_of_channels; + struct mwl_device_pwr_tbl device_pwr_tbl[SYSADPT_MAX_NUM_CHANNELS]; int chip_type; struct device_node *dt_node; @@ -293,7 +308,6 @@ struct mwl_priv { u8 powinited; u16 max_tx_pow[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* max tx power (dBm) */ u16 target_powers[SYSADPT_TX_POWER_LEVEL_TOTAL]; /* target powers */ - u8 cal_tbl[200]; struct pci_dev *pdev; struct device *dev; @@ -363,7 +377,7 @@ struct mwl_priv { /* ampdu stream information */ /* for ampdu stream */ struct { - spinlock_t stream_lock; + spinlock_t stream_lock; /* for BA stream */ struct mwl_ampdu_stream ampdu[SYSADPT_TX_AMPDU_QUEUES]; } ____cacheline_aligned_in_smp; struct work_struct watchdog_ba_handle; @@ -382,8 +396,6 @@ struct mwl_priv { u32 quiet_period; int temperature; - bool mfg_mode; - #ifdef CONFIG_DEBUG_FS struct dentry *debugfs_phy; u32 reg_type; @@ -408,11 +420,6 @@ struct beacon_info { u8 *ie_ht_ptr; u8 *ie_vht_ptr; u8 *ie_country_ptr; -#ifdef CONFIG_MAC80211_MESH - u8 *ie_meshid_ptr; - u8 *ie_meshcfg_ptr; - u8 *ie_meshchsw_ptr; -#endif u8 ie_wmm_len; u8 ie_wsc_len; u8 ie_rsn_len; @@ -420,11 +427,6 @@ struct beacon_info { u8 ie_ht_len; u8 ie_vht_len; u8 ie_country_len; -#ifdef CONFIG_MAC80211_MESH - u8 ie_meshid_len; - u8 ie_meshcfg_len; - u8 ie_meshchsw_len; -#endif }; struct mwl_vif { @@ -473,7 +475,7 @@ struct mwl_sta { bool is_amsdu_allowed; /* for amsdu aggregation */ struct { - spinlock_t amsdu_lock; + spinlock_t amsdu_lock; /* for amsdu */ struct mwl_amsdu_ctrl amsdu_ctrl; } ____cacheline_aligned_in_smp; u16 iv16; @@ -48,16 +48,6 @@ static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv) static void mwl_fwcmd_send_cmd(struct mwl_priv *priv) { - if (priv->mfg_mode) { - struct cmd_header *cmd_hdr = - (struct cmd_header *)&priv->pcmd_buf[2]; - u16 len = le16_to_cpu(cmd_hdr->len); - - writel(priv->pphys_cmd_buf, priv->iobase1 + 0xcd0); - writel(0x00, priv->iobase1 + 0xcd4); - writel(0x00, priv->iobase1 + MACREG_REG_INT_CODE); - writel(len + 4, priv->iobase1 + 0xc40); - } writel(priv->pphys_cmd_buf, priv->iobase1 + MACREG_REG_GEN_PTR); writel(MACREG_H2ARIC_BIT_DOOR_BELL, priv->iobase1 + MACREG_REG_H2A_INTERRUPT_EVENTS); @@ -111,6 +101,8 @@ static char *mwl_fwcmd_get_cmd_string(unsigned short cmd) { HOSTCMD_CMD_FW_FLUSH_TIMER, "FwFlushTimer" }, { HOSTCMD_CMD_SET_CDD, "SetCDD" }, { HOSTCMD_CMD_GET_TEMP, "GetTemp" }, + { HOSTCMD_CMD_GET_FW_REGION_CODE, "GetFwRegionCode" }, + { HOSTCMD_CMD_GET_DEVICE_PWR_TBL, "GetDevicePwrTbl" }, { HOSTCMD_CMD_QUIET_MODE, "QuietMode" }, }; @@ -129,11 +121,8 @@ static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd) unsigned short int_code = 0; do { - if (priv->mfg_mode) - int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[2])); - else - int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0])); - mdelay(1); + int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0])); + usleep_range(1000, 2000); } while ((int_code != cmd) && (--curr_iteration)); if (curr_iteration == 0) { @@ -143,7 +132,7 @@ static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd) return -EIO; } - mdelay(3); + usleep_range(3000, 5000); return 0; } @@ -471,20 +460,6 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv, beacon_info->ie_ht_ptr += elen; } break; -#ifdef CONFIG_MAC80211_MESH - case WLAN_EID_MESH_CONFIG: - beacon_info->ie_meshcfg_len = (elen + 2); - beacon_info->ie_meshcfg_ptr = (pos - 2); - break; - case WLAN_EID_MESH_ID: - beacon_info->ie_meshid_len = (elen + 2); - beacon_info->ie_meshid_ptr = (pos - 2); - break; - case WLAN_EID_CHAN_SWITCH_PARAM: - beacon_info->ie_meshchsw_len = (elen + 2); - beacon_info->ie_meshchsw_ptr = (pos - 2); - break; -#endif case WLAN_EID_VHT_CAPABILITY: case WLAN_EID_VHT_OPERATION: case WLAN_EID_OPMODE_NOTIF: @@ -562,18 +537,6 @@ static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif) memcpy(pcmd->ie_list_vht, beacon->ie_vht_ptr, beacon->ie_vht_len); pcmd->ie_list_len_vht = cpu_to_le16(beacon->ie_vht_len); -#ifdef CONFIG_MAC80211_MESH - memcpy(pcmd->ie_list_proprietary, beacon->ie_meshid_ptr, - beacon->ie_meshid_len); - ie_list_len_proprietary = beacon->ie_meshid_len; - memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary, - beacon->ie_meshcfg_ptr, beacon->ie_meshcfg_len); - ie_list_len_proprietary += beacon->ie_meshcfg_len; - memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary, - beacon->ie_meshchsw_ptr, beacon->ie_meshchsw_len); - ie_list_len_proprietary += beacon->ie_meshchsw_len; -#endif - if (priv->chip_type == MWL8897) { memcpy(pcmd->ie_list_proprietary + ie_list_len_proprietary, beacon->ie_wmm_ptr, beacon->ie_wmm_len); @@ -873,9 +836,6 @@ int mwl_fwcmd_get_hw_specs(struct ieee80211_hw *hw) int retry; int i; - if (priv->mfg_mode) - return 0; - pcmd = (struct hostcmd_cmd_get_hw_spec *)&priv->pcmd_buf[0]; mutex_lock(&priv->fwcmd_mutex); @@ -929,9 +889,6 @@ int mwl_fwcmd_set_hw_specs(struct ieee80211_hw *hw) struct hostcmd_cmd_set_hw_spec *pcmd; int i; - if (priv->mfg_mode) - return 0; - pcmd = (struct hostcmd_cmd_set_hw_spec *)&priv->pcmd_buf[0]; mutex_lock(&priv->fwcmd_mutex); @@ -1009,9 +966,6 @@ int mwl_fwcmd_set_radio_preamble(struct ieee80211_hw *hw, bool short_preamble) struct mwl_priv *priv = hw->priv; int rc; - if (priv->mfg_mode) - return 0; - priv->radio_short_preamble = short_preamble; rc = mwl_fwcmd_802_11_radio_control(priv, true, true); @@ -1060,7 +1014,10 @@ int mwl_fwcmd_max_tx_power(struct ieee80211_hw *hw, u16 band = 0, width = 0, sub_ch = 0; u16 maxtxpow[SYSADPT_TX_POWER_LEVEL_TOTAL]; int i, tmp; - int rc; + int rc = 0; + + if (priv->forbidden_setting) + return rc; switch (fraction) { case 0: @@ -1146,7 +1103,10 @@ int mwl_fwcmd_tx_power(struct ieee80211_hw *hw, u16 txpow[SYSADPT_TX_POWER_LEVEL_TOTAL]; int index, found = 0; int i, tmp; - int rc; + int rc = 0; + + if (priv->forbidden_setting) + return rc; switch (fraction) { case 0: @@ -1272,9 +1232,6 @@ int mwl_fwcmd_rf_antenna(struct ieee80211_hw *hw, int dir, int antenna) struct mwl_priv *priv = hw->priv; struct hostcmd_cmd_802_11_rf_antenna *pcmd; - if (priv->mfg_mode) - return 0; - pcmd = (struct hostcmd_cmd_802_11_rf_antenna *)&priv->pcmd_buf[0]; mutex_lock(&priv->fwcmd_mutex); @@ -1404,6 +1361,11 @@ int mwl_fwcmd_set_rf_channel(struct ieee80211_hw *hw, return -EIO; } + if (pcmd->cmd_hdr.result != 0) { + mutex_unlock(&priv->fwcmd_mutex); + return -EINVAL; + } + mutex_unlock(&priv->fwcmd_mutex); return 0; @@ -1957,21 +1919,6 @@ int mwl_fwcmd_set_new_stn_add(struct ieee80211_hw *hw, pcmd->peer_info.vht_rx_channel_width = sta->bandwidth; } - /* Patch mesh interface for VHT based on chip type. Once if mac80211 - * supports VHT for mesh interface, following code should be removed. - */ - if (vif->type == NL80211_IFTYPE_MESH_POINT) { - pcmd->peer_info.vht_max_rx_mcs = cpu_to_le32(0x0000fffa); - pcmd->peer_info.vht_cap = cpu_to_le32(0x33801931); - pcmd->peer_info.vht_rx_channel_width = 2; - if (priv->chip_type == MWL8864) { - if (priv->antenna_rx == ANTENNA_RX_4_AUTO) { - pcmd->peer_info.vht_max_rx_mcs = - cpu_to_le32(0x0000ffea); - } - } - } - pcmd->is_qos_sta = sta->wme; pcmd->qos_info = ((sta->uapsd_queues << 4) | (sta->max_sp << 1)); @@ -2254,15 +2201,10 @@ int mwl_fwcmd_encryption_set_key(struct ieee80211_hw *hw, idx = key->keyidx; - if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) { + if (key->flags & IEEE80211_KEY_FLAG_PAIRWISE) action = ENCR_ACTION_TYPE_SET_KEY; - } else { + else action = ENCR_ACTION_TYPE_SET_GROUP_KEY; - if (vif->type == NL80211_IFTYPE_MESH_POINT && - !ether_addr_equal(mwl_vif->bssid, addr)) - pcmd->key_param.key_info |= - cpu_to_le32(ENCR_KEY_FLAG_RXGROUPKEY); - } switch (key->cipher) { case WLAN_CIPHER_SUITE_WEP40: @@ -2643,6 +2585,14 @@ int mwl_fwcmd_set_wsc_ie(struct ieee80211_hw *hw, u8 len, u8 *data) return -EIO; } + pcmd->ie_type = cpu_to_le16(WSC_IE_SET_PROBE_RESPONSE); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_WSC_IE)) { + mutex_unlock(&priv->fwcmd_mutex); + wiphy_err(hw->wiphy, "failed execution\n"); + return -EIO; + } + mutex_unlock(&priv->fwcmd_mutex); return 0; @@ -2749,6 +2699,83 @@ int mwl_fwcmd_get_temp(struct ieee80211_hw *hw, u32 *temp) return 0; } +int mwl_fwcmd_get_fw_region_code(struct ieee80211_hw *hw, + u32 *fw_region_code) +{ + struct mwl_priv *priv = hw->priv; + struct hostcmd_cmd_get_fw_region_code *pcmd; + int status; + + pcmd = (struct hostcmd_cmd_get_fw_region_code *)&priv->pcmd_buf[0]; + + mutex_lock(&priv->fwcmd_mutex); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_FW_REGION_CODE); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_FW_REGION_CODE)) { + mutex_unlock(&priv->fwcmd_mutex); + wiphy_err(hw->wiphy, "failed execution\n"); + return -EIO; + } + + if (pcmd->cmd_hdr.result != 0) { + mutex_unlock(&priv->fwcmd_mutex); + return -EINVAL; + } + + status = le32_to_cpu(pcmd->status); + + if (!status) + *fw_region_code = le32_to_cpu(pcmd->fw_region_code); + + mutex_unlock(&priv->fwcmd_mutex); + + return 0; +} + +int mwl_fwcmd_get_device_pwr_tbl(struct ieee80211_hw *hw, + struct mwl_device_pwr_tbl *device_ch_pwrtbl, + u8 *region_code, + u8 *number_of_channels, + u32 channel_index) +{ + struct mwl_priv *priv = hw->priv; + struct hostcmd_cmd_get_device_pwr_tbl *pcmd; + int status; + + pcmd = (struct hostcmd_cmd_get_device_pwr_tbl *)&priv->pcmd_buf[0]; + + mutex_lock(&priv->fwcmd_mutex); + + memset(pcmd, 0x00, sizeof(*pcmd)); + pcmd->cmd_hdr.cmd = cpu_to_le16(HOSTCMD_CMD_GET_DEVICE_PWR_TBL); + pcmd->cmd_hdr.len = cpu_to_le16(sizeof(*pcmd)); + pcmd->status = cpu_to_le16(HOSTCMD_CMD_GET_DEVICE_PWR_TBL); + pcmd->current_channel_index = cpu_to_le32(channel_index); + + if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_GET_DEVICE_PWR_TBL)) { + mutex_unlock(&priv->fwcmd_mutex); + wiphy_err(hw->wiphy, "failed execution\n"); + return -EIO; + } + + device_ch_pwrtbl->channel = pcmd->channel_pwr_tbl.channel; + memcpy(device_ch_pwrtbl->tx_pwr, pcmd->channel_pwr_tbl.tx_pwr, + SYSADPT_TX_POWER_LEVEL_TOTAL); + device_ch_pwrtbl->dfs_capable = pcmd->channel_pwr_tbl.dfs_capable; + device_ch_pwrtbl->ax_ant = pcmd->channel_pwr_tbl.ax_ant; + device_ch_pwrtbl->cdd = pcmd->channel_pwr_tbl.cdd; + *region_code = pcmd->region_code; + *number_of_channels = pcmd->number_of_channels; + status = le16_to_cpu(pcmd->status); + + mutex_unlock(&priv->fwcmd_mutex); + + return status; +} + int mwl_fwcmd_quiet_mode(struct ieee80211_hw *hw, bool enable, u32 period, u32 duration, u32 next_offset) { @@ -206,6 +206,15 @@ int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw); int mwl_fwcmd_get_temp(struct ieee80211_hw *hw, u32 *temp); +int mwl_fwcmd_get_fw_region_code(struct ieee80211_hw *hw, + u32 *fw_region_code); + +int mwl_fwcmd_get_device_pwr_tbl(struct ieee80211_hw *hw, + struct mwl_device_pwr_tbl *device_ch_pwrtbl, + u8 *region_code, + u8 *number_of_channels, + u32 channel_index); + int mwl_fwcmd_quiet_mode(struct ieee80211_hw *hw, bool enable, u32 period, u32 duration, u32 next_offset); @@ -22,9 +22,6 @@ #include "sysadpt.h" #include "dev.h" #include "fwcmd.h" -#ifdef SUPPORT_MFG -#include "mfg.h" -#endif #include "fwdl.h" #define FW_DOWNLOAD_BLOCK_SIZE 256 @@ -60,12 +57,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) u32 size_fw_downloaded = 0; u32 int_code = 0; u32 len = 0; -#ifdef SUPPORT_MFG - u32 fwreadysignature = (priv->mfg_mode && priv->chip_type == MWL8897) ? - MFG_FW_READY_SIGNATURE : HOSTCMD_SOFTAP_FWRDY_SIGNATURE; -#else u32 fwreadysignature = HOSTCMD_SOFTAP_FWRDY_SIGNATURE; -#endif fw = priv->fw_ucode; @@ -74,7 +66,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) /* FW before jumping to boot rom, it will enable PCIe transaction retry, * wait for boot code to stop it. */ - mdelay(FW_CHECK_MSECS); + usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000); writel(MACREG_A2HRIC_BIT_MASK, priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CLEAR_SEL); @@ -95,7 +87,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) /* make sure SCRATCH2 C40 is clear, in case we are too quick */ while (readl(priv->iobase1 + 0xc40) == 0) - ; + cond_resched(); while (size_fw_downloaded < fw->size) { len = readl(priv->iobase1 + 0xc40); @@ -125,6 +117,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) int_code = readl(priv->iobase1 + 0xc1c); if (int_code != 0) break; + cond_resched(); curr_iteration--; } while (curr_iteration); @@ -133,6 +126,7 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) if ((int_code & MACREG_H2ARIC_BIT_DOOR_BELL) != MACREG_H2ARIC_BIT_DOOR_BELL) break; + cond_resched(); curr_iteration--; } while (curr_iteration); @@ -162,19 +156,12 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw) *((u32 *)&priv->pcmd_buf[1]) = 0; mwl_fwdl_trig_pcicmd(priv); curr_iteration = FW_MAX_NUM_CHECKS; - if (priv->mfg_mode && priv->chip_type == MWL8897) - writel(fwreadysignature, priv->iobase1 + 0xcf0); do { curr_iteration--; - if (priv->mfg_mode && priv->chip_type == MWL8897) { - mdelay(FW_CHECK_MSECS); - int_code = readl(priv->iobase1 + 0xc44); - } else { - writel(HOSTCMD_SOFTAP_MODE, - priv->iobase1 + MACREG_REG_GEN_PTR); - mdelay(FW_CHECK_MSECS); - int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE); - } + writel(HOSTCMD_SOFTAP_MODE, + priv->iobase1 + MACREG_REG_GEN_PTR); + usleep_range(FW_CHECK_MSECS * 1000, FW_CHECK_MSECS * 2000); + int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE); if (!(curr_iteration % 0xff) && (int_code != 0)) wiphy_err(hw->wiphy, "%x;", int_code); } while ((curr_iteration) && @@ -60,6 +60,8 @@ #define HOSTCMD_CMD_FW_FLUSH_TIMER 0x1148 #define HOSTCMD_CMD_SET_CDD 0x1150 #define HOSTCMD_CMD_GET_TEMP 0x1159 +#define HOSTCMD_CMD_GET_FW_REGION_CODE 0x116A +#define HOSTCMD_CMD_GET_DEVICE_PWR_TBL 0x116B #define HOSTCMD_CMD_QUIET_MODE 0x1201 /* Define general result code for each command */ @@ -129,6 +131,8 @@ /* Misc */ #define WSC_IE_MAX_LENGTH 251 +#define WSC_IE_SET_BEACON 0 +#define WSC_IE_SET_PROBE_RESPONSE 1 enum { WL_DISABLE = 0, @@ -868,6 +872,34 @@ struct hostcmd_cmd_get_temp { __le32 raw_data; } __packed; +/* HOSTCMD_CMD_GET_FW_REGION_CODE */ +struct hostcmd_cmd_get_fw_region_code { + struct hostcmd_header cmd_hdr; + __le32 status; /* 0 = Found, 1 = Error */ + __le32 fw_region_code; +} __packed; + +/* HOSTCMD_CMD_GET_DEVICE_PWR_TBL */ +#define HAL_TRPC_ID_MAX 16 + +struct channel_power_tbl { + u8 channel; + u8 tx_pwr[HAL_TRPC_ID_MAX]; + u8 dfs_capable; + u8 ax_ant; + u8 cdd; +} __packed; + +struct hostcmd_cmd_get_device_pwr_tbl { + struct hostcmd_header cmd_hdr; + __le16 status; /* 0 = Found, 1 = Error */ + u8 region_code; + u8 number_of_channels; + __le32 current_channel_index; + /* Only for 1 channel, so, 1 channel at a time */ + struct channel_power_tbl channel_pwr_tbl; +} __packed; + /* HOSTCMD_CMD_QUIET_MODE */ struct hostcmd_cmd_quiet_mode { struct hostcmd_header cmd_hdr; @@ -21,24 +21,15 @@ #include "isr.h" #define INVALID_WATCHDOG 0xAA -#ifdef BG4CT_A0_WORKAROUND -#define MAX_ISR_ITERATION 2 -#endif irqreturn_t mwl_isr(int irq, void *dev_id) { struct ieee80211_hw *hw = dev_id; struct mwl_priv *priv = hw->priv; void __iomem *int_status_mask; -#ifdef BG4CT_A0_WORKAROUND - unsigned int currIteration = 0; -#endif u32 int_status; u32 status; -#ifdef BG4CT_A0_WORKAROUND - do { -#endif int_status_mask = priv->iobase1 + MACREG_REG_A2H_INTERRUPT_STATUS_MASK; int_status = readl(priv->iobase1 + MACREG_REG_A2H_INTERRUPT_CAUSE); @@ -98,11 +89,7 @@ irqreturn_t mwl_isr(int irq, void *dev_id) if (int_status & MACREG_A2HRIC_BA_WATCHDOG) ieee80211_queue_work(hw, &priv->watchdog_ba_handle); - } -#ifdef BG4CT_A0_WORKAROUND - } while (currIteration++ < MAX_ISR_ITERATION); -#endif return IRQ_HANDLED; } @@ -149,7 +149,6 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: macids_supported = priv->ap_macids_supported; break; case NL80211_IFTYPE_STATION: @@ -183,10 +182,6 @@ static int mwl_mac80211_add_interface(struct ieee80211_hw *hw, ether_addr_copy(mwl_vif->bssid, vif->addr); mwl_fwcmd_set_new_stn_add_self(hw, vif); break; - case NL80211_IFTYPE_MESH_POINT: - ether_addr_copy(mwl_vif->bssid, vif->addr); - mwl_fwcmd_set_new_stn_add_self(hw, vif); - break; case NL80211_IFTYPE_STATION: ether_addr_copy(mwl_vif->sta_mac, vif->addr); mwl_fwcmd_bss_start(hw, vif, true); @@ -228,7 +223,6 @@ static void mwl_mac80211_remove_interface(struct ieee80211_hw *hw, switch (vif->type) { case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: mwl_fwcmd_set_new_stn_del(hw, vif, vif->addr); break; case NL80211_IFTYPE_STATION: @@ -370,7 +364,6 @@ static void mwl_mac80211_bss_info_changed(struct ieee80211_hw *hw, { switch (vif->type) { case NL80211_IFTYPE_AP: - case NL80211_IFTYPE_MESH_POINT: mwl_mac80211_bss_info_changed_ap(hw, vif, info, changed); break; case NL80211_IFTYPE_STATION: @@ -473,24 +466,6 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, memset(sta_info, 0, sizeof(*sta_info)); - if (vif->type == NL80211_IFTYPE_MESH_POINT) { - sta_info->is_mesh_node = true; - /* Patch mesh interface for HT based on chip type. When authsae - * or wpa_supplicant is used for mesh security, HT capbility - * won't be set. This would be removed if problem is fixed. - */ - sta->ht_cap.ht_supported = true; - sta->ht_cap.cap = 0x6f; - sta->ht_cap.mcs.rx_mask[0] = 0xff; - sta->ht_cap.mcs.rx_mask[1] = 0xff; - sta->ht_cap.ampdu_factor = 0x3; - sta->ht_cap.ampdu_density = 0x5; - if (priv->chip_type == MWL8864) { - if (priv->antenna_rx == ANTENNA_RX_4_AUTO) - sta->ht_cap.mcs.rx_mask[2] = 0xff; - } - } - if (sta->ht_cap.ht_supported) { sta_info->is_ampdu_allowed = true; sta_info->is_amsdu_allowed = false; @@ -498,6 +473,8 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw, sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_8K; else sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_4K; + if ((sta->tdls) && (!sta->wme)) + sta->wme = true; } sta_info->iv16 = 1; sta_info->iv32 = 0; @@ -610,6 +587,10 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, int rc = 0; struct mwl_priv *priv = hw->priv; struct mwl_ampdu_stream *stream; + enum ieee80211_ampdu_mlme_action action = params->action; + struct ieee80211_sta *sta = params->sta; + u16 tid = params->tid; + u8 buf_size = params->buf_size; u8 *addr = sta->addr, idx; struct mwl_sta *sta_info; @@ -649,7 +630,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, break; } stream->state = AMPDU_STREAM_IN_PROGRESS; - *ssn = 0; + params->ssn = 0; ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid); break; case IEEE80211_AMPDU_TX_STOP_CONT: @@ -662,6 +643,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, spin_unlock_bh(&priv->stream_lock); mwl_fwcmd_destroy_ba(hw, idx); spin_lock_bh(&priv->stream_lock); + sta_info->is_amsdu_allowed = false; } mwl_fwcmd_remove_stream(hw, stream); @@ -684,6 +666,7 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, if (!rc) { stream->state = AMPDU_STREAM_ACTIVE; sta_info->check_ba_failed[tid] = 0; + sta_info->is_amsdu_allowed = params->amsdu; } else { idx = stream->idx; spin_unlock_bh(&priv->stream_lock); @@ -708,7 +691,6 @@ static int mwl_mac80211_ampdu_action(struct ieee80211_hw *hw, return rc; } -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) static int mwl_mac80211_chnl_switch(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_channel_switch *ch_switch) @@ -720,7 +702,6 @@ static int mwl_mac80211_chnl_switch(struct ieee80211_hw *hw, return rc; } -#endif const struct ieee80211_ops mwl_mac80211_ops = { .tx = mwl_mac80211_tx, @@ -739,7 +720,5 @@ const struct ieee80211_ops mwl_mac80211_ops = { .get_stats = mwl_mac80211_get_stats, .get_survey = mwl_mac80211_get_survey, .ampdu_action = mwl_mac80211_ampdu_action, -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0) .pre_channel_switch = mwl_mac80211_chnl_switch, -#endif }; @@ -31,9 +31,6 @@ #ifdef CONFIG_DEBUG_FS #include "debugfs.h" #endif -#ifdef SUPPORT_MFG -#include "mfg.h" -#endif #define MWL_DESC "Marvell 802.11ac Wireless Network Driver" #define MWL_DEV_NAME "Marvell 802.11ac Adapter" @@ -135,9 +132,6 @@ static const struct ieee80211_rate mwl_rates_50[] = { static const struct ieee80211_iface_limit ap_if_limits[] = { { .max = SYSADPT_NUM_OF_AP, .types = BIT(NL80211_IFTYPE_AP) }, -#ifdef CONFIG_MAC80211_MESH - { .max = 1, .types = BIT(NL80211_IFTYPE_MESH_POINT) }, -#endif { .max = 1, .types = BIT(NL80211_IFTYPE_STATION) }, }; @@ -152,6 +146,23 @@ static const struct ieee80211_iface_combination ap_if_comb = { BIT(NL80211_CHAN_WIDTH_80), }; +struct region_code_mapping { + const char *alpha2; + u32 region_code; +}; + +static const struct region_code_mapping regmap[] = { + {"US", 0x10}, /* US FCC */ + {"CA", 0x20}, /* Canada */ + {"EU", 0x30}, /* ETSI */ + {"ES", 0x31}, /* Spain */ + {"FR", 0x32}, /* France */ + {"JP", 0x40}, /* Japan */ + {"TW", 0x80}, /* Taiwan */ + {"AU", 0x81}, /* Australia */ + {"CN", 0x90}, /* China (Asia) */ +}; + static int mwl_alloc_pci_resource(struct mwl_priv *priv) { struct pci_dev *pdev = priv->pdev; @@ -211,32 +222,21 @@ static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name) { int rc = 0; -#ifdef SUPPORT_MFG - if (priv->mfg_mode) - rc = mwl_mfg_request_firmware(priv); - else -#endif - rc = request_firmware((const struct firmware **)&priv->fw_ucode, - fw_name, priv->dev); + rc = request_firmware((const struct firmware **)&priv->fw_ucode, + fw_name, priv->dev); if (rc) { - if (priv->mfg_mode) - wiphy_err(priv->hw->wiphy, "cannot find firmware\n"); - else - wiphy_err(priv->hw->wiphy, - "%s: cannot find firmware image <%s>\n", + wiphy_err(priv->hw->wiphy, + "%s: cannot find firmware image <%s>\n", MWL_DRV_NAME, fw_name); goto err_load_fw; } rc = mwl_fwdl_download_firmware(priv->hw); if (rc) { - if (priv->mfg_mode) - wiphy_err(priv->hw->wiphy, "download firmware fail\n"); - else - wiphy_err(priv->hw->wiphy, - "%s: cannot download firmware image <%s>\n", - MWL_DRV_NAME, fw_name); + wiphy_err(priv->hw->wiphy, + "%s: cannot download firmware image <%s>\n", + MWL_DRV_NAME, fw_name); goto err_download_fw; } @@ -244,12 +244,7 @@ static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name) err_download_fw: -#ifdef SUPPORT_MFG - if (priv->mfg_mode) - mwl_mfg_release_firmware(priv); - else -#endif - release_firmware(priv->fw_ucode); + release_firmware(priv->fw_ucode); err_load_fw: @@ -275,6 +270,17 @@ static void mwl_reg_notifier(struct wiphy *wiphy, hw = (struct ieee80211_hw *)wiphy_priv(wiphy); priv = hw->priv; + if (priv->forbidden_setting) { + if (!priv->regulatory_set) { + regulatory_hint(wiphy, priv->fw_alpha2); + priv->regulatory_set = true; + } else { + if (memcmp(priv->fw_alpha2, request->alpha2, 2)) + regulatory_hint(wiphy, priv->fw_alpha2); + } + return; + } + priv->dfs_region = request->dfs_region; #ifdef CONFIG_OF @@ -424,6 +430,7 @@ static void mwl_set_ht_caps(struct mwl_priv *priv, band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; ieee80211_hw_set(hw, AMPDU_AGGREGATION); + ieee80211_hw_set(hw, SUPPORTS_AMSDU_IN_AMPDU); band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_4; @@ -441,7 +448,7 @@ static void mwl_set_vht_caps(struct mwl_priv *priv, { band->vht_cap.vht_supported = 1; - band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_7991; + band->vht_cap.cap |= IEEE80211_VHT_CAP_MAX_MPDU_LENGTH_3895; band->vht_cap.cap |= IEEE80211_VHT_CAP_RXLDPC; band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80; band->vht_cap.cap |= IEEE80211_VHT_CAP_RXSTBC_1; @@ -513,6 +520,37 @@ static void mwl_set_caps(struct mwl_priv *priv) } } +static void mwl_regd_init(struct mwl_priv *priv) +{ + u8 region_code; + int i; + + /* hook regulatory domain change notification */ + priv->hw->wiphy->reg_notifier = mwl_reg_notifier; + + if (mwl_fwcmd_get_device_pwr_tbl(priv->hw, + &priv->device_pwr_tbl[0], + ®ion_code, + &priv->number_of_channels, + 0)) + return; + + priv->forbidden_setting = true; + + for (i = 0; i < priv->number_of_channels; i++) + mwl_fwcmd_get_device_pwr_tbl(priv->hw, + &priv->device_pwr_tbl[i], + ®ion_code, + &priv->number_of_channels, + i); + + for (i = 0; i < ARRAY_SIZE(regmap); i++) + if (regmap[i].region_code == priv->fw_region_code) { + memcpy(priv->fw_alpha2, regmap[i].alpha2, 2); + break; + } +} + static void timer_routine(unsigned long data) { struct mwl_priv *priv = (struct mwl_priv *)data; @@ -573,6 +611,8 @@ static int mwl_wl_init(struct mwl_priv *priv) hw->wiphy->flags |= WIPHY_FLAG_IBSS_RSN; hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH; + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; + hw->vif_data_size = sizeof(struct mwl_vif); hw->sta_data_size = sizeof(struct mwl_sta); @@ -674,6 +714,13 @@ static int mwl_wl_init(struct mwl_priv *priv) wiphy_info(hw->wiphy, "firmware version: 0x%x\n", priv->hw_data.fw_release_num); + if (!mwl_fwcmd_get_fw_region_code(hw, &priv->fw_region_code)) { + priv->fw_device_pwrtbl = true; + mwl_regd_init(priv); + wiphy_info(hw->wiphy, + "firmware region code: %x\n", priv->fw_region_code); + } + mwl_fwcmd_radio_disable(hw); mwl_fwcmd_rf_antenna(hw, WL_ANTENNATYPE_TX, priv->antenna_tx); @@ -682,9 +729,6 @@ static int mwl_wl_init(struct mwl_priv *priv) hw->wiphy->interface_modes = 0; hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_AP); -#ifdef CONFIG_MAC80211_MESH - hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT); -#endif hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_STATION); hw->wiphy->iface_combinations = &ap_if_comb; hw->wiphy->n_iface_combinations = 1; @@ -796,9 +840,6 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) goto err_pci_disable_device; } - /* hook regulatory domain change notification */ - hw->wiphy->reg_notifier = mwl_reg_notifier; - pci_set_drvdata(pdev, hw); priv = hw->priv; @@ -806,6 +847,9 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) priv->pdev = pdev; priv->dev = &pdev->dev; priv->chip_type = id->driver_data; + priv->fw_device_pwrtbl = false; + priv->forbidden_setting = false; + priv->regulatory_set = false; priv->disable_2g = false; priv->disable_5g = false; priv->antenna_tx = mwl_chip_tbl[priv->chip_type].antenna_tx; @@ -819,11 +863,6 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) fw_name = mwl_chip_tbl[priv->chip_type].fw_image; -#ifdef SUPPORT_MFG - if (mfg_mode) - mwl_mfg_handler_init(priv); -#endif - rc = mwl_init_firmware(priv, fw_name); if (rc) { @@ -833,12 +872,7 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id) } /* firmware is loaded to H/W, it can be released now */ -#ifdef SUPPORT_MFG - if (priv->mfg_mode) - mwl_mfg_release_firmware(priv); - else -#endif - release_firmware(priv->fw_ucode); + release_firmware(priv->fw_ucode); mwl_process_of_dts(priv); @@ -280,24 +280,6 @@ static inline void mwl_rx_prepare_status(struct mwl_rx_desc *pdesc, } } -static inline void mwl_rx_enable_sta_amsdu(struct mwl_priv *priv, - u8 *sta_addr) -{ - struct mwl_sta *sta_info; - struct ieee80211_sta *sta; - - spin_lock_bh(&priv->sta_lock); - list_for_each_entry(sta_info, &priv->sta_list, list) { - sta = container_of((char *)sta_info, struct ieee80211_sta, - drv_priv[0]); - if (ether_addr_equal(sta->addr, sta_addr)) { - sta_info->is_amsdu_allowed = true; - break; - } - } - spin_unlock_bh(&priv->sta_lock); -} - static inline struct mwl_vif *mwl_rx_find_vif_bss(struct mwl_priv *priv, u8 *bssid) { @@ -336,78 +318,6 @@ static inline void mwl_rx_remove_dma_header(struct sk_buff *skb, __le16 qos) skb_pull(skb, sizeof(*tr) - hdrlen); } -#ifdef CONFIG_MAC80211_MESH -static inline bool mwl_rx_process_mesh_amsdu(struct mwl_priv *priv, - struct sk_buff *skb, - struct ieee80211_rx_status *status) -{ - struct ieee80211_hdr *wh; - struct mwl_sta *sta_info; - struct ieee80211_sta *sta; - u8 *qc; - int wh_len; - int len; - u8 pad; - u8 *data; - u16 frame_len; - struct sk_buff *newskb; - - wh = (struct ieee80211_hdr *)skb->data; - - spin_lock_bh(&priv->sta_lock); - list_for_each_entry(sta_info, &priv->sta_list, list) { - sta = container_of((char *)sta_info, struct ieee80211_sta, - drv_priv[0]); - if (ether_addr_equal(sta->addr, wh->addr2)) { - if (!sta_info->is_mesh_node) { - spin_unlock_bh(&priv->sta_lock); - return false; - } - } - } - spin_unlock_bh(&priv->sta_lock); - - qc = ieee80211_get_qos_ctl(wh); - *qc &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT; - - wh_len = ieee80211_hdrlen(wh->frame_control); - len = wh_len; - data = skb->data; - - while (len < skb->len) { - frame_len = *(u8 *)(data + len + ETH_HLEN - 1) | - (*(u8 *)(data + len + ETH_HLEN - 2) << 8); - - if ((len + ETH_HLEN + frame_len) > skb->len) - break; - - newskb = dev_alloc_skb(wh_len + frame_len); - if (!newskb) - break; - - ether_addr_copy(wh->addr3, data + len); - ether_addr_copy(wh->addr4, data + len + ETH_ALEN); - memcpy(newskb->data, wh, wh_len); - memcpy(newskb->data + wh_len, data + len + ETH_HLEN, frame_len); - skb_put(newskb, wh_len + frame_len); - - pad = ((ETH_HLEN + frame_len) % 4) ? - (4 - (ETH_HLEN + frame_len) % 4) : 0; - len += (ETH_HLEN + frame_len + pad); - if (len < skb->len) - status->flag |= RX_FLAG_AMSDU_MORE; - else - status->flag &= ~RX_FLAG_AMSDU_MORE; - memcpy(IEEE80211_SKB_RXCB(newskb), status, sizeof(*status)); - ieee80211_rx(priv->hw, newskb); - } - - dev_kfree_skb_any(skb); - - return true; -} -#endif - static int mwl_rx_refill(struct mwl_priv *priv, struct mwl_rx_hndl *rx_hndl) { struct mwl_desc_data *desc; @@ -584,34 +494,17 @@ void mwl_rx_recv(unsigned long data) wh = (struct ieee80211_hdr *)prx_skb->data; - if (ieee80211_is_mgmt(wh->frame_control)) { - struct ieee80211_mgmt *mgmt; - __le16 capab; - - mgmt = (struct ieee80211_mgmt *)prx_skb->data; - - if (unlikely(ieee80211_is_action(wh->frame_control) && - mgmt->u.action.category == - WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_resp.action_code == - WLAN_ACTION_ADDBA_RESP)) { - capab = mgmt->u.action.u.addba_resp.capab; - if (le16_to_cpu(capab) & 1) - mwl_rx_enable_sta_amsdu(priv, mgmt->sa); - } - } - -#ifdef CONFIG_MAC80211_MESH - if (ieee80211_is_data_qos(wh->frame_control) && - ieee80211_has_a4(wh->frame_control)) { + if (ieee80211_is_data_qos(wh->frame_control)) { + const u8 eapol[] = {0x88, 0x8e}; u8 *qc = ieee80211_get_qos_ctl(wh); + u8 *data; + + data = prx_skb->data + + ieee80211_hdrlen(wh->frame_control) + 6; - if (*qc & IEEE80211_QOS_CTL_A_MSDU_PRESENT) - if (mwl_rx_process_mesh_amsdu(priv, prx_skb, - &status)) - goto out; + if (!memcmp(data, eapol, sizeof(eapol))) + *qc |= 7; } -#endif memcpy(IEEE80211_SKB_RXCB(prx_skb), &status, sizeof(status)); ieee80211_rx(hw, prx_skb); diff --git a/test/AP+STA.zip b/test/AP+STA.zip Binary files differdeleted file mode 100755 index 8223745..0000000 --- a/test/AP+STA.zip +++ /dev/null diff --git a/test/AP+STA/README.txt b/test/AP+STA/README.txt new file mode 100644 index 0000000..6981b94 --- /dev/null +++ b/test/AP+STA/README.txt @@ -0,0 +1,36 @@ +<<How to set up AP+STA>> + +1. Bring up driver: + + a. iw reg set US + --> set regulatory domain. + b. insmod mwlwifi.ko + --> After module is inserted, physical interfaces phy0 and phy1 and network + device wlan0 and wlan1 will be created. You can issue "iw dev" to check them. + +2. Use interface wlan0/wlan1 as client mode to connect to remote AP: + + wpa_supplicant -B -D nl80211 -i wlan0 -c wpa_supplicant.conf + wpa_supplicant -B -D nl80211 -i wlan1 -c wpa_supplicant.conf + +3. Create local AP: + + a. Create anther interface on phy0/phy1: + + iw phy0 interface add wlan0-1 type managed + iw phy1 interface add wlan1-1 type managed + + b. Use iw dev to check channel setting for client mode and modify related channel + setting of hostapd.conf to be complied with currecnt channel setting. + + c. Check MAC address of client interface and add "bssid=02:XX:XX:XX:XX:XX" to hostapd.conf. + + d. Create local AP: + + hostapd -B ./hostapd.conf + --> Channel setting of hostapd.conf should be complied with current channel setting. + Please make sure interface of hostapd.conf is complied with the interface you just created. + +4. Bridge local AP and STA: + + You need to use relayd to bridge them. Same as LAN and STA. diff --git a/test/AP+STA/hostapd.conf.1.open b/test/AP+STA/hostapd.conf.1.open new file mode 100644 index 0000000..7add81b --- /dev/null +++ b/test/AP+STA/hostapd.conf.1.open @@ -0,0 +1,14 @@ +interface=wlan0 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=g +channel=1 +auth_algs=1 +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] +ieee80211d=1 +country_code=US + diff --git a/test/AP+STA/hostapd.conf.1.wpa2pskaes b/test/AP+STA/hostapd.conf.1.wpa2pskaes new file mode 100644 index 0000000..8acb88a --- /dev/null +++ b/test/AP+STA/hostapd.conf.1.wpa2pskaes @@ -0,0 +1,18 @@ +interface=wlan0 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=g +channel=1 +auth_algs=1 +wpa=2 +wpa_passphrase=12345678 +wpa_key_mgmt=WPA-PSK +wpa_pairwise=CCMP +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] +ieee80211d=1 +country_code=US + diff --git a/test/AP+STA/hostapd.conf.36.open b/test/AP+STA/hostapd.conf.36.open new file mode 100644 index 0000000..6e5e776 --- /dev/null +++ b/test/AP+STA/hostapd.conf.36.open @@ -0,0 +1,17 @@ +interface=wlan1 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=a +channel=36 +auth_algs=1 +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] +ieee80211ac=1 +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +ieee80211d=1 +country_code=US +ieee80211h=1 + diff --git a/test/AP+STA/hostapd.conf.36.open.40mhz b/test/AP+STA/hostapd.conf.36.open.40mhz new file mode 100644 index 0000000..a931774 --- /dev/null +++ b/test/AP+STA/hostapd.conf.36.open.40mhz @@ -0,0 +1,17 @@ +interface=wlan1 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=a +channel=36 +auth_algs=1 +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] +ieee80211ac=1 +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +ieee80211d=1 +country_code=US +ieee80211h=1 + diff --git a/test/AP+STA/hostapd.conf.36.open.80mhz b/test/AP+STA/hostapd.conf.36.open.80mhz new file mode 100644 index 0000000..ee7ab7f --- /dev/null +++ b/test/AP+STA/hostapd.conf.36.open.80mhz @@ -0,0 +1,19 @@ +interface=wlan1 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=a +channel=36 +auth_algs=1 +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] +ieee80211ac=1 +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_oper_chwidth=1 +vht_oper_centr_freq_seg0_idx=42 +ieee80211d=1 +country_code=US +ieee80211h=1 + diff --git a/test/AP+STA/hostapd.conf.36.wpa2pskaes b/test/AP+STA/hostapd.conf.36.wpa2pskaes new file mode 100644 index 0000000..b388f03 --- /dev/null +++ b/test/AP+STA/hostapd.conf.36.wpa2pskaes @@ -0,0 +1,21 @@ +interface=wlan1 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=a +channel=36 +auth_algs=1 +wpa=2 +wpa_passphrase=12345678 +wpa_key_mgmt=WPA-PSK +wpa_pairwise=CCMP +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] +ieee80211ac=1 +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +ieee80211d=1 +country_code=US +ieee80211h=1 + diff --git a/test/AP+STA/hostapd.conf.36.wpa2pskaes.40mhz b/test/AP+STA/hostapd.conf.36.wpa2pskaes.40mhz new file mode 100644 index 0000000..124eb0c --- /dev/null +++ b/test/AP+STA/hostapd.conf.36.wpa2pskaes.40mhz @@ -0,0 +1,22 @@ +interface=wlan1 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=a +channel=36 +auth_algs=1 +wpa=2 +wpa_passphrase=12345678 +wpa_key_mgmt=WPA-PSK +wpa_pairwise=CCMP +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] +ieee80211ac=1 +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +ieee80211d=1 +country_code=US +ieee80211h=1 + + diff --git a/test/AP+STA/hostapd.conf.36.wpa2pskaes.80mhz b/test/AP+STA/hostapd.conf.36.wpa2pskaes.80mhz new file mode 100644 index 0000000..5891e72 --- /dev/null +++ b/test/AP+STA/hostapd.conf.36.wpa2pskaes.80mhz @@ -0,0 +1,24 @@ +interface=wlan1 +driver=nl80211 +ctrl_interface=/var/run/hostapd +ssid=mwlwifi_ap_test +ignore_broadcast_ssid=0 +hw_mode=a +channel=36 +auth_algs=1 +wpa=2 +wpa_passphrase=12345678 +wpa_key_mgmt=WPA-PSK +wpa_pairwise=CCMP +wmm_enabled=1 +ieee80211n=1 +ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] +ieee80211ac=1 +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_oper_chwidth=1 +vht_oper_centr_freq_seg0_idx=42 +ieee80211d=1 +country_code=US +ieee80211h=1 + + diff --git a/test/AP+STA/wpa_supplicant.conf.open b/test/AP+STA/wpa_supplicant.conf.open new file mode 100644 index 0000000..d7677b9 --- /dev/null +++ b/test/AP+STA/wpa_supplicant.conf.open @@ -0,0 +1,8 @@ +ctrl_interface=/var/run/wpa_supplicant + +network={ + +ssid="mwlwifi_ap_test" +key_mgmt=NONE + +} diff --git a/test/AP+STA/wpa_supplicant.conf.psk b/test/AP+STA/wpa_supplicant.conf.psk new file mode 100644 index 0000000..ce154a6 --- /dev/null +++ b/test/AP+STA/wpa_supplicant.conf.psk @@ -0,0 +1,9 @@ +ctrl_interface=/var/run/wpa_supplicant + +network={ + +ssid="mwlwifi_ap_test" +key_mgmt=WPA-PSK +psk="12345678" + +} diff --git a/test/hostapd.conf.36.multi_bssid b/test/hostapd.conf.36.multi_bssid index 0e5492d..5ecebe9 100644 --- a/test/hostapd.conf.36.multi_bssid +++ b/test/hostapd.conf.36.multi_bssid @@ -10,7 +10,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] bss=wlan1_0 ssid=mwlwifi_ap_tset2 wpa=2 diff --git a/test/hostapd.conf.36.open b/test/hostapd.conf.36.open index 842a1cb..85fb4a0 100644 --- a/test/hostapd.conf.36.open +++ b/test/hostapd.conf.36.open @@ -10,5 +10,5 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] diff --git a/test/hostapd.conf.36.open.80mhz b/test/hostapd.conf.36.open.80mhz index 5d094f2..0a47a0f 100644 --- a/test/hostapd.conf.36.open.80mhz +++ b/test/hostapd.conf.36.open.80mhz @@ -10,7 +10,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] vht_oper_chwidth=1 vht_oper_centr_freq_seg0_idx=42 diff --git a/test/hostapd.conf.36.wpa2pskaes b/test/hostapd.conf.36.wpa2pskaes index cf60121..51b2837 100644 --- a/test/hostapd.conf.36.wpa2pskaes +++ b/test/hostapd.conf.36.wpa2pskaes @@ -14,5 +14,5 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] diff --git a/test/hostapd.conf.36.wpa2pskaes.80mhz b/test/hostapd.conf.36.wpa2pskaes.80mhz index 492fc17..0419b7d 100644 --- a/test/hostapd.conf.36.wpa2pskaes.80mhz +++ b/test/hostapd.conf.36.wpa2pskaes.80mhz @@ -14,7 +14,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] vht_oper_chwidth=1 vht_oper_centr_freq_seg0_idx=42 diff --git a/test/hostapd.conf.dfs b/test/hostapd.conf.dfs index dc81e47..c770b8d 100755..100644 --- a/test/hostapd.conf.dfs +++ b/test/hostapd.conf.dfs @@ -10,7 +10,7 @@ wmm_enabled=1 ieee80211n=1 ht_capab=[LDPC][HT40+][SHORT-GI-20][SHORT-GI-40] ieee80211ac=1 -vht_capab=[MAX-MPDU-7991][RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] +vht_capab=[RXLDPC][SHORT-GI-80][RX-STBC-1][SU-BEAMFORMER][SU-BEAMFORMEE][MAX-A-MPDU-LEN-EXP7][RX-ANTENNA-PATTERN][TX-ANTENNA-PATTERN] vht_oper_chwidth=1 vht_oper_centr_freq_seg0_idx=106 ieee80211d=1 @@ -798,7 +798,7 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, qos |= MWL_QOS_ACK_POLICY_NORMAL; } - if (is_multicast_ether_addr(wh->addr1)) + if (is_multicast_ether_addr(wh->addr1) || eapol_frame) xmitcontrol |= EAGLE_TXD_XMITCTRL_USE_MC_RATE; } @@ -823,17 +823,6 @@ void mwl_tx_xmit(struct ieee80211_hw *hw, capab = le16_to_cpu(mgmt->u.action.u.addba_req.capab); tid = (capab & IEEE80211_ADDBA_PARAM_TID_MASK) >> 2; index = mwl_tx_tid_queue_mapping(tid); - capab |= 1; - mgmt->u.action.u.addba_req.capab = cpu_to_le16(capab); - } - - if (unlikely(ieee80211_is_action(wh->frame_control) && - mgmt->u.action.category == WLAN_CATEGORY_BACK && - mgmt->u.action.u.addba_resp.action_code == - WLAN_ACTION_ADDBA_RESP)) { - capab = le16_to_cpu(mgmt->u.action.u.addba_resp.capab); - capab |= 1; - mgmt->u.action.u.addba_resp.capab = cpu_to_le16(capab); } } |