summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Lin <dlin@marvell.com>2015-10-29 13:20:51 +0800
committerDavid Lin <dlin@marvell.com>2015-10-29 13:20:51 +0800
commit30e6b06de659f1d5e46d1dd3bf590caf3529bb65 (patch)
tree8c07d46accca9c8073882b7a31ce4209c3fb8f76
parent7a6aff718d2de7dee6f9d82eae8af91667e8ee86 (diff)
Commit mwlwifi driver 10.3.0.12.
1. Change FW_CHECK_MSECS from 1 to 3. 2. Modify the code to support client without AMSDU support. Signed-off-by: David Lin <dlin@marvell.com>
-rw-r--r--Makefile7
-rw-r--r--Makefile.external7
-rw-r--r--debugfs.c5
-rw-r--r--dev.h17
-rw-r--r--fwcmd.c111
-rw-r--r--fwcmd.h2
-rw-r--r--fwdl.c27
-rw-r--r--mac80211.c9
-rw-r--r--main.c47
-rw-r--r--rx.c36
-rw-r--r--tx.c2
11 files changed, 244 insertions, 26 deletions
diff --git a/Makefile b/Makefile
index ea3f265..e86508c 100644
--- a/Makefile
+++ b/Makefile
@@ -8,6 +8,9 @@ mwlwifi-objs += tx.o
mwlwifi-objs += rx.o
mwlwifi-objs += isr.o
mwlwifi-$(CONFIG_DEBUG_FS) += debugfs.o
+ifeq (1, $(BUILD_MFG))
+mwlwifi-objs += mfg.o
+endif
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
@@ -16,6 +19,10 @@ CC = $(CROSS_COMPILE)gcc
EXTRA_CFLAGS+= -I${KDIR}
EXTRA_CFLAGS+= -O2 -funroll-loops -D__CHECK_ENDIAN__
+ifeq (1, $(BUILD_MFG))
+EXTRA_CFLAGS+= -DCONFIG_SUPPORT_MFG
+endif
+
EXTRA_CFLAGS+= -I${PWD}
all:
diff --git a/Makefile.external b/Makefile.external
index ea3f265..e86508c 100644
--- a/Makefile.external
+++ b/Makefile.external
@@ -8,6 +8,9 @@ mwlwifi-objs += tx.o
mwlwifi-objs += rx.o
mwlwifi-objs += isr.o
mwlwifi-$(CONFIG_DEBUG_FS) += debugfs.o
+ifeq (1, $(BUILD_MFG))
+mwlwifi-objs += mfg.o
+endif
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
@@ -16,6 +19,10 @@ CC = $(CROSS_COMPILE)gcc
EXTRA_CFLAGS+= -I${KDIR}
EXTRA_CFLAGS+= -O2 -funroll-loops -D__CHECK_ENDIAN__
+ifeq (1, $(BUILD_MFG))
+EXTRA_CFLAGS+= -DCONFIG_SUPPORT_MFG
+endif
+
EXTRA_CFLAGS+= -I${PWD}
all:
diff --git a/debugfs.c b/debugfs.c
index 00aa12d..2f6bae3 100644
--- a/debugfs.c
+++ b/debugfs.c
@@ -121,6 +121,7 @@ static ssize_t mwl_debugfs_info_read(struct file *file, char __user *ubuf,
p += sprintf(p, "sta macid support: %08x\n",
priv->sta_macids_supported);
p += sprintf(p, "macid used: %08x\n", priv->macids_used);
+ p += sprintf(p, "mfg mode: %s\n", priv->mfg_mode ? "true" : "false");
p += sprintf(p, "\n");
ret = simple_read_from_buffer(ubuf, count, ppos, (char *) page,
@@ -159,6 +160,10 @@ static ssize_t mwl_debugfs_vif_read(struct file *file, char __user *ubuf,
p += sprintf(p, "ssid: %s\n", ssid);
p += print_mac_addr(p, mwl_vif->bssid);
break;
+ case NL80211_IFTYPE_MESH_POINT:
+ p += sprintf(p, "type: mesh\n");
+ p += print_mac_addr(p, mwl_vif->bssid);
+ break;
case NL80211_IFTYPE_STATION:
p += sprintf(p, "type: sta\n");
p += print_mac_addr(p, mwl_vif->sta_mac);
diff --git a/dev.h b/dev.h
index b488977..10c9d0e 100644
--- a/dev.h
+++ b/dev.h
@@ -27,7 +27,7 @@
#include <net/mac80211.h>
#define MWL_DRV_NAME KBUILD_MODNAME
-#define MWL_DRV_VERSION "10.3.0.10"
+#define MWL_DRV_VERSION "10.3.0.12"
/* Map to 0x80000000 (Bus control) on BAR0 */
#define MACREG_REG_H2A_INTERRUPT_EVENTS 0x00000C18 /* (From host to ARM) */
@@ -143,6 +143,7 @@ enum {
struct mwl_chip_info {
const char *part_name;
const char *fw_image;
+ const char *mfg_fw_image;
int antenna_tx;
int antenna_rx;
};
@@ -277,7 +278,7 @@ struct mwl_ampdu_stream {
struct mwl_priv {
struct ieee80211_hw *hw;
- const struct firmware *fw_ucode;
+ struct firmware *fw_ucode;
int chip_type;
struct device_node *dt_node;
@@ -354,6 +355,8 @@ struct mwl_priv {
struct mwl_ampdu_stream ampdu[SYSADPT_TX_AMPDU_QUEUES];
struct work_struct watchdog_ba_handle;
+ bool mfg_mode;
+
#ifdef CONFIG_DEBUG_FS
struct dentry *debugfs_phy;
u32 reg_type;
@@ -374,11 +377,21 @@ struct beacon_info {
u8 *ie_rsn48_ptr;
u8 *ie_ht_ptr;
u8 *ie_vht_ptr;
+#ifdef CONFIG_MAC80211_MESH
+ u8 *ie_meshid_ptr;
+ u8 *ie_meshcfg_ptr;
+ u8 *ie_meshchsw_ptr;
+#endif
u8 ie_wmm_len;
u8 ie_rsn_len;
u8 ie_rsn48_len;
u8 ie_ht_len;
u8 ie_vht_len;
+#ifdef CONFIG_MAC80211_MESH
+ u8 ie_meshid_len;
+ u8 ie_meshcfg_len;
+ u8 ie_meshchsw_len;
+#endif
};
struct mwl_vif {
diff --git a/fwcmd.c b/fwcmd.c
index 62ed88a..f754036 100644
--- a/fwcmd.c
+++ b/fwcmd.c
@@ -27,6 +27,11 @@
#define MAX_WAIT_FW_COMPLETE_ITERATIONS 2000
#define MAX_WAIT_GET_HW_SPECS_ITERATONS 3
+struct cmd_header {
+ __le16 command;
+ __le16 len;
+} __packed;
+
static bool mwl_fwcmd_chk_adapter(struct mwl_priv *priv)
{
u32 regval;
@@ -43,6 +48,16 @@ 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);
@@ -109,7 +124,10 @@ static int mwl_fwcmd_wait_complete(struct mwl_priv *priv, unsigned short cmd)
unsigned short int_code = 0;
do {
- int_code = le16_to_cpu(*((__le16 *)&priv->pcmd_buf[0]));
+ 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);
} while ((int_code != cmd) && (--curr_iteration));
@@ -437,6 +455,20 @@ 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:
@@ -483,14 +515,15 @@ static void mwl_fwcmd_parse_beacon(struct mwl_priv *priv,
static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif)
{
struct hostcmd_cmd_set_ies *pcmd;
+ struct beacon_info *beacon = &mwl_vif->beacon_info;
- if (!mwl_vif->beacon_info.valid)
+ if (!beacon->valid)
return -EINVAL;
- if (mwl_vif->beacon_info.ie_ht_len > sizeof(pcmd->ie_list_ht))
+ if (beacon->ie_ht_len > sizeof(pcmd->ie_list_ht))
goto einval;
- if (mwl_vif->beacon_info.ie_vht_len > sizeof(pcmd->ie_list_vht))
+ if (beacon->ie_vht_len > sizeof(pcmd->ie_list_vht))
goto einval;
pcmd = (struct hostcmd_cmd_set_ies *)&priv->pcmd_buf[0];
@@ -504,20 +537,30 @@ static int mwl_fwcmd_set_ies(struct mwl_priv *priv, struct mwl_vif *mwl_vif)
pcmd->action = cpu_to_le16(HOSTCMD_ACT_GEN_SET);
- pcmd->ie_list_len_ht = cpu_to_le16(mwl_vif->beacon_info.ie_ht_len);
- memcpy(pcmd->ie_list_ht, mwl_vif->beacon_info.ie_ht_ptr,
- mwl_vif->beacon_info.ie_ht_len);
+ memcpy(pcmd->ie_list_ht, beacon->ie_ht_ptr, beacon->ie_ht_len);
+ pcmd->ie_list_len_ht = cpu_to_le16(beacon->ie_ht_len);
- pcmd->ie_list_len_vht = cpu_to_le16(mwl_vif->beacon_info.ie_vht_len);
- memcpy(pcmd->ie_list_vht, mwl_vif->beacon_info.ie_vht_ptr,
- mwl_vif->beacon_info.ie_vht_len);
+ 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);
+ pcmd->ie_list_len_proprietary = cpu_to_le16(beacon->ie_meshid_len);
+ memcpy(pcmd->ie_list_proprietary + pcmd->ie_list_len_proprietary,
+ beacon->ie_meshcfg_ptr, beacon->ie_meshcfg_len);
+ pcmd->ie_list_len_proprietary += cpu_to_le16(beacon->ie_meshcfg_len);
+ memcpy(pcmd->ie_list_proprietary + pcmd->ie_list_len_proprietary,
+ beacon->ie_meshchsw_ptr, beacon->ie_meshchsw_len);
+ pcmd->ie_list_len_proprietary += cpu_to_le16(beacon->ie_meshchsw_len);
+#endif
if (priv->chip_type == MWL8897) {
- pcmd->ie_list_len_proprietary =
+ memcpy(pcmd->ie_list_proprietary +
+ pcmd->ie_list_len_proprietary,
+ beacon->ie_wmm_ptr, beacon->ie_wmm_len);
+ pcmd->ie_list_len_proprietary +=
cpu_to_le16(mwl_vif->beacon_info.ie_wmm_len);
- memcpy(pcmd->ie_list_proprietary,
- mwl_vif->beacon_info.ie_wmm_ptr,
- mwl_vif->beacon_info.ie_wmm_len);
}
if (mwl_fwcmd_exec_cmd(priv, HOSTCMD_CMD_SET_IES)) {
@@ -698,6 +741,9 @@ 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];
spin_lock_bh(&priv->fwcmd_lock);
@@ -751,6 +797,9 @@ 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];
spin_lock_bh(&priv->fwcmd_lock);
@@ -886,6 +935,9 @@ 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);
@@ -1146,6 +1198,9 @@ 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];
spin_lock_bh(&priv->fwcmd_lock);
@@ -2425,3 +2480,31 @@ int mwl_fwcmd_reg_cau(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val)
return 0;
}
+
+int mwl_fwcmd_send_mfg_cmd(struct mwl_priv *priv, char *mfgcmd)
+{
+ struct hostcmd_header *pcmd;
+ struct cmd_header *cmd_hd = (struct cmd_header *)(mfgcmd+4);
+ u16 len;
+ u16 cmd;
+
+ pcmd = (struct hostcmd_header *)&priv->pcmd_buf[0];
+
+ spin_lock_bh(&priv->fwcmd_lock);
+
+ len = le16_to_cpu(cmd_hd->len);
+ memset(pcmd, 0x00, len+4);
+ memcpy((char *)pcmd, mfgcmd, len+4);
+ cmd = le16_to_cpu(cmd_hd->command);
+ if (mwl_fwcmd_exec_cmd(priv, cmd)) {
+ spin_unlock_bh(&priv->fwcmd_lock);
+ wiphy_err(priv->hw->wiphy, "failed execution");
+ return -EIO;
+ }
+ cmd_hd = (struct cmd_header *)&priv->pcmd_buf[2];
+ len = le16_to_cpu(cmd_hd->len);
+ memcpy(mfgcmd, (char *)&priv->pcmd_buf[2], len);
+ spin_unlock_bh(&priv->fwcmd_lock);
+
+ return 0;
+}
diff --git a/fwcmd.h b/fwcmd.h
index 6775c98..202b05a 100644
--- a/fwcmd.h
+++ b/fwcmd.h
@@ -199,4 +199,6 @@ int mwl_fwcmd_set_cdd(struct ieee80211_hw *hw);
int mwl_fwcmd_reg_cau(struct ieee80211_hw *hw, u8 flag, u32 reg, u32 *val);
+int mwl_fwcmd_send_mfg_cmd(struct mwl_priv *priv, char *mfgcmd);
+
#endif /* _fwcmd_h_ */
diff --git a/fwdl.c b/fwdl.c
index 48c8c3e..ec44aa4 100644
--- a/fwdl.c
+++ b/fwdl.c
@@ -22,10 +22,13 @@
#include "sysadpt.h"
#include "dev.h"
#include "fwcmd.h"
+#ifdef CONFIG_SUPPORT_MFG
+#include "mfg.h"
+#endif
#include "fwdl.h"
#define FW_DOWNLOAD_BLOCK_SIZE 256
-#define FW_CHECK_MSECS 1
+#define FW_CHECK_MSECS 3
#define FW_MAX_NUM_CHECKS 0xffff
@@ -57,6 +60,12 @@ int mwl_fwdl_download_firmware(struct ieee80211_hw *hw)
u32 size_fw_downloaded = 0;
u32 int_code = 0;
u32 len = 0;
+#ifdef CONFIG_SUPPORT_MFG
+ u32 fwreadysignature = priv->mfg_mode ?
+ MFG_FW_READY_SIGNATURE : HOSTCMD_SOFTAP_FWRDY_SIGNATURE;
+#else
+ u32 fwreadysignature = HOSTCMD_SOFTAP_FWRDY_SIGNATURE;
+#endif
fw = priv->fw_ucode;
@@ -153,15 +162,23 @@ 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)
+ writel(fwreadysignature, priv->iobase1 + 0xcf0);
do {
curr_iteration--;
- writel(HOSTCMD_SOFTAP_MODE, priv->iobase1 + MACREG_REG_GEN_PTR);
- mdelay(FW_CHECK_MSECS);
- int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE);
+ if (!priv->mfg_mode) {
+ writel(HOSTCMD_SOFTAP_MODE,
+ priv->iobase1 + MACREG_REG_GEN_PTR);
+ mdelay(FW_CHECK_MSECS);
+ int_code = readl(priv->iobase1 + MACREG_REG_INT_CODE);
+ } else {
+ mdelay(FW_CHECK_MSECS);
+ int_code = readl(priv->iobase1 + 0xc44);
+ }
if (!(curr_iteration % 0xff))
wiphy_err(hw->wiphy, "%x;", int_code);
} while ((curr_iteration) &&
- (int_code != HOSTCMD_SOFTAP_FWRDY_SIGNATURE));
+ (int_code != fwreadysignature));
if (curr_iteration == 0) {
wiphy_err(hw->wiphy,
diff --git a/mac80211.c b/mac80211.c
index ec96f25..afce509 100644
--- a/mac80211.c
+++ b/mac80211.c
@@ -146,6 +146,7 @@ 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:
@@ -179,6 +180,10 @@ 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);
@@ -220,6 +225,7 @@ 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:
@@ -355,6 +361,7 @@ 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:
@@ -458,7 +465,7 @@ static int mwl_mac80211_sta_add(struct ieee80211_hw *hw,
memset(sta_info, 0, sizeof(*sta_info));
if (sta->ht_cap.ht_supported) {
sta_info->is_ampdu_allowed = true;
- sta_info->is_amsdu_allowed = true;
+ sta_info->is_amsdu_allowed = false;
if (sta->ht_cap.cap & IEEE80211_HT_CAP_MAX_AMSDU)
sta_info->amsdu_ctrl.cap = MWL_AMSDU_SIZE_8K;
else
diff --git a/main.c b/main.c
index 5a000c0..8c19474 100644
--- a/main.c
+++ b/main.c
@@ -27,6 +27,9 @@
#include "tx.h"
#include "rx.h"
#include "isr.h"
+#ifdef CONFIG_SUPPORT_MFG
+#include "mfg.h"
+#endif
#ifdef CONFIG_DEBUG_FS
#include "debugfs.h"
#endif
@@ -47,12 +50,14 @@ static struct mwl_chip_info mwl_chip_tbl[] = {
[MWL8864] = {
.part_name = "88W8864",
.fw_image = "mwlwifi/88W8864.bin",
+ .mfg_fw_image = "./88W8864-MFG.bin",
.antenna_tx = ANTENNA_TX_4_AUTO,
.antenna_rx = ANTENNA_RX_4_AUTO,
},
[MWL8897] = {
.part_name = "88W8897",
.fw_image = "mwlwifi/88W8897.bin",
+ .mfg_fw_image = "./88W8897-MFG.bin",
.antenna_tx = ANTENNA_TX_2,
.antenna_rx = ANTENNA_RX_2,
},
@@ -131,6 +136,9 @@ 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) },
};
@@ -203,7 +211,14 @@ static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name)
pdev = priv->pdev;
- rc = request_firmware(&priv->fw_ucode, fw_name, &priv->pdev->dev);
+#ifdef CONFIG_SUPPORT_MFG
+ if (priv->mfg_mode)
+ rc = mwl_mfg_request_firmware(priv, fw_name);
+ else
+#endif
+ rc = request_firmware((const struct firmware **)&priv->fw_ucode,
+ fw_name, &priv->pdev->dev);
+
if (rc) {
wiphy_err(priv->hw->wiphy,
"%s: cannot load firmware image <%s>\n",
@@ -223,7 +238,12 @@ static int mwl_init_firmware(struct mwl_priv *priv, const char *fw_name)
err_download_fw:
- release_firmware(priv->fw_ucode);
+#ifdef CONFIG_SUPPORT_MFG
+ if (priv->mfg_mode)
+ mwl_mfg_release_firmware(priv);
+ else
+#endif
+ release_firmware(priv->fw_ucode);
err_load_fw:
@@ -606,6 +626,9 @@ 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;
@@ -674,6 +697,7 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
static bool printed_version;
struct ieee80211_hw *hw;
struct mwl_priv *priv;
+ const char *fw_name;
int rc = 0;
if (id->driver_data >= MWLUNKNOWN)
@@ -728,7 +752,17 @@ static int mwl_probe(struct pci_dev *pdev, const struct pci_device_id *id)
if (rc)
goto err_alloc_pci_resource;
- rc = mwl_init_firmware(priv, mwl_chip_tbl[priv->chip_type].fw_image);
+ fw_name = mwl_chip_tbl[priv->chip_type].fw_image;
+
+#ifdef CONFIG_SUPPORT_MFG
+ if (mfg_mode) {
+ mwl_mfg_handler_init(priv);
+ fw_name = mwl_chip_tbl[priv->chip_type].mfg_fw_image;
+ }
+#endif
+
+ rc = mwl_init_firmware(priv, fw_name);
+
if (rc) {
wiphy_err(hw->wiphy, "%s: fail to initialize firmware\n",
MWL_DRV_NAME);
@@ -736,7 +770,12 @@ 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 */
- release_firmware(priv->fw_ucode);
+#ifdef CONFIG_SUPPORT_MFG
+ if (priv->mfg_mode)
+ mwl_mfg_release_firmware(priv);
+ else
+#endif
+ release_firmware(priv->fw_ucode);
mwl_process_of_dts(priv);
diff --git a/rx.c b/rx.c
index 210269b..3908eef 100644
--- a/rx.c
+++ b/rx.c
@@ -282,6 +282,24 @@ 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)
{
@@ -485,6 +503,24 @@ void mwl_rx_recv(unsigned long data)
skb_put(prx_skb, pkt_len);
mwl_rx_remove_dma_header(prx_skb, curr_hndl->pdesc->qos_ctrl);
+
+ 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);
+ }
+ }
+
memcpy(IEEE80211_SKB_RXCB(prx_skb), &status, sizeof(status));
ieee80211_rx(hw, prx_skb);
out:
diff --git a/tx.c b/tx.c
index 1db6b71..9bd247b 100644
--- a/tx.c
+++ b/tx.c
@@ -852,6 +852,8 @@ 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) &&