aboutsummaryrefslogtreecommitdiff
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/at76c50x-usb.c180
-rw-r--r--drivers/net/wireless/at76c50x-usb.h26
-rw-r--r--drivers/net/wireless/ath/ath10k/bmi.h3
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.c27
-rw-r--r--drivers/net/wireless/ath/ath10k/ce.h2
-rw-r--r--drivers/net/wireless/ath/ath10k/core.c287
-rw-r--r--drivers/net/wireless/ath/ath10k/core.h8
-rw-r--r--drivers/net/wireless/ath/ath10k/htc.c6
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.c42
-rw-r--r--drivers/net/wireless/ath/ath10k/htt.h18
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_rx.c74
-rw-r--r--drivers/net/wireless/ath/ath10k/htt_tx.c8
-rw-r--r--drivers/net/wireless/ath/ath10k/mac.c224
-rw-r--r--drivers/net/wireless/ath/ath10k/pci.c121
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.c28
-rw-r--r--drivers/net/wireless/ath/ath10k/wmi.h10
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c7
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c2
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile3
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ani.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.c253
-rw-r--r--drivers/net/wireless/ath/ath9k/common-debug.h72
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c214
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h44
-rw-r--r--drivers/net/wireless/ath/ath9k/debug_sta.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/dfs.c6
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h19
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_debug.c555
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_main.c5
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_txrx.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c33
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c22
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c74
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c35
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c23
-rw-r--r--drivers/net/wireless/ath/carl9170/usb.c8
-rw-r--r--drivers/net/wireless/ath/dfs_pattern_detector.c45
-rw-r--r--drivers/net/wireless/ath/wcn36xx/smd.c3
-rw-r--r--drivers/net/wireless/ath/wil6210/cfg80211.c5
-rw-r--r--drivers/net/wireless/ath/wil6210/debugfs.c4
-rw-r--r--drivers/net/wireless/ath/wil6210/main.c39
-rw-r--r--drivers/net/wireless/ath/wil6210/netdev.c14
-rw-r--r--drivers/net/wireless/ath/wil6210/pcie_bus.c2
-rw-r--r--drivers/net/wireless/ath/wil6210/rx_reorder.c9
-rw-r--r--drivers/net/wireless/ath/wil6210/txrx.c28
-rw-r--r--drivers/net/wireless/ath/wil6210/wil6210.h8
-rw-r--r--drivers/net/wireless/ath/wil6210/wmi.c25
-rw-r--r--drivers/net/wireless/b43/Kconfig42
-rw-r--r--drivers/net/wireless/b43/bus.h10
-rw-r--r--drivers/net/wireless/b43/main.c418
-rw-r--r--drivers/net/wireless/b43/phy_common.c90
-rw-r--r--drivers/net/wireless/b43/phy_common.h8
-rw-r--r--drivers/net/wireless/b43/phy_n.c17
-rw-r--r--drivers/net/wireless/b43/phy_n.h1
-rw-r--r--drivers/net/wireless/b43/radio_2056.c918
-rw-r--r--drivers/net/wireless/b43/tables_nphy.c80
-rw-r--r--drivers/net/wireless/b43/xmit.c12
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/Makefile2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/chip.c5
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd.h2
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h7
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c18
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c39
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c283
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.c332
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/firmware.h (renamed from drivers/net/wireless/brcm80211/brcmfmac/nvram.h)24
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h24
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c80
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/nvram.c94
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/usb.c273
-rw-r--r--drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c215
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/main.c13
-rw-r--r--drivers/net/wireless/brcm80211/brcmutil/d11.c93
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_d11.h14
-rw-r--r--drivers/net/wireless/brcm80211/include/brcmu_wifi.h1
-rw-r--r--drivers/net/wireless/hostap/hostap_main.c2
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig13
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/calib.c1
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/debugfs.c7
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/dev.h2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/devices.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/led.h12
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/lib.c17
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/main.c27
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/power.c4
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rs.c10
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/rxon.c30
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/scan.c3
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/sta.c29
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tt.c2
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/tx.c24
-rw-r--r--drivers/net/wireless/iwlwifi/dvm/ucode.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-7000.c2
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-8000.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-config.h7
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.c6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-debug.h41
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-drv.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h (renamed from drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h)26
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-fw.h11
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.c18
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-io.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-modparams.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-nvm-parse.c50
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-phy-db.c9
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-prph.h3
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.h50
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/Makefile3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/coex.c86
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/d3.c35
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c48
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/debugfs.c11
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h8
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/fw.c19
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c134
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mac80211.c194
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/mvm.h37
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/nvm.c102
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/ops.c43
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c23
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/power.c208
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/quota.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/rs.c181
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/scan.c133
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.c18
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/sta.h3
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/time-event.c4
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tt.c1
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/tx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/mvm/utils.c60
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/drv.c17
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/internal.h24
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/rx.c2
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/trans.c100
-rw-r--r--drivers/net/wireless/iwlwifi/pcie/tx.c139
-rw-r--r--drivers/net/wireless/libertas/cfg.c7
-rw-r--r--drivers/net/wireless/libertas/defs.h3
-rw-r--r--drivers/net/wireless/libertas/rx.c8
-rw-r--r--drivers/net/wireless/mwifiex/11n.c42
-rw-r--r--drivers/net/wireless/mwifiex/11n.h3
-rw-r--r--drivers/net/wireless/mwifiex/11n_aggr.c8
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c20
-rw-r--r--drivers/net/wireless/mwifiex/cmdevt.c1
-rw-r--r--drivers/net/wireless/mwifiex/fw.h25
-rw-r--r--drivers/net/wireless/mwifiex/main.c1
-rw-r--r--drivers/net/wireless/mwifiex/main.h24
-rw-r--r--drivers/net/wireless/mwifiex/pcie.c5
-rw-r--r--drivers/net/wireless/mwifiex/scan.c29
-rw-r--r--drivers/net/wireless/mwifiex/sdio.c6
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmd.c7
-rw-r--r--drivers/net/wireless/mwifiex/sta_cmdresp.c18
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c44
-rw-r--r--drivers/net/wireless/mwifiex/sta_rx.c16
-rw-r--r--drivers/net/wireless/mwifiex/sta_tx.c5
-rw-r--r--drivers/net/wireless/mwifiex/tdls.c99
-rw-r--r--drivers/net/wireless/mwifiex/txrx.c1
-rw-r--r--drivers/net/wireless/mwifiex/uap_txrx.c1
-rw-r--r--drivers/net/wireless/mwifiex/util.c6
-rw-r--r--drivers/net/wireless/mwifiex/util.h43
-rw-r--r--drivers/net/wireless/mwifiex/wmm.c13
-rw-r--r--drivers/net/wireless/mwifiex/wmm.h5
-rw-r--r--drivers/net/wireless/orinoco/hw.c4
-rw-r--r--drivers/net/wireless/orinoco/hw.h4
-rw-r--r--drivers/net/wireless/orinoco/orinoco_usb.c52
-rw-r--r--drivers/net/wireless/orinoco/wext.c4
-rw-r--r--drivers/net/wireless/rndis_wlan.c4
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_mac80211.c1
-rw-r--r--drivers/net/wireless/rsi/rsi_91x_sdio.c4
-rw-r--r--drivers/net/wireless/rsi/rsi_common.h2
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c7
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c55
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c24
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00usb.h1
-rw-r--r--drivers/net/wireless/rtl818x/rtl8180/dev.c17
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187/dev.c11
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/hw.c20
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/hw.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/sw.c5
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8188ee/trx.c2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.c21
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/hw.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192ce/sw.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/hw.c4
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192cu/sw.c3
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.c20
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/hw.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/sw.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8192se/trx.c6
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hw.c21
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/hw.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723ae/sw.c1
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/hw.c20
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/hw.h2
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/sw.c5
-rw-r--r--drivers/net/wireless/rtlwifi/rtl8723be/trx.c1
-rw-r--r--drivers/net/wireless/rtlwifi/wifi.h6
-rw-r--r--drivers/net/wireless/ti/wl1251/acx.c1
-rw-r--r--drivers/net/wireless/ti/wl1251/cmd.c1
-rw-r--r--drivers/net/wireless/ti/wl1251/event.c5
-rw-r--r--drivers/net/wireless/ti/wl1251/main.c68
-rw-r--r--drivers/net/wireless/ti/wl1251/spi.c44
-rw-r--r--drivers/net/wireless/ti/wlcore/debugfs.h4
-rw-r--r--drivers/net/wireless/ti/wlcore/main.c4
-rw-r--r--drivers/net/wireless/ti/wlcore/spi.c46
-rw-r--r--drivers/net/wireless/ti/wlcore/wlcore_i.h4
221 files changed, 5443 insertions, 3399 deletions
diff --git a/drivers/net/wireless/at76c50x-usb.c b/drivers/net/wireless/at76c50x-usb.c
index 99b3bfa717d..d48776e4f34 100644
--- a/drivers/net/wireless/at76c50x-usb.c
+++ b/drivers/net/wireless/at76c50x-usb.c
@@ -365,15 +365,15 @@ static inline unsigned long at76_get_timeout(struct dfu_status *s)
static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
int manifest_sync_timeout)
{
- u8 *block;
- struct dfu_status dfu_stat_buf;
int ret = 0;
int need_dfu_state = 1;
int is_done = 0;
- u8 dfu_state = 0;
u32 dfu_timeout = 0;
int bsize = 0;
int blockno = 0;
+ struct dfu_status *dfu_stat_buf = NULL;
+ u8 *dfu_state = NULL;
+ u8 *block = NULL;
at76_dbg(DBG_DFU, "%s( %p, %u, %d)", __func__, buf, size,
manifest_sync_timeout);
@@ -383,13 +383,28 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
return -EINVAL;
}
+ dfu_stat_buf = kmalloc(sizeof(struct dfu_status), GFP_KERNEL);
+ if (!dfu_stat_buf) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
block = kmalloc(FW_BLOCK_SIZE, GFP_KERNEL);
- if (!block)
- return -ENOMEM;
+ if (!block) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
+ dfu_state = kmalloc(sizeof(u8), GFP_KERNEL);
+ if (!dfu_state) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+ *dfu_state = 0;
do {
if (need_dfu_state) {
- ret = at76_dfu_get_state(udev, &dfu_state);
+ ret = at76_dfu_get_state(udev, dfu_state);
if (ret < 0) {
dev_err(&udev->dev,
"cannot get DFU state: %d\n", ret);
@@ -398,13 +413,13 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
need_dfu_state = 0;
}
- switch (dfu_state) {
+ switch (*dfu_state) {
case STATE_DFU_DOWNLOAD_SYNC:
at76_dbg(DBG_DFU, "STATE_DFU_DOWNLOAD_SYNC");
- ret = at76_dfu_get_status(udev, &dfu_stat_buf);
+ ret = at76_dfu_get_status(udev, dfu_stat_buf);
if (ret >= 0) {
- dfu_state = dfu_stat_buf.state;
- dfu_timeout = at76_get_timeout(&dfu_stat_buf);
+ *dfu_state = dfu_stat_buf->state;
+ dfu_timeout = at76_get_timeout(dfu_stat_buf);
need_dfu_state = 0;
} else
dev_err(&udev->dev,
@@ -447,12 +462,12 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
case STATE_DFU_MANIFEST_SYNC:
at76_dbg(DBG_DFU, "STATE_DFU_MANIFEST_SYNC");
- ret = at76_dfu_get_status(udev, &dfu_stat_buf);
+ ret = at76_dfu_get_status(udev, dfu_stat_buf);
if (ret < 0)
break;
- dfu_state = dfu_stat_buf.state;
- dfu_timeout = at76_get_timeout(&dfu_stat_buf);
+ *dfu_state = dfu_stat_buf->state;
+ dfu_timeout = at76_get_timeout(dfu_stat_buf);
need_dfu_state = 0;
/* override the timeout from the status response,
@@ -484,14 +499,17 @@ static int at76_usbdfu_download(struct usb_device *udev, u8 *buf, u32 size,
break;
default:
- at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", dfu_state);
+ at76_dbg(DBG_DFU, "DFU UNKNOWN STATE (%d)", *dfu_state);
ret = -EINVAL;
break;
}
} while (!is_done && (ret >= 0));
exit:
+ kfree(dfu_state);
kfree(block);
+ kfree(dfu_stat_buf);
+
if (ret >= 0)
ret = 0;
@@ -1277,6 +1295,7 @@ static int at76_load_external_fw(struct usb_device *udev, struct fwentry *fwe)
dev_err(&udev->dev,
"loading %dth firmware block failed: %d\n",
blockno, ret);
+ ret = -EIO;
goto exit;
}
buf += bsize;
@@ -1410,6 +1429,8 @@ static int at76_startup_device(struct at76_priv *priv)
/* remove BSSID from previous run */
memset(priv->bssid, 0, ETH_ALEN);
+ priv->scanning = false;
+
if (at76_set_radio(priv, 1) == 1)
at76_wait_completion(priv, CMD_RADIO_ON);
@@ -1483,6 +1504,52 @@ static void at76_work_submit_rx(struct work_struct *work)
mutex_unlock(&priv->mtx);
}
+/* This is a workaround to make scan working:
+ * currently mac80211 does not process frames with no frequency
+ * information.
+ * However during scan the HW performs a sweep by itself, and we
+ * are unable to know where the radio is actually tuned.
+ * This function tries to do its best to guess this information..
+ * During scan, If the current frame is a beacon or a probe response,
+ * the channel information is extracted from it.
+ * When not scanning, for other frames, or if it happens that for
+ * whatever reason we fail to parse beacons and probe responses, this
+ * function returns the priv->channel information, that should be correct
+ * at least when we are not scanning.
+ */
+static inline int at76_guess_freq(struct at76_priv *priv)
+{
+ size_t el_off;
+ const u8 *el;
+ int channel = priv->channel;
+ int len = priv->rx_skb->len;
+ struct ieee80211_hdr *hdr = (void *)priv->rx_skb->data;
+
+ if (!priv->scanning)
+ goto exit;
+
+ if (len < 24)
+ goto exit;
+
+ if (ieee80211_is_probe_resp(hdr->frame_control)) {
+ el_off = offsetof(struct ieee80211_mgmt, u.probe_resp.variable);
+ el = ((struct ieee80211_mgmt *)hdr)->u.probe_resp.variable;
+ } else if (ieee80211_is_beacon(hdr->frame_control)) {
+ el_off = offsetof(struct ieee80211_mgmt, u.beacon.variable);
+ el = ((struct ieee80211_mgmt *)hdr)->u.beacon.variable;
+ } else {
+ goto exit;
+ }
+ len -= el_off;
+
+ el = cfg80211_find_ie(WLAN_EID_DS_PARAMS, el, len);
+ if (el && el[1] > 0)
+ channel = el[2];
+
+exit:
+ return ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+}
+
static void at76_rx_tasklet(unsigned long param)
{
struct urb *urb = (struct urb *)param;
@@ -1523,6 +1590,8 @@ static void at76_rx_tasklet(unsigned long param)
rx_status.signal = buf->rssi;
rx_status.flag |= RX_FLAG_DECRYPTED;
rx_status.flag |= RX_FLAG_IV_STRIPPED;
+ rx_status.band = IEEE80211_BAND_2GHZ;
+ rx_status.freq = at76_guess_freq(priv);
at76_dbg(DBG_MAC80211, "calling ieee80211_rx_irqsafe(): %d/%d",
priv->rx_skb->len, priv->rx_skb->data_len);
@@ -1875,6 +1944,8 @@ static void at76_dwork_hw_scan(struct work_struct *work)
if (is_valid_ether_addr(priv->bssid))
at76_join(priv);
+ priv->scanning = false;
+
mutex_unlock(&priv->mtx);
ieee80211_scan_completed(priv->hw, false);
@@ -1929,6 +2000,7 @@ static int at76_hw_scan(struct ieee80211_hw *hw,
goto exit;
}
+ priv->scanning = true;
ieee80211_queue_delayed_work(priv->hw, &priv->dwork_hw_scan,
SCAN_POLL_INTERVAL);
@@ -2020,6 +2092,44 @@ static void at76_configure_filter(struct ieee80211_hw *hw,
ieee80211_queue_work(hw, &priv->work_set_promisc);
}
+static int at76_set_wep(struct at76_priv *priv)
+{
+ int ret = 0;
+ struct mib_mac_wep *mib_data = &priv->mib_buf.data.wep_mib;
+
+ priv->mib_buf.type = MIB_MAC_WEP;
+ priv->mib_buf.size = sizeof(struct mib_mac_wep);
+ priv->mib_buf.index = 0;
+
+ memset(mib_data, 0, sizeof(*mib_data));
+
+ if (priv->wep_enabled) {
+ if (priv->wep_keys_len[priv->wep_key_id] > WEP_SMALL_KEY_LEN)
+ mib_data->encryption_level = 2;
+ else
+ mib_data->encryption_level = 1;
+
+ /* always exclude unencrypted if WEP is active */
+ mib_data->exclude_unencrypted = 1;
+ } else {
+ mib_data->exclude_unencrypted = 0;
+ mib_data->encryption_level = 0;
+ }
+
+ mib_data->privacy_invoked = priv->wep_enabled;
+ mib_data->wep_default_key_id = priv->wep_key_id;
+ memcpy(mib_data->wep_default_keyvalue, priv->wep_keys,
+ sizeof(priv->wep_keys));
+
+ ret = at76_set_mib(priv, &priv->mib_buf);
+
+ if (ret < 0)
+ wiphy_err(priv->hw->wiphy,
+ "set_mib (wep) failed: %d\n", ret);
+
+ return ret;
+}
+
static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
struct ieee80211_vif *vif, struct ieee80211_sta *sta,
struct ieee80211_key_conf *key)
@@ -2062,7 +2172,7 @@ static int at76_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
priv->wep_enabled = 1;
}
- at76_startup_device(priv);
+ at76_set_wep(priv);
mutex_unlock(&priv->mtx);
@@ -2330,16 +2440,22 @@ static int at76_probe(struct usb_interface *interface,
struct usb_device *udev;
int op_mode;
int need_ext_fw = 0;
- struct mib_fw_version fwv;
+ struct mib_fw_version *fwv = NULL;
int board_type = (int)id->driver_info;
udev = usb_get_dev(interface_to_usbdev(interface));
+ fwv = kmalloc(sizeof(*fwv), GFP_KERNEL);
+ if (!fwv) {
+ ret = -ENOMEM;
+ goto exit;
+ }
+
/* Load firmware into kernel memory */
fwe = at76_load_firmware(udev, board_type);
if (!fwe) {
ret = -ENOENT;
- goto error;
+ goto exit;
}
op_mode = at76_get_op_mode(udev);
@@ -2353,7 +2469,7 @@ static int at76_probe(struct usb_interface *interface,
dev_err(&interface->dev,
"cannot handle a device in HW_CONFIG_MODE\n");
ret = -EBUSY;
- goto error;
+ goto exit;
}
if (op_mode != OPMODE_NORMAL_NIC_WITH_FLASH
@@ -2366,10 +2482,10 @@ static int at76_probe(struct usb_interface *interface,
dev_err(&interface->dev,
"error %d downloading internal firmware\n",
ret);
- goto error;
+ goto exit;
}
usb_put_dev(udev);
- return ret;
+ goto exit;
}
/* Internal firmware already inside the device. Get firmware
@@ -2382,8 +2498,8 @@ static int at76_probe(struct usb_interface *interface,
* query the device for the fw version */
if ((fwe->fw_version.major > 0 || fwe->fw_version.minor >= 100)
|| (op_mode == OPMODE_NORMAL_NIC_WITH_FLASH)) {
- ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
- if (ret < 0 || (fwv.major | fwv.minor) == 0)
+ ret = at76_get_mib(udev, MIB_FW_VERSION, fwv, sizeof(*fwv));
+ if (ret < 0 || (fwv->major | fwv->minor) == 0)
need_ext_fw = 1;
} else
/* No way to check firmware version, reload to be sure */
@@ -2394,37 +2510,37 @@ static int at76_probe(struct usb_interface *interface,
"downloading external firmware\n");
ret = at76_load_external_fw(udev, fwe);
- if (ret)
- goto error;
+ if (ret < 0)
+ goto exit;
/* Re-check firmware version */
- ret = at76_get_mib(udev, MIB_FW_VERSION, &fwv, sizeof(fwv));
+ ret = at76_get_mib(udev, MIB_FW_VERSION, fwv, sizeof(*fwv));
if (ret < 0) {
dev_err(&interface->dev,
"error %d getting firmware version\n", ret);
- goto error;
+ goto exit;
}
}
priv = at76_alloc_new_device(udev);
if (!priv) {
ret = -ENOMEM;
- goto error;
+ goto exit;
}
usb_set_intfdata(interface, priv);
- memcpy(&priv->fw_version, &fwv, sizeof(struct mib_fw_version));
+ memcpy(&priv->fw_version, fwv, sizeof(struct mib_fw_version));
priv->board_type = board_type;
ret = at76_init_new_device(priv, interface);
if (ret < 0)
at76_delete_device(priv);
- return ret;
-
-error:
- usb_put_dev(udev);
+exit:
+ kfree(fwv);
+ if (ret < 0)
+ usb_put_dev(udev);
return ret;
}
diff --git a/drivers/net/wireless/at76c50x-usb.h b/drivers/net/wireless/at76c50x-usb.h
index f14a65473fe..55090a38ac9 100644
--- a/drivers/net/wireless/at76c50x-usb.h
+++ b/drivers/net/wireless/at76c50x-usb.h
@@ -219,18 +219,6 @@ struct at76_req_join {
u8 reserved;
} __packed;
-struct set_mib_buffer {
- u8 type;
- u8 size;
- u8 index;
- u8 reserved;
- union {
- u8 byte;
- __le16 word;
- u8 addr[ETH_ALEN];
- } data;
-} __packed;
-
struct mib_local {
u16 reserved0;
u8 beacon_enable;
@@ -334,6 +322,19 @@ struct mib_mdomain {
u8 channel_list[14]; /* 0 for invalid channels */
} __packed;
+struct set_mib_buffer {
+ u8 type;
+ u8 size;
+ u8 index;
+ u8 reserved;
+ union {
+ u8 byte;
+ __le16 word;
+ u8 addr[ETH_ALEN];
+ struct mib_mac_wep wep_mib;
+ } data;
+} __packed;
+
struct at76_fw_header {
__le32 crc; /* CRC32 of the whole image */
__le32 board_type; /* firmware compatibility code */
@@ -417,6 +418,7 @@ struct at76_priv {
int scan_max_time; /* scan max channel time */
int scan_mode; /* SCAN_TYPE_ACTIVE, SCAN_TYPE_PASSIVE */
int scan_need_any; /* if set, need to scan for any ESSID */
+ bool scanning; /* if set, the scan is running */
u16 assoc_id; /* current association ID, if associated */
diff --git a/drivers/net/wireless/ath/ath10k/bmi.h b/drivers/net/wireless/ath/ath10k/bmi.h
index 3a9bdf51c96..111ab701465 100644
--- a/drivers/net/wireless/ath/ath10k/bmi.h
+++ b/drivers/net/wireless/ath/ath10k/bmi.h
@@ -201,7 +201,8 @@ int ath10k_bmi_write_memory(struct ath10k *ar, u32 address,
\
addr = host_interest_item_address(HI_ITEM(item)); \
ret = ath10k_bmi_read_memory(ar, addr, (u8 *)&tmp, 4); \
- *val = __le32_to_cpu(tmp); \
+ if (!ret) \
+ *val = __le32_to_cpu(tmp); \
ret; \
})
diff --git a/drivers/net/wireless/ath/ath10k/ce.c b/drivers/net/wireless/ath/ath10k/ce.c
index 1e4cad8632b..d185dc0cd12 100644
--- a/drivers/net/wireless/ath/ath10k/ce.c
+++ b/drivers/net/wireless/ath/ath10k/ce.c
@@ -329,6 +329,33 @@ exit:
return ret;
}
+void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe)
+{
+ struct ath10k *ar = pipe->ar;
+ struct ath10k_pci *ar_pci = ath10k_pci_priv(ar);
+ struct ath10k_ce_ring *src_ring = pipe->src_ring;
+ u32 ctrl_addr = pipe->ctrl_addr;
+
+ lockdep_assert_held(&ar_pci->ce_lock);
+
+ /*
+ * This function must be called only if there is an incomplete
+ * scatter-gather transfer (before index register is updated)
+ * that needs to be cleaned up.
+ */
+ if (WARN_ON_ONCE(src_ring->write_index == src_ring->sw_index))
+ return;
+
+ if (WARN_ON_ONCE(src_ring->write_index ==
+ ath10k_ce_src_ring_write_index_get(ar, ctrl_addr)))
+ return;
+
+ src_ring->write_index--;
+ src_ring->write_index &= src_ring->nentries_mask;
+
+ src_ring->per_transfer_context[src_ring->write_index] = NULL;
+}
+
int ath10k_ce_send(struct ath10k_ce_pipe *ce_state,
void *per_transfer_context,
u32 buffer,
diff --git a/drivers/net/wireless/ath/ath10k/ce.h b/drivers/net/wireless/ath/ath10k/ce.h
index fd0bc3561e4..7a5a36fc59c 100644
--- a/drivers/net/wireless/ath/ath10k/ce.h
+++ b/drivers/net/wireless/ath/ath10k/ce.h
@@ -160,6 +160,8 @@ int ath10k_ce_send_nolock(struct ath10k_ce_pipe *ce_state,
unsigned int transfer_id,
unsigned int flags);
+void __ath10k_ce_send_revert(struct ath10k_ce_pipe *pipe);
+
void ath10k_ce_send_cb_register(struct ath10k_ce_pipe *ce_state,
void (*send_cb)(struct ath10k_ce_pipe *),
int disable_interrupts);
diff --git a/drivers/net/wireless/ath/ath10k/core.c b/drivers/net/wireless/ath/ath10k/core.c
index 6abde37fb33..e6c56c5bb0f 100644
--- a/drivers/net/wireless/ath/ath10k/core.c
+++ b/drivers/net/wireless/ath/ath10k/core.c
@@ -58,36 +58,6 @@ static void ath10k_send_suspend_complete(struct ath10k *ar)
complete(&ar->target_suspend);
}
-static int ath10k_init_connect_htc(struct ath10k *ar)
-{
- int status;
-
- status = ath10k_wmi_connect_htc_service(ar);
- if (status)
- goto conn_fail;
-
- /* Start HTC */
- status = ath10k_htc_start(&ar->htc);
- if (status)
- goto conn_fail;
-
- /* Wait for WMI event to be ready */
- status = ath10k_wmi_wait_for_service_ready(ar);
- if (status <= 0) {
- ath10k_warn("wmi service ready event not received");
- status = -ETIMEDOUT;
- goto timeout;
- }
-
- ath10k_dbg(ATH10K_DBG_BOOT, "boot wmi ready\n");
- return 0;
-
-timeout:
- ath10k_htc_stop(&ar->htc);
-conn_fail:
- return status;
-}
-
static int ath10k_init_configure_target(struct ath10k *ar)
{
u32 param_host;
@@ -680,8 +650,9 @@ static void ath10k_core_restart(struct work_struct *work)
switch (ar->state) {
case ATH10K_STATE_ON:
- ath10k_halt(ar);
ar->state = ATH10K_STATE_RESTARTING;
+ del_timer_sync(&ar->scan.timeout);
+ ath10k_reset_scan((unsigned long)ar);
ieee80211_restart_hw(ar->hw);
break;
case ATH10K_STATE_OFF:
@@ -690,6 +661,8 @@ static void ath10k_core_restart(struct work_struct *work)
ath10k_warn("cannot restart a device that hasn't been started\n");
break;
case ATH10K_STATE_RESTARTING:
+ /* hw restart might be requested from multiple places */
+ break;
case ATH10K_STATE_RESTARTED:
ar->state = ATH10K_STATE_WEDGED;
/* fall through */
@@ -701,70 +674,6 @@ static void ath10k_core_restart(struct work_struct *work)
mutex_unlock(&ar->conf_mutex);
}
-struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
- const struct ath10k_hif_ops *hif_ops)
-{
- struct ath10k *ar;
-
- ar = ath10k_mac_create();
- if (!ar)
- return NULL;
-
- ar->ath_common.priv = ar;
- ar->ath_common.hw = ar->hw;
-
- ar->p2p = !!ath10k_p2p;
- ar->dev = dev;
-
- ar->hif.priv = hif_priv;
- ar->hif.ops = hif_ops;
-
- init_completion(&ar->scan.started);
- init_completion(&ar->scan.completed);
- init_completion(&ar->scan.on_channel);
- init_completion(&ar->target_suspend);
-
- init_completion(&ar->install_key_done);
- init_completion(&ar->vdev_setup_done);
-
- setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar);
-
- ar->workqueue = create_singlethread_workqueue("ath10k_wq");
- if (!ar->workqueue)
- goto err_wq;
-
- mutex_init(&ar->conf_mutex);
- spin_lock_init(&ar->data_lock);
-
- INIT_LIST_HEAD(&ar->peers);
- init_waitqueue_head(&ar->peer_mapping_wq);
-
- init_completion(&ar->offchan_tx_completed);
- INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
- skb_queue_head_init(&ar->offchan_tx_queue);
-
- INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
- skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
-
- INIT_WORK(&ar->restart_work, ath10k_core_restart);
-
- return ar;
-
-err_wq:
- ath10k_mac_destroy(ar);
- return NULL;
-}
-EXPORT_SYMBOL(ath10k_core_create);
-
-void ath10k_core_destroy(struct ath10k *ar)
-{
- flush_workqueue(ar->workqueue);
- destroy_workqueue(ar->workqueue);
-
- ath10k_mac_destroy(ar);
-}
-EXPORT_SYMBOL(ath10k_core_destroy);
-
int ath10k_core_start(struct ath10k *ar)
{
int status;
@@ -805,10 +714,28 @@ int ath10k_core_start(struct ath10k *ar)
goto err;
}
+ status = ath10k_htt_init(ar);
+ if (status) {
+ ath10k_err("failed to init htt: %d\n", status);
+ goto err_wmi_detach;
+ }
+
+ status = ath10k_htt_tx_alloc(&ar->htt);
+ if (status) {
+ ath10k_err("failed to alloc htt tx: %d\n", status);
+ goto err_wmi_detach;
+ }
+
+ status = ath10k_htt_rx_alloc(&ar->htt);
+ if (status) {
+ ath10k_err("failed to alloc htt rx: %d\n", status);
+ goto err_htt_tx_detach;
+ }
+
status = ath10k_hif_start(ar);
if (status) {
ath10k_err("could not start HIF: %d\n", status);
- goto err_wmi_detach;
+ goto err_htt_rx_detach;
}
status = ath10k_htc_wait_target(&ar->htc);
@@ -817,15 +744,30 @@ int ath10k_core_start(struct ath10k *ar)
goto err_hif_stop;
}
- status = ath10k_htt_attach(ar);
+ status = ath10k_htt_connect(&ar->htt);
if (status) {
- ath10k_err("could not attach htt (%d)\n", status);
+ ath10k_err("failed to connect htt (%d)\n", status);
goto err_hif_stop;
}
- status = ath10k_init_connect_htc(ar);
- if (status)
- goto err_htt_detach;
+ status = ath10k_wmi_connect(ar);
+ if (status) {
+ ath10k_err("could not connect wmi: %d\n", status);
+ goto err_hif_stop;
+ }
+
+ status = ath10k_htc_start(&ar->htc);
+ if (status) {
+ ath10k_err("failed to start htc: %d\n", status);
+ goto err_hif_stop;
+ }
+
+ status = ath10k_wmi_wait_for_service_ready(ar);
+ if (status <= 0) {
+ ath10k_warn("wmi service ready event not received");
+ status = -ETIMEDOUT;
+ goto err_htc_stop;
+ }
ath10k_dbg(ATH10K_DBG_BOOT, "firmware %s booted\n",
ar->hw->wiphy->fw_version);
@@ -833,25 +775,31 @@ int ath10k_core_start(struct ath10k *ar)
status = ath10k_wmi_cmd_init(ar);
if (status) {
ath10k_err("could not send WMI init command (%d)\n", status);
- goto err_disconnect_htc;
+ goto err_htc_stop;
}
status = ath10k_wmi_wait_for_unified_ready(ar);
if (status <= 0) {
ath10k_err("wmi unified ready event not received\n");
status = -ETIMEDOUT;
- goto err_disconnect_htc;
+ goto err_htc_stop;
}
- status = ath10k_htt_attach_target(&ar->htt);
- if (status)
- goto err_disconnect_htc;
+ status = ath10k_htt_setup(&ar->htt);
+ if (status) {
+ ath10k_err("failed to setup htt: %d\n", status);
+ goto err_htc_stop;
+ }
status = ath10k_debug_start(ar);
if (status)
- goto err_disconnect_htc;
+ goto err_htc_stop;
+
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features))
+ ar->free_vdev_map = (1 << TARGET_10X_NUM_VDEVS) - 1;
+ else
+ ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
- ar->free_vdev_map = (1 << TARGET_NUM_VDEVS) - 1;
INIT_LIST_HEAD(&ar->arvifs);
if (!test_bit(ATH10K_FLAG_FIRST_BOOT_DONE, &ar->dev_flags))
@@ -868,12 +816,14 @@ int ath10k_core_start(struct ath10k *ar)
return 0;
-err_disconnect_htc:
+err_htc_stop:
ath10k_htc_stop(&ar->htc);
-err_htt_detach:
- ath10k_htt_detach(&ar->htt);
err_hif_stop:
ath10k_hif_stop(ar);
+err_htt_rx_detach:
+ ath10k_htt_rx_free(&ar->htt);
+err_htt_tx_detach:
+ ath10k_htt_tx_free(&ar->htt);
err_wmi_detach:
ath10k_wmi_detach(ar);
err:
@@ -908,10 +858,14 @@ void ath10k_core_stop(struct ath10k *ar)
lockdep_assert_held(&ar->conf_mutex);
/* try to suspend target */
- ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
+ if (ar->state != ATH10K_STATE_RESTARTING)
+ ath10k_wait_for_suspend(ar, WMI_PDEV_SUSPEND_AND_DISABLE_INTR);
+
ath10k_debug_stop(ar);
ath10k_htc_stop(&ar->htc);
- ath10k_htt_detach(&ar->htt);
+ ath10k_hif_stop(ar);
+ ath10k_htt_tx_free(&ar->htt);
+ ath10k_htt_rx_free(&ar->htt);
ath10k_wmi_detach(ar);
}
EXPORT_SYMBOL(ath10k_core_stop);
@@ -1003,22 +957,15 @@ static int ath10k_core_check_chip_id(struct ath10k *ar)
return 0;
}
-int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+static void ath10k_core_register_work(struct work_struct *work)
{
+ struct ath10k *ar = container_of(work, struct ath10k, register_work);
int status;
- ar->chip_id = chip_id;
-
- status = ath10k_core_check_chip_id(ar);
- if (status) {
- ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
- return status;
- }
-
status = ath10k_core_probe_fw(ar);
if (status) {
ath10k_err("could not probe fw (%d)\n", status);
- return status;
+ goto err;
}
status = ath10k_mac_register(ar);
@@ -1033,18 +980,43 @@ int ath10k_core_register(struct ath10k *ar, u32 chip_id)
goto err_unregister_mac;
}
- return 0;
+ set_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags);
+ return;
err_unregister_mac:
ath10k_mac_unregister(ar);
err_release_fw:
ath10k_core_free_firmware_files(ar);
- return status;
+err:
+ device_release_driver(ar->dev);
+ return;
+}
+
+int ath10k_core_register(struct ath10k *ar, u32 chip_id)
+{
+ int status;
+
+ ar->chip_id = chip_id;
+
+ status = ath10k_core_check_chip_id(ar);
+ if (status) {
+ ath10k_err("Unsupported chip id 0x%08x\n", ar->chip_id);
+ return status;
+ }
+
+ queue_work(ar->workqueue, &ar->register_work);
+
+ return 0;
}
EXPORT_SYMBOL(ath10k_core_register);
void ath10k_core_unregister(struct ath10k *ar)
{
+ cancel_work_sync(&ar->register_work);
+
+ if (!test_bit(ATH10K_FLAG_CORE_REGISTERED, &ar->dev_flags))
+ return;
+
/* We must unregister from mac80211 before we stop HTC and HIF.
* Otherwise we will fail to submit commands to FW and mac80211 will be
* unhappy about callback failures. */
@@ -1056,6 +1028,71 @@ void ath10k_core_unregister(struct ath10k *ar)
}
EXPORT_SYMBOL(ath10k_core_unregister);
+struct ath10k *ath10k_core_create(void *hif_priv, struct device *dev,
+ const struct ath10k_hif_ops *hif_ops)
+{
+ struct ath10k *ar;
+
+ ar = ath10k_mac_create();
+ if (!ar)
+ return NULL;
+
+ ar->ath_common.priv = ar;
+ ar->ath_common.hw = ar->hw;
+
+ ar->p2p = !!ath10k_p2p;
+ ar->dev = dev;
+
+ ar->hif.priv = hif_priv;
+ ar->hif.ops = hif_ops;
+
+ init_completion(&ar->scan.started);
+ init_completion(&ar->scan.completed);
+ init_completion(&ar->scan.on_channel);
+ init_completion(&ar->target_suspend);
+
+ init_completion(&ar->install_key_done);
+ init_completion(&ar->vdev_setup_done);
+
+ setup_timer(&ar->scan.timeout, ath10k_reset_scan, (unsigned long)ar);
+
+ ar->workqueue = create_singlethread_workqueue("ath10k_wq");
+ if (!ar->workqueue)
+ goto err_wq;
+
+ mutex_init(&ar->conf_mutex);
+ spin_lock_init(&ar->data_lock);
+
+ INIT_LIST_HEAD(&ar->peers);
+ init_waitqueue_head(&ar->peer_mapping_wq);
+
+ init_completion(&ar->offchan_tx_completed);
+ INIT_WORK(&ar->offchan_tx_work, ath10k_offchan_tx_work);
+ skb_queue_head_init(&ar->offchan_tx_queue);
+
+ INIT_WORK(&ar->wmi_mgmt_tx_work, ath10k_mgmt_over_wmi_tx_work);
+ skb_queue_head_init(&ar->wmi_mgmt_tx_queue);
+
+ INIT_WORK(&ar->register_work, ath10k_core_register_work);
+ INIT_WORK(&ar->restart_work, ath10k_core_restart);
+
+ return ar;
+
+err_wq:
+ ath10k_mac_destroy(ar);
+ return NULL;
+}
+EXPORT_SYMBOL(ath10k_core_create);
+
+void ath10k_core_destroy(struct ath10k *ar)
+{
+ flush_workqueue(ar->workqueue);
+ destroy_workqueue(ar->workqueue);
+
+ ath10k_mac_destroy(ar);
+}
+EXPORT_SYMBOL(ath10k_core_destroy);
+
MODULE_AUTHOR("Qualcomm Atheros");
MODULE_DESCRIPTION("Core module for QCA988X PCIe devices.");
MODULE_LICENSE("Dual BSD/GPL");
diff --git a/drivers/net/wireless/ath/ath10k/core.h b/drivers/net/wireless/ath/ath10k/core.h
index 2c1dfd71914..68ceef61933 100644
--- a/drivers/net/wireless/ath/ath10k/core.h
+++ b/drivers/net/wireless/ath/ath10k/core.h
@@ -335,6 +335,7 @@ enum ath10k_dev_flags {
/* Indicates that ath10k device is during CAC phase of DFS */
ATH10K_CAC_RUNNING,
ATH10K_FLAG_FIRST_BOOT_DONE,
+ ATH10K_FLAG_CORE_REGISTERED,
};
struct ath10k {
@@ -440,6 +441,12 @@ struct ath10k {
bool radar_enabled;
int num_started_vdevs;
+ /* Protected by conf-mutex */
+ u8 supp_tx_chainmask;
+ u8 supp_rx_chainmask;
+ u8 cfg_tx_chainmask;
+ u8 cfg_rx_chainmask;
+
struct wmi_pdev_set_wmm_params_arg wmm_params;
struct completion install_key_done;
@@ -470,6 +477,7 @@ struct ath10k {
enum ath10k_state state;
+ struct work_struct register_work;
struct work_struct restart_work;
/* cycle count is reported twice for each visited channel during scan.
diff --git a/drivers/net/wireless/ath/ath10k/htc.c b/drivers/net/wireless/ath/ath10k/htc.c
index 5b58dbb1741..e493db4b4a4 100644
--- a/drivers/net/wireless/ath/ath10k/htc.c
+++ b/drivers/net/wireless/ath/ath10k/htc.c
@@ -830,17 +830,11 @@ int ath10k_htc_start(struct ath10k_htc *htc)
return 0;
}
-/*
- * stop HTC communications, i.e. stop interrupt reception, and flush all
- * queued buffers
- */
void ath10k_htc_stop(struct ath10k_htc *htc)
{
spin_lock_bh(&htc->tx_lock);
htc->stopped = true;
spin_unlock_bh(&htc->tx_lock);
-
- ath10k_hif_stop(htc->ar);
}
/* registered target arrival callback from the HIF layer */
diff --git a/drivers/net/wireless/ath/ath10k/htt.c b/drivers/net/wireless/ath/ath10k/htt.c
index 69697af59ce..19c12cc8d66 100644
--- a/drivers/net/wireless/ath/ath10k/htt.c
+++ b/drivers/net/wireless/ath/ath10k/htt.c
@@ -22,7 +22,7 @@
#include "core.h"
#include "debug.h"
-static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
+int ath10k_htt_connect(struct ath10k_htt *htt)
{
struct ath10k_htc_svc_conn_req conn_req;
struct ath10k_htc_svc_conn_resp conn_resp;
@@ -48,39 +48,14 @@ static int ath10k_htt_htc_attach(struct ath10k_htt *htt)
return 0;
}
-int ath10k_htt_attach(struct ath10k *ar)
+int ath10k_htt_init(struct ath10k *ar)
{
struct ath10k_htt *htt = &ar->htt;
- int ret;
htt->ar = ar;
htt->max_throughput_mbps = 800;
/*
- * Connect to HTC service.
- * This has to be done before calling ath10k_htt_rx_attach,
- * since ath10k_htt_rx_attach involves sending a rx ring configure
- * message to the target.
- */
- ret = ath10k_htt_htc_attach(htt);
- if (ret) {
- ath10k_err("could not attach htt htc (%d)\n", ret);
- goto err_htc_attach;
- }
-
- ret = ath10k_htt_tx_attach(htt);
- if (ret) {
- ath10k_err("could not attach htt tx (%d)\n", ret);
- goto err_htc_attach;
- }
-
- ret = ath10k_htt_rx_attach(htt);
- if (ret) {
- ath10k_err("could not attach htt rx (%d)\n", ret);
- goto err_rx_attach;
- }
-
- /*
* Prefetch enough data to satisfy target
* classification engine.
* This is for LL chips. HL chips will probably
@@ -93,11 +68,6 @@ int ath10k_htt_attach(struct ath10k *ar)
2; /* ip4 dscp or ip6 priority */
return 0;
-
-err_rx_attach:
- ath10k_htt_tx_detach(htt);
-err_htc_attach:
- return ret;
}
#define HTT_TARGET_VERSION_TIMEOUT_HZ (3*HZ)
@@ -117,7 +87,7 @@ static int ath10k_htt_verify_version(struct ath10k_htt *htt)
return 0;
}
-int ath10k_htt_attach_target(struct ath10k_htt *htt)
+int ath10k_htt_setup(struct ath10k_htt *htt)
{
int status;
@@ -140,9 +110,3 @@ int ath10k_htt_attach_target(struct ath10k_htt *htt)
return ath10k_htt_send_rx_ring_cfg_ll(htt);
}
-
-void ath10k_htt_detach(struct ath10k_htt *htt)
-{
- ath10k_htt_rx_detach(htt);
- ath10k_htt_tx_detach(htt);
-}
diff --git a/drivers/net/wireless/ath/ath10k/htt.h b/drivers/net/wireless/ath/ath10k/htt.h
index 645a563e3fb..9a263462c79 100644
--- a/drivers/net/wireless/ath/ath10k/htt.h
+++ b/drivers/net/wireless/ath/ath10k/htt.h
@@ -1328,14 +1328,16 @@ struct htt_rx_desc {
#define HTT_LOG2_MAX_CACHE_LINE_SIZE 7 /* 2^7 = 128 */
#define HTT_MAX_CACHE_LINE_SIZE_MASK ((1 << HTT_LOG2_MAX_CACHE_LINE_SIZE) - 1)
-int ath10k_htt_attach(struct ath10k *ar);
-int ath10k_htt_attach_target(struct ath10k_htt *htt);
-void ath10k_htt_detach(struct ath10k_htt *htt);
-
-int ath10k_htt_tx_attach(struct ath10k_htt *htt);
-void ath10k_htt_tx_detach(struct ath10k_htt *htt);
-int ath10k_htt_rx_attach(struct ath10k_htt *htt);
-void ath10k_htt_rx_detach(struct ath10k_htt *htt);
+int ath10k_htt_connect(struct ath10k_htt *htt);
+int ath10k_htt_init(struct ath10k *ar);
+int ath10k_htt_setup(struct ath10k_htt *htt);
+
+int ath10k_htt_tx_alloc(struct ath10k_htt *htt);
+void ath10k_htt_tx_free(struct ath10k_htt *htt);
+
+int ath10k_htt_rx_alloc(struct ath10k_htt *htt);
+void ath10k_htt_rx_free(struct ath10k_htt *htt);
+
void ath10k_htt_htc_tx_complete(struct ath10k *ar, struct sk_buff *skb);
void ath10k_htt_t2h_msg_handler(struct ath10k *ar, struct sk_buff *skb);
int ath10k_htt_h2t_ver_req_msg(struct ath10k_htt *htt);
diff --git a/drivers/net/wireless/ath/ath10k/htt_rx.c b/drivers/net/wireless/ath/ath10k/htt_rx.c
index f85a3cf6da3..eebc860c365 100644
--- a/drivers/net/wireless/ath/ath10k/htt_rx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_rx.c
@@ -225,10 +225,26 @@ static void ath10k_htt_rx_ring_refill_retry(unsigned long arg)
ath10k_htt_rx_msdu_buff_replenish(htt);
}
-void ath10k_htt_rx_detach(struct ath10k_htt *htt)
+static void ath10k_htt_rx_ring_clean_up(struct ath10k_htt *htt)
{
- int sw_rd_idx = htt->rx_ring.sw_rd_idx.msdu_payld;
+ struct sk_buff *skb;
+ int i;
+
+ for (i = 0; i < htt->rx_ring.size; i++) {
+ skb = htt->rx_ring.netbufs_ring[i];
+ if (!skb)
+ continue;
+ dma_unmap_single(htt->ar->dev, ATH10K_SKB_CB(skb)->paddr,
+ skb->len + skb_tailroom(skb),
+ DMA_FROM_DEVICE);
+ dev_kfree_skb_any(skb);
+ htt->rx_ring.netbufs_ring[i] = NULL;
+ }
+}
+
+void ath10k_htt_rx_free(struct ath10k_htt *htt)
+{
del_timer_sync(&htt->rx_ring.refill_retry_timer);
tasklet_kill(&htt->rx_replenish_task);
tasklet_kill(&htt->txrx_compl_task);
@@ -236,18 +252,7 @@ void ath10k_htt_rx_detach(struct ath10k_htt *htt)
skb_queue_purge(&htt->tx_compl_q);
skb_queue_purge(&htt->rx_compl_q);
- while (sw_rd_idx != __le32_to_cpu(*(htt->rx_ring.alloc_idx.vaddr))) {
- struct sk_buff *skb =
- htt->rx_ring.netbufs_ring[sw_rd_idx];
- struct ath10k_skb_cb *cb = ATH10K_SKB_CB(skb);
-
- dma_unmap_single(htt->ar->dev, cb->paddr,
- skb->len + skb_tailroom(skb),
- DMA_FROM_DEVICE);
- dev_kfree_skb_any(htt->rx_ring.netbufs_ring[sw_rd_idx]);
- sw_rd_idx++;
- sw_rd_idx &= htt->rx_ring.size_mask;
- }
+ ath10k_htt_rx_ring_clean_up(htt);
dma_free_coherent(htt->ar->dev,
(htt->rx_ring.size *
@@ -277,6 +282,7 @@ static inline struct sk_buff *ath10k_htt_rx_netbuf_pop(struct ath10k_htt *htt)
idx = htt->rx_ring.sw_rd_idx.msdu_payld;
msdu = htt->rx_ring.netbufs_ring[idx];
+ htt->rx_ring.netbufs_ring[idx] = NULL;
idx++;
idx &= htt->rx_ring.size_mask;
@@ -399,7 +405,6 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu_len = MS(__le32_to_cpu(rx_desc->msdu_start.info0),
RX_MSDU_START_INFO0_MSDU_LENGTH);
msdu_chained = rx_desc->frag_info.ring2_more_count;
- msdu_chaining = msdu_chained;
if (msdu_len_invalid)
msdu_len = 0;
@@ -427,6 +432,7 @@ static int ath10k_htt_rx_amsdu_pop(struct ath10k_htt *htt,
msdu->next = next;
msdu = next;
+ msdu_chaining = 1;
}
last_msdu = __le32_to_cpu(rx_desc->msdu_end.info0) &
@@ -468,7 +474,7 @@ static void ath10k_htt_rx_replenish_task(unsigned long ptr)
ath10k_htt_rx_msdu_buff_replenish(htt);
}
-int ath10k_htt_rx_attach(struct ath10k_htt *htt)
+int ath10k_htt_rx_alloc(struct ath10k_htt *htt)
{
dma_addr_t paddr;
void *vaddr;
@@ -494,7 +500,7 @@ int ath10k_htt_rx_attach(struct ath10k_htt *htt)
htt->rx_ring.fill_level = ath10k_htt_rx_ring_fill_level(htt);
htt->rx_ring.netbufs_ring =
- kmalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
+ kzalloc(htt->rx_ring.size * sizeof(struct sk_buff *),
GFP_KERNEL);
if (!htt->rx_ring.netbufs_ring)
goto err_netbuf;
@@ -754,17 +760,30 @@ static void ath10k_htt_rx_h_rates(struct ath10k *ar,
static void ath10k_htt_rx_h_protected(struct ath10k_htt *htt,
struct ieee80211_rx_status *rx_status,
struct sk_buff *skb,
- enum htt_rx_mpdu_encrypt_type enctype)
+ enum htt_rx_mpdu_encrypt_type enctype,
+ enum rx_msdu_decap_format fmt,
+ bool dot11frag)
{
struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
+ rx_status->flag &= ~(RX_FLAG_DECRYPTED |
+ RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED);
- if (enctype == HTT_RX_MPDU_ENCRYPT_NONE) {
- rx_status->flag &= ~(RX_FLAG_DECRYPTED |
- RX_FLAG_IV_STRIPPED |
- RX_FLAG_MMIC_STRIPPED);
+ if (enctype == HTT_RX_MPDU_ENCRYPT_NONE)
+ return;
+
+ /*
+ * There's no explicit rx descriptor flag to indicate whether a given
+ * frame has been decrypted or not. We're forced to use the decap
+ * format as an implicit indication. However fragmentation rx is always
+ * raw and it probably never reports undecrypted raws.
+ *
+ * This makes sure sniffed frames are reported as-is without stripping
+ * the protected flag.
+ */
+ if (fmt == RX_MSDU_DECAP_RAW && !dot11frag)
return;
- }
rx_status->flag |= RX_FLAG_DECRYPTED |
RX_FLAG_IV_STRIPPED |
@@ -918,7 +937,8 @@ static void ath10k_htt_rx_amsdu(struct ath10k_htt *htt,
}
skb_in = skb;
- ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype);
+ ath10k_htt_rx_h_protected(htt, rx_status, skb_in, enctype, fmt,
+ false);
skb = skb->next;
skb_in->next = NULL;
@@ -1000,7 +1020,7 @@ static void ath10k_htt_rx_msdu(struct ath10k_htt *htt,
break;
}
- ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype);
+ ath10k_htt_rx_h_protected(htt, rx_status, skb, enctype, fmt, false);
ath10k_process_rx(htt->ar, rx_status, skb);
}
@@ -1288,6 +1308,7 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
}
/* FIXME: implement signal strength */
+ rx_status->flag |= RX_FLAG_NO_SIGNAL_VAL;
hdr = (struct ieee80211_hdr *)msdu_head->data;
rxd = (void *)msdu_head->data - sizeof(*rxd);
@@ -1306,7 +1327,8 @@ static void ath10k_htt_rx_frag_handler(struct ath10k_htt *htt,
enctype = MS(__le32_to_cpu(rxd->mpdu_start.info0),
RX_MPDU_START_INFO0_ENCRYPT_TYPE);
- ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype);
+ ath10k_htt_rx_h_protected(htt, rx_status, msdu_head, enctype, fmt,
+ true);
msdu_head->ip_summed = ath10k_htt_rx_get_csum_state(msdu_head);
if (tkip_mic_err)
diff --git a/drivers/net/wireless/ath/ath10k/htt_tx.c b/drivers/net/wireless/ath/ath10k/htt_tx.c
index 7a3e2e40dd5..7064354d1f4 100644
--- a/drivers/net/wireless/ath/ath10k/htt_tx.c
+++ b/drivers/net/wireless/ath/ath10k/htt_tx.c
@@ -83,7 +83,7 @@ void ath10k_htt_tx_free_msdu_id(struct ath10k_htt *htt, u16 msdu_id)
__clear_bit(msdu_id, htt->used_msdu_ids);
}
-int ath10k_htt_tx_attach(struct ath10k_htt *htt)
+int ath10k_htt_tx_alloc(struct ath10k_htt *htt)
{
spin_lock_init(&htt->tx_lock);
init_waitqueue_head(&htt->empty_tx_wq);
@@ -120,7 +120,7 @@ int ath10k_htt_tx_attach(struct ath10k_htt *htt)
return 0;
}
-static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
+static void ath10k_htt_tx_free_pending(struct ath10k_htt *htt)
{
struct htt_tx_done tx_done = {0};
int msdu_id;
@@ -141,9 +141,9 @@ static void ath10k_htt_tx_cleanup_pending(struct ath10k_htt *htt)
spin_unlock_bh(&htt->tx_lock);
}
-void ath10k_htt_tx_detach(struct ath10k_htt *htt)
+void ath10k_htt_tx_free(struct ath10k_htt *htt)
{
- ath10k_htt_tx_cleanup_pending(htt);
+ ath10k_htt_tx_free_pending(htt);
kfree(htt->pending_tx);
kfree(htt->used_msdu_ids);
dma_pool_destroy(htt->tx_pool);
diff --git a/drivers/net/wireless/ath/ath10k/mac.c b/drivers/net/wireless/ath/ath10k/mac.c
index 0ac5437492f..a21080028c5 100644
--- a/drivers/net/wireless/ath/ath10k/mac.c
+++ b/drivers/net/wireless/ath/ath10k/mac.c
@@ -54,7 +54,10 @@ static int ath10k_send_key(struct ath10k_vif *arvif,
switch (key->cipher) {
case WLAN_CIPHER_SUITE_CCMP:
arg.key_cipher = WMI_CIPHER_AES_CCM;
- key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
+ if (arvif->vdev_type == WMI_VDEV_TYPE_AP)
+ key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV_MGMT;
+ else
+ key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
break;
case WLAN_CIPHER_SUITE_TKIP:
arg.key_cipher = WMI_CIPHER_TKIP;
@@ -1888,8 +1891,13 @@ static void ath10k_tx_wep_key_work(struct work_struct *work)
wep_key_work);
int ret, keyidx = arvif->def_wep_key_newidx;
+ mutex_lock(&arvif->ar->conf_mutex);
+
+ if (arvif->ar->state != ATH10K_STATE_ON)
+ goto unlock;
+
if (arvif->def_wep_key_idx == keyidx)
- return;
+ goto unlock;
ath10k_dbg(ATH10K_DBG_MAC, "mac vdev %d set keyidx %d\n",
arvif->vdev_id, keyidx);
@@ -1902,10 +1910,13 @@ static void ath10k_tx_wep_key_work(struct work_struct *work)
ath10k_warn("failed to update wep key index for vdev %d: %d\n",
arvif->vdev_id,
ret);
- return;
+ goto unlock;
}
arvif->def_wep_key_idx = keyidx;
+
+unlock:
+ mutex_unlock(&arvif->ar->conf_mutex);
}
static void ath10k_tx_h_update_wep_key(struct sk_buff *skb)
@@ -2286,11 +2297,23 @@ static void ath10k_tx(struct ieee80211_hw *hw,
ath10k_tx_htt(ar, skb);
}
-/*
- * Initialize various parameters with default vaules.
- */
+/* Must not be called with conf_mutex held as workers can use that also. */
+static void ath10k_drain_tx(struct ath10k *ar)
+{
+ /* make sure rcu-protected mac80211 tx path itself is drained */
+ synchronize_net();
+
+ ath10k_offchan_tx_purge(ar);
+ ath10k_mgmt_over_wmi_tx_purge(ar);
+
+ cancel_work_sync(&ar->offchan_tx_work);
+ cancel_work_sync(&ar->wmi_mgmt_tx_work);
+}
+
void ath10k_halt(struct ath10k *ar)
{
+ struct ath10k_vif *arvif;
+
lockdep_assert_held(&ar->conf_mutex);
if (ath10k_monitor_is_enabled(ar)) {
@@ -2301,61 +2324,144 @@ void ath10k_halt(struct ath10k *ar)
}
del_timer_sync(&ar->scan.timeout);
- ath10k_offchan_tx_purge(ar);
- ath10k_mgmt_over_wmi_tx_purge(ar);
+ ath10k_reset_scan((unsigned long)ar);
ath10k_peer_cleanup_all(ar);
ath10k_core_stop(ar);
ath10k_hif_power_down(ar);
spin_lock_bh(&ar->data_lock);
- if (ar->scan.in_progress) {
- del_timer(&ar->scan.timeout);
- ar->scan.in_progress = false;
- ieee80211_scan_completed(ar->hw, true);
+ list_for_each_entry(arvif, &ar->arvifs, list) {
+ if (!arvif->beacon)
+ continue;
+
+ dma_unmap_single(arvif->ar->dev,
+ ATH10K_SKB_CB(arvif->beacon)->paddr,
+ arvif->beacon->len, DMA_TO_DEVICE);
+ dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
}
spin_unlock_bh(&ar->data_lock);
}
+static int ath10k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
+{
+ struct ath10k *ar = hw->priv;
+
+ mutex_lock(&ar->conf_mutex);
+
+ if (ar->cfg_tx_chainmask) {
+ *tx_ant = ar->cfg_tx_chainmask;
+ *rx_ant = ar->cfg_rx_chainmask;
+ } else {
+ *tx_ant = ar->supp_tx_chainmask;
+ *rx_ant = ar->supp_rx_chainmask;
+ }
+
+ mutex_unlock(&ar->conf_mutex);
+
+ return 0;
+}
+
+static int __ath10k_set_antenna(struct ath10k *ar, u32 tx_ant, u32 rx_ant)
+{
+ int ret;
+
+ lockdep_assert_held(&ar->conf_mutex);
+
+ ar->cfg_tx_chainmask = tx_ant;
+ ar->cfg_rx_chainmask = rx_ant;
+
+ if ((ar->state != ATH10K_STATE_ON) &&
+ (ar->state != ATH10K_STATE_RESTARTED))
+ return 0;
+
+ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->tx_chain_mask,
+ tx_ant);
+ if (ret) {
+ ath10k_warn("failed to set tx-chainmask: %d, req 0x%x\n",
+ ret, tx_ant);
+ return ret;
+ }
+
+ ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->rx_chain_mask,
+ rx_ant);
+ if (ret) {
+ ath10k_warn("failed to set rx-chainmask: %d, req 0x%x\n",
+ ret, rx_ant);
+ return ret;
+ }
+
+ return 0;
+}
+
+static int ath10k_set_antenna(struct ieee80211_hw *hw, u32 tx_ant, u32 rx_ant)
+{
+ struct ath10k *ar = hw->priv;
+ int ret;
+
+ mutex_lock(&ar->conf_mutex);
+ ret = __ath10k_set_antenna(ar, tx_ant, rx_ant);
+ mutex_unlock(&ar->conf_mutex);
+ return ret;
+}
+
static int ath10k_start(struct ieee80211_hw *hw)
{
struct ath10k *ar = hw->priv;
int ret = 0;
+ /*
+ * This makes sense only when restarting hw. It is harmless to call
+ * uncoditionally. This is necessary to make sure no HTT/WMI tx
+ * commands will be submitted while restarting.
+ */
+ ath10k_drain_tx(ar);
+
mutex_lock(&ar->conf_mutex);
- if (ar->state != ATH10K_STATE_OFF &&
- ar->state != ATH10K_STATE_RESTARTING) {
+ switch (ar->state) {
+ case ATH10K_STATE_OFF:
+ ar->state = ATH10K_STATE_ON;
+ break;
+ case ATH10K_STATE_RESTARTING:
+ ath10k_halt(ar);
+ ar->state = ATH10K_STATE_RESTARTED;
+ break;
+ case ATH10K_STATE_ON:
+ case ATH10K_STATE_RESTARTED:
+ case ATH10K_STATE_WEDGED:
+ WARN_ON(1);
ret = -EINVAL;
- goto exit;
+ goto err;
}
ret = ath10k_hif_power_up(ar);
if (ret) {
ath10k_err("Could not init hif: %d\n", ret);
- ar->state = ATH10K_STATE_OFF;
- goto exit;
+ goto err_off;
}
ret = ath10k_core_start(ar);
if (ret) {
ath10k_err("Could not init core: %d\n", ret);
- ath10k_hif_power_down(ar);
- ar->state = ATH10K_STATE_OFF;
- goto exit;
+ goto err_power_down;
}
- if (ar->state == ATH10K_STATE_OFF)
- ar->state = ATH10K_STATE_ON;
- else if (ar->state == ATH10K_STATE_RESTARTING)
- ar->state = ATH10K_STATE_RESTARTED;
-
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->pmf_qos, 1);
- if (ret)
+ if (ret) {
ath10k_warn("failed to enable PMF QOS: %d\n", ret);
+ goto err_core_stop;
+ }
ret = ath10k_wmi_pdev_set_param(ar, ar->wmi.pdev_param->dynamic_bw, 1);
- if (ret)
+ if (ret) {
ath10k_warn("failed to enable dynamic BW: %d\n", ret);
+ goto err_core_stop;
+ }
+
+ if (ar->cfg_tx_chainmask)
+ __ath10k_set_antenna(ar, ar->cfg_tx_chainmask,
+ ar->cfg_rx_chainmask);
/*
* By default FW set ARP frames ac to voice (6). In that case ARP
@@ -2371,14 +2477,25 @@ static int ath10k_start(struct ieee80211_hw *hw)
if (ret) {
ath10k_warn("failed to set arp ac override parameter: %d\n",
ret);
- goto exit;
+ goto err_core_stop;
}
ar->num_started_vdevs = 0;
ath10k_regd_update(ar);
- ret = 0;
-exit:
+ mutex_unlock(&ar->conf_mutex);
+ return 0;
+
+err_core_stop:
+ ath10k_core_stop(ar);
+
+err_power_down:
+ ath10k_hif_power_down(ar);
+
+err_off:
+ ar->state = ATH10K_STATE_OFF;
+
+err:
mutex_unlock(&ar->conf_mutex);
return ret;
}
@@ -2387,19 +2504,15 @@ static void ath10k_stop(struct ieee80211_hw *hw)
{
struct ath10k *ar = hw->priv;
+ ath10k_drain_tx(ar);
+
mutex_lock(&ar->conf_mutex);
- if (ar->state == ATH10K_STATE_ON ||
- ar->state == ATH10K_STATE_RESTARTED ||
- ar->state == ATH10K_STATE_WEDGED)
+ if (ar->state != ATH10K_STATE_OFF) {
ath10k_halt(ar);
-
- ar->state = ATH10K_STATE_OFF;
+ ar->state = ATH10K_STATE_OFF;
+ }
mutex_unlock(&ar->conf_mutex);
- ath10k_mgmt_over_wmi_tx_purge(ar);
-
- cancel_work_sync(&ar->offchan_tx_work);
- cancel_work_sync(&ar->wmi_mgmt_tx_work);
cancel_work_sync(&ar->restart_work);
}
@@ -2771,6 +2884,9 @@ static void ath10k_remove_interface(struct ieee80211_hw *hw,
spin_lock_bh(&ar->data_lock);
if (arvif->beacon) {
+ dma_unmap_single(arvif->ar->dev,
+ ATH10K_SKB_CB(arvif->beacon)->paddr,
+ arvif->beacon->len, DMA_TO_DEVICE);
dev_kfree_skb_any(arvif->beacon);
arvif->beacon = NULL;
}
@@ -2909,7 +3025,12 @@ static void ath10k_bss_info_changed(struct ieee80211_hw *hw,
arvif->u.ap.hidden_ssid = info->hidden_ssid;
}
- if (changed & BSS_CHANGED_BSSID) {
+ /*
+ * Firmware manages AP self-peer internally so make sure to not create
+ * it in driver. Otherwise AP self-peer deletion may timeout later.
+ */
+ if (changed & BSS_CHANGED_BSSID &&
+ vif->type != NL80211_IFTYPE_AP) {
if (!is_zero_ether_addr(info->bssid)) {
ath10k_dbg(ATH10K_DBG_MAC,
"mac vdev %d create peer %pM\n",
@@ -4126,14 +4247,6 @@ static int ath10k_set_bitrate_mask(struct ieee80211_hw *hw,
fixed_nss, force_sgi);
}
-static void ath10k_channel_switch_beacon(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_chan_def *chandef)
-{
- /* there's no need to do anything here. vif->csa_active is enough */
- return;
-}
-
static void ath10k_sta_rc_update(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
struct ieee80211_sta *sta,
@@ -4237,10 +4350,11 @@ static const struct ieee80211_ops ath10k_ops = {
.set_frag_threshold = ath10k_set_frag_threshold,
.flush = ath10k_flush,
.tx_last_beacon = ath10k_tx_last_beacon,
+ .set_antenna = ath10k_set_antenna,
+ .get_antenna = ath10k_get_antenna,
.restart_complete = ath10k_restart_complete,
.get_survey = ath10k_get_survey,
.set_bitrate_mask = ath10k_set_bitrate_mask,
- .channel_switch_beacon = ath10k_channel_switch_beacon,
.sta_rc_update = ath10k_sta_rc_update,
.get_tsf = ath10k_get_tsf,
#ifdef CONFIG_PM
@@ -4586,6 +4700,18 @@ int ath10k_mac_register(struct ath10k *ar)
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_AP);
+ if (test_bit(ATH10K_FW_FEATURE_WMI_10X, ar->fw_features)) {
+ /* TODO: Have to deal with 2x2 chips if/when the come out. */
+ ar->supp_tx_chainmask = TARGET_10X_TX_CHAIN_MASK;
+ ar->supp_rx_chainmask = TARGET_10X_RX_CHAIN_MASK;
+ } else {
+ ar->supp_tx_chainmask = TARGET_TX_CHAIN_MASK;
+ ar->supp_rx_chainmask = TARGET_RX_CHAIN_MASK;
+ }
+
+ ar->hw->wiphy->available_antennas_rx = ar->supp_rx_chainmask;
+ ar->hw->wiphy->available_antennas_tx = ar->supp_tx_chainmask;
+
if (!test_bit(ATH10K_FW_FEATURE_NO_P2P, ar->fw_features))
ar->hw->wiphy->interface_modes |=
BIT(NL80211_IFTYPE_P2P_CLIENT) |
diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c
index bf1083d52e6..d0004d59c97 100644
--- a/drivers/net/wireless/ath/ath10k/pci.c
+++ b/drivers/net/wireless/ath/ath10k/pci.c
@@ -59,6 +59,7 @@ MODULE_PARM_DESC(reset_mode, "0: auto, 1: warm only (default: 0)");
/* how long wait to wait for target to initialise, in ms */
#define ATH10K_PCI_TARGET_WAIT 3000
+#define ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS 3
#define QCA988X_2_0_DEVICE_ID (0x003c)
@@ -761,17 +762,21 @@ static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
struct ath10k_pci_pipe *pci_pipe = &ar_pci->pipe_info[pipe_id];
struct ath10k_ce_pipe *ce_pipe = pci_pipe->ce_hdl;
struct ath10k_ce_ring *src_ring = ce_pipe->src_ring;
- unsigned int nentries_mask = src_ring->nentries_mask;
- unsigned int sw_index = src_ring->sw_index;
- unsigned int write_index = src_ring->write_index;
- int err, i;
+ unsigned int nentries_mask;
+ unsigned int sw_index;
+ unsigned int write_index;
+ int err, i = 0;
spin_lock_bh(&ar_pci->ce_lock);
+ nentries_mask = src_ring->nentries_mask;
+ sw_index = src_ring->sw_index;
+ write_index = src_ring->write_index;
+
if (unlikely(CE_RING_DELTA(nentries_mask,
write_index, sw_index - 1) < n_items)) {
err = -ENOBUFS;
- goto unlock;
+ goto err;
}
for (i = 0; i < n_items - 1; i++) {
@@ -788,7 +793,7 @@ static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
items[i].transfer_id,
CE_SEND_FLAG_GATHER);
if (err)
- goto unlock;
+ goto err;
}
/* `i` is equal to `n_items -1` after for() */
@@ -806,10 +811,15 @@ static int ath10k_pci_hif_tx_sg(struct ath10k *ar, u8 pipe_id,
items[i].transfer_id,
0);
if (err)
- goto unlock;
+ goto err;
+
+ spin_unlock_bh(&ar_pci->ce_lock);
+ return 0;
+
+err:
+ for (; i > 0; i--)
+ __ath10k_ce_send_revert(ce_pipe);
- err = 0;
-unlock:
spin_unlock_bh(&ar_pci->ce_lock);
return err;
}
@@ -1271,6 +1281,9 @@ static void ath10k_pci_hif_stop(struct ath10k *ar)
ath10k_dbg(ATH10K_DBG_BOOT, "boot hif stop\n");
+ if (WARN_ON(!ar_pci->started))
+ return;
+
ret = ath10k_ce_disable_interrupts(ar);
if (ret)
ath10k_warn("failed to disable CE interrupts: %d\n", ret);
@@ -1802,6 +1815,26 @@ static void ath10k_pci_fw_interrupt_handler(struct ath10k *ar)
ath10k_pci_sleep(ar);
}
+/* this function effectively clears target memory controller assert line */
+static void ath10k_pci_warm_reset_si0(struct ath10k *ar)
+{
+ u32 val;
+
+ val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
+ ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
+ val | SOC_RESET_CONTROL_SI0_RST_MASK);
+ val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
+
+ msleep(10);
+
+ val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
+ ath10k_pci_soc_write32(ar, SOC_RESET_CONTROL_ADDRESS,
+ val & ~SOC_RESET_CONTROL_SI0_RST_MASK);
+ val = ath10k_pci_soc_read32(ar, SOC_RESET_CONTROL_ADDRESS);
+
+ msleep(10);
+}
+
static int ath10k_pci_warm_reset(struct ath10k *ar)
{
int ret = 0;
@@ -1860,6 +1893,8 @@ static int ath10k_pci_warm_reset(struct ath10k *ar)
SOC_RESET_CONTROL_ADDRESS);
msleep(10);
+ ath10k_pci_warm_reset_si0(ar);
+
/* debug */
val = ath10k_pci_read32(ar, SOC_CORE_BASE_ADDRESS +
PCIE_INTR_CAUSE_ADDRESS);
@@ -1988,6 +2023,28 @@ err:
return ret;
}
+static int ath10k_pci_hif_power_up_warm(struct ath10k *ar)
+{
+ int i, ret;
+
+ /*
+ * Sometime warm reset succeeds after retries.
+ *
+ * FIXME: It might be possible to tune ath10k_pci_warm_reset() to work
+ * at first try.
+ */
+ for (i = 0; i < ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS; i++) {
+ ret = __ath10k_pci_hif_power_up(ar, false);
+ if (ret == 0)
+ break;
+
+ ath10k_warn("failed to warm reset (attempt %d out of %d): %d\n",
+ i + 1, ATH10K_PCI_NUM_WARM_RESET_ATTEMPTS, ret);
+ }
+
+ return ret;
+}
+
static int ath10k_pci_hif_power_up(struct ath10k *ar)
{
int ret;
@@ -1999,10 +2056,10 @@ static int ath10k_pci_hif_power_up(struct ath10k *ar)
* preferred (and safer) way to perform a device reset is through a
* warm reset.
*
- * Warm reset doesn't always work though (notably after a firmware
- * crash) so fall back to cold reset if necessary.
+ * Warm reset doesn't always work though so fall back to cold reset may
+ * be necessary.
*/
- ret = __ath10k_pci_hif_power_up(ar, false);
+ ret = ath10k_pci_hif_power_up_warm(ar);
if (ret) {
ath10k_warn("failed to power up target using warm reset: %d\n",
ret);
@@ -2196,10 +2253,7 @@ static void ath10k_pci_early_irq_tasklet(unsigned long data)
if (fw_ind & FW_IND_EVENT_PENDING) {
ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS,
fw_ind & ~FW_IND_EVENT_PENDING);
-
- /* Some structures are unavailable during early boot or at
- * driver teardown so just print that the device has crashed. */
- ath10k_warn("device crashed - no diagnostics available\n");
+ ath10k_pci_hif_dump_area(ar);
}
ath10k_pci_sleep(ar);
@@ -2452,6 +2506,10 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
if (val == 0xffffffff)
continue;
+ /* the device has crashed so don't bother trying anymore */
+ if (val & FW_IND_EVENT_PENDING)
+ break;
+
if (val & FW_IND_INITIALIZED)
break;
@@ -2464,7 +2522,22 @@ static int ath10k_pci_wait_for_target_init(struct ath10k *ar)
mdelay(10);
} while (time_before(jiffies, timeout));
- if (val == 0xffffffff || !(val & FW_IND_INITIALIZED)) {
+ if (val == 0xffffffff) {
+ ath10k_err("failed to read device register, device is gone\n");
+ ret = -EIO;
+ goto out;
+ }
+
+ if (val & FW_IND_EVENT_PENDING) {
+ ath10k_warn("device has crashed during init\n");
+ ath10k_pci_write32(ar, FW_INDICATOR_ADDRESS,
+ val & ~FW_IND_EVENT_PENDING);
+ ath10k_pci_hif_dump_area(ar);
+ ret = -ECOMM;
+ goto out;
+ }
+
+ if (!(val & FW_IND_INITIALIZED)) {
ath10k_err("failed to receive initialized event from target: %08x\n",
val);
ret = -ETIMEDOUT;
@@ -2586,18 +2659,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev,
pci_set_drvdata(pdev, ar);
- /*
- * Without any knowledge of the Host, the Target may have been reset or
- * power cycled and its Config Space may no longer reflect the PCI
- * address space that was assigned earlier by the PCI infrastructure.
- * Refresh it now.
- */
- ret = pci_assign_resource(pdev, BAR_NUM);
- if (ret) {
- ath10k_err("failed to assign PCI space: %d\n", ret);
- goto err_ar;
- }
-
ret = pci_enable_device(pdev);
if (ret) {
ath10k_err("failed to enable PCI device: %d\n", ret);
@@ -2709,8 +2770,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev)
if (!ar_pci)
return;
- tasklet_kill(&ar_pci->msi_fw_err);
-
ath10k_core_unregister(ar);
ath10k_pci_free_ce(ar);
diff --git a/drivers/net/wireless/ath/ath10k/wmi.c b/drivers/net/wireless/ath/ath10k/wmi.c
index fe4d5f1c672..4b7782a529a 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.c
+++ b/drivers/net/wireless/ath/ath10k/wmi.c
@@ -639,6 +639,7 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
struct sk_buff *wmi_skb;
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
int len;
+ u32 buf_len = skb->len;
u16 fc;
hdr = (struct ieee80211_hdr *)skb->data;
@@ -648,6 +649,15 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
return -EINVAL;
len = sizeof(cmd->hdr) + skb->len;
+
+ if ((ieee80211_is_action(hdr->frame_control) ||
+ ieee80211_is_deauth(hdr->frame_control) ||
+ ieee80211_is_disassoc(hdr->frame_control)) &&
+ ieee80211_has_protected(hdr->frame_control)) {
+ len += IEEE80211_CCMP_MIC_LEN;
+ buf_len += IEEE80211_CCMP_MIC_LEN;
+ }
+
len = round_up(len, 4);
wmi_skb = ath10k_wmi_alloc_skb(len);
@@ -659,7 +669,7 @@ int ath10k_wmi_mgmt_tx(struct ath10k *ar, struct sk_buff *skb)
cmd->hdr.vdev_id = __cpu_to_le32(ATH10K_SKB_CB(skb)->vdev_id);
cmd->hdr.tx_rate = 0;
cmd->hdr.tx_power = 0;
- cmd->hdr.buf_len = __cpu_to_le32((u32)(skb->len));
+ cmd->hdr.buf_len = __cpu_to_le32(buf_len);
memcpy(cmd->hdr.peer_macaddr.addr, ieee80211_get_DA(hdr), ETH_ALEN);
memcpy(cmd->buf, skb->data, skb->len);
@@ -957,10 +967,16 @@ static int ath10k_wmi_event_mgmt_rx(struct ath10k *ar, struct sk_buff *skb)
* frames with Protected Bit set. */
if (ieee80211_has_protected(hdr->frame_control) &&
!ieee80211_is_auth(hdr->frame_control)) {
- status->flag |= RX_FLAG_DECRYPTED | RX_FLAG_IV_STRIPPED |
- RX_FLAG_MMIC_STRIPPED;
- hdr->frame_control = __cpu_to_le16(fc &
+ status->flag |= RX_FLAG_DECRYPTED;
+
+ if (!ieee80211_is_action(hdr->frame_control) &&
+ !ieee80211_is_deauth(hdr->frame_control) &&
+ !ieee80211_is_disassoc(hdr->frame_control)) {
+ status->flag |= RX_FLAG_IV_STRIPPED |
+ RX_FLAG_MMIC_STRIPPED;
+ hdr->frame_control = __cpu_to_le16(fc &
~IEEE80211_FCTL_PROTECTED);
+ }
}
ath10k_dbg(ATH10K_DBG_MGMT,
@@ -1431,6 +1447,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ATH10K_SKB_CB(arvif->beacon)->paddr,
arvif->beacon->len, DMA_TO_DEVICE);
dev_kfree_skb_any(arvif->beacon);
+ arvif->beacon = NULL;
}
ATH10K_SKB_CB(bcn)->paddr = dma_map_single(arvif->ar->dev,
@@ -1440,6 +1457,7 @@ static void ath10k_wmi_event_host_swba(struct ath10k *ar, struct sk_buff *skb)
ATH10K_SKB_CB(bcn)->paddr);
if (ret) {
ath10k_warn("failed to map beacon: %d\n", ret);
+ dev_kfree_skb_any(bcn);
goto skip;
}
@@ -2357,7 +2375,7 @@ void ath10k_wmi_detach(struct ath10k *ar)
ar->wmi.num_mem_chunks = 0;
}
-int ath10k_wmi_connect_htc_service(struct ath10k *ar)
+int ath10k_wmi_connect(struct ath10k *ar)
{
int status;
struct ath10k_htc_svc_conn_req conn_req;
diff --git a/drivers/net/wireless/ath/ath10k/wmi.h b/drivers/net/wireless/ath/ath10k/wmi.h
index ae838221af6..e93df2c1041 100644
--- a/drivers/net/wireless/ath/ath10k/wmi.h
+++ b/drivers/net/wireless/ath/ath10k/wmi.h
@@ -1255,7 +1255,7 @@ struct wmi_resource_config {
*/
__le32 rx_decap_mode;
- /* what is the maximum scan requests than can be queued */
+ /* what is the maximum number of scan requests that can be queued */
__le32 scan_max_pending_reqs;
/* maximum VDEV that could use BMISS offload */
@@ -1440,7 +1440,7 @@ struct wmi_resource_config_10x {
*/
__le32 rx_decap_mode;
- /* what is the maximum scan requests than can be queued */
+ /* what is the maximum number of scan requests that can be queued */
__le32 scan_max_pending_reqs;
/* maximum VDEV that could use BMISS offload */
@@ -2323,9 +2323,9 @@ struct wmi_pdev_param_map {
#define WMI_PDEV_PARAM_UNSUPPORTED 0
enum wmi_pdev_param {
- /* TX chian mask */
+ /* TX chain mask */
WMI_PDEV_PARAM_TX_CHAIN_MASK = 0x1,
- /* RX chian mask */
+ /* RX chain mask */
WMI_PDEV_PARAM_RX_CHAIN_MASK,
/* TX power limit for 2G Radio */
WMI_PDEV_PARAM_TXPOWER_LIMIT2G,
@@ -4259,7 +4259,7 @@ void ath10k_wmi_detach(struct ath10k *ar);
int ath10k_wmi_wait_for_service_ready(struct ath10k *ar);
int ath10k_wmi_wait_for_unified_ready(struct ath10k *ar);
-int ath10k_wmi_connect_htc_service(struct ath10k *ar);
+int ath10k_wmi_connect(struct ath10k *ar);
int ath10k_wmi_pdev_set_channel(struct ath10k *ar,
const struct wmi_channel_arg *);
int ath10k_wmi_pdev_suspend_target(struct ath10k *ar, u32 suspend_opt);
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
index 09285084bcd..0e26f4a34fd 100644
--- a/drivers/net/wireless/ath/ath6kl/cfg80211.c
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -1759,7 +1759,7 @@ static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
}
static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_info *sinfo)
+ const u8 *mac, struct station_info *sinfo)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
@@ -2974,7 +2974,7 @@ static int ath6kl_stop_ap(struct wiphy *wiphy, struct net_device *dev)
static const u8 bcast_addr[ETH_ALEN] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac)
+ const u8 *mac)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
@@ -2985,7 +2985,8 @@ static int ath6kl_del_station(struct wiphy *wiphy, struct net_device *dev,
}
static int ath6kl_change_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_parameters *params)
+ const u8 *mac,
+ struct station_parameters *params)
{
struct ath6kl *ar = ath6kl_priv(dev);
struct ath6kl_vif *vif = netdev_priv(dev);
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
index 0c0e1e36e40..4d7f9e4712e 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.c
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -2320,7 +2320,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
return ret;
}
-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk)
+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk)
{
struct sk_buff *skb;
struct wmi_add_krk_cmd *cmd;
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
index 1f05ecd97c9..bb23fc00111 100644
--- a/drivers/net/wireless/ath/ath6kl/wmi.h
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -1067,7 +1067,7 @@ struct wmi_power_mode_cmd {
} __packed;
/*
- * Policy to determnine whether power save failure event should be sent to
+ * Policy to determine whether power save failure event should be sent to
* host during scanning
*/
enum power_save_fail_event_policy {
@@ -2616,7 +2616,7 @@ int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index,
u8 *key_material,
u8 key_op_ctrl, u8 *mac_addr,
enum wmi_sync_flag sync_flag);
-int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, u8 *krk);
+int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 if_idx, const u8 *krk);
int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 if_idx, u8 key_index);
int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, u8 if_idx, const u8 *bssid,
const u8 *pmkid, bool set);
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index 8e1c7b0fe76..8fcd586d1c3 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -53,7 +53,8 @@ obj-$(CONFIG_ATH9K_HW) += ath9k_hw.o
obj-$(CONFIG_ATH9K_COMMON) += ath9k_common.o
ath9k_common-y:= common.o \
common-init.o \
- common-beacon.o
+ common-beacon.o \
+ common-debug.o
ath9k_htc-y += htc_hst.o \
hif_usb.o \
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index a0398fe3eb2..be3eb2a8d60 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -86,7 +86,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
int irq;
int ret = 0;
struct ath_hw *ah;
- struct ath_common *common;
char hw_name[64];
if (!dev_get_platdata(&pdev->dev)) {
@@ -146,9 +145,6 @@ static int ath_ahb_probe(struct platform_device *pdev)
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)mem, irq);
- common = ath9k_hw_common(sc->sc_ah);
- /* Will be cleared in ath9k_start() */
- set_bit(ATH_OP_INVALID, &common->op_flags);
return 0;
err_irq:
diff --git a/drivers/net/wireless/ath/ath9k/ani.c b/drivers/net/wireless/ath/ath9k/ani.c
index 6d47783f2e5..ba502a2d199 100644
--- a/drivers/net/wireless/ath/ath9k/ani.c
+++ b/drivers/net/wireless/ath/ath9k/ani.c
@@ -155,6 +155,9 @@ static void ath9k_hw_set_ofdm_nil(struct ath_hw *ah, u8 immunityLevel,
ATH9K_ANI_RSSI_THR_LOW,
ATH9K_ANI_RSSI_THR_HIGH);
+ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_OFDM_DEF_LEVEL)
+ immunityLevel = ATH9K_ANI_OFDM_DEF_LEVEL;
+
if (!scan)
aniState->ofdmNoiseImmunityLevel = immunityLevel;
@@ -235,6 +238,9 @@ static void ath9k_hw_set_cck_nil(struct ath_hw *ah, u_int8_t immunityLevel,
BEACON_RSSI(ah), ATH9K_ANI_RSSI_THR_LOW,
ATH9K_ANI_RSSI_THR_HIGH);
+ if (AR_SREV_9100(ah) && immunityLevel < ATH9K_ANI_CCK_DEF_LEVEL)
+ immunityLevel = ATH9K_ANI_CCK_DEF_LEVEL;
+
if (ah->opmode == NL80211_IFTYPE_STATION &&
BEACON_RSSI(ah) <= ATH9K_ANI_RSSI_THR_LOW &&
immunityLevel > ATH9K_ANI_CCK_MAX_LEVEL_LOW_RSSI)
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 05935f63852..2ca8f7e0617 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -23,8 +23,8 @@
#include <linux/leds.h>
#include <linux/completion.h>
-#include "debug.h"
#include "common.h"
+#include "debug.h"
#include "mci.h"
#include "dfs.h"
#include "spectral.h"
@@ -254,7 +254,6 @@ struct ath_atx_tid {
s8 bar_index;
bool sched;
- bool paused;
bool active;
};
@@ -275,6 +274,7 @@ struct ath_node {
#ifdef CONFIG_ATH9K_STATION_STATISTICS
struct ath_rx_rate_stats rx_rate_stats;
#endif
+ u8 key_idx[4];
};
struct ath_tx_control {
@@ -770,6 +770,7 @@ struct ath_softc {
struct ath_ant_comb ant_comb;
u8 ant_tx, ant_rx;
struct dfs_pattern_detector *dfs_detector;
+ u64 dfs_prev_pulse_ts;
u32 wow_enabled;
/* relay(fs) channel for spectral scan */
struct rchan *rfs_chan_spec_scan;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index bd9e634879e..e387f0b2954 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -537,8 +537,6 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
cur_conf->dtim_period = bss_conf->dtim_period;
cur_conf->dtim_count = 1;
cur_conf->ibss_creator = bss_conf->ibss_creator;
- cur_conf->bmiss_timeout =
- ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
/*
* It looks like mac80211 may end up using beacon interval of zero in
@@ -549,6 +547,9 @@ static void ath9k_cache_beacon_config(struct ath_softc *sc,
if (cur_conf->beacon_interval == 0)
cur_conf->beacon_interval = 100;
+ cur_conf->bmiss_timeout =
+ ATH_DEFAULT_BMISS_LIMIT * cur_conf->beacon_interval;
+
/*
* We don't parse dtim period from mac80211 during the driver
* initialization as it breaks association with hidden-ssid
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.c b/drivers/net/wireless/ath/ath9k/common-debug.c
new file mode 100644
index 00000000000..3b289f93340
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/common-debug.c
@@ -0,0 +1,253 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include "common.h"
+
+static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_hw *ah = file->private_data;
+ u32 len = 0, size = 6000;
+ char *buf;
+ size_t retval;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_modal_eeprom = {
+ .read = read_file_modal_eeprom,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+
+void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,
+ struct ath_hw *ah)
+{
+ debugfs_create_file("modal_eeprom", S_IRUSR, debugfs_phy, ah,
+ &fops_modal_eeprom);
+}
+EXPORT_SYMBOL(ath9k_cmn_debug_modal_eeprom);
+
+static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct ath_hw *ah = file->private_data;
+ u32 len = 0, size = 1500;
+ ssize_t retval = 0;
+ char *buf;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+}
+
+static const struct file_operations fops_base_eeprom = {
+ .read = read_file_base_eeprom,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,
+ struct ath_hw *ah)
+{
+ debugfs_create_file("base_eeprom", S_IRUSR, debugfs_phy, ah,
+ &fops_base_eeprom);
+}
+EXPORT_SYMBOL(ath9k_cmn_debug_base_eeprom);
+
+void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,
+ struct ath_rx_status *rs)
+{
+#define RX_PHY_ERR_INC(c) rxstats->phy_err_stats[c]++
+#define RX_CMN_STAT_INC(c) (rxstats->c++)
+
+ RX_CMN_STAT_INC(rx_pkts_all);
+ rxstats->rx_bytes_all += rs->rs_datalen;
+
+ if (rs->rs_status & ATH9K_RXERR_CRC)
+ RX_CMN_STAT_INC(crc_err);
+ if (rs->rs_status & ATH9K_RXERR_DECRYPT)
+ RX_CMN_STAT_INC(decrypt_crc_err);
+ if (rs->rs_status & ATH9K_RXERR_MIC)
+ RX_CMN_STAT_INC(mic_err);
+ if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
+ RX_CMN_STAT_INC(pre_delim_crc_err);
+ if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
+ RX_CMN_STAT_INC(post_delim_crc_err);
+ if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
+ RX_CMN_STAT_INC(decrypt_busy_err);
+
+ if (rs->rs_status & ATH9K_RXERR_PHY) {
+ RX_CMN_STAT_INC(phy_err);
+ if (rs->rs_phyerr < ATH9K_PHYERR_MAX)
+ RX_PHY_ERR_INC(rs->rs_phyerr);
+ }
+
+#undef RX_CMN_STAT_INC
+#undef RX_PHY_ERR_INC
+}
+EXPORT_SYMBOL(ath9k_cmn_debug_stat_rx);
+
+static ssize_t read_file_recv(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+#define RXS_ERR(s, e) \
+ do { \
+ len += scnprintf(buf + len, size - len, \
+ "%18s : %10u\n", s, \
+ rxstats->e); \
+ } while (0)
+
+ struct ath_rx_stats *rxstats = file->private_data;
+ char *buf;
+ unsigned int len = 0, size = 1600;
+ ssize_t retval = 0;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ RXS_ERR("PKTS-ALL", rx_pkts_all);
+ RXS_ERR("BYTES-ALL", rx_bytes_all);
+ RXS_ERR("BEACONS", rx_beacons);
+ RXS_ERR("FRAGS", rx_frags);
+ RXS_ERR("SPECTRAL", rx_spectral);
+
+ RXS_ERR("CRC ERR", crc_err);
+ RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err);
+ RXS_ERR("PHY ERR", phy_err);
+ RXS_ERR("MIC ERR", mic_err);
+ RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err);
+ RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err);
+ RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err);
+ RXS_ERR("LENGTH-ERR", rx_len_err);
+ RXS_ERR("OOM-ERR", rx_oom_err);
+ RXS_ERR("RATE-ERR", rx_rate_err);
+ RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err);
+
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+
+#undef RXS_ERR
+}
+
+static const struct file_operations fops_recv = {
+ .read = read_file_recv,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,
+ struct ath_rx_stats *rxstats)
+{
+ debugfs_create_file("recv", S_IRUSR, debugfs_phy, rxstats,
+ &fops_recv);
+}
+EXPORT_SYMBOL(ath9k_cmn_debug_recv);
+
+static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+#define PHY_ERR(s, p) \
+ len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \
+ rxstats->phy_err_stats[p]);
+
+ struct ath_rx_stats *rxstats = file->private_data;
+ char *buf;
+ unsigned int len = 0, size = 1600;
+ ssize_t retval = 0;
+
+ buf = kzalloc(size, GFP_KERNEL);
+ if (buf == NULL)
+ return -ENOMEM;
+
+ PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
+ PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);
+ PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY);
+ PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE);
+ PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH);
+ PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
+ PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
+ PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
+ PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
+ PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
+ PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
+ PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
+ PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
+ PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
+ PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
+ PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
+ PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
+ PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
+ PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
+ PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
+ PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
+ PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
+ PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
+ PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
+ PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
+ PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+
+ if (len > size)
+ len = size;
+
+ retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+
+ return retval;
+
+#undef PHY_ERR
+}
+
+static const struct file_operations fops_phy_err = {
+ .read = read_file_phy_err,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
+
+void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,
+ struct ath_rx_stats *rxstats)
+{
+ debugfs_create_file("phy_err", S_IRUSR, debugfs_phy, rxstats,
+ &fops_phy_err);
+}
+EXPORT_SYMBOL(ath9k_cmn_debug_phy_err);
diff --git a/drivers/net/wireless/ath/ath9k/common-debug.h b/drivers/net/wireless/ath/ath9k/common-debug.h
new file mode 100644
index 00000000000..7c9788490f7
--- /dev/null
+++ b/drivers/net/wireless/ath/ath9k/common-debug.h
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2008-2011 Atheros Communications Inc.
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+
+/**
+ * struct ath_rx_stats - RX Statistics
+ * @rx_pkts_all: No. of total frames received, including ones that
+ may have had errors.
+ * @rx_bytes_all: No. of total bytes received, including ones that
+ may have had errors.
+ * @crc_err: No. of frames with incorrect CRC value
+ * @decrypt_crc_err: No. of frames whose CRC check failed after
+ decryption process completed
+ * @phy_err: No. of frames whose reception failed because the PHY
+ encountered an error
+ * @mic_err: No. of frames with incorrect TKIP MIC verification failure
+ * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
+ * @post_delim_crc_err: Post-Frame delimiter CRC error detections
+ * @decrypt_busy_err: Decryption interruptions counter
+ * @phy_err_stats: Individual PHY error statistics
+ * @rx_len_err: No. of frames discarded due to bad length.
+ * @rx_oom_err: No. of frames dropped due to OOM issues.
+ * @rx_rate_err: No. of frames dropped due to rate errors.
+ * @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
+ * @rx_beacons: No. of beacons received.
+ * @rx_frags: No. of rx-fragements received.
+ * @rx_spectral: No of spectral packets received.
+ */
+struct ath_rx_stats {
+ u32 rx_pkts_all;
+ u32 rx_bytes_all;
+ u32 crc_err;
+ u32 decrypt_crc_err;
+ u32 phy_err;
+ u32 mic_err;
+ u32 pre_delim_crc_err;
+ u32 post_delim_crc_err;
+ u32 decrypt_busy_err;
+ u32 phy_err_stats[ATH9K_PHYERR_MAX];
+ u32 rx_len_err;
+ u32 rx_oom_err;
+ u32 rx_rate_err;
+ u32 rx_too_many_frags_err;
+ u32 rx_beacons;
+ u32 rx_frags;
+ u32 rx_spectral;
+};
+
+void ath9k_cmn_debug_modal_eeprom(struct dentry *debugfs_phy,
+ struct ath_hw *ah);
+void ath9k_cmn_debug_base_eeprom(struct dentry *debugfs_phy,
+ struct ath_hw *ah);
+void ath9k_cmn_debug_stat_rx(struct ath_rx_stats *rxstats,
+ struct ath_rx_status *rs);
+void ath9k_cmn_debug_recv(struct dentry *debugfs_phy,
+ struct ath_rx_stats *rxstats);
+void ath9k_cmn_debug_phy_err(struct dentry *debugfs_phy,
+ struct ath_rx_stats *rxstats);
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index ca38116838f..ffc454b1863 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -23,6 +23,7 @@
#include "common-init.h"
#include "common-beacon.h"
+#include "common-debug.h"
/* Common header for Atheros 802.11n base driver cores */
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 780ff1bee6f..6cc42be48d4 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -948,151 +948,11 @@ static const struct file_operations fops_reset = {
.llseek = default_llseek,
};
-static ssize_t read_file_recv(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
-#define RXS_ERR(s, e) \
- do { \
- len += scnprintf(buf + len, size - len, \
- "%18s : %10u\n", s, \
- sc->debug.stats.rxstats.e);\
- } while (0)
-
- struct ath_softc *sc = file->private_data;
- char *buf;
- unsigned int len = 0, size = 1600;
- ssize_t retval = 0;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- RXS_ERR("PKTS-ALL", rx_pkts_all);
- RXS_ERR("BYTES-ALL", rx_bytes_all);
- RXS_ERR("BEACONS", rx_beacons);
- RXS_ERR("FRAGS", rx_frags);
- RXS_ERR("SPECTRAL", rx_spectral);
-
- RXS_ERR("CRC ERR", crc_err);
- RXS_ERR("DECRYPT CRC ERR", decrypt_crc_err);
- RXS_ERR("PHY ERR", phy_err);
- RXS_ERR("MIC ERR", mic_err);
- RXS_ERR("PRE-DELIM CRC ERR", pre_delim_crc_err);
- RXS_ERR("POST-DELIM CRC ERR", post_delim_crc_err);
- RXS_ERR("DECRYPT BUSY ERR", decrypt_busy_err);
- RXS_ERR("LENGTH-ERR", rx_len_err);
- RXS_ERR("OOM-ERR", rx_oom_err);
- RXS_ERR("RATE-ERR", rx_rate_err);
- RXS_ERR("TOO-MANY-FRAGS", rx_too_many_frags_err);
-
- if (len > size)
- len = size;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-
-#undef RXS_ERR
-}
-
void ath_debug_stat_rx(struct ath_softc *sc, struct ath_rx_status *rs)
{
-#define RX_PHY_ERR_INC(c) sc->debug.stats.rxstats.phy_err_stats[c]++
-
- RX_STAT_INC(rx_pkts_all);
- sc->debug.stats.rxstats.rx_bytes_all += rs->rs_datalen;
-
- if (rs->rs_status & ATH9K_RXERR_CRC)
- RX_STAT_INC(crc_err);
- if (rs->rs_status & ATH9K_RXERR_DECRYPT)
- RX_STAT_INC(decrypt_crc_err);
- if (rs->rs_status & ATH9K_RXERR_MIC)
- RX_STAT_INC(mic_err);
- if (rs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
- RX_STAT_INC(pre_delim_crc_err);
- if (rs->rs_status & ATH9K_RX_DELIM_CRC_POST)
- RX_STAT_INC(post_delim_crc_err);
- if (rs->rs_status & ATH9K_RX_DECRYPT_BUSY)
- RX_STAT_INC(decrypt_busy_err);
-
- if (rs->rs_status & ATH9K_RXERR_PHY) {
- RX_STAT_INC(phy_err);
- if (rs->rs_phyerr < ATH9K_PHYERR_MAX)
- RX_PHY_ERR_INC(rs->rs_phyerr);
- }
-
-#undef RX_PHY_ERR_INC
+ ath9k_cmn_debug_stat_rx(&sc->debug.stats.rxstats, rs);
}
-static const struct file_operations fops_recv = {
- .read = read_file_recv,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-static ssize_t read_file_phy_err(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
-#define PHY_ERR(s, p) \
- len += scnprintf(buf + len, size - len, "%22s : %10u\n", s, \
- sc->debug.stats.rxstats.phy_err_stats[p]);
-
- struct ath_softc *sc = file->private_data;
- char *buf;
- unsigned int len = 0, size = 1600;
- ssize_t retval = 0;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- PHY_ERR("UNDERRUN ERR", ATH9K_PHYERR_UNDERRUN);
- PHY_ERR("TIMING ERR", ATH9K_PHYERR_TIMING);
- PHY_ERR("PARITY ERR", ATH9K_PHYERR_PARITY);
- PHY_ERR("RATE ERR", ATH9K_PHYERR_RATE);
- PHY_ERR("LENGTH ERR", ATH9K_PHYERR_LENGTH);
- PHY_ERR("RADAR ERR", ATH9K_PHYERR_RADAR);
- PHY_ERR("SERVICE ERR", ATH9K_PHYERR_SERVICE);
- PHY_ERR("TOR ERR", ATH9K_PHYERR_TOR);
- PHY_ERR("OFDM-TIMING ERR", ATH9K_PHYERR_OFDM_TIMING);
- PHY_ERR("OFDM-SIGNAL-PARITY ERR", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
- PHY_ERR("OFDM-RATE ERR", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
- PHY_ERR("OFDM-LENGTH ERR", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
- PHY_ERR("OFDM-POWER-DROP ERR", ATH9K_PHYERR_OFDM_POWER_DROP);
- PHY_ERR("OFDM-SERVICE ERR", ATH9K_PHYERR_OFDM_SERVICE);
- PHY_ERR("OFDM-RESTART ERR", ATH9K_PHYERR_OFDM_RESTART);
- PHY_ERR("FALSE-RADAR-EXT ERR", ATH9K_PHYERR_FALSE_RADAR_EXT);
- PHY_ERR("CCK-TIMING ERR", ATH9K_PHYERR_CCK_TIMING);
- PHY_ERR("CCK-HEADER-CRC ERR", ATH9K_PHYERR_CCK_HEADER_CRC);
- PHY_ERR("CCK-RATE ERR", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
- PHY_ERR("CCK-SERVICE ERR", ATH9K_PHYERR_CCK_SERVICE);
- PHY_ERR("CCK-RESTART ERR", ATH9K_PHYERR_CCK_RESTART);
- PHY_ERR("CCK-LENGTH ERR", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
- PHY_ERR("CCK-POWER-DROP ERR", ATH9K_PHYERR_CCK_POWER_DROP);
- PHY_ERR("HT-CRC ERR", ATH9K_PHYERR_HT_CRC_ERROR);
- PHY_ERR("HT-LENGTH ERR", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
- PHY_ERR("HT-RATE ERR", ATH9K_PHYERR_HT_RATE_ILLEGAL);
-
- if (len > size)
- len = size;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-
-#undef PHY_ERR
-}
-
-static const struct file_operations fops_phy_err = {
- .read = read_file_phy_err,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
static ssize_t read_file_regidx(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
@@ -1268,62 +1128,6 @@ static const struct file_operations fops_dump_nfcal = {
.llseek = default_llseek,
};
-static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath_softc *sc = file->private_data;
- struct ath_hw *ah = sc->sc_ah;
- u32 len = 0, size = 1500;
- ssize_t retval = 0;
- char *buf;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (!buf)
- return -ENOMEM;
-
- len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-}
-
-static const struct file_operations fops_base_eeprom = {
- .read = read_file_base_eeprom,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath_softc *sc = file->private_data;
- struct ath_hw *ah = sc->sc_ah;
- u32 len = 0, size = 6000;
- char *buf;
- size_t retval;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-}
-
-static const struct file_operations fops_modal_eeprom = {
- .read = read_file_modal_eeprom,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
#ifdef CONFIG_ATH9K_BTCOEX_SUPPORT
static ssize_t read_file_btcoex(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
@@ -1524,10 +1328,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_misc);
debugfs_create_file("reset", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_reset);
- debugfs_create_file("recv", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_recv);
- debugfs_create_file("phy_err", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_phy_err);
+
+ ath9k_cmn_debug_recv(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
+ ath9k_cmn_debug_phy_err(sc->debug.debugfs_phy, &sc->debug.stats.rxstats);
+
debugfs_create_u8("rx_chainmask", S_IRUSR, sc->debug.debugfs_phy,
&ah->rxchainmask);
debugfs_create_u8("tx_chainmask", S_IRUSR, sc->debug.debugfs_phy,
@@ -1547,10 +1351,10 @@ int ath9k_init_debug(struct ath_hw *ah)
&fops_regdump);
debugfs_create_file("dump_nfcal", S_IRUSR, sc->debug.debugfs_phy, sc,
&fops_dump_nfcal);
- debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_base_eeprom);
- debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
- &fops_modal_eeprom);
+
+ ath9k_cmn_debug_base_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
+ ath9k_cmn_debug_modal_eeprom(sc->debug.debugfs_phy, sc->sc_ah);
+
debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 559a68c2709..53ae15bd0c9 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -221,50 +221,6 @@ struct ath_rx_rate_stats {
} cck_stats[4];
};
-/**
- * struct ath_rx_stats - RX Statistics
- * @rx_pkts_all: No. of total frames received, including ones that
- may have had errors.
- * @rx_bytes_all: No. of total bytes received, including ones that
- may have had errors.
- * @crc_err: No. of frames with incorrect CRC value
- * @decrypt_crc_err: No. of frames whose CRC check failed after
- decryption process completed
- * @phy_err: No. of frames whose reception failed because the PHY
- encountered an error
- * @mic_err: No. of frames with incorrect TKIP MIC verification failure
- * @pre_delim_crc_err: Pre-Frame delimiter CRC error detections
- * @post_delim_crc_err: Post-Frame delimiter CRC error detections
- * @decrypt_busy_err: Decryption interruptions counter
- * @phy_err_stats: Individual PHY error statistics
- * @rx_len_err: No. of frames discarded due to bad length.
- * @rx_oom_err: No. of frames dropped due to OOM issues.
- * @rx_rate_err: No. of frames dropped due to rate errors.
- * @rx_too_many_frags_err: Frames dropped due to too-many-frags received.
- * @rx_beacons: No. of beacons received.
- * @rx_frags: No. of rx-fragements received.
- * @rx_spectral: No of spectral packets received.
- */
-struct ath_rx_stats {
- u32 rx_pkts_all;
- u32 rx_bytes_all;
- u32 crc_err;
- u32 decrypt_crc_err;
- u32 phy_err;
- u32 mic_err;
- u32 pre_delim_crc_err;
- u32 post_delim_crc_err;
- u32 decrypt_busy_err;
- u32 phy_err_stats[ATH9K_PHYERR_MAX];
- u32 rx_len_err;
- u32 rx_oom_err;
- u32 rx_rate_err;
- u32 rx_too_many_frags_err;
- u32 rx_beacons;
- u32 rx_frags;
- u32 rx_spectral;
-};
-
#define ANT_MAIN 0
#define ANT_ALT 1
diff --git a/drivers/net/wireless/ath/ath9k/debug_sta.c b/drivers/net/wireless/ath/ath9k/debug_sta.c
index d76e6e0120d..ffca918ff16 100644
--- a/drivers/net/wireless/ath/ath9k/debug_sta.c
+++ b/drivers/net/wireless/ath/ath9k/debug_sta.c
@@ -72,7 +72,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
ath_txq_lock(sc, txq);
if (tid->active) {
len += scnprintf(buf + len, size - len,
- "%3d%11d%10d%10d%10d%10d%9d%6d%8d\n",
+ "%3d%11d%10d%10d%10d%10d%9d%6d\n",
tid->tidno,
tid->seq_start,
tid->seq_next,
@@ -80,8 +80,7 @@ static ssize_t read_file_node_aggr(struct file *file, char __user *user_buf,
tid->baw_head,
tid->baw_tail,
tid->bar_index,
- tid->sched,
- tid->paused);
+ tid->sched);
}
ath_txq_unlock(sc, txq);
}
diff --git a/drivers/net/wireless/ath/ath9k/dfs.c b/drivers/net/wireless/ath/ath9k/dfs.c
index 857bb28b389..726271c7c33 100644
--- a/drivers/net/wireless/ath/ath9k/dfs.c
+++ b/drivers/net/wireless/ath/ath9k/dfs.c
@@ -178,12 +178,12 @@ void ath9k_dfs_process_phyerr(struct ath_softc *sc, void *data,
pe.ts = mactime;
if (ath9k_postprocess_radar_event(sc, &ard, &pe)) {
struct dfs_pattern_detector *pd = sc->dfs_detector;
- static u64 last_ts;
ath_dbg(common, DFS,
"ath9k_dfs_process_phyerr: channel=%d, ts=%llu, "
"width=%d, rssi=%d, delta_ts=%llu\n",
- pe.freq, pe.ts, pe.width, pe.rssi, pe.ts-last_ts);
- last_ts = pe.ts;
+ pe.freq, pe.ts, pe.width, pe.rssi,
+ pe.ts - sc->dfs_prev_pulse_ts);
+ sc->dfs_prev_pulse_ts = pe.ts;
DFS_STAT_INC(sc, pulses_processed);
if (pd != NULL && pd->add_pulse(pd, &pe)) {
DFS_STAT_INC(sc, radar_detected);
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index dab1f0cab99..09a5d72f3ff 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -325,14 +325,14 @@ static inline struct ath9k_htc_tx_ctl *HTC_SKB_CB(struct sk_buff *skb)
#define TX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c++)
#define TX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.tx_stats.c += a)
-#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c++)
-#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.rx_stats.c += a)
+#define RX_STAT_INC(c) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c++)
+#define RX_STAT_ADD(c, a) (hif_dev->htc_handle->drv_priv->debug.skbrx_stats.c += a)
#define CAB_STAT_INC priv->debug.tx_stats.cab_queued++
#define TX_QSTAT_INC(q) (priv->debug.tx_stats.queue_stats[q]++)
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
- struct ath_htc_rx_status *rxs);
+ struct ath_rx_status *rs);
struct ath_tx_stats {
u32 buf_queued;
@@ -345,25 +345,18 @@ struct ath_tx_stats {
u32 queue_stats[IEEE80211_NUM_ACS];
};
-struct ath_rx_stats {
+struct ath_skbrx_stats {
u32 skb_allocated;
u32 skb_completed;
u32 skb_completed_bytes;
u32 skb_dropped;
- u32 err_crc;
- u32 err_decrypt_crc;
- u32 err_mic;
- u32 err_pre_delim;
- u32 err_post_delim;
- u32 err_decrypt_busy;
- u32 err_phy;
- u32 err_phy_stats[ATH9K_PHYERR_MAX];
};
struct ath9k_debug {
struct dentry *debugfs_phy;
struct ath_tx_stats tx_stats;
struct ath_rx_stats rx_stats;
+ struct ath_skbrx_stats skbrx_stats;
};
void ath9k_htc_get_et_strings(struct ieee80211_hw *hw,
@@ -385,7 +378,7 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
#define TX_QSTAT_INC(c) do { } while (0)
static inline void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
- struct ath_htc_rx_status *rxs)
+ struct ath_rx_status *rs)
{
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
index fb071ee4fcf..8b529e4b8ac 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_debug.c
@@ -243,39 +243,14 @@ static const struct file_operations fops_xmit = {
};
void ath9k_htc_err_stat_rx(struct ath9k_htc_priv *priv,
- struct ath_htc_rx_status *rxs)
+ struct ath_rx_status *rs)
{
-#define RX_PHY_ERR_INC(c) priv->debug.rx_stats.err_phy_stats[c]++
-
- if (rxs->rs_status & ATH9K_RXERR_CRC)
- priv->debug.rx_stats.err_crc++;
- if (rxs->rs_status & ATH9K_RXERR_DECRYPT)
- priv->debug.rx_stats.err_decrypt_crc++;
- if (rxs->rs_status & ATH9K_RXERR_MIC)
- priv->debug.rx_stats.err_mic++;
- if (rxs->rs_status & ATH9K_RX_DELIM_CRC_PRE)
- priv->debug.rx_stats.err_pre_delim++;
- if (rxs->rs_status & ATH9K_RX_DELIM_CRC_POST)
- priv->debug.rx_stats.err_post_delim++;
- if (rxs->rs_status & ATH9K_RX_DECRYPT_BUSY)
- priv->debug.rx_stats.err_decrypt_busy++;
-
- if (rxs->rs_status & ATH9K_RXERR_PHY) {
- priv->debug.rx_stats.err_phy++;
- if (rxs->rs_phyerr < ATH9K_PHYERR_MAX)
- RX_PHY_ERR_INC(rxs->rs_phyerr);
- }
-
-#undef RX_PHY_ERR_INC
+ ath9k_cmn_debug_stat_rx(&priv->debug.rx_stats, rs);
}
-static ssize_t read_file_recv(struct file *file, char __user *user_buf,
+static ssize_t read_file_skb_rx(struct file *file, char __user *user_buf,
size_t count, loff_t *ppos)
{
-#define PHY_ERR(s, p) \
- len += scnprintf(buf + len, size - len, "%20s : %10u\n", s, \
- priv->debug.rx_stats.err_phy_stats[p]);
-
struct ath9k_htc_priv *priv = file->private_data;
char *buf;
unsigned int len = 0, size = 1500;
@@ -287,63 +262,13 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "SKBs allocated",
- priv->debug.rx_stats.skb_allocated);
+ priv->debug.skbrx_stats.skb_allocated);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "SKBs completed",
- priv->debug.rx_stats.skb_completed);
+ priv->debug.skbrx_stats.skb_completed);
len += scnprintf(buf + len, size - len,
"%20s : %10u\n", "SKBs Dropped",
- priv->debug.rx_stats.skb_dropped);
-
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "CRC ERR",
- priv->debug.rx_stats.err_crc);
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "DECRYPT CRC ERR",
- priv->debug.rx_stats.err_decrypt_crc);
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "MIC ERR",
- priv->debug.rx_stats.err_mic);
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "PRE-DELIM CRC ERR",
- priv->debug.rx_stats.err_pre_delim);
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "POST-DELIM CRC ERR",
- priv->debug.rx_stats.err_post_delim);
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "DECRYPT BUSY ERR",
- priv->debug.rx_stats.err_decrypt_busy);
- len += scnprintf(buf + len, size - len,
- "%20s : %10u\n", "TOTAL PHY ERR",
- priv->debug.rx_stats.err_phy);
-
-
- PHY_ERR("UNDERRUN", ATH9K_PHYERR_UNDERRUN);
- PHY_ERR("TIMING", ATH9K_PHYERR_TIMING);
- PHY_ERR("PARITY", ATH9K_PHYERR_PARITY);
- PHY_ERR("RATE", ATH9K_PHYERR_RATE);
- PHY_ERR("LENGTH", ATH9K_PHYERR_LENGTH);
- PHY_ERR("RADAR", ATH9K_PHYERR_RADAR);
- PHY_ERR("SERVICE", ATH9K_PHYERR_SERVICE);
- PHY_ERR("TOR", ATH9K_PHYERR_TOR);
- PHY_ERR("OFDM-TIMING", ATH9K_PHYERR_OFDM_TIMING);
- PHY_ERR("OFDM-SIGNAL-PARITY", ATH9K_PHYERR_OFDM_SIGNAL_PARITY);
- PHY_ERR("OFDM-RATE", ATH9K_PHYERR_OFDM_RATE_ILLEGAL);
- PHY_ERR("OFDM-LENGTH", ATH9K_PHYERR_OFDM_LENGTH_ILLEGAL);
- PHY_ERR("OFDM-POWER-DROP", ATH9K_PHYERR_OFDM_POWER_DROP);
- PHY_ERR("OFDM-SERVICE", ATH9K_PHYERR_OFDM_SERVICE);
- PHY_ERR("OFDM-RESTART", ATH9K_PHYERR_OFDM_RESTART);
- PHY_ERR("FALSE-RADAR-EXT", ATH9K_PHYERR_FALSE_RADAR_EXT);
- PHY_ERR("CCK-TIMING", ATH9K_PHYERR_CCK_TIMING);
- PHY_ERR("CCK-HEADER-CRC", ATH9K_PHYERR_CCK_HEADER_CRC);
- PHY_ERR("CCK-RATE", ATH9K_PHYERR_CCK_RATE_ILLEGAL);
- PHY_ERR("CCK-SERVICE", ATH9K_PHYERR_CCK_SERVICE);
- PHY_ERR("CCK-RESTART", ATH9K_PHYERR_CCK_RESTART);
- PHY_ERR("CCK-LENGTH", ATH9K_PHYERR_CCK_LENGTH_ILLEGAL);
- PHY_ERR("CCK-POWER-DROP", ATH9K_PHYERR_CCK_POWER_DROP);
- PHY_ERR("HT-CRC", ATH9K_PHYERR_HT_CRC_ERROR);
- PHY_ERR("HT-LENGTH", ATH9K_PHYERR_HT_LENGTH_ILLEGAL);
- PHY_ERR("HT-RATE", ATH9K_PHYERR_HT_RATE_ILLEGAL);
+ priv->debug.skbrx_stats.skb_dropped);
if (len > size)
len = size;
@@ -352,12 +277,10 @@ static ssize_t read_file_recv(struct file *file, char __user *user_buf,
kfree(buf);
return retval;
-
-#undef PHY_ERR
}
-static const struct file_operations fops_recv = {
- .read = read_file_recv,
+static const struct file_operations fops_skb_rx = {
+ .read = read_file_skb_rx,
.open = simple_open,
.owner = THIS_MODULE,
.llseek = default_llseek,
@@ -486,423 +409,6 @@ static const struct file_operations fops_debug = {
.llseek = default_llseek,
};
-static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath9k_htc_priv *priv = file->private_data;
- struct ath_common *common = ath9k_hw_common(priv->ah);
- struct base_eep_header *pBase = NULL;
- unsigned int len = 0, size = 1500;
- ssize_t retval = 0;
- char *buf;
-
- pBase = ath9k_htc_get_eeprom_base(priv);
-
- if (pBase == NULL) {
- ath_err(common, "Unknown EEPROM type\n");
- return 0;
- }
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n", "Major Version",
- pBase->version >> 12);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n", "Minor Version",
- pBase->version & 0xFFF);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n", "Checksum",
- pBase->checksum);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n", "Length",
- pBase->length);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n", "RegDomain1",
- pBase->regDmn[0]);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n", "RegDomain2",
- pBase->regDmn[1]);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "TX Mask", pBase->txMask);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "RX Mask", pBase->rxMask);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Allow 5GHz",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Allow 2GHz",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 2GHz HT20",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT20));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 2GHz HT40",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_2G_HT40));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 5Ghz HT20",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT20));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Disable 5Ghz HT40",
- !!(pBase->opCapFlags & AR5416_OPFLAGS_N_5G_HT40));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Big Endian",
- !!(pBase->eepMisc & 0x01));
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Cal Bin Major Ver",
- (pBase->binBuildNumber >> 24) & 0xFF);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Cal Bin Minor Ver",
- (pBase->binBuildNumber >> 16) & 0xFF);
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "Cal Bin Build",
- (pBase->binBuildNumber >> 8) & 0xFF);
-
- /*
- * UB91 specific data.
- */
- if (AR_SREV_9271(priv->ah)) {
- struct base_eep_header_4k *pBase4k =
- &priv->ah->eeprom.map4k.baseEepHeader;
-
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "TX Gain type",
- pBase4k->txGainType);
- }
-
- /*
- * UB95 specific data.
- */
- if (priv->ah->hw_version.usbdev == AR9287_USB) {
- struct base_eep_ar9287_header *pBase9287 =
- &priv->ah->eeprom.map9287.baseEepHeader;
-
- len += scnprintf(buf + len, size - len,
- "%20s : %10ddB\n",
- "Power Table Offset",
- pBase9287->pwrTableOffset);
-
- len += scnprintf(buf + len, size - len,
- "%20s : %10d\n",
- "OpenLoop Power Ctrl",
- pBase9287->openLoopPwrCntl);
- }
-
- len += scnprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
- pBase->macAddr);
- if (len > size)
- len = size;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-}
-
-static const struct file_operations fops_base_eeprom = {
- .read = read_file_base_eeprom,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-static ssize_t read_4k_modal_eeprom(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
-#define PR_EEP(_s, _val) \
- do { \
- len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
- _s, (_val)); \
- } while (0)
-
- struct ath9k_htc_priv *priv = file->private_data;
- struct modal_eep_4k_header *pModal = &priv->ah->eeprom.map4k.modalHeader;
- unsigned int len = 0, size = 2048;
- ssize_t retval = 0;
- char *buf;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
- PR_EEP("Ant. Common Control", pModal->antCtrlCommon);
- PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]);
- PR_EEP("Switch Settle", pModal->switchSettling);
- PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]);
- PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]);
- PR_EEP("ADC Desired size", pModal->adcDesiredSize);
- PR_EEP("PGA Desired size", pModal->pgaDesiredSize);
- PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]);
- PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff);
- PR_EEP("txEndToRxOn", pModal->txEndToRxOn);
- PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn);
- PR_EEP("CCA Threshold)", pModal->thresh62);
- PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]);
- PR_EEP("xpdGain", pModal->xpdGain);
- PR_EEP("External PD", pModal->xpd);
- PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]);
- PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]);
- PR_EEP("pdGainOverlap", pModal->pdGainOverlap);
- PR_EEP("O/D Bias Version", pModal->version);
- PR_EEP("CCK OutputBias", pModal->ob_0);
- PR_EEP("BPSK OutputBias", pModal->ob_1);
- PR_EEP("QPSK OutputBias", pModal->ob_2);
- PR_EEP("16QAM OutputBias", pModal->ob_3);
- PR_EEP("64QAM OutputBias", pModal->ob_4);
- PR_EEP("CCK Driver1_Bias", pModal->db1_0);
- PR_EEP("BPSK Driver1_Bias", pModal->db1_1);
- PR_EEP("QPSK Driver1_Bias", pModal->db1_2);
- PR_EEP("16QAM Driver1_Bias", pModal->db1_3);
- PR_EEP("64QAM Driver1_Bias", pModal->db1_4);
- PR_EEP("CCK Driver2_Bias", pModal->db2_0);
- PR_EEP("BPSK Driver2_Bias", pModal->db2_1);
- PR_EEP("QPSK Driver2_Bias", pModal->db2_2);
- PR_EEP("16QAM Driver2_Bias", pModal->db2_3);
- PR_EEP("64QAM Driver2_Bias", pModal->db2_4);
- PR_EEP("xPA Bias Level", pModal->xpaBiasLvl);
- PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart);
- PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn);
- PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc);
- PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]);
- PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]);
- PR_EEP("HT40 Switch Settle", pModal->swSettleHt40);
- PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]);
- PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]);
- PR_EEP("Ant. Diversity ctl1", pModal->antdiv_ctl1);
- PR_EEP("Ant. Diversity ctl2", pModal->antdiv_ctl2);
- PR_EEP("TX Diversity", pModal->tx_diversity);
-
- if (len > size)
- len = size;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-
-#undef PR_EEP
-}
-
-static ssize_t read_def_modal_eeprom(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
-#define PR_EEP(_s, _val) \
- do { \
- if (pBase->opCapFlags & AR5416_OPFLAGS_11G) { \
- pModal = &priv->ah->eeprom.def.modalHeader[1]; \
- len += scnprintf(buf + len, size - len, "%20s : %8d%7s", \
- _s, (_val), "|"); \
- } \
- if (pBase->opCapFlags & AR5416_OPFLAGS_11A) { \
- pModal = &priv->ah->eeprom.def.modalHeader[0]; \
- len += scnprintf(buf + len, size - len, "%9d\n",\
- (_val)); \
- } \
- } while (0)
-
- struct ath9k_htc_priv *priv = file->private_data;
- struct base_eep_header *pBase = &priv->ah->eeprom.def.baseEepHeader;
- struct modal_eep_header *pModal = NULL;
- unsigned int len = 0, size = 3500;
- ssize_t retval = 0;
- char *buf;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- len += scnprintf(buf + len, size - len,
- "%31s %15s\n", "2G", "5G");
- len += scnprintf(buf + len, size - len,
- "%32s %16s\n", "====", "====\n");
-
- PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
- PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]);
- PR_EEP("Chain2 Ant. Control", pModal->antCtrlChain[2]);
- PR_EEP("Ant. Common Control", pModal->antCtrlCommon);
- PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]);
- PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]);
- PR_EEP("Chain2 Ant. Gain", pModal->antennaGainCh[2]);
- PR_EEP("Switch Settle", pModal->switchSettling);
- PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]);
- PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]);
- PR_EEP("Chain2 TxRxAtten", pModal->txRxAttenCh[2]);
- PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]);
- PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]);
- PR_EEP("Chain2 RxTxMargin", pModal->rxTxMarginCh[2]);
- PR_EEP("ADC Desired size", pModal->adcDesiredSize);
- PR_EEP("PGA Desired size", pModal->pgaDesiredSize);
- PR_EEP("Chain0 xlna Gain", pModal->xlnaGainCh[0]);
- PR_EEP("Chain1 xlna Gain", pModal->xlnaGainCh[1]);
- PR_EEP("Chain2 xlna Gain", pModal->xlnaGainCh[2]);
- PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff);
- PR_EEP("txEndToRxOn", pModal->txEndToRxOn);
- PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn);
- PR_EEP("CCA Threshold)", pModal->thresh62);
- PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]);
- PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]);
- PR_EEP("Chain2 NF Threshold", pModal->noiseFloorThreshCh[2]);
- PR_EEP("xpdGain", pModal->xpdGain);
- PR_EEP("External PD", pModal->xpd);
- PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]);
- PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]);
- PR_EEP("Chain2 I Coefficient", pModal->iqCalICh[2]);
- PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]);
- PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]);
- PR_EEP("Chain2 Q Coefficient", pModal->iqCalQCh[2]);
- PR_EEP("pdGainOverlap", pModal->pdGainOverlap);
- PR_EEP("Chain0 OutputBias", pModal->ob);
- PR_EEP("Chain0 DriverBias", pModal->db);
- PR_EEP("xPA Bias Level", pModal->xpaBiasLvl);
- PR_EEP("2chain pwr decrease", pModal->pwrDecreaseFor2Chain);
- PR_EEP("3chain pwr decrease", pModal->pwrDecreaseFor3Chain);
- PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart);
- PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn);
- PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc);
- PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]);
- PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]);
- PR_EEP("Chain2 bswAtten", pModal->bswAtten[2]);
- PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]);
- PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]);
- PR_EEP("Chain2 bswMargin", pModal->bswMargin[2]);
- PR_EEP("HT40 Switch Settle", pModal->swSettleHt40);
- PR_EEP("Chain0 xatten2Db", pModal->xatten2Db[0]);
- PR_EEP("Chain1 xatten2Db", pModal->xatten2Db[1]);
- PR_EEP("Chain2 xatten2Db", pModal->xatten2Db[2]);
- PR_EEP("Chain0 xatten2Margin", pModal->xatten2Margin[0]);
- PR_EEP("Chain1 xatten2Margin", pModal->xatten2Margin[1]);
- PR_EEP("Chain2 xatten2Margin", pModal->xatten2Margin[2]);
- PR_EEP("Chain1 OutputBias", pModal->ob_ch1);
- PR_EEP("Chain1 DriverBias", pModal->db_ch1);
- PR_EEP("LNA Control", pModal->lna_ctl);
- PR_EEP("XPA Bias Freq0", pModal->xpaBiasLvlFreq[0]);
- PR_EEP("XPA Bias Freq1", pModal->xpaBiasLvlFreq[1]);
- PR_EEP("XPA Bias Freq2", pModal->xpaBiasLvlFreq[2]);
-
- if (len > size)
- len = size;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-
-#undef PR_EEP
-}
-
-static ssize_t read_9287_modal_eeprom(struct file *file,
- char __user *user_buf,
- size_t count, loff_t *ppos)
-{
-#define PR_EEP(_s, _val) \
- do { \
- len += scnprintf(buf + len, size - len, "%20s : %10d\n",\
- _s, (_val)); \
- } while (0)
-
- struct ath9k_htc_priv *priv = file->private_data;
- struct modal_eep_ar9287_header *pModal = &priv->ah->eeprom.map9287.modalHeader;
- unsigned int len = 0, size = 3000;
- ssize_t retval = 0;
- char *buf;
-
- buf = kzalloc(size, GFP_KERNEL);
- if (buf == NULL)
- return -ENOMEM;
-
- PR_EEP("Chain0 Ant. Control", pModal->antCtrlChain[0]);
- PR_EEP("Chain1 Ant. Control", pModal->antCtrlChain[1]);
- PR_EEP("Ant. Common Control", pModal->antCtrlCommon);
- PR_EEP("Chain0 Ant. Gain", pModal->antennaGainCh[0]);
- PR_EEP("Chain1 Ant. Gain", pModal->antennaGainCh[1]);
- PR_EEP("Switch Settle", pModal->switchSettling);
- PR_EEP("Chain0 TxRxAtten", pModal->txRxAttenCh[0]);
- PR_EEP("Chain1 TxRxAtten", pModal->txRxAttenCh[1]);
- PR_EEP("Chain0 RxTxMargin", pModal->rxTxMarginCh[0]);
- PR_EEP("Chain1 RxTxMargin", pModal->rxTxMarginCh[1]);
- PR_EEP("ADC Desired size", pModal->adcDesiredSize);
- PR_EEP("txEndToXpaOff", pModal->txEndToXpaOff);
- PR_EEP("txEndToRxOn", pModal->txEndToRxOn);
- PR_EEP("txFrameToXpaOn", pModal->txFrameToXpaOn);
- PR_EEP("CCA Threshold)", pModal->thresh62);
- PR_EEP("Chain0 NF Threshold", pModal->noiseFloorThreshCh[0]);
- PR_EEP("Chain1 NF Threshold", pModal->noiseFloorThreshCh[1]);
- PR_EEP("xpdGain", pModal->xpdGain);
- PR_EEP("External PD", pModal->xpd);
- PR_EEP("Chain0 I Coefficient", pModal->iqCalICh[0]);
- PR_EEP("Chain1 I Coefficient", pModal->iqCalICh[1]);
- PR_EEP("Chain0 Q Coefficient", pModal->iqCalQCh[0]);
- PR_EEP("Chain1 Q Coefficient", pModal->iqCalQCh[1]);
- PR_EEP("pdGainOverlap", pModal->pdGainOverlap);
- PR_EEP("xPA Bias Level", pModal->xpaBiasLvl);
- PR_EEP("txFrameToDataStart", pModal->txFrameToDataStart);
- PR_EEP("txFrameToPaOn", pModal->txFrameToPaOn);
- PR_EEP("HT40 Power Inc.", pModal->ht40PowerIncForPdadc);
- PR_EEP("Chain0 bswAtten", pModal->bswAtten[0]);
- PR_EEP("Chain1 bswAtten", pModal->bswAtten[1]);
- PR_EEP("Chain0 bswMargin", pModal->bswMargin[0]);
- PR_EEP("Chain1 bswMargin", pModal->bswMargin[1]);
- PR_EEP("HT40 Switch Settle", pModal->swSettleHt40);
- PR_EEP("AR92x7 Version", pModal->version);
- PR_EEP("DriverBias1", pModal->db1);
- PR_EEP("DriverBias2", pModal->db1);
- PR_EEP("CCK OutputBias", pModal->ob_cck);
- PR_EEP("PSK OutputBias", pModal->ob_psk);
- PR_EEP("QAM OutputBias", pModal->ob_qam);
- PR_EEP("PAL_OFF OutputBias", pModal->ob_pal_off);
-
- if (len > size)
- len = size;
-
- retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
- kfree(buf);
-
- return retval;
-
-#undef PR_EEP
-}
-
-static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
- size_t count, loff_t *ppos)
-{
- struct ath9k_htc_priv *priv = file->private_data;
-
- if (AR_SREV_9271(priv->ah))
- return read_4k_modal_eeprom(file, user_buf, count, ppos);
- else if (priv->ah->hw_version.usbdev == AR9280_USB)
- return read_def_modal_eeprom(file, user_buf, count, ppos);
- else if (priv->ah->hw_version.usbdev == AR9287_USB)
- return read_9287_modal_eeprom(file, user_buf, count, ppos);
-
- return 0;
-}
-
-static const struct file_operations fops_modal_eeprom = {
- .read = read_file_modal_eeprom,
- .open = simple_open,
- .owner = THIS_MODULE,
- .llseek = default_llseek,
-};
-
-
/* Ethtool support for get-stats */
#define AMKSTR(nm) #nm "_BE", #nm "_BK", #nm "_VI", #nm "_VO"
static const char ath9k_htc_gstrings_stats[][ETH_GSTRING_LEN] = {
@@ -947,6 +453,8 @@ int ath9k_htc_get_et_sset_count(struct ieee80211_hw *hw,
#define STXBASE priv->debug.tx_stats
#define SRXBASE priv->debug.rx_stats
+#define SKBTXBASE priv->debug.tx_stats
+#define SKBRXBASE priv->debug.skbrx_stats
#define ASTXQ(a) \
data[i++] = STXBASE.a[IEEE80211_AC_BE]; \
data[i++] = STXBASE.a[IEEE80211_AC_BK]; \
@@ -960,24 +468,24 @@ void ath9k_htc_get_et_stats(struct ieee80211_hw *hw,
struct ath9k_htc_priv *priv = hw->priv;
int i = 0;
- data[i++] = STXBASE.skb_success;
- data[i++] = STXBASE.skb_success_bytes;
- data[i++] = SRXBASE.skb_completed;
- data[i++] = SRXBASE.skb_completed_bytes;
+ data[i++] = SKBTXBASE.skb_success;
+ data[i++] = SKBTXBASE.skb_success_bytes;
+ data[i++] = SKBRXBASE.skb_completed;
+ data[i++] = SKBRXBASE.skb_completed_bytes;
ASTXQ(queue_stats);
- data[i++] = SRXBASE.err_crc;
- data[i++] = SRXBASE.err_decrypt_crc;
- data[i++] = SRXBASE.err_phy;
- data[i++] = SRXBASE.err_mic;
- data[i++] = SRXBASE.err_pre_delim;
- data[i++] = SRXBASE.err_post_delim;
- data[i++] = SRXBASE.err_decrypt_busy;
+ data[i++] = SRXBASE.crc_err;
+ data[i++] = SRXBASE.decrypt_crc_err;
+ data[i++] = SRXBASE.phy_err;
+ data[i++] = SRXBASE.mic_err;
+ data[i++] = SRXBASE.pre_delim_crc_err;
+ data[i++] = SRXBASE.post_delim_crc_err;
+ data[i++] = SRXBASE.decrypt_busy_err;
- data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_RADAR];
- data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_OFDM_TIMING];
- data[i++] = SRXBASE.err_phy_stats[ATH9K_PHYERR_CCK_TIMING];
+ data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_RADAR];
+ data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_OFDM_TIMING];
+ data[i++] = SRXBASE.phy_err_stats[ATH9K_PHYERR_CCK_TIMING];
WARN_ON(i != ATH9K_HTC_SSTATS_LEN);
}
@@ -1001,18 +509,21 @@ int ath9k_htc_init_debug(struct ath_hw *ah)
priv, &fops_tgt_rx_stats);
debugfs_create_file("xmit", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_xmit);
- debugfs_create_file("recv", S_IRUSR, priv->debug.debugfs_phy,
- priv, &fops_recv);
+ debugfs_create_file("skb_rx", S_IRUSR, priv->debug.debugfs_phy,
+ priv, &fops_skb_rx);
+
+ ath9k_cmn_debug_recv(priv->debug.debugfs_phy, &priv->debug.rx_stats);
+ ath9k_cmn_debug_phy_err(priv->debug.debugfs_phy, &priv->debug.rx_stats);
+
debugfs_create_file("slot", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_slot);
debugfs_create_file("queue", S_IRUSR, priv->debug.debugfs_phy,
priv, &fops_queue);
debugfs_create_file("debug", S_IRUSR | S_IWUSR, priv->debug.debugfs_phy,
priv, &fops_debug);
- debugfs_create_file("base_eeprom", S_IRUSR, priv->debug.debugfs_phy,
- priv, &fops_base_eeprom);
- debugfs_create_file("modal_eeprom", S_IRUSR, priv->debug.debugfs_phy,
- priv, &fops_modal_eeprom);
+
+ ath9k_cmn_debug_base_eeprom(priv->debug.debugfs_phy, priv->ah);
+ ath9k_cmn_debug_modal_eeprom(priv->debug.debugfs_phy, priv->ah);
return 0;
}
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_main.c b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
index f46cd0250e4..5627917c5ff 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_main.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_main.c
@@ -95,8 +95,10 @@ static void ath9k_htc_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif)
if ((vif->type == NL80211_IFTYPE_AP ||
vif->type == NL80211_IFTYPE_MESH_POINT) &&
- bss_conf->enable_beacon)
+ bss_conf->enable_beacon) {
priv->reconfig_beacon = true;
+ priv->rearm_ani = true;
+ }
if (bss_conf->assoc) {
priv->rearm_ani = true;
@@ -257,6 +259,7 @@ static int ath9k_htc_set_channel(struct ath9k_htc_priv *priv,
ath9k_htc_ps_wakeup(priv);
+ ath9k_htc_stop_ani(priv);
del_timer_sync(&priv->tx.cleanup_timer);
ath9k_htc_tx_drain(priv);
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
index 289f3d8924b..bb86eb2ffc9 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c
@@ -996,8 +996,6 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
goto rx_next;
}
- ath9k_htc_err_stat_rx(priv, rxstatus);
-
/* Get the RX status information */
memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
@@ -1005,6 +1003,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv,
/* Copy everything from ath_htc_rx_status (HTC_RX_FRAME_HEADER).
* After this, we can drop this part of skb. */
rx_status_htc_to_ath(&rx_stats, rxstatus);
+ ath9k_htc_err_stat_rx(priv, &rx_stats);
rx_status->mactime = be64_to_cpu(rxstatus->rs_tstamp);
skb_pull(skb, HTC_RX_FRAME_HEADER_SIZE);
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index c8a9dfab1fe..2a8ed8375ec 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -26,7 +26,6 @@
#include "ar9003_mac.h"
#include "ar9003_mci.h"
#include "ar9003_phy.h"
-#include "debug.h"
#include "ath9k.h"
static bool ath9k_hw_set_reset_reg(struct ath_hw *ah, u32 type);
@@ -246,6 +245,8 @@ static void ath9k_hw_read_revisions(struct ath_hw *ah)
return;
case AR9300_DEVID_AR953X:
ah->hw_version.macVersion = AR_SREV_VERSION_9531;
+ if (ah->get_mac_revision)
+ ah->hw_version.macRev = ah->get_mac_revision();
return;
}
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index 21e174cfc90..0246b990fe8 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -61,6 +61,10 @@ static int ath9k_ps_enable;
module_param_named(ps_enable, ath9k_ps_enable, int, 0444);
MODULE_PARM_DESC(ps_enable, "Enable WLAN PowerSave");
+static int ath9k_use_chanctx;
+module_param_named(use_chanctx, ath9k_use_chanctx, int, 0444);
+MODULE_PARM_DESC(use_chanctx, "Enable channel context for concurrency");
+
bool is_ath9k_unloaded;
#ifdef CONFIG_MAC80211_LEDS
@@ -508,7 +512,7 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
sc->tx99_power = MAX_RATE_POWER + 1;
init_waitqueue_head(&sc->tx_wait);
- if (!pdata) {
+ if (!pdata || pdata->use_eeprom) {
ah->ah_flags |= AH_USE_EEPROM;
sc->sc_ah->led_pin = -1;
} else {
@@ -646,8 +650,7 @@ static void ath9k_init_txpower_limits(struct ath_softc *sc)
}
static const struct ieee80211_iface_limit if_limits[] = {
- { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) |
- BIT(NL80211_IFTYPE_WDS) },
+ { .max = 2048, .types = BIT(NL80211_IFTYPE_STATION) },
{ .max = 8, .types =
#ifdef CONFIG_MAC80211_MESH
BIT(NL80211_IFTYPE_MESH_POINT) |
@@ -657,6 +660,10 @@ static const struct ieee80211_iface_limit if_limits[] = {
BIT(NL80211_IFTYPE_P2P_GO) },
};
+static const struct ieee80211_iface_limit wds_limits[] = {
+ { .max = 2048, .types = BIT(NL80211_IFTYPE_WDS) },
+};
+
static const struct ieee80211_iface_limit if_dfs_limits[] = {
{ .max = 1, .types = BIT(NL80211_IFTYPE_AP) |
#ifdef CONFIG_MAC80211_MESH
@@ -673,6 +680,13 @@ static const struct ieee80211_iface_combination if_comb[] = {
.num_different_channels = 1,
.beacon_int_infra_match = true,
},
+ {
+ .limits = wds_limits,
+ .n_limits = ARRAY_SIZE(wds_limits),
+ .max_interfaces = 2048,
+ .num_different_channels = 1,
+ .beacon_int_infra_match = true,
+ },
#ifdef CONFIG_ATH9K_DFS_CERTIFIED
{
.limits = if_dfs_limits,
@@ -714,19 +728,23 @@ static void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
if (AR_SREV_9160_10_OR_LATER(sc->sc_ah) || ath9k_modparam_nohwcrypt)
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
- hw->wiphy->features |= NL80211_FEATURE_ACTIVE_MONITOR;
+ hw->wiphy->features |= (NL80211_FEATURE_ACTIVE_MONITOR |
+ NL80211_FEATURE_AP_MODE_CHAN_WIDTH_CHANGE);
if (!config_enabled(CONFIG_ATH9K_TX99)) {
hw->wiphy->interface_modes =
BIT(NL80211_IFTYPE_P2P_GO) |
BIT(NL80211_IFTYPE_P2P_CLIENT) |
BIT(NL80211_IFTYPE_AP) |
- BIT(NL80211_IFTYPE_WDS) |
BIT(NL80211_IFTYPE_STATION) |
BIT(NL80211_IFTYPE_ADHOC) |
BIT(NL80211_IFTYPE_MESH_POINT);
hw->wiphy->iface_combinations = if_comb;
- hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+ if (!ath9k_use_chanctx) {
+ hw->wiphy->n_iface_combinations = ARRAY_SIZE(if_comb);
+ hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_WDS);
+ } else
+ hw->wiphy->n_iface_combinations = 1;
}
hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
@@ -786,6 +804,9 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc,
common = ath9k_hw_common(ah);
ath9k_set_hw_capab(sc, hw);
+ /* Will be cleared in ath9k_start() */
+ set_bit(ATH_OP_INVALID, &common->op_flags);
+
/* Initialize regulatory */
error = ath_regd_init(&common->regulatory, sc->hw->wiphy,
ath9k_reg_notifier);
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 51ce36f108f..275205ab5f1 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -958,3 +958,25 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah)
return;
}
EXPORT_SYMBOL(ath9k_hw_set_interrupts);
+
+#define ATH9K_HW_MAX_DCU 10
+#define ATH9K_HW_SLICE_PER_DCU 16
+#define ATH9K_HW_BIT_IN_SLICE 16
+void ath9k_hw_set_tx_filter(struct ath_hw *ah, u8 destidx, bool set)
+{
+ int dcu_idx;
+ u32 filter;
+
+ for (dcu_idx = 0; dcu_idx < 10; dcu_idx++) {
+ filter = SM(set, AR_D_TXBLK_WRITE_COMMAND);
+ filter |= SM(dcu_idx, AR_D_TXBLK_WRITE_DCU);
+ filter |= SM((destidx / ATH9K_HW_SLICE_PER_DCU),
+ AR_D_TXBLK_WRITE_SLICE);
+ filter |= BIT(destidx % ATH9K_HW_BIT_IN_SLICE);
+ ath_dbg(ath9k_hw_common(ah), PS,
+ "DCU%d staid %d set %d txfilter %08x\n",
+ dcu_idx, destidx, set, filter);
+ REG_WRITE(ah, AR_D_TXBLK_BASE, filter);
+ }
+}
+EXPORT_SYMBOL(ath9k_hw_set_tx_filter);
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 89df634e81f..da768675753 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -729,6 +729,7 @@ void ath9k_hw_startpcureceive(struct ath_hw *ah, bool is_scanning);
void ath9k_hw_abortpcurecv(struct ath_hw *ah);
bool ath9k_hw_stopdmarecv(struct ath_hw *ah, bool *reset);
int ath9k_hw_beaconq_setup(struct ath_hw *ah);
+void ath9k_hw_set_tx_filter(struct ath_hw *ah, u8 destidx, bool set);
/* Interrupt Handling */
bool ath9k_hw_intrpend(struct ath_hw *ah);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 8d7b9b66fef..62ac95d6bb9 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -421,6 +421,7 @@ static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
an->sc = sc;
an->sta = sta;
an->vif = vif;
+ memset(&an->key_idx, 0, sizeof(an->key_idx));
ath_tx_node_init(sc, an);
}
@@ -1461,8 +1462,10 @@ static int ath9k_sta_add(struct ieee80211_hw *hw,
return 0;
key = ath_key_config(common, vif, sta, &ps_key);
- if (key > 0)
+ if (key > 0) {
an->ps_key = key;
+ an->key_idx[0] = key;
+ }
return 0;
}
@@ -1480,6 +1483,7 @@ static void ath9k_del_ps_key(struct ath_softc *sc,
ath_key_delete(common, &ps_key);
an->ps_key = 0;
+ an->key_idx[0] = 0;
}
static int ath9k_sta_remove(struct ieee80211_hw *hw,
@@ -1494,6 +1498,19 @@ static int ath9k_sta_remove(struct ieee80211_hw *hw,
return 0;
}
+static void ath9k_sta_set_tx_filter(struct ath_hw *ah,
+ struct ath_node *an,
+ bool set)
+{
+ int i;
+
+ for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
+ if (!an->key_idx[i])
+ continue;
+ ath9k_hw_set_tx_filter(ah, an->key_idx[i], set);
+ }
+}
+
static void ath9k_sta_notify(struct ieee80211_hw *hw,
struct ieee80211_vif *vif,
enum sta_notify_cmd cmd,
@@ -1506,8 +1523,10 @@ static void ath9k_sta_notify(struct ieee80211_hw *hw,
case STA_NOTIFY_SLEEP:
an->sleeping = true;
ath_tx_aggr_sleep(sta, sc, an);
+ ath9k_sta_set_tx_filter(sc->sc_ah, an, true);
break;
case STA_NOTIFY_AWAKE:
+ ath9k_sta_set_tx_filter(sc->sc_ah, an, false);
an->sleeping = false;
ath_tx_aggr_wakeup(sc, an);
break;
@@ -1563,7 +1582,8 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
{
struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
- int ret = 0;
+ struct ath_node *an = NULL;
+ int ret = 0, i;
if (ath9k_modparam_nohwcrypt)
return -ENOSPC;
@@ -1585,13 +1605,16 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
mutex_lock(&sc->mutex);
ath9k_ps_wakeup(sc);
- ath_dbg(common, CONFIG, "Set HW Key\n");
+ ath_dbg(common, CONFIG, "Set HW Key %d\n", cmd);
+ if (sta)
+ an = (struct ath_node *)sta->drv_priv;
switch (cmd) {
case SET_KEY:
if (sta)
ath9k_del_ps_key(sc, vif, sta);
+ key->hw_key_idx = 0;
ret = ath_key_config(common, vif, sta, key);
if (ret >= 0) {
key->hw_key_idx = ret;
@@ -1604,9 +1627,27 @@ static int ath9k_set_key(struct ieee80211_hw *hw,
key->flags |= IEEE80211_KEY_FLAG_SW_MGMT_TX;
ret = 0;
}
+ if (an && key->hw_key_idx) {
+ for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
+ if (an->key_idx[i])
+ continue;
+ an->key_idx[i] = key->hw_key_idx;
+ break;
+ }
+ WARN_ON(i == ARRAY_SIZE(an->key_idx));
+ }
break;
case DISABLE_KEY:
ath_key_delete(common, key);
+ if (an) {
+ for (i = 0; i < ARRAY_SIZE(an->key_idx); i++) {
+ if (an->key_idx[i] != key->hw_key_idx)
+ continue;
+ an->key_idx[i] = 0;
+ break;
+ }
+ }
+ key->hw_key_idx = 0;
break;
default:
ret = -EINVAL;
@@ -1716,7 +1757,6 @@ out:
void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
{
struct ath_vif *avp = (void *)vif->drv_priv;
- unsigned long flags;
u32 tsf;
if (!sc->p2p_ps_timer)
@@ -1726,14 +1766,9 @@ void ath9k_update_p2p_ps(struct ath_softc *sc, struct ieee80211_vif *vif)
return;
sc->p2p_ps_vif = avp;
-
- spin_lock_irqsave(&sc->sc_pm_lock, flags);
- if (!(sc->ps_flags & PS_BEACON_SYNC)) {
- tsf = ath9k_hw_gettsf32(sc->sc_ah);
- ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
- ath9k_update_p2p_ps_timer(sc, avp);
- }
- spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
+ tsf = ath9k_hw_gettsf32(sc->sc_ah);
+ ieee80211_parse_p2p_noa(&vif->bss_conf.p2p_noa_attr, &avp->noa, tsf);
+ ath9k_update_p2p_ps_timer(sc, avp);
}
static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
@@ -1750,6 +1785,7 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
struct ath_vif *avp = (void *)vif->drv_priv;
+ unsigned long flags;
int slottime;
ath9k_ps_wakeup(sc);
@@ -1812,7 +1848,10 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw,
if (changed & BSS_CHANGED_P2P_PS) {
spin_lock_bh(&sc->sc_pcu_lock);
- ath9k_update_p2p_ps(sc, vif);
+ spin_lock_irqsave(&sc->sc_pm_lock, flags);
+ if (!(sc->ps_flags & PS_BEACON_SYNC))
+ ath9k_update_p2p_ps(sc, vif);
+ spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
spin_unlock_bh(&sc->sc_pcu_lock);
}
@@ -2191,14 +2230,6 @@ static void ath9k_sw_scan_complete(struct ieee80211_hw *hw)
clear_bit(ATH_OP_SCANNING, &common->op_flags);
}
-static void ath9k_channel_switch_beacon(struct ieee80211_hw *hw,
- struct ieee80211_vif *vif,
- struct cfg80211_chan_def *chandef)
-{
- /* depend on vif->csa_active only */
- return;
-}
-
struct ieee80211_ops ath9k_ops = {
.tx = ath9k_tx,
.start = ath9k_start,
@@ -2246,5 +2277,4 @@ struct ieee80211_ops ath9k_ops = {
#endif
.sw_scan_start = ath9k_sw_scan_start,
.sw_scan_complete = ath9k_sw_scan_complete,
- .channel_switch_beacon = ath9k_channel_switch_beacon,
};
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index 25304adece5..4dec09e565e 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -686,7 +686,7 @@ static bool ath_pci_eeprom_read(struct ath_common *common, u32 off, u16 *data)
struct ath_softc *sc = (struct ath_softc *) common->priv;
struct ath9k_platform_data *pdata = sc->dev->platform_data;
- if (pdata) {
+ if (pdata && !pdata->use_eeprom) {
if (off >= (ARRAY_SIZE(pdata->eeprom_data))) {
ath_err(common,
"%s: eeprom read failed, offset %08x is out of range\n",
@@ -784,7 +784,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
{
struct ath_softc *sc;
struct ieee80211_hw *hw;
- struct ath_common *common;
u8 csz;
u32 val;
int ret = 0;
@@ -877,10 +876,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
wiphy_info(hw->wiphy, "%s mem=0x%lx, irq=%d\n",
hw_name, (unsigned long)sc->mem, pdev->irq);
- /* Will be cleared in ath9k_start() */
- common = ath9k_hw_common(sc->sc_ah);
- set_bit(ATH_OP_INVALID, &common->op_flags);
-
return 0;
err_init:
@@ -919,6 +914,7 @@ static int ath_pci_suspend(struct device *device)
*/
ath9k_stop_btcoex(sc);
ath9k_hw_disable(sc->sc_ah);
+ del_timer_sync(&sc->sleep_timer);
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
return 0;
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index a01efd3e741..9105a92364f 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -34,7 +34,8 @@ static inline bool ath9k_check_auto_sleep(struct ath_softc *sc)
* buffer (or rx fifo). This can incorrectly acknowledge packets
* to a sender if last desc is self-linked.
*/
-static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
+static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf,
+ bool flush)
{
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
@@ -59,18 +60,19 @@ static void ath_rx_buf_link(struct ath_softc *sc, struct ath_rxbuf *bf)
common->rx_bufsize,
0);
- if (sc->rx.rxlink == NULL)
- ath9k_hw_putrxbuf(ah, bf->bf_daddr);
- else
+ if (sc->rx.rxlink)
*sc->rx.rxlink = bf->bf_daddr;
+ else if (!flush)
+ ath9k_hw_putrxbuf(ah, bf->bf_daddr);
sc->rx.rxlink = &ds->ds_link;
}
-static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf)
+static void ath_rx_buf_relink(struct ath_softc *sc, struct ath_rxbuf *bf,
+ bool flush)
{
if (sc->rx.buf_hold)
- ath_rx_buf_link(sc, sc->rx.buf_hold);
+ ath_rx_buf_link(sc, sc->rx.buf_hold, flush);
sc->rx.buf_hold = bf;
}
@@ -442,7 +444,7 @@ int ath_startrecv(struct ath_softc *sc)
sc->rx.buf_hold = NULL;
sc->rx.rxlink = NULL;
list_for_each_entry_safe(bf, tbf, &sc->rx.rxbuf, list) {
- ath_rx_buf_link(sc, bf);
+ ath_rx_buf_link(sc, bf, false);
}
/* We could have deleted elements so the list may be empty now */
@@ -538,8 +540,8 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
sc->ps_flags &= ~PS_BEACON_SYNC;
ath_dbg(common, PS,
"Reconfigure beacon timers based on synchronized timestamp\n");
- ath9k_set_beacon(sc);
-
+ if (!(WARN_ON_ONCE(sc->cur_beacon_conf.beacon_interval == 0)))
+ ath9k_set_beacon(sc);
if (sc->p2p_ps_vif)
ath9k_update_p2p_ps(sc, sc->p2p_ps_vif->vif);
}
@@ -978,6 +980,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
u64 tsf = 0;
unsigned long flags;
dma_addr_t new_buf_addr;
+ unsigned int budget = 512;
if (edma)
dma_type = DMA_BIDIRECTIONAL;
@@ -1116,15 +1119,17 @@ requeue_drop_frag:
}
requeue:
list_add_tail(&bf->list, &sc->rx.rxbuf);
- if (flush)
- continue;
- if (edma) {
+ if (!edma) {
+ ath_rx_buf_relink(sc, bf, flush);
+ if (!flush)
+ ath9k_hw_rxena(ah);
+ } else if (!flush) {
ath_rx_edma_buf_link(sc, qtype);
- } else {
- ath_rx_buf_relink(sc, bf);
- ath9k_hw_rxena(ah);
}
+
+ if (!budget--)
+ break;
} while (1);
if (!(ah->imask & ATH9K_INT_RXEOL)) {
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index b1fd3fa8498..f1bbce3f777 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -505,9 +505,6 @@
#define AR_D_QCUMASK 0x000003FF
#define AR_D_QCUMASK_RESV0 0xFFFFFC00
-#define AR_D_TXBLK_CMD 0x1038
-#define AR_D_TXBLK_DATA(i) (AR_D_TXBLK_CMD+(i))
-
#define AR_D0_LCL_IFS 0x1040
#define AR_D1_LCL_IFS 0x1044
#define AR_D2_LCL_IFS 0x1048
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 87cbec47fb4..7c28cb55610 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -107,9 +107,6 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid)
{
struct ath_atx_ac *ac = tid->ac;
- if (tid->paused)
- return;
-
if (tid->sched)
return;
@@ -890,6 +887,15 @@ ath_tx_get_tid_subframe(struct ath_softc *sc, struct ath_txq *txq,
tx_info = IEEE80211_SKB_CB(skb);
tx_info->flags &= ~IEEE80211_TX_CTL_CLEAR_PS_FILT;
+
+ /*
+ * No aggregation session is running, but there may be frames
+ * from a previous session or a failed attempt in the queue.
+ * Send them out as normal data frames
+ */
+ if (!tid->active)
+ tx_info->flags &= ~IEEE80211_TX_CTL_AMPDU;
+
if (!(tx_info->flags & IEEE80211_TX_CTL_AMPDU)) {
bf->bf_state.bf_type = 0;
return bf;
@@ -1407,7 +1413,6 @@ int ath_tx_aggr_start(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_tx_tid_change_state(sc, txtid);
txtid->active = true;
- txtid->paused = true;
*ssn = txtid->seq_start = txtid->seq_next;
txtid->bar_index = -1;
@@ -1427,7 +1432,6 @@ void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
ath_txq_lock(sc, txq);
txtid->active = false;
- txtid->paused = false;
ath_tx_flush_tid(sc, txtid);
ath_tx_tid_change_state(sc, txtid);
ath_txq_unlock_complete(sc, txq);
@@ -1487,7 +1491,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an)
ath_txq_lock(sc, txq);
ac->clear_ps_filter = true;
- if (!tid->paused && ath_tid_has_buffered(tid)) {
+ if (ath_tid_has_buffered(tid)) {
ath_tx_queue_tid(txq, tid);
ath_txq_schedule(sc, txq);
}
@@ -1510,7 +1514,6 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta,
ath_txq_lock(sc, txq);
tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor;
- tid->paused = false;
if (ath_tid_has_buffered(tid)) {
ath_tx_queue_tid(txq, tid);
@@ -1544,8 +1547,6 @@ void ath9k_release_buffered_frames(struct ieee80211_hw *hw,
continue;
tid = ATH_AN_2_TID(an, i);
- if (tid->paused)
- continue;
ath_txq_lock(sc, tid->ac->txq);
while (nframes > 0) {
@@ -1844,9 +1845,6 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
list_del(&tid->list);
tid->sched = false;
- if (tid->paused)
- continue;
-
if (ath_tx_sched_aggr(sc, txq, tid, &stop))
sent = true;
@@ -2698,7 +2696,6 @@ void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an)
tid->baw_size = WME_MAX_BA;
tid->baw_head = tid->baw_tail = 0;
tid->sched = false;
- tid->paused = false;
tid->active = false;
__skb_queue_head_init(&tid->buf_q);
__skb_queue_head_init(&tid->retry_q);
diff --git a/drivers/net/wireless/ath/carl9170/usb.c b/drivers/net/wireless/ath/carl9170/usb.c
index ca115f33746..f35c7f30f9a 100644
--- a/drivers/net/wireless/ath/carl9170/usb.c
+++ b/drivers/net/wireless/ath/carl9170/usb.c
@@ -1076,8 +1076,14 @@ static int carl9170_usb_probe(struct usb_interface *intf,
carl9170_set_state(ar, CARL9170_STOPPED);
- return request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
+ err = request_firmware_nowait(THIS_MODULE, 1, CARL9170FW_NAME,
&ar->udev->dev, GFP_KERNEL, ar, carl9170_usb_firmware_step2);
+ if (err) {
+ usb_put_dev(udev);
+ usb_put_dev(udev);
+ carl9170_free(ar);
+ }
+ return err;
}
static void carl9170_usb_disconnect(struct usb_interface *intf)
diff --git a/drivers/net/wireless/ath/dfs_pattern_detector.c b/drivers/net/wireless/ath/dfs_pattern_detector.c
index a1a69c5db40..650be79c7ac 100644
--- a/drivers/net/wireless/ath/dfs_pattern_detector.c
+++ b/drivers/net/wireless/ath/dfs_pattern_detector.c
@@ -73,9 +73,52 @@ static const struct radar_types etsi_radar_types_v15 = {
.radar_types = etsi_radar_ref_types_v15,
};
-/* for now, we support ETSI radar types, FCC and JP are TODO */
+#define FCC_PATTERN(ID, WMIN, WMAX, PMIN, PMAX, PRF, PPB) \
+{ \
+ ID, WIDTH_LOWER(WMIN), WIDTH_UPPER(WMAX), \
+ PMIN - PRI_TOLERANCE, \
+ PMAX * PRF + PRI_TOLERANCE, PRF, PPB * PRF, \
+ PPB_THRESH(PPB), PRI_TOLERANCE, \
+}
+
+static const struct radar_detector_specs fcc_radar_ref_types[] = {
+ FCC_PATTERN(0, 0, 1, 1428, 1428, 1, 18),
+ FCC_PATTERN(1, 0, 5, 150, 230, 1, 23),
+ FCC_PATTERN(2, 6, 10, 200, 500, 1, 16),
+ FCC_PATTERN(3, 11, 20, 200, 500, 1, 12),
+ FCC_PATTERN(4, 50, 100, 1000, 2000, 20, 1),
+ FCC_PATTERN(5, 0, 1, 333, 333, 1, 9),
+};
+
+static const struct radar_types fcc_radar_types = {
+ .region = NL80211_DFS_FCC,
+ .num_radar_types = ARRAY_SIZE(fcc_radar_ref_types),
+ .radar_types = fcc_radar_ref_types,
+};
+
+#define JP_PATTERN FCC_PATTERN
+static const struct radar_detector_specs jp_radar_ref_types[] = {
+ JP_PATTERN(0, 0, 1, 1428, 1428, 1, 18),
+ JP_PATTERN(1, 2, 3, 3846, 3846, 1, 18),
+ JP_PATTERN(2, 0, 1, 1388, 1388, 1, 18),
+ JP_PATTERN(3, 1, 2, 4000, 4000, 1, 18),
+ JP_PATTERN(4, 0, 5, 150, 230, 1, 23),
+ JP_PATTERN(5, 6, 10, 200, 500, 1, 16),
+ JP_PATTERN(6, 11, 20, 200, 500, 1, 12),
+ JP_PATTERN(7, 50, 100, 1000, 2000, 20, 1),
+ JP_PATTERN(5, 0, 1, 333, 333, 1, 9),
+};
+
+static const struct radar_types jp_radar_types = {
+ .region = NL80211_DFS_JP,
+ .num_radar_types = ARRAY_SIZE(jp_radar_ref_types),
+ .radar_types = jp_radar_ref_types,
+};
+
static const struct radar_types *dfs_domains[] = {
&etsi_radar_types_v15,
+ &fcc_radar_types,
+ &jp_radar_types,
};
/**
diff --git a/drivers/net/wireless/ath/wcn36xx/smd.c b/drivers/net/wireless/ath/wcn36xx/smd.c
index 7bf0ef8a1f5..63986931829 100644
--- a/drivers/net/wireless/ath/wcn36xx/smd.c
+++ b/drivers/net/wireless/ath/wcn36xx/smd.c
@@ -2068,7 +2068,7 @@ static void wcn36xx_smd_rsp_process(struct wcn36xx *wcn, void *buf, size_t len)
if (!msg_ind)
goto nomem;
msg_ind->msg_len = len;
- msg_ind->msg = kmalloc(len, GFP_KERNEL);
+ msg_ind->msg = kmemdup(buf, len, GFP_KERNEL);
if (!msg_ind->msg) {
kfree(msg_ind);
nomem:
@@ -2080,7 +2080,6 @@ nomem:
msg_header->msg_type);
break;
}
- memcpy(msg_ind->msg, buf, len);
mutex_lock(&wcn->hal_ind_mutex);
list_add_tail(&msg_ind->list, &wcn->hal_ind_queue);
queue_work(wcn->hal_ind_wq, &wcn->hal_ind_work);
diff --git a/drivers/net/wireless/ath/wil6210/cfg80211.c b/drivers/net/wireless/ath/wil6210/cfg80211.c
index 4806a49cb61..820d4ebd932 100644
--- a/drivers/net/wireless/ath/wil6210/cfg80211.c
+++ b/drivers/net/wireless/ath/wil6210/cfg80211.c
@@ -172,7 +172,7 @@ static int wil_cid_fill_sinfo(struct wil6210_priv *wil, int cid,
static int wil_cfg80211_get_station(struct wiphy *wiphy,
struct net_device *ndev,
- u8 *mac, struct station_info *sinfo)
+ const u8 *mac, struct station_info *sinfo)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
int rc;
@@ -288,6 +288,7 @@ static int wil_cfg80211_scan(struct wiphy *wiphy,
}
wil->scan_request = request;
+ mod_timer(&wil->scan_timer, jiffies + WIL6210_SCAN_TO);
memset(&cmd, 0, sizeof(cmd));
cmd.cmd.num_channels = 0;
@@ -671,7 +672,7 @@ static int wil_cfg80211_stop_ap(struct wiphy *wiphy,
}
static int wil_cfg80211_del_station(struct wiphy *wiphy,
- struct net_device *dev, u8 *mac)
+ struct net_device *dev, const u8 *mac)
{
struct wil6210_priv *wil = wiphy_to_wil(wiphy);
diff --git a/drivers/net/wireless/ath/wil6210/debugfs.c b/drivers/net/wireless/ath/wil6210/debugfs.c
index ecdabe4adec..8d4bc4bfb66 100644
--- a/drivers/net/wireless/ath/wil6210/debugfs.c
+++ b/drivers/net/wireless/ath/wil6210/debugfs.c
@@ -35,7 +35,7 @@ static void wil_print_vring(struct seq_file *s, struct wil6210_priv *wil,
void __iomem *x = wmi_addr(wil, vring->hwtail);
seq_printf(s, "VRING %s = {\n", name);
- seq_printf(s, " pa = 0x%016llx\n", (unsigned long long)vring->pa);
+ seq_printf(s, " pa = %pad\n", &vring->pa);
seq_printf(s, " va = 0x%p\n", vring->va);
seq_printf(s, " size = %d\n", vring->size);
seq_printf(s, " swtail = %d\n", vring->swtail);
@@ -473,7 +473,7 @@ static int wil_txdesc_debugfs_show(struct seq_file *s, void *data)
u[0], u[1], u[2], u[3]);
seq_printf(s, " DMA = 0x%08x 0x%08x 0x%08x 0x%08x\n",
u[4], u[5], u[6], u[7]);
- seq_printf(s, " SKB = %p\n", skb);
+ seq_printf(s, " SKB = 0x%p\n", skb);
if (skb) {
skb_get(skb);
diff --git a/drivers/net/wireless/ath/wil6210/main.c b/drivers/net/wireless/ath/wil6210/main.c
index 1b265fd19de..11e6d9d22ea 100644
--- a/drivers/net/wireless/ath/wil6210/main.c
+++ b/drivers/net/wireless/ath/wil6210/main.c
@@ -81,7 +81,7 @@ static void wil_disconnect_cid(struct wil6210_priv *wil, int cid)
memset(&sta->stats, 0, sizeof(sta->stats));
}
-static void _wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+static void _wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
{
int cid = -ENOENT;
struct net_device *ndev = wil_to_ndev(wil);
@@ -150,6 +150,15 @@ static void wil_connect_timer_fn(ulong x)
schedule_work(&wil->disconnect_worker);
}
+static void wil_scan_timer_fn(ulong x)
+{
+ struct wil6210_priv *wil = (void *)x;
+
+ clear_bit(wil_status_fwready, &wil->status);
+ wil_err(wil, "Scan timeout detected, start fw error recovery\n");
+ schedule_work(&wil->fw_error_worker);
+}
+
static void wil_fw_error_worker(struct work_struct *work)
{
struct wil6210_priv *wil = container_of(work,
@@ -161,12 +170,30 @@ static void wil_fw_error_worker(struct work_struct *work)
if (no_fw_recovery)
return;
+ /* increment @recovery_count if less then WIL6210_FW_RECOVERY_TO
+ * passed since last recovery attempt
+ */
+ if (time_is_after_jiffies(wil->last_fw_recovery +
+ WIL6210_FW_RECOVERY_TO))
+ wil->recovery_count++;
+ else
+ wil->recovery_count = 1; /* fw was alive for a long time */
+
+ if (wil->recovery_count > WIL6210_FW_RECOVERY_RETRIES) {
+ wil_err(wil, "too many recovery attempts (%d), giving up\n",
+ wil->recovery_count);
+ return;
+ }
+
+ wil->last_fw_recovery = jiffies;
+
mutex_lock(&wil->mutex);
switch (wdev->iftype) {
case NL80211_IFTYPE_STATION:
case NL80211_IFTYPE_P2P_CLIENT:
case NL80211_IFTYPE_MONITOR:
- wil_info(wil, "fw error recovery started...\n");
+ wil_info(wil, "fw error recovery started (try %d)...\n",
+ wil->recovery_count);
wil_reset(wil);
/* need to re-allocate Rx ring after reset */
@@ -230,6 +257,7 @@ int wil_priv_init(struct wil6210_priv *wil)
wil->pending_connect_cid = -1;
setup_timer(&wil->connect_timer, wil_connect_timer_fn, (ulong)wil);
+ setup_timer(&wil->scan_timer, wil_scan_timer_fn, (ulong)wil);
INIT_WORK(&wil->connect_worker, wil_connect_worker);
INIT_WORK(&wil->disconnect_worker, wil_disconnect_worker);
@@ -249,10 +277,12 @@ int wil_priv_init(struct wil6210_priv *wil)
return -EAGAIN;
}
+ wil->last_fw_recovery = jiffies;
+
return 0;
}
-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid)
{
del_timer_sync(&wil->connect_timer);
_wil6210_disconnect(wil, bssid);
@@ -260,6 +290,7 @@ void wil6210_disconnect(struct wil6210_priv *wil, void *bssid)
void wil_priv_deinit(struct wil6210_priv *wil)
{
+ del_timer_sync(&wil->scan_timer);
cancel_work_sync(&wil->disconnect_worker);
cancel_work_sync(&wil->fw_error_worker);
mutex_lock(&wil->mutex);
@@ -391,6 +422,7 @@ int wil_reset(struct wil6210_priv *wil)
if (wil->scan_request) {
wil_dbg_misc(wil, "Abort scan_request 0x%p\n",
wil->scan_request);
+ del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, true);
wil->scan_request = NULL;
}
@@ -520,6 +552,7 @@ static int __wil_down(struct wil6210_priv *wil)
napi_disable(&wil->napi_tx);
if (wil->scan_request) {
+ del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, true);
wil->scan_request = NULL;
}
diff --git a/drivers/net/wireless/ath/wil6210/netdev.c b/drivers/net/wireless/ath/wil6210/netdev.c
index fdcaeb820e7..106b6dcb773 100644
--- a/drivers/net/wireless/ath/wil6210/netdev.c
+++ b/drivers/net/wireless/ath/wil6210/netdev.c
@@ -32,12 +32,26 @@ static int wil_stop(struct net_device *ndev)
return wil_down(wil);
}
+static int wil_change_mtu(struct net_device *ndev, int new_mtu)
+{
+ struct wil6210_priv *wil = ndev_to_wil(ndev);
+
+ if (new_mtu < 68 || new_mtu > IEEE80211_MAX_DATA_LEN_DMG)
+ return -EINVAL;
+
+ wil_dbg_misc(wil, "change MTU %d -> %d\n", ndev->mtu, new_mtu);
+ ndev->mtu = new_mtu;
+
+ return 0;
+}
+
static const struct net_device_ops wil_netdev_ops = {
.ndo_open = wil_open,
.ndo_stop = wil_stop,
.ndo_start_xmit = wil_start_xmit,
.ndo_set_mac_address = eth_mac_addr,
.ndo_validate_addr = eth_validate_addr,
+ .ndo_change_mtu = wil_change_mtu,
};
static int wil6210_netdev_poll_rx(struct napi_struct *napi, int budget)
diff --git a/drivers/net/wireless/ath/wil6210/pcie_bus.c b/drivers/net/wireless/ath/wil6210/pcie_bus.c
index 06608841830..1e2e07b9d13 100644
--- a/drivers/net/wireless/ath/wil6210/pcie_bus.c
+++ b/drivers/net/wireless/ath/wil6210/pcie_bus.c
@@ -138,7 +138,7 @@ static int wil_pcie_probe(struct pci_dev *pdev, const struct pci_device_id *id)
goto err_release_reg;
}
/* rollback to err_iounmap */
- dev_info(&pdev->dev, "CSR at %pR -> %p\n", &pdev->resource[0], csr);
+ dev_info(&pdev->dev, "CSR at %pR -> 0x%p\n", &pdev->resource[0], csr);
wil = wil_if_alloc(dev, csr);
if (IS_ERR(wil)) {
diff --git a/drivers/net/wireless/ath/wil6210/rx_reorder.c b/drivers/net/wireless/ath/wil6210/rx_reorder.c
index ec29954bd44..747ae127587 100644
--- a/drivers/net/wireless/ath/wil6210/rx_reorder.c
+++ b/drivers/net/wireless/ath/wil6210/rx_reorder.c
@@ -49,10 +49,17 @@ static void wil_release_reorder_frames(struct wil6210_priv *wil,
{
int index;
- while (seq_less(r->head_seq_num, hseq)) {
+ /* note: this function is never called with
+ * hseq preceding r->head_seq_num, i.e it is always true
+ * !seq_less(hseq, r->head_seq_num)
+ * and thus on loop exit it should be
+ * r->head_seq_num == hseq
+ */
+ while (seq_less(r->head_seq_num, hseq) && r->stored_mpdu_num) {
index = reorder_index(r, r->head_seq_num);
wil_release_reorder_frame(wil, r, index);
}
+ r->head_seq_num = hseq;
}
static void wil_reorder_release(struct wil6210_priv *wil,
diff --git a/drivers/net/wireless/ath/wil6210/txrx.c b/drivers/net/wireless/ath/wil6210/txrx.c
index c8c547457eb..0784ef3d4ce 100644
--- a/drivers/net/wireless/ath/wil6210/txrx.c
+++ b/drivers/net/wireless/ath/wil6210/txrx.c
@@ -64,6 +64,22 @@ static inline int wil_vring_avail_tx(struct vring *vring)
return vring->size - used - 1;
}
+/**
+ * wil_vring_wmark_low - low watermark for available descriptor space
+ */
+static inline int wil_vring_wmark_low(struct vring *vring)
+{
+ return vring->size/8;
+}
+
+/**
+ * wil_vring_wmark_high - high watermark for available descriptor space
+ */
+static inline int wil_vring_wmark_high(struct vring *vring)
+{
+ return vring->size/4;
+}
+
static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
{
struct device *dev = wil_to_dev(wil);
@@ -98,8 +114,8 @@ static int wil_vring_alloc(struct wil6210_priv *wil, struct vring *vring)
_d->dma.status = TX_DMA_STATUS_DU;
}
- wil_dbg_misc(wil, "vring[%d] 0x%p:0x%016llx 0x%p\n", vring->size,
- vring->va, (unsigned long long)vring->pa, vring->ctx);
+ wil_dbg_misc(wil, "vring[%d] 0x%p:%pad 0x%p\n", vring->size,
+ vring->va, &vring->pa, vring->ctx);
return 0;
}
@@ -880,8 +896,8 @@ static int wil_tx_vring(struct wil6210_priv *wil, struct vring *vring,
pa = dma_map_single(dev, skb->data,
skb_headlen(skb), DMA_TO_DEVICE);
- wil_dbg_txrx(wil, "Tx skb %d bytes %p -> %#08llx\n", skb_headlen(skb),
- skb->data, (unsigned long long)pa);
+ wil_dbg_txrx(wil, "Tx skb %d bytes 0x%p -> %pad\n", skb_headlen(skb),
+ skb->data, &pa);
wil_hex_dump_txrx("Tx ", DUMP_PREFIX_OFFSET, 16, 1,
skb->data, skb_headlen(skb), false);
@@ -1007,7 +1023,7 @@ netdev_tx_t wil_start_xmit(struct sk_buff *skb, struct net_device *ndev)
rc = wil_tx_vring(wil, vring, skb);
/* do we still have enough room in the vring? */
- if (wil_vring_avail_tx(vring) < vring->size/8)
+ if (wil_vring_avail_tx(vring) < wil_vring_wmark_low(vring))
netif_tx_stop_all_queues(wil_to_ndev(wil));
switch (rc) {
@@ -1116,7 +1132,7 @@ int wil_tx_complete(struct wil6210_priv *wil, int ringid)
done++;
}
}
- if (wil_vring_avail_tx(vring) > vring->size/4)
+ if (wil_vring_avail_tx(vring) > wil_vring_wmark_high(vring))
netif_tx_wake_all_queues(wil_to_ndev(wil));
return done;
diff --git a/drivers/net/wireless/ath/wil6210/wil6210.h b/drivers/net/wireless/ath/wil6210/wil6210.h
index d3b8659ca32..e25edc52398 100644
--- a/drivers/net/wireless/ath/wil6210/wil6210.h
+++ b/drivers/net/wireless/ath/wil6210/wil6210.h
@@ -40,6 +40,9 @@ static inline u32 WIL_GET_BITS(u32 x, int b0, int b1)
#define WIL6210_MAX_CID (8) /* HW limit */
#define WIL6210_NAPI_BUDGET (16) /* arbitrary */
#define WIL6210_ITR_TRSH (10000) /* arbitrary - about 15 IRQs/msec */
+#define WIL6210_FW_RECOVERY_RETRIES (5) /* try to recover this many times */
+#define WIL6210_FW_RECOVERY_TO msecs_to_jiffies(5000)
+#define WIL6210_SCAN_TO msecs_to_jiffies(10000)
/* Hardware definitions begin */
@@ -361,6 +364,8 @@ struct wil6210_priv {
u32 fw_version;
u32 hw_version;
u8 n_mids; /* number of additional MIDs as reported by FW */
+ int recovery_count; /* num of FW recovery attempts in a short time */
+ unsigned long last_fw_recovery; /* jiffies of last fw recovery */
/* profile */
u32 monitor_flags;
u32 secure_pcp; /* create secure PCP? */
@@ -382,6 +387,7 @@ struct wil6210_priv {
struct work_struct disconnect_worker;
struct work_struct fw_error_worker; /* for FW error recovery */
struct timer_list connect_timer;
+ struct timer_list scan_timer; /* detect scan timeout */
int pending_connect_cid;
struct list_head pending_wmi_ev;
/*
@@ -508,7 +514,7 @@ void wil_wdev_free(struct wil6210_priv *wil);
int wmi_set_mac_address(struct wil6210_priv *wil, void *addr);
int wmi_pcp_start(struct wil6210_priv *wil, int bi, u8 wmi_nettype, u8 chan);
int wmi_pcp_stop(struct wil6210_priv *wil);
-void wil6210_disconnect(struct wil6210_priv *wil, void *bssid);
+void wil6210_disconnect(struct wil6210_priv *wil, const u8 *bssid);
int wil_rx_init(struct wil6210_priv *wil);
void wil_rx_fini(struct wil6210_priv *wil);
diff --git a/drivers/net/wireless/ath/wil6210/wmi.c b/drivers/net/wireless/ath/wil6210/wmi.c
index e9a11cb3428..6cc0e182cc7 100644
--- a/drivers/net/wireless/ath/wil6210/wmi.c
+++ b/drivers/net/wireless/ath/wil6210/wmi.c
@@ -351,6 +351,7 @@ static void wmi_evt_scan_complete(struct wil6210_priv *wil, int id,
bool aborted = (data->status != WMI_SCAN_SUCCESS);
wil_dbg_wmi(wil, "SCAN_COMPLETE(0x%08x)\n", data->status);
+ del_timer_sync(&wil->scan_timer);
cfg80211_scan_done(wil->scan_request, aborted);
wil->scan_request = NULL;
} else {
@@ -658,21 +659,27 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
u8 *cmd;
void __iomem *src;
ulong flags;
+ unsigned n;
if (!test_bit(wil_status_reset_done, &wil->status)) {
wil_err(wil, "Reset not completed\n");
return;
}
- for (;;) {
+ for (n = 0;; n++) {
u16 len;
r->head = ioread32(wil->csr + HOST_MBOX +
offsetof(struct wil6210_mbox_ctl, rx.head));
- if (r->tail == r->head)
+ if (r->tail == r->head) {
+ if (n == 0)
+ wil_dbg_wmi(wil, "No events?\n");
return;
+ }
- /* read cmd from tail */
+ wil_dbg_wmi(wil, "Mbox head %08x tail %08x\n",
+ r->head, r->tail);
+ /* read cmd descriptor from tail */
wil_memcpy_fromio_32(&d_tail, wil->csr + HOSTADDR(r->tail),
sizeof(struct wil6210_mbox_ring_desc));
if (d_tail.sync == 0) {
@@ -680,13 +687,18 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
return;
}
+ /* read cmd header from descriptor */
if (0 != wmi_read_hdr(wil, d_tail.addr, &hdr)) {
wil_err(wil, "Mbox evt at 0x%08x?\n",
le32_to_cpu(d_tail.addr));
return;
}
-
len = le16_to_cpu(hdr.len);
+ wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
+ le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
+ hdr.flags);
+
+ /* read cmd buffer from descriptor */
src = wmi_buffer(wil, d_tail.addr) +
sizeof(struct wil6210_mbox_hdr);
evt = kmalloc(ALIGN(offsetof(struct pending_wmi_event,
@@ -702,9 +714,6 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
iowrite32(0, wil->csr + HOSTADDR(r->tail) +
offsetof(struct wil6210_mbox_ring_desc, sync));
/* indicate */
- wil_dbg_wmi(wil, "Mbox evt %04x %04x %04x %02x\n",
- le16_to_cpu(hdr.seq), len, le16_to_cpu(hdr.type),
- hdr.flags);
if ((hdr.type == WIL_MBOX_HDR_TYPE_WMI) &&
(len >= sizeof(struct wil6210_mbox_hdr_wmi))) {
struct wil6210_mbox_hdr_wmi *wmi = &evt->event.wmi;
@@ -734,6 +743,8 @@ void wmi_recv_cmd(struct wil6210_priv *wil)
wil_dbg_wmi(wil, "queue_work -> %d\n", q);
}
}
+ if (n > 1)
+ wil_dbg_wmi(wil, "%s -> %d events processed\n", __func__, n);
}
int wmi_call(struct wil6210_priv *wil, u16 cmdid, void *buf, u16 len,
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 088d544ec63..40fd9b7b142 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -1,7 +1,8 @@
config B43
tristate "Broadcom 43xx wireless support (mac80211 stack)"
- depends on SSB_POSSIBLE && MAC80211 && HAS_DMA
- select SSB
+ depends on (BCMA_POSSIBLE || SSB_POSSIBLE) && MAC80211 && HAS_DMA
+ select BCMA if B43_BCMA
+ select SSB if B43_SSB
select FW_LOADER
---help---
b43 is a driver for the Broadcom 43xx series wireless devices.
@@ -27,14 +28,33 @@ config B43
If unsure, say M.
config B43_BCMA
- bool "Support for BCMA bus"
- depends on B43 && (BCMA = y || BCMA = B43)
- default y
+ bool
config B43_SSB
bool
- depends on B43 && (SSB = y || SSB = B43)
- default y
+
+choice
+ prompt "Supported bus types"
+ depends on B43
+ default B43_BUSES_BCMA_AND_SSB
+
+config B43_BUSES_BCMA_AND_SSB
+ bool "BCMA and SSB"
+ depends on BCMA_POSSIBLE && SSB_POSSIBLE
+ select B43_BCMA
+ select B43_SSB
+
+config B43_BUSES_BCMA
+ bool "BCMA only"
+ depends on BCMA_POSSIBLE
+ select B43_BCMA
+
+config B43_BUSES_SSB
+ bool "SSB only"
+ depends on SSB_POSSIBLE
+ select B43_SSB
+
+endchoice
# Auto-select SSB PCI-HOST support, if possible
config B43_PCI_AUTOSELECT
@@ -53,7 +73,7 @@ config B43_PCICORE_AUTOSELECT
config B43_PCMCIA
bool "Broadcom 43xx PCMCIA device support"
- depends on B43 && SSB_PCMCIAHOST_POSSIBLE
+ depends on B43 && B43_SSB && SSB_PCMCIAHOST_POSSIBLE
select SSB_PCMCIAHOST
---help---
Broadcom 43xx PCMCIA device support.
@@ -73,7 +93,7 @@ config B43_PCMCIA
config B43_SDIO
bool "Broadcom 43xx SDIO device support"
- depends on B43 && SSB_SDIOHOST_POSSIBLE
+ depends on B43 && B43_SSB && SSB_SDIOHOST_POSSIBLE
select SSB_SDIOHOST
---help---
Broadcom 43xx device support for Soft-MAC SDIO devices.
@@ -98,7 +118,7 @@ config B43_BCMA_PIO
config B43_PIO
bool
- depends on B43
+ depends on B43 && B43_SSB
select SSB_BLOCKIO
default y
@@ -116,7 +136,7 @@ config B43_PHY_N
config B43_PHY_LP
bool "Support for low-power (LP-PHY) devices"
- depends on B43
+ depends on B43 && B43_SSB
default y
---help---
Support for the LP-PHY.
diff --git a/drivers/net/wireless/b43/bus.h b/drivers/net/wireless/b43/bus.h
index 184c9565927..f3205c6988b 100644
--- a/drivers/net/wireless/b43/bus.h
+++ b/drivers/net/wireless/b43/bus.h
@@ -5,7 +5,9 @@ enum b43_bus_type {
#ifdef CONFIG_B43_BCMA
B43_BUS_BCMA,
#endif
+#ifdef CONFIG_B43_SSB
B43_BUS_SSB,
+#endif
};
struct b43_bus_dev {
@@ -52,13 +54,21 @@ struct b43_bus_dev {
static inline bool b43_bus_host_is_pcmcia(struct b43_bus_dev *dev)
{
+#ifdef CONFIG_B43_SSB
return (dev->bus_type == B43_BUS_SSB &&
dev->sdev->bus->bustype == SSB_BUSTYPE_PCMCIA);
+#else
+ return false;
+#endif
}
static inline bool b43_bus_host_is_sdio(struct b43_bus_dev *dev)
{
+#ifdef CONFIG_B43_SSB
return (dev->bus_type == B43_BUS_SSB &&
dev->sdev->bus->bustype == SSB_BUSTYPE_SDIO);
+#else
+ return false;
+#endif
}
struct b43_bus_dev *b43_bus_dev_bcma_init(struct bcma_device *core);
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 32e08d35c06..0d6a0bb1f87 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -182,7 +182,7 @@ static struct ieee80211_rate __b43_ratetable[] = {
#define b43_g_ratetable (__b43_ratetable + 0)
#define b43_g_ratetable_size 12
-#define CHAN4G(_channel, _freq, _flags) { \
+#define CHAN2G(_channel, _freq, _flags) { \
.band = IEEE80211_BAND_2GHZ, \
.center_freq = (_freq), \
.hw_value = (_channel), \
@@ -191,23 +191,31 @@ static struct ieee80211_rate __b43_ratetable[] = {
.max_power = 30, \
}
static struct ieee80211_channel b43_2ghz_chantable[] = {
- CHAN4G(1, 2412, 0),
- CHAN4G(2, 2417, 0),
- CHAN4G(3, 2422, 0),
- CHAN4G(4, 2427, 0),
- CHAN4G(5, 2432, 0),
- CHAN4G(6, 2437, 0),
- CHAN4G(7, 2442, 0),
- CHAN4G(8, 2447, 0),
- CHAN4G(9, 2452, 0),
- CHAN4G(10, 2457, 0),
- CHAN4G(11, 2462, 0),
- CHAN4G(12, 2467, 0),
- CHAN4G(13, 2472, 0),
- CHAN4G(14, 2484, 0),
+ CHAN2G(1, 2412, 0),
+ CHAN2G(2, 2417, 0),
+ CHAN2G(3, 2422, 0),
+ CHAN2G(4, 2427, 0),
+ CHAN2G(5, 2432, 0),
+ CHAN2G(6, 2437, 0),
+ CHAN2G(7, 2442, 0),
+ CHAN2G(8, 2447, 0),
+ CHAN2G(9, 2452, 0),
+ CHAN2G(10, 2457, 0),
+ CHAN2G(11, 2462, 0),
+ CHAN2G(12, 2467, 0),
+ CHAN2G(13, 2472, 0),
+ CHAN2G(14, 2484, 0),
};
-#undef CHAN4G
+#undef CHAN2G
+#define CHAN4G(_channel, _flags) { \
+ .band = IEEE80211_BAND_5GHZ, \
+ .center_freq = 4000 + (5 * (_channel)), \
+ .hw_value = (_channel), \
+ .flags = (_flags), \
+ .max_antenna_gain = 0, \
+ .max_power = 30, \
+}
#define CHAN5G(_channel, _flags) { \
.band = IEEE80211_BAND_5GHZ, \
.center_freq = 5000 + (5 * (_channel)), \
@@ -217,6 +225,18 @@ static struct ieee80211_channel b43_2ghz_chantable[] = {
.max_power = 30, \
}
static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
+ CHAN4G(184, 0), CHAN4G(186, 0),
+ CHAN4G(188, 0), CHAN4G(190, 0),
+ CHAN4G(192, 0), CHAN4G(194, 0),
+ CHAN4G(196, 0), CHAN4G(198, 0),
+ CHAN4G(200, 0), CHAN4G(202, 0),
+ CHAN4G(204, 0), CHAN4G(206, 0),
+ CHAN4G(208, 0), CHAN4G(210, 0),
+ CHAN4G(212, 0), CHAN4G(214, 0),
+ CHAN4G(216, 0), CHAN4G(218, 0),
+ CHAN4G(220, 0), CHAN4G(222, 0),
+ CHAN4G(224, 0), CHAN4G(226, 0),
+ CHAN4G(228, 0),
CHAN5G(32, 0), CHAN5G(34, 0),
CHAN5G(36, 0), CHAN5G(38, 0),
CHAN5G(40, 0), CHAN5G(42, 0),
@@ -260,18 +280,7 @@ static struct ieee80211_channel b43_5ghz_nphy_chantable[] = {
CHAN5G(170, 0), CHAN5G(172, 0),
CHAN5G(174, 0), CHAN5G(176, 0),
CHAN5G(178, 0), CHAN5G(180, 0),
- CHAN5G(182, 0), CHAN5G(184, 0),
- CHAN5G(186, 0), CHAN5G(188, 0),
- CHAN5G(190, 0), CHAN5G(192, 0),
- CHAN5G(194, 0), CHAN5G(196, 0),
- CHAN5G(198, 0), CHAN5G(200, 0),
- CHAN5G(202, 0), CHAN5G(204, 0),
- CHAN5G(206, 0), CHAN5G(208, 0),
- CHAN5G(210, 0), CHAN5G(212, 0),
- CHAN5G(214, 0), CHAN5G(216, 0),
- CHAN5G(218, 0), CHAN5G(220, 0),
- CHAN5G(222, 0), CHAN5G(224, 0),
- CHAN5G(226, 0), CHAN5G(228, 0),
+ CHAN5G(182, 0),
};
static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
@@ -295,6 +304,7 @@ static struct ieee80211_channel b43_5ghz_aphy_chantable[] = {
CHAN5G(208, 0), CHAN5G(212, 0),
CHAN5G(216, 0),
};
+#undef CHAN4G
#undef CHAN5G
static struct ieee80211_supported_band b43_band_5GHz_nphy = {
@@ -1175,18 +1185,7 @@ static void b43_bcma_phy_reset(struct b43_wldev *dev)
bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
udelay(2);
- /* Take PHY out of reset */
- flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
- flags &= ~B43_BCMA_IOCTL_PHY_RESET;
- flags |= BCMA_IOCTL_FGC;
- bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
- udelay(1);
-
- /* Do not force clock anymore */
- flags = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
- flags &= ~BCMA_IOCTL_FGC;
- bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, flags);
- udelay(1);
+ b43_phy_take_out_of_reset(dev);
}
static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
@@ -1208,10 +1207,9 @@ static void b43_bcma_wireless_core_reset(struct b43_wldev *dev, bool gmode)
}
#endif
+#ifdef CONFIG_B43_SSB
static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
- struct ssb_device *sdev = dev->dev->sdev;
- u32 tmslow;
u32 flags = 0;
if (gmode)
@@ -1223,18 +1221,9 @@ static void b43_ssb_wireless_core_reset(struct b43_wldev *dev, bool gmode)
b43_device_enable(dev, flags);
msleep(2); /* Wait for the PLL to turn on. */
- /* Now take the PHY out of Reset again */
- tmslow = ssb_read32(sdev, SSB_TMSLOW);
- tmslow |= SSB_TMSLOW_FGC;
- tmslow &= ~B43_TMSLOW_PHYRESET;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- ssb_read32(sdev, SSB_TMSLOW); /* flush */
- msleep(1);
- tmslow &= ~SSB_TMSLOW_FGC;
- ssb_write32(sdev, SSB_TMSLOW, tmslow);
- ssb_read32(sdev, SSB_TMSLOW); /* flush */
- msleep(1);
+ b43_phy_take_out_of_reset(dev);
}
+#endif
void b43_wireless_core_reset(struct b43_wldev *dev, bool gmode)
{
@@ -2709,32 +2698,37 @@ static int b43_upload_initvals(struct b43_wldev *dev)
struct b43_firmware *fw = &dev->fw;
const struct b43_iv *ivals;
size_t count;
- int err;
hdr = (const struct b43_fw_header *)(fw->initvals.data->data);
ivals = (const struct b43_iv *)(fw->initvals.data->data + hdr_len);
count = be32_to_cpu(hdr->size);
- err = b43_write_initvals(dev, ivals, count,
+ return b43_write_initvals(dev, ivals, count,
fw->initvals.data->size - hdr_len);
- if (err)
- goto out;
- if (fw->initvals_band.data) {
- hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data);
- ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len);
- count = be32_to_cpu(hdr->size);
- err = b43_write_initvals(dev, ivals, count,
- fw->initvals_band.data->size - hdr_len);
- if (err)
- goto out;
- }
-out:
+}
- return err;
+static int b43_upload_initvals_band(struct b43_wldev *dev)
+{
+ const size_t hdr_len = sizeof(struct b43_fw_header);
+ const struct b43_fw_header *hdr;
+ struct b43_firmware *fw = &dev->fw;
+ const struct b43_iv *ivals;
+ size_t count;
+
+ if (!fw->initvals_band.data)
+ return 0;
+
+ hdr = (const struct b43_fw_header *)(fw->initvals_band.data->data);
+ ivals = (const struct b43_iv *)(fw->initvals_band.data->data + hdr_len);
+ count = be32_to_cpu(hdr->size);
+ return b43_write_initvals(dev, ivals, count,
+ fw->initvals_band.data->size - hdr_len);
}
/* Initialize the GPIOs
* http://bcm-specs.sipsolutions.net/GPIO
*/
+
+#ifdef CONFIG_B43_SSB
static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
{
struct ssb_bus *bus = dev->dev->sdev->bus;
@@ -2745,10 +2739,13 @@ static struct ssb_device *b43_ssb_gpio_dev(struct b43_wldev *dev)
return bus->chipco.dev;
#endif
}
+#endif
static int b43_gpio_init(struct b43_wldev *dev)
{
+#ifdef CONFIG_B43_SSB
struct ssb_device *gpiodev;
+#endif
u32 mask, set;
b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
@@ -2807,7 +2804,9 @@ static int b43_gpio_init(struct b43_wldev *dev)
/* Turn off all GPIO stuff. Call this on module unload, for example. */
static void b43_gpio_cleanup(struct b43_wldev *dev)
{
+#ifdef CONFIG_B43_SSB
struct ssb_device *gpiodev;
+#endif
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
@@ -3091,6 +3090,10 @@ static int b43_chip_init(struct b43_wldev *dev)
if (err)
goto err_gpio_clean;
+ err = b43_upload_initvals_band(dev);
+ if (err)
+ goto err_gpio_clean;
+
/* Turn the Analog on and initialize the PHY. */
phy->ops->switch_analog(dev, 1);
err = b43_phy_init(dev);
@@ -3690,37 +3693,6 @@ static void b43_op_set_tsf(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
-static void b43_put_phy_into_reset(struct b43_wldev *dev)
-{
- u32 tmp;
-
- switch (dev->dev->bus_type) {
-#ifdef CONFIG_B43_BCMA
- case B43_BUS_BCMA:
- b43err(dev->wl,
- "Putting PHY into reset not supported on BCMA\n");
- break;
-#endif
-#ifdef CONFIG_B43_SSB
- case B43_BUS_SSB:
- tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
- tmp &= ~B43_TMSLOW_GMODE;
- tmp |= B43_TMSLOW_PHYRESET;
- tmp |= SSB_TMSLOW_FGC;
- ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
- msleep(1);
-
- tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
- tmp &= ~SSB_TMSLOW_FGC;
- tmp |= B43_TMSLOW_PHYRESET;
- ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
- msleep(1);
-
- break;
-#endif
- }
-}
-
static const char *band_to_string(enum ieee80211_band band)
{
switch (band) {
@@ -3736,89 +3708,75 @@ static const char *band_to_string(enum ieee80211_band band)
}
/* Expects wl->mutex locked */
-static int b43_switch_band(struct b43_wl *wl, struct ieee80211_channel *chan)
+static int b43_switch_band(struct b43_wldev *dev,
+ struct ieee80211_channel *chan)
{
- struct b43_wldev *up_dev = NULL;
- struct b43_wldev *down_dev;
- int err;
- bool uninitialized_var(gmode);
- int prev_status;
+ struct b43_phy *phy = &dev->phy;
+ bool gmode;
+ u32 tmp;
- /* Find a device and PHY which supports the band. */
switch (chan->band) {
case IEEE80211_BAND_5GHZ:
- if (wl->current_dev->phy.supports_5ghz) {
- up_dev = wl->current_dev;
- gmode = false;
- }
+ gmode = false;
break;
case IEEE80211_BAND_2GHZ:
- if (wl->current_dev->phy.supports_2ghz) {
- up_dev = wl->current_dev;
- gmode = true;
- }
+ gmode = true;
break;
default:
B43_WARN_ON(1);
return -EINVAL;
}
- if (!up_dev) {
- b43err(wl, "Could not find a device for %s-GHz band operation\n",
+ if (!((gmode && phy->supports_2ghz) ||
+ (!gmode && phy->supports_5ghz))) {
+ b43err(dev->wl, "This device doesn't support %s-GHz band\n",
band_to_string(chan->band));
return -ENODEV;
}
- if (!!wl->current_dev->phy.gmode == !!gmode) {
+
+ if (!!phy->gmode == !!gmode) {
/* This device is already running. */
return 0;
}
- b43dbg(wl, "Switching to %s-GHz band\n",
+
+ b43dbg(dev->wl, "Switching to %s GHz band\n",
band_to_string(chan->band));
- down_dev = wl->current_dev;
- prev_status = b43_status(down_dev);
- /* Shutdown the currently running core. */
- if (prev_status >= B43_STAT_STARTED)
- down_dev = b43_wireless_core_stop(down_dev);
- if (prev_status >= B43_STAT_INITIALIZED)
- b43_wireless_core_exit(down_dev);
+ /* Some new devices don't need disabling radio for band switching */
+ if (!(phy->type == B43_PHYTYPE_N && phy->rev >= 3))
+ b43_software_rfkill(dev, true);
- if (down_dev != up_dev) {
- /* We switch to a different core, so we put PHY into
- * RESET on the old core. */
- b43_put_phy_into_reset(down_dev);
+ phy->gmode = gmode;
+ b43_phy_put_into_reset(dev);
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ if (gmode)
+ tmp |= B43_BCMA_IOCTL_GMODE;
+ else
+ tmp &= ~B43_BCMA_IOCTL_GMODE;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ if (gmode)
+ tmp |= B43_TMSLOW_GMODE;
+ else
+ tmp &= ~B43_TMSLOW_GMODE;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ break;
+#endif
}
+ b43_phy_take_out_of_reset(dev);
- /* Now start the new core. */
- up_dev->phy.gmode = gmode;
- if (prev_status >= B43_STAT_INITIALIZED) {
- err = b43_wireless_core_init(up_dev);
- if (err) {
- b43err(wl, "Fatal: Could not initialize device for "
- "selected %s-GHz band\n",
- band_to_string(chan->band));
- goto init_failure;
- }
- }
- if (prev_status >= B43_STAT_STARTED) {
- err = b43_wireless_core_start(up_dev);
- if (err) {
- b43err(wl, "Fatal: Could not start device for "
- "selected %s-GHz band\n",
- band_to_string(chan->band));
- b43_wireless_core_exit(up_dev);
- goto init_failure;
- }
- }
- B43_WARN_ON(b43_status(up_dev) != prev_status);
+ b43_upload_initvals_band(dev);
- wl->current_dev = up_dev;
+ b43_phy_init(dev);
return 0;
-init_failure:
- /* Whoops, failed to init the new core. No core is operating now. */
- wl->current_dev = NULL;
- return err;
}
/* Write the short and long frame retry limit values. */
@@ -3851,8 +3809,10 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
dev = wl->current_dev;
+ b43_mac_suspend(dev);
+
/* Switch the band (if necessary). This might change the active core. */
- err = b43_switch_band(wl, conf->chandef.chan);
+ err = b43_switch_band(dev, conf->chandef.chan);
if (err)
goto out_unlock_mutex;
@@ -3871,8 +3831,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed)
else
phy->is_40mhz = false;
- b43_mac_suspend(dev);
-
if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS)
b43_set_retry_limits(dev, conf->short_frame_max_tx_count,
conf->long_frame_max_tx_count);
@@ -4582,8 +4540,12 @@ static void b43_imcfglo_timeouts_workaround(struct b43_wldev *dev)
struct ssb_bus *bus;
u32 tmp;
+#ifdef CONFIG_B43_SSB
if (dev->dev->bus_type != B43_BUS_SSB)
return;
+#else
+ return;
+#endif
bus = dev->dev->sdev->bus;
@@ -4738,7 +4700,7 @@ static int b43_wireless_core_init(struct b43_wldev *dev)
}
if (sprom->boardflags_lo & B43_BFL_XTAL_NOSLOW)
hf |= B43_HF_DSCRQ; /* Disable slowclock requests from ucode. */
-#ifdef CONFIG_SSB_DRIVER_PCICORE
+#if defined(CONFIG_B43_SSB) && defined(CONFIG_SSB_DRIVER_PCICORE)
if (dev->dev->bus_type == B43_BUS_SSB &&
dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI &&
dev->dev->sdev->bus->pcicore.dev->id.revision <= 10)
@@ -5129,10 +5091,82 @@ static void b43_wireless_core_detach(struct b43_wldev *dev)
b43_phy_free(dev);
}
+static void b43_supported_bands(struct b43_wldev *dev, bool *have_2ghz_phy,
+ bool *have_5ghz_phy)
+{
+ u16 dev_id = 0;
+
+#ifdef CONFIG_B43_BCMA
+ if (dev->dev->bus_type == B43_BUS_BCMA &&
+ dev->dev->bdev->bus->hosttype == BCMA_HOSTTYPE_PCI)
+ dev_id = dev->dev->bdev->bus->host_pci->device;
+#endif
+#ifdef CONFIG_B43_SSB
+ if (dev->dev->bus_type == B43_BUS_SSB &&
+ dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
+ dev_id = dev->dev->sdev->bus->host_pci->device;
+#endif
+ /* Override with SPROM value if available */
+ if (dev->dev->bus_sprom->dev_id)
+ dev_id = dev->dev->bus_sprom->dev_id;
+
+ /* Note: below IDs can be "virtual" (not maching e.g. real PCI ID) */
+ switch (dev_id) {
+ case 0x4324: /* BCM4306 */
+ case 0x4312: /* BCM4311 */
+ case 0x4319: /* BCM4318 */
+ case 0x4328: /* BCM4321 */
+ case 0x432b: /* BCM4322 */
+ case 0x4350: /* BCM43222 */
+ case 0x4353: /* BCM43224 */
+ case 0x0576: /* BCM43224 */
+ case 0x435f: /* BCM6362 */
+ case 0x4331: /* BCM4331 */
+ case 0x4359: /* BCM43228 */
+ case 0x43a0: /* BCM4360 */
+ case 0x43b1: /* BCM4352 */
+ /* Dual band devices */
+ *have_2ghz_phy = true;
+ *have_5ghz_phy = true;
+ return;
+ case 0x4321: /* BCM4306 */
+ case 0x4313: /* BCM4311 */
+ case 0x431a: /* BCM4318 */
+ case 0x432a: /* BCM4321 */
+ case 0x432d: /* BCM4322 */
+ case 0x4352: /* BCM43222 */
+ case 0x4333: /* BCM4331 */
+ case 0x43a2: /* BCM4360 */
+ case 0x43b3: /* BCM4352 */
+ /* 5 GHz only devices */
+ *have_2ghz_phy = false;
+ *have_5ghz_phy = true;
+ return;
+ }
+
+ /* As a fallback, try to guess using PHY type */
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_A:
+ *have_2ghz_phy = false;
+ *have_5ghz_phy = true;
+ return;
+ case B43_PHYTYPE_G:
+ case B43_PHYTYPE_N:
+ case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
+ case B43_PHYTYPE_LCN:
+ *have_2ghz_phy = true;
+ *have_5ghz_phy = false;
+ return;
+ }
+
+ B43_WARN_ON(1);
+}
+
static int b43_wireless_core_attach(struct b43_wldev *dev)
{
struct b43_wl *wl = dev->wl;
- struct pci_dev *pdev = NULL;
+ struct b43_phy *phy = &dev->phy;
int err;
u32 tmp;
bool have_2ghz_phy = false, have_5ghz_phy = false;
@@ -5144,19 +5178,15 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
* that in core_init(), too.
*/
-#ifdef CONFIG_B43_SSB
- if (dev->dev->bus_type == B43_BUS_SSB &&
- dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI)
- pdev = dev->dev->sdev->bus->host_pci;
-#endif
-
err = b43_bus_powerup(dev, 0);
if (err) {
b43err(wl, "Bus powerup failed\n");
goto out;
}
- /* Get the PHY type. */
+ phy->do_full_init = true;
+
+ /* Try to guess supported bands for the first init needs */
switch (dev->dev->bus_type) {
#ifdef CONFIG_B43_BCMA
case B43_BUS_BCMA:
@@ -5180,48 +5210,30 @@ static int b43_wireless_core_attach(struct b43_wldev *dev)
dev->phy.gmode = have_2ghz_phy;
b43_wireless_core_reset(dev, dev->phy.gmode);
+ /* Get the PHY type. */
err = b43_phy_versioning(dev);
if (err)
goto err_powerdown;
- /* Check if this device supports multiband. */
- if (!pdev ||
- (pdev->device != 0x4312 &&
- pdev->device != 0x4319 && pdev->device != 0x4324)) {
- /* No multiband support. */
- have_2ghz_phy = false;
+
+ /* Get real info about supported bands */
+ b43_supported_bands(dev, &have_2ghz_phy, &have_5ghz_phy);
+
+ /* We don't support 5 GHz on some PHYs yet */
+ switch (dev->phy.type) {
+ case B43_PHYTYPE_A:
+ case B43_PHYTYPE_G:
+ case B43_PHYTYPE_N:
+ case B43_PHYTYPE_LP:
+ case B43_PHYTYPE_HT:
+ b43warn(wl, "5 GHz band is unsupported on this PHY\n");
have_5ghz_phy = false;
- switch (dev->phy.type) {
- case B43_PHYTYPE_A:
- have_5ghz_phy = true;
- break;
- case B43_PHYTYPE_LP: //FIXME not always!
-#if 0 //FIXME enabling 5GHz causes a NULL pointer dereference
- have_5ghz_phy = 1;
-#endif
- case B43_PHYTYPE_G:
- case B43_PHYTYPE_N:
- case B43_PHYTYPE_HT:
- case B43_PHYTYPE_LCN:
- have_2ghz_phy = true;
- break;
- default:
- B43_WARN_ON(1);
- }
}
- if (dev->phy.type == B43_PHYTYPE_A) {
- /* FIXME */
- b43err(wl, "IEEE 802.11a devices are unsupported\n");
+
+ if (!have_2ghz_phy && !have_5ghz_phy) {
+ b43err(wl, "b43 can't support any band on this device\n");
err = -EOPNOTSUPP;
goto err_powerdown;
}
- if (1 /* disable A-PHY */) {
- /* FIXME: For now we disable the A-PHY on multi-PHY devices. */
- if (dev->phy.type != B43_PHYTYPE_N &&
- dev->phy.type != B43_PHYTYPE_LP) {
- have_2ghz_phy = true;
- have_5ghz_phy = false;
- }
- }
err = b43_phy_allocate(dev);
if (err)
@@ -5310,6 +5322,7 @@ static int b43_one_core_attach(struct b43_bus_dev *dev, struct b43_wl *wl)
(pdev->subsystem_vendor == PCI_VENDOR_ID_##_subvendor) && \
(pdev->subsystem_device == _subdevice) )
+#ifdef CONFIG_B43_SSB
static void b43_sprom_fixup(struct ssb_bus *bus)
{
struct pci_dev *pdev;
@@ -5341,6 +5354,7 @@ static void b43_wireless_exit(struct b43_bus_dev *dev, struct b43_wl *wl)
ssb_set_devtypedata(dev->sdev, NULL);
ieee80211_free_hw(hw);
}
+#endif
static struct b43_wl *b43_wireless_init(struct b43_bus_dev *dev)
{
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c
index 3e45989f418..08244b3b327 100644
--- a/drivers/net/wireless/b43/phy_common.c
+++ b/drivers/net/wireless/b43/phy_common.c
@@ -96,12 +96,16 @@ int b43_phy_init(struct b43_wldev *dev)
phy->channel = ops->get_default_chan(dev);
+ phy->ops->switch_analog(dev, true);
b43_software_rfkill(dev, false);
+
err = ops->init(dev);
if (err) {
b43err(dev->wl, "PHY init failed\n");
goto err_block_rf;
}
+ phy->do_full_init = false;
+
/* Make sure to switch hardware and firmware (SHM) to
* the default channel. */
err = b43_switch_channel(dev, ops->get_default_chan(dev));
@@ -113,6 +117,7 @@ int b43_phy_init(struct b43_wldev *dev)
return 0;
err_phy_exit:
+ phy->do_full_init = true;
if (ops->exit)
ops->exit(dev);
err_block_rf:
@@ -126,6 +131,7 @@ void b43_phy_exit(struct b43_wldev *dev)
const struct b43_phy_operations *ops = dev->phy.ops;
b43_software_rfkill(dev, true);
+ dev->phy.do_full_init = true;
if (ops->exit)
ops->exit(dev);
}
@@ -312,6 +318,90 @@ void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set)
}
}
+void b43_phy_put_into_reset(struct b43_wldev *dev)
+{
+ u32 tmp;
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ tmp &= ~B43_BCMA_IOCTL_GMODE;
+ tmp |= B43_BCMA_IOCTL_PHY_RESET;
+ tmp |= BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ udelay(1);
+
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ tmp &= ~BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ udelay(1);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~B43_TMSLOW_GMODE;
+ tmp |= B43_TMSLOW_PHYRESET;
+ tmp |= SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ usleep_range(1000, 2000);
+
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ usleep_range(1000, 2000);
+
+ break;
+#endif
+ }
+}
+
+void b43_phy_take_out_of_reset(struct b43_wldev *dev)
+{
+ u32 tmp;
+
+ switch (dev->dev->bus_type) {
+#ifdef CONFIG_B43_BCMA
+ case B43_BUS_BCMA:
+ /* Unset reset bit (with forcing clock) */
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ tmp &= ~B43_BCMA_IOCTL_PHY_RESET;
+ tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN;
+ tmp |= BCMA_IOCTL_FGC;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ udelay(1);
+
+ /* Do not force clock anymore */
+ tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL);
+ tmp &= ~BCMA_IOCTL_FGC;
+ tmp |= B43_BCMA_IOCTL_PHY_CLKEN;
+ bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp);
+ udelay(1);
+ break;
+#endif
+#ifdef CONFIG_B43_SSB
+ case B43_BUS_SSB:
+ /* Unset reset bit (with forcing clock) */
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~B43_TMSLOW_PHYRESET;
+ tmp &= ~B43_TMSLOW_PHYCLKEN;
+ tmp |= SSB_TMSLOW_FGC;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */
+ usleep_range(1000, 2000);
+
+ tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW);
+ tmp &= ~SSB_TMSLOW_FGC;
+ tmp |= B43_TMSLOW_PHYCLKEN;
+ ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp);
+ ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */
+ usleep_range(1000, 2000);
+ break;
+#endif
+ }
+}
+
int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel)
{
struct b43_phy *phy = &(dev->phy);
diff --git a/drivers/net/wireless/b43/phy_common.h b/drivers/net/wireless/b43/phy_common.h
index f1b99934987..4ad6240d9ff 100644
--- a/drivers/net/wireless/b43/phy_common.h
+++ b/drivers/net/wireless/b43/phy_common.h
@@ -231,9 +231,12 @@ struct b43_phy {
/* HT info */
bool is_40mhz;
- /* GMODE bit enabled? */
+ /* Is GMODE (2 GHz mode) bit enabled? */
bool gmode;
+ /* After power reset full init has to be performed */
+ bool do_full_init;
+
/* Analog Type */
u8 analog;
/* B43_PHYTYPE_ */
@@ -390,6 +393,9 @@ void b43_phy_lock(struct b43_wldev *dev);
*/
void b43_phy_unlock(struct b43_wldev *dev);
+void b43_phy_put_into_reset(struct b43_wldev *dev);
+void b43_phy_take_out_of_reset(struct b43_wldev *dev);
+
/**
* b43_switch_channel - Switch to another channel
*/
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 41dab89a294..86569f6a870 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -700,13 +700,11 @@ static void b43_radio_2057_init_post(struct b43_wldev *dev)
b43_radio_mask(dev, R2057_RFPLL_MISC_CAL_RESETN, ~0x78);
b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
- if (dev->phy.n->init_por) {
+ if (dev->phy.do_full_init) {
b43_radio_2057_rcal(dev);
b43_radio_2057_rccal(dev);
}
b43_radio_mask(dev, R2057_RFPLL_MASTER, ~0x8);
-
- dev->phy.n->init_por = false;
}
/* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
@@ -1028,7 +1026,7 @@ static void b43_radio_init2056_post(struct b43_wldev *dev)
b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
- if (dev->phy.n->init_por)
+ if (dev->phy.do_full_init)
b43_radio_2056_rcal(dev);
}
@@ -1041,8 +1039,6 @@ static void b43_radio_init2056(struct b43_wldev *dev)
b43_radio_init2056_pre(dev);
b2056_upload_inittabs(dev, 0, 0);
b43_radio_init2056_post(dev);
-
- dev->phy.n->init_por = false;
}
/**************************************************
@@ -5561,7 +5557,6 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
nphy->spur_avoid = (phy->rev >= 3) ?
B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
- nphy->init_por = true;
nphy->gain_boost = true; /* this way we follow wl, assume it is true */
nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
@@ -5602,8 +5597,6 @@ static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
}
-
- nphy->init_por = true;
}
static void b43_nphy_op_free(struct b43_wldev *dev)
@@ -5714,10 +5707,12 @@ static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
}
} else {
if (dev->phy.rev >= 7) {
- b43_radio_2057_init(dev);
+ if (!dev->phy.radio_on)
+ b43_radio_2057_init(dev);
b43_switch_channel(dev, dev->phy.channel);
} else if (dev->phy.rev >= 3) {
- b43_radio_init2056(dev);
+ if (!dev->phy.radio_on)
+ b43_radio_init2056(dev);
b43_switch_channel(dev, dev->phy.channel);
} else {
b43_radio_init2055(dev);
diff --git a/drivers/net/wireless/b43/phy_n.h b/drivers/net/wireless/b43/phy_n.h
index 9a5b6bc27d2..ecfbf66dbc3 100644
--- a/drivers/net/wireless/b43/phy_n.h
+++ b/drivers/net/wireless/b43/phy_n.h
@@ -931,7 +931,6 @@ struct b43_phy_n {
u16 papd_epsilon_offset[2];
s32 preamble_override;
u32 bb_mult_save;
- bool init_por;
bool gain_boost;
bool elna_gain_config;
diff --git a/drivers/net/wireless/b43/radio_2056.c b/drivers/net/wireless/b43/radio_2056.c
index a07e4cacab7..2ce25607c60 100644
--- a/drivers/net/wireless/b43/radio_2056.c
+++ b/drivers/net/wireless/b43/radio_2056.c
@@ -9058,6 +9058,231 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev11[] = {
{
+ .freq = 4920,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xec, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07b4, 0x07b0, 0x07ac, 0x0214, 0x0215, 0x0216),
+ },
+ {
+ .freq = 4930,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xed, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07b8, 0x07b4, 0x07b0, 0x0213, 0x0214, 0x0215),
+ },
+ {
+ .freq = 4940,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xee, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07bc, 0x07b8, 0x07b4, 0x0212, 0x0213, 0x0214),
+ },
+ {
+ .freq = 4950,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xef, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x00, 0x00, 0x00, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07c0, 0x07bc, 0x07b8, 0x0211, 0x0212, 0x0213),
+ },
+ {
+ .freq = 4960,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf0, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07c4, 0x07c0, 0x07bc, 0x020f, 0x0211, 0x0212),
+ },
+ {
+ .freq = 4970,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf1, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07c8, 0x07c4, 0x07c0, 0x020e, 0x020f, 0x0211),
+ },
+ {
+ .freq = 4980,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf2, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07cc, 0x07c8, 0x07c4, 0x020d, 0x020e, 0x020f),
+ },
+ {
+ .freq = 4990,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf3, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07d0, 0x07cc, 0x07c8, 0x020c, 0x020d, 0x020e),
+ },
+ {
+ .freq = 5000,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf4, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07d4, 0x07d0, 0x07cc, 0x020b, 0x020c, 0x020d),
+ },
+ {
+ .freq = 5010,
+ RADIOREGS3(0xff, 0x01, 0x01, 0x01, 0xf5, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07d8, 0x07d4, 0x07d0, 0x020a, 0x020b, 0x020c),
+ },
+ {
+ .freq = 5020,
+ RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf6, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07dc, 0x07d8, 0x07d4, 0x0209, 0x020a, 0x020b),
+ },
+ {
+ .freq = 5030,
+ RADIOREGS3(0xf7, 0x01, 0x01, 0x01, 0xf7, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07e0, 0x07dc, 0x07d8, 0x0208, 0x0209, 0x020a),
+ },
+ {
+ .freq = 5040,
+ RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf8, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07e4, 0x07e0, 0x07dc, 0x0207, 0x0208, 0x0209),
+ },
+ {
+ .freq = 5050,
+ RADIOREGS3(0xef, 0x01, 0x01, 0x01, 0xf9, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07e8, 0x07e4, 0x07e0, 0x0206, 0x0207, 0x0208),
+ },
+ {
+ .freq = 5060,
+ RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfa, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfe, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfe, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07ec, 0x07e8, 0x07e4, 0x0205, 0x0206, 0x0207),
+ },
+ {
+ .freq = 5070,
+ RADIOREGS3(0xe6, 0x01, 0x01, 0x01, 0xfb, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07f0, 0x07ec, 0x07e8, 0x0204, 0x0205, 0x0206),
+ },
+ {
+ .freq = 5080,
+ RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfc, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07f4, 0x07f0, 0x07ec, 0x0203, 0x0204, 0x0205),
+ },
+ {
+ .freq = 5090,
+ RADIOREGS3(0xde, 0x01, 0x01, 0x01, 0xfd, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x01, 0x01, 0x01, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfd, 0x00, 0x09, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x09, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07f8, 0x07f4, 0x07f0, 0x0202, 0x0203, 0x0204),
+ },
+ {
+ .freq = 5100,
+ RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xfe, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfd, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfd, 0x00, 0x08, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x07fc, 0x07f8, 0x07f4, 0x0201, 0x0202, 0x0203),
+ },
+ {
+ .freq = 5110,
+ RADIOREGS3(0xd6, 0x01, 0x01, 0x01, 0xff, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0800, 0x07fc, 0x07f8, 0x0200, 0x0201, 0x0202),
+ },
+ {
+ .freq = 5120,
+ RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x00, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0804, 0x0800, 0x07fc, 0x01ff, 0x0200, 0x0201),
+ },
+ {
+ .freq = 5130,
+ RADIOREGS3(0xce, 0x01, 0x01, 0x02, 0x01, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfc, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfc, 0x00, 0x08, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0808, 0x0804, 0x0800, 0x01fe, 0x01ff, 0x0200),
+ },
+ {
+ .freq = 5140,
+ RADIOREGS3(0xc6, 0x01, 0x01, 0x02, 0x02, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfb, 0x00, 0x08, 0x00, 0x77, 0x00, 0x0f,
+ 0x00, 0x6f, 0x00, 0xfb, 0x00, 0x08, 0x00, 0x77,
+ 0x00, 0x0f, 0x00, 0x6f, 0x00),
+ PHYREGS(0x080c, 0x0808, 0x0804, 0x01fd, 0x01fe, 0x01ff),
+ },
+ {
+ .freq = 5160,
+ RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x04, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+ 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+ 0x00, 0x0e, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0814, 0x0810, 0x080c, 0x01fb, 0x01fc, 0x01fd),
+ },
+ {
+ .freq = 5170,
+ RADIOREGS3(0xbe, 0x01, 0x01, 0x02, 0x05, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xfa, 0x00, 0x07, 0x00, 0x77, 0x00, 0x0e,
+ 0x00, 0x6f, 0x00, 0xfa, 0x00, 0x07, 0x00, 0x77,
+ 0x00, 0x0e, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0818, 0x0814, 0x0810, 0x01fa, 0x01fb, 0x01fc),
+ },
+ {
.freq = 5180,
RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x06, 0x05, 0x05, 0x02,
0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
@@ -9067,6 +9292,15 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x081c, 0x0818, 0x0814, 0x01f9, 0x01fa, 0x01fb),
},
{
+ .freq = 5190,
+ RADIOREGS3(0xb6, 0x01, 0x01, 0x02, 0x07, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xf9, 0x00, 0x06, 0x00, 0x77, 0x00, 0x0d,
+ 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x06, 0x00, 0x77,
+ 0x00, 0x0d, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0820, 0x081c, 0x0818, 0x01f8, 0x01f9, 0x01fa),
+ },
+ {
.freq = 5200,
RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x08, 0x05, 0x05, 0x02,
0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
@@ -9076,6 +9310,15 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x0824, 0x0820, 0x081c, 0x01f7, 0x01f8, 0x01f9),
},
{
+ .freq = 5210,
+ RADIOREGS3(0xaf, 0x01, 0x01, 0x02, 0x09, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8f, 0x0f, 0x00,
+ 0xff, 0xf9, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+ 0x00, 0x6f, 0x00, 0xf9, 0x00, 0x05, 0x00, 0x77,
+ 0x00, 0x0d, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0828, 0x0824, 0x0820, 0x01f6, 0x01f7, 0x01f8),
+ },
+ {
.freq = 5220,
RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0a, 0x05, 0x05, 0x02,
0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
@@ -9085,6 +9328,492 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x082c, 0x0828, 0x0824, 0x01f5, 0x01f6, 0x01f7),
},
{
+ .freq = 5230,
+ RADIOREGS3(0xa7, 0x01, 0x01, 0x02, 0x0b, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+ 0xee, 0xd8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+ 0x00, 0x6f, 0x00, 0xd8, 0x00, 0x05, 0x00, 0x77,
+ 0x00, 0x0d, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0830, 0x082c, 0x0828, 0x01f4, 0x01f5, 0x01f6),
+ },
+ {
+ .freq = 5240,
+ RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0c, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+ 0xee, 0xc8, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+ 0x00, 0x6f, 0x00, 0xc8, 0x00, 0x05, 0x00, 0x77,
+ 0x00, 0x0d, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0834, 0x0830, 0x082c, 0x01f3, 0x01f4, 0x01f5),
+ },
+ {
+ .freq = 5250,
+ RADIOREGS3(0xa0, 0x01, 0x01, 0x02, 0x0d, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0f, 0x00,
+ 0xed, 0xc7, 0x00, 0x05, 0x00, 0x77, 0x00, 0x0d,
+ 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x05, 0x00, 0x77,
+ 0x00, 0x0d, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0838, 0x0834, 0x0830, 0x01f2, 0x01f3, 0x01f4),
+ },
+ {
+ .freq = 5260,
+ RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0e, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x02, 0x02, 0x02, 0x8e, 0x0e, 0x00,
+ 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0d,
+ 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+ 0x00, 0x0d, 0x00, 0x6f, 0x00),
+ PHYREGS(0x083c, 0x0838, 0x0834, 0x01f1, 0x01f2, 0x01f3),
+ },
+ {
+ .freq = 5270,
+ RADIOREGS3(0x98, 0x01, 0x01, 0x02, 0x0f, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8e, 0x0e, 0x00,
+ 0xed, 0xc7, 0x00, 0x04, 0x00, 0x77, 0x00, 0x0c,
+ 0x00, 0x6f, 0x00, 0xc7, 0x00, 0x04, 0x00, 0x77,
+ 0x00, 0x0c, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0840, 0x083c, 0x0838, 0x01f0, 0x01f1, 0x01f2),
+ },
+ {
+ .freq = 5280,
+ RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x10, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+ 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+ 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0c, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0844, 0x0840, 0x083c, 0x01f0, 0x01f0, 0x01f1),
+ },
+ {
+ .freq = 5290,
+ RADIOREGS3(0x91, 0x01, 0x01, 0x02, 0x11, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+ 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+ 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0c, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0848, 0x0844, 0x0840, 0x01ef, 0x01f0, 0x01f0),
+ },
+ {
+ .freq = 5300,
+ RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x12, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+ 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+ 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0c, 0x00, 0x6f, 0x00),
+ PHYREGS(0x084c, 0x0848, 0x0844, 0x01ee, 0x01ef, 0x01f0),
+ },
+ {
+ .freq = 5310,
+ RADIOREGS3(0x8a, 0x01, 0x01, 0x02, 0x13, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+ 0xdc, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+ 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0c, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0850, 0x084c, 0x0848, 0x01ed, 0x01ee, 0x01ef),
+ },
+ {
+ .freq = 5320,
+ RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x14, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0e, 0x00,
+ 0xdb, 0xb7, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0c,
+ 0x00, 0x6f, 0x00, 0xb7, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0c, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0854, 0x0850, 0x084c, 0x01ec, 0x01ed, 0x01ee),
+ },
+ {
+ .freq = 5330,
+ RADIOREGS3(0x83, 0x01, 0x01, 0x02, 0x15, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+ 0xcb, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+ 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0b, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0858, 0x0854, 0x0850, 0x01eb, 0x01ec, 0x01ed),
+ },
+ {
+ .freq = 5340,
+ RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x16, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8d, 0x0d, 0x00,
+ 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+ 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0b, 0x00, 0x6f, 0x00),
+ PHYREGS(0x085c, 0x0858, 0x0854, 0x01ea, 0x01eb, 0x01ec),
+ },
+ {
+ .freq = 5350,
+ RADIOREGS3(0x7c, 0x01, 0x01, 0x02, 0x17, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+ 0xca, 0xa6, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0b,
+ 0x00, 0x6f, 0x00, 0xa6, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0b, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0860, 0x085c, 0x0858, 0x01e9, 0x01ea, 0x01eb),
+ },
+ {
+ .freq = 5360,
+ RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x18, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+ 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0864, 0x0860, 0x085c, 0x01e8, 0x01e9, 0x01ea),
+ },
+ {
+ .freq = 5370,
+ RADIOREGS3(0x75, 0x01, 0x01, 0x02, 0x19, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0d, 0x00,
+ 0xc9, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0868, 0x0864, 0x0860, 0x01e7, 0x01e8, 0x01e9),
+ },
+ {
+ .freq = 5380,
+ RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1a, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+ 0xb8, 0x95, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x95, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x086c, 0x0868, 0x0864, 0x01e6, 0x01e7, 0x01e8),
+ },
+ {
+ .freq = 5390,
+ RADIOREGS3(0x6e, 0x01, 0x01, 0x02, 0x1b, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+ 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0870, 0x086c, 0x0868, 0x01e5, 0x01e6, 0x01e7),
+ },
+ {
+ .freq = 5400,
+ RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1c, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+ 0xb8, 0x84, 0x00, 0x03, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x03, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0874, 0x0870, 0x086c, 0x01e5, 0x01e5, 0x01e6),
+ },
+ {
+ .freq = 5410,
+ RADIOREGS3(0x67, 0x01, 0x01, 0x02, 0x1d, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+ 0xb7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0878, 0x0874, 0x0870, 0x01e4, 0x01e5, 0x01e5),
+ },
+ {
+ .freq = 5420,
+ RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1e, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0c, 0x00,
+ 0xa7, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x087c, 0x0878, 0x0874, 0x01e3, 0x01e4, 0x01e5),
+ },
+ {
+ .freq = 5430,
+ RADIOREGS3(0x61, 0x01, 0x01, 0x02, 0x1f, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x03, 0x03, 0x03, 0x8c, 0x0b, 0x00,
+ 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x0a,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+ 0x00, 0x0a, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0880, 0x087c, 0x0878, 0x01e2, 0x01e3, 0x01e4),
+ },
+ {
+ .freq = 5440,
+ RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x20, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+ 0xa6, 0x84, 0x00, 0x02, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x02, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0884, 0x0880, 0x087c, 0x01e1, 0x01e2, 0x01e3),
+ },
+ {
+ .freq = 5450,
+ RADIOREGS3(0x5a, 0x01, 0x01, 0x02, 0x21, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+ 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0888, 0x0884, 0x0880, 0x01e0, 0x01e1, 0x01e2),
+ },
+ {
+ .freq = 5460,
+ RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x22, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+ 0x95, 0x84, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x84, 0x00, 0x01, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x088c, 0x0888, 0x0884, 0x01df, 0x01e0, 0x01e1),
+ },
+ {
+ .freq = 5470,
+ RADIOREGS3(0x53, 0x01, 0x01, 0x02, 0x23, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8b, 0x0b, 0x00,
+ 0x94, 0x73, 0x00, 0x01, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x01, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0890, 0x088c, 0x0888, 0x01de, 0x01df, 0x01e0),
+ },
+ {
+ .freq = 5480,
+ RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x24, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+ 0x84, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0894, 0x0890, 0x088c, 0x01dd, 0x01de, 0x01df),
+ },
+ {
+ .freq = 5490,
+ RADIOREGS3(0x4d, 0x01, 0x01, 0x02, 0x25, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+ 0x83, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x0898, 0x0894, 0x0890, 0x01dd, 0x01dd, 0x01de),
+ },
+ {
+ .freq = 5500,
+ RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x26, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+ 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x089c, 0x0898, 0x0894, 0x01dc, 0x01dd, 0x01dd),
+ },
+ {
+ .freq = 5510,
+ RADIOREGS3(0x47, 0x01, 0x01, 0x02, 0x27, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+ 0x82, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08a0, 0x089c, 0x0898, 0x01db, 0x01dc, 0x01dd),
+ },
+ {
+ .freq = 5520,
+ RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x28, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x0a, 0x00,
+ 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08a4, 0x08a0, 0x089c, 0x01da, 0x01db, 0x01dc),
+ },
+ {
+ .freq = 5530,
+ RADIOREGS3(0x40, 0x01, 0x01, 0x02, 0x29, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+ 0x72, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08a8, 0x08a4, 0x08a0, 0x01d9, 0x01da, 0x01db),
+ },
+ {
+ .freq = 5540,
+ RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2a, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x8a, 0x09, 0x00,
+ 0x71, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08ac, 0x08a8, 0x08a4, 0x01d8, 0x01d9, 0x01da),
+ },
+ {
+ .freq = 5550,
+ RADIOREGS3(0x3a, 0x01, 0x01, 0x02, 0x2b, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+ 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08b0, 0x08ac, 0x08a8, 0x01d7, 0x01d8, 0x01d9),
+ },
+ {
+ .freq = 5560,
+ RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2c, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+ 0x61, 0x73, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x73, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08b4, 0x08b0, 0x08ac, 0x01d7, 0x01d7, 0x01d8),
+ },
+ {
+ .freq = 5570,
+ RADIOREGS3(0x34, 0x01, 0x01, 0x02, 0x2d, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x09, 0x00,
+ 0x61, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x09,
+ 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x09, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08b8, 0x08b4, 0x08b0, 0x01d6, 0x01d7, 0x01d7),
+ },
+ {
+ .freq = 5580,
+ RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2e, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+ 0x60, 0x62, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+ 0x00, 0x6f, 0x00, 0x62, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x08, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08bc, 0x08b8, 0x08b4, 0x01d5, 0x01d6, 0x01d7),
+ },
+ {
+ .freq = 5590,
+ RADIOREGS3(0x2e, 0x01, 0x01, 0x02, 0x2f, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x04, 0x04, 0x04, 0x89, 0x08, 0x00,
+ 0x50, 0x61, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+ 0x00, 0x6f, 0x00, 0x61, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x08, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08c0, 0x08bc, 0x08b8, 0x01d4, 0x01d5, 0x01d6),
+ },
+ {
+ .freq = 5600,
+ RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x30, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+ 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+ 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x08, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08c4, 0x08c0, 0x08bc, 0x01d3, 0x01d4, 0x01d5),
+ },
+ {
+ .freq = 5610,
+ RADIOREGS3(0x28, 0x01, 0x01, 0x02, 0x31, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+ 0x50, 0x51, 0x00, 0x00, 0x00, 0x77, 0x00, 0x08,
+ 0x00, 0x6f, 0x00, 0x51, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x08, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08c8, 0x08c4, 0x08c0, 0x01d2, 0x01d3, 0x01d4),
+ },
+ {
+ .freq = 5620,
+ RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x32, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x89, 0x08, 0x00,
+ 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+ 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x07, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08cc, 0x08c8, 0x08c4, 0x01d2, 0x01d2, 0x01d3),
+ },
+ {
+ .freq = 5630,
+ RADIOREGS3(0x21, 0x01, 0x01, 0x02, 0x33, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+ 0x50, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+ 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x07, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08d0, 0x08cc, 0x08c8, 0x01d1, 0x01d2, 0x01d2),
+ },
+ {
+ .freq = 5640,
+ RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x34, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+ 0x40, 0x50, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+ 0x00, 0x6f, 0x00, 0x50, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x07, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08d4, 0x08d0, 0x08cc, 0x01d0, 0x01d1, 0x01d2),
+ },
+ {
+ .freq = 5650,
+ RADIOREGS3(0x1c, 0x01, 0x01, 0x02, 0x35, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+ 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x07,
+ 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x07, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08d8, 0x08d4, 0x08d0, 0x01cf, 0x01d0, 0x01d1),
+ },
+ {
+ .freq = 5660,
+ RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x36, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+ 0x40, 0x40, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6f, 0x00, 0x40, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08dc, 0x08d8, 0x08d4, 0x01ce, 0x01cf, 0x01d0),
+ },
+ {
+ .freq = 5670,
+ RADIOREGS3(0x16, 0x01, 0x01, 0x02, 0x37, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x88, 0x07, 0x00,
+ 0x40, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08e0, 0x08dc, 0x08d8, 0x01ce, 0x01ce, 0x01cf),
+ },
+ {
+ .freq = 5680,
+ RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x38, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08e4, 0x08e0, 0x08dc, 0x01cd, 0x01ce, 0x01ce),
+ },
+ {
+ .freq = 5690,
+ RADIOREGS3(0x10, 0x01, 0x01, 0x02, 0x39, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6f, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6f, 0x00),
+ PHYREGS(0x08e8, 0x08e4, 0x08e0, 0x01cc, 0x01cd, 0x01ce),
+ },
+ {
+ .freq = 5700,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3a, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6e, 0x00),
+ PHYREGS(0x08ec, 0x08e8, 0x08e4, 0x01cb, 0x01cc, 0x01cd),
+ },
+ {
+ .freq = 5710,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3b, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6e, 0x00),
+ PHYREGS(0x08f0, 0x08ec, 0x08e8, 0x01ca, 0x01cb, 0x01cc),
+ },
+ {
+ .freq = 5720,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3c, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6e, 0x00),
+ PHYREGS(0x08f4, 0x08f0, 0x08ec, 0x01c9, 0x01ca, 0x01cb),
+ },
+ {
+ .freq = 5725,
+ RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x79, 0x05, 0x05, 0x02,
+ 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x06, 0x00,
+ 0x30, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6e, 0x00),
+ PHYREGS(0x08f6, 0x08f2, 0x08ee, 0x01c9, 0x01ca, 0x01cb),
+ },
+ {
+ .freq = 5730,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3d, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+ 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6e, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6e, 0x00),
+ PHYREGS(0x08f8, 0x08f4, 0x08f0, 0x01c9, 0x01c9, 0x01ca),
+ },
+ {
+ .freq = 5735,
+ RADIOREGS3(0x03, 0x01, 0x02, 0x04, 0x7b, 0x05, 0x05, 0x02,
+ 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+ 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6d, 0x00),
+ PHYREGS(0x08fa, 0x08f6, 0x08f2, 0x01c8, 0x01c9, 0x01ca),
+ },
+ {
+ .freq = 5740,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3e, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+ 0x20, 0x30, 0x00, 0x00, 0x00, 0x77, 0x00, 0x06,
+ 0x00, 0x6d, 0x00, 0x30, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x06, 0x00, 0x6d, 0x00),
+ PHYREGS(0x08fc, 0x08f8, 0x08f4, 0x01c8, 0x01c9, 0x01c9),
+ },
+ {
.freq = 5745,
RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7d, 0x05, 0x05, 0x02,
0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
@@ -9094,6 +9823,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x08fe, 0x08fa, 0x08f6, 0x01c8, 0x01c8, 0x01c9),
},
{
+ .freq = 5750,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x3f, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+ 0x20, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6d, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6d, 0x00),
+ PHYREGS(0x0900, 0x08fc, 0x08f8, 0x01c7, 0x01c8, 0x01c9),
+ },
+ {
+ .freq = 5755,
+ RADIOREGS3(0xfe, 0x00, 0x02, 0x04, 0x7f, 0x05, 0x05, 0x02,
+ 0x15, 0x01, 0x05, 0x05, 0x05, 0x87, 0x05, 0x00,
+ 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6c, 0x00),
+ PHYREGS(0x0902, 0x08fe, 0x08fa, 0x01c7, 0x01c8, 0x01c8),
+ },
+ {
+ .freq = 5760,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x40, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
+ 0x10, 0x20, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6c, 0x00, 0x20, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6c, 0x00),
+ PHYREGS(0x0904, 0x0900, 0x08fc, 0x01c6, 0x01c7, 0x01c8),
+ },
+ {
.freq = 5765,
RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x81, 0x05, 0x05, 0x02,
0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x05, 0x00,
@@ -9103,6 +9859,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x0906, 0x0902, 0x08fe, 0x01c6, 0x01c7, 0x01c8),
},
{
+ .freq = 5770,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x41, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+ 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6b, 0x00),
+ PHYREGS(0x0908, 0x0904, 0x0900, 0x01c6, 0x01c6, 0x01c7),
+ },
+ {
+ .freq = 5775,
+ RADIOREGS3(0xf8, 0x00, 0x02, 0x04, 0x83, 0x05, 0x05, 0x02,
+ 0x15, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+ 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6b, 0x00),
+ PHYREGS(0x090a, 0x0906, 0x0902, 0x01c5, 0x01c6, 0x01c7),
+ },
+ {
+ .freq = 5780,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x42, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x05, 0x05, 0x05, 0x86, 0x04, 0x00,
+ 0x10, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6b, 0x00),
+ PHYREGS(0x090c, 0x0908, 0x0904, 0x01c5, 0x01c6, 0x01c6),
+ },
+ {
.freq = 5785,
RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x85, 0x05, 0x05, 0x02,
0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
@@ -9112,6 +9895,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x090e, 0x090a, 0x0906, 0x01c4, 0x01c5, 0x01c6),
},
{
+ .freq = 5790,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x43, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x10, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6b, 0x00, 0x10, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6b, 0x00),
+ PHYREGS(0x0910, 0x090c, 0x0908, 0x01c4, 0x01c5, 0x01c6),
+ },
+ {
+ .freq = 5795,
+ RADIOREGS3(0xf2, 0x00, 0x02, 0x04, 0x87, 0x05, 0x05, 0x02,
+ 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6b, 0x00),
+ PHYREGS(0x0912, 0x090e, 0x090a, 0x01c4, 0x01c4, 0x01c5),
+ },
+ {
+ .freq = 5800,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x44, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6b, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6b, 0x00),
+ PHYREGS(0x0914, 0x0910, 0x090c, 0x01c3, 0x01c4, 0x01c5),
+ },
+ {
.freq = 5805,
RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x89, 0x05, 0x05, 0x02,
0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
@@ -9121,6 +9931,33 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x0916, 0x0912, 0x090e, 0x01c3, 0x01c4, 0x01c4),
},
{
+ .freq = 5810,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x45, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6a, 0x00),
+ PHYREGS(0x0918, 0x0914, 0x0910, 0x01c2, 0x01c3, 0x01c4),
+ },
+ {
+ .freq = 5815,
+ RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8b, 0x05, 0x05, 0x02,
+ 0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6a, 0x00),
+ PHYREGS(0x091a, 0x0916, 0x0912, 0x01c2, 0x01c3, 0x01c4),
+ },
+ {
+ .freq = 5820,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x46, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x6a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x6a, 0x00),
+ PHYREGS(0x091c, 0x0918, 0x0914, 0x01c2, 0x01c2, 0x01c3),
+ },
+ {
.freq = 5825,
RADIOREGS3(0xed, 0x00, 0x02, 0x04, 0x8d, 0x05, 0x05, 0x02,
0x15, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
@@ -9130,6 +9967,87 @@ static const struct b43_nphy_channeltab_entry_rev3 b43_nphy_channeltab_radio_rev
PHYREGS(0x091e, 0x091a, 0x0916, 0x01c1, 0x01c2, 0x01c3),
},
{
+ .freq = 5830,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x47, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x05,
+ 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x05, 0x00, 0x69, 0x00),
+ PHYREGS(0x0920, 0x091c, 0x0918, 0x01c1, 0x01c2, 0x01c2),
+ },
+ {
+ .freq = 5840,
+ RADIOREGS3(0x0a, 0x01, 0x01, 0x02, 0x48, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x86, 0x04, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x69, 0x00),
+ PHYREGS(0x0924, 0x0920, 0x091c, 0x01c0, 0x01c1, 0x01c2),
+ },
+ {
+ .freq = 5850,
+ RADIOREGS3(0xe0, 0x00, 0x01, 0x02, 0x49, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x69, 0x00),
+ PHYREGS(0x0928, 0x0924, 0x0920, 0x01bf, 0x01c0, 0x01c1),
+ },
+ {
+ .freq = 5860,
+ RADIOREGS3(0xde, 0x00, 0x01, 0x02, 0x4a, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x69, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x69, 0x00),
+ PHYREGS(0x092c, 0x0928, 0x0924, 0x01bf, 0x01bf, 0x01c0),
+ },
+ {
+ .freq = 5870,
+ RADIOREGS3(0xdb, 0x00, 0x01, 0x02, 0x4b, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x68, 0x00),
+ PHYREGS(0x0930, 0x092c, 0x0928, 0x01be, 0x01bf, 0x01bf),
+ },
+ {
+ .freq = 5880,
+ RADIOREGS3(0xd8, 0x00, 0x01, 0x02, 0x4c, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x68, 0x00),
+ PHYREGS(0x0934, 0x0930, 0x092c, 0x01bd, 0x01be, 0x01bf),
+ },
+ {
+ .freq = 5890,
+ RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4d, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x68, 0x00),
+ PHYREGS(0x0938, 0x0934, 0x0930, 0x01bc, 0x01bd, 0x01be),
+ },
+ {
+ .freq = 5900,
+ RADIOREGS3(0xd3, 0x00, 0x01, 0x02, 0x4e, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x68, 0x00),
+ PHYREGS(0x093c, 0x0938, 0x0934, 0x01bc, 0x01bc, 0x01bd),
+ },
+ {
+ .freq = 5910,
+ RADIOREGS3(0xd6, 0x00, 0x01, 0x02, 0x4f, 0x05, 0x05, 0x02,
+ 0x0c, 0x01, 0x06, 0x06, 0x06, 0x85, 0x03, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x77, 0x00, 0x04,
+ 0x00, 0x68, 0x00, 0x00, 0x00, 0x00, 0x00, 0x77,
+ 0x00, 0x04, 0x00, 0x68, 0x00),
+ PHYREGS(0x0940, 0x093c, 0x0938, 0x01bb, 0x01bc, 0x01bc),
+ },
+ {
.freq = 2412,
RADIOREGS3(0x00, 0x01, 0x03, 0x09, 0x6c, 0x06, 0x06, 0x04,
0x2b, 0x01, 0x04, 0x04, 0x04, 0x8f, 0x30, 0x00,
diff --git a/drivers/net/wireless/b43/tables_nphy.c b/drivers/net/wireless/b43/tables_nphy.c
index 50d03ffeac8..4047c05e380 100644
--- a/drivers/net/wireless/b43/tables_nphy.c
+++ b/drivers/net/wireless/b43/tables_nphy.c
@@ -3042,30 +3042,32 @@ static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
antswlut = sprom->fem.ghz2.antswlut;
/* Static tables */
- ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
- ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
- ntab_upload(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
- ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
- ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
- ntab_upload(dev, B43_NTAB_NOISEVAR_R3, b43_ntab_noisevar_r3);
- ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
- ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
- ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
- ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
- ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
- ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
- ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
- ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
- ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
- ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
- ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
- ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
- ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
- ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
- ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
- ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
- ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
- ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+ if (dev->phy.do_full_init) {
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT_R3, b43_ntab_framestruct_r3);
+ ntab_upload(dev, B43_NTAB_PILOT_R3, b43_ntab_pilot_r3);
+ ntab_upload(dev, B43_NTAB_TMAP_R3, b43_ntab_tmap_r3);
+ ntab_upload(dev, B43_NTAB_INTLEVEL_R3, b43_ntab_intlevel_r3);
+ ntab_upload(dev, B43_NTAB_TDTRN_R3, b43_ntab_tdtrn_r3);
+ ntab_upload(dev, B43_NTAB_NOISEVAR_R3, b43_ntab_noisevar_r3);
+ ntab_upload(dev, B43_NTAB_MCS_R3, b43_ntab_mcs_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A0_R3, b43_ntab_tdi20a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI20A1_R3, b43_ntab_tdi20a1_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A0_R3, b43_ntab_tdi40a0_r3);
+ ntab_upload(dev, B43_NTAB_TDI40A1_R3, b43_ntab_tdi40a1_r3);
+ ntab_upload(dev, B43_NTAB_PILOTLT_R3, b43_ntab_pilotlt_r3);
+ ntab_upload(dev, B43_NTAB_CHANEST_R3, b43_ntab_channelest_r3);
+ ntab_upload(dev, B43_NTAB_FRAMELT_R3, b43_ntab_framelookup_r3);
+ ntab_upload(dev, B43_NTAB_C0_ESTPLT_R3, b43_ntab_estimatepowerlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ESTPLT_R3, b43_ntab_estimatepowerlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_ADJPLT_R3, b43_ntab_adjustpower0_r3);
+ ntab_upload(dev, B43_NTAB_C1_ADJPLT_R3, b43_ntab_adjustpower1_r3);
+ ntab_upload(dev, B43_NTAB_C0_GAINCTL_R3, b43_ntab_gainctl0_r3);
+ ntab_upload(dev, B43_NTAB_C1_GAINCTL_R3, b43_ntab_gainctl1_r3);
+ ntab_upload(dev, B43_NTAB_C0_IQLT_R3, b43_ntab_iqlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_IQLT_R3, b43_ntab_iqlt1_r3);
+ ntab_upload(dev, B43_NTAB_C0_LOFEEDTH_R3, b43_ntab_loftlt0_r3);
+ ntab_upload(dev, B43_NTAB_C1_LOFEEDTH_R3, b43_ntab_loftlt1_r3);
+ }
/* Volatile tables */
if (antswlut < ARRAY_SIZE(b43_ntab_antswctl_r3))
@@ -3078,20 +3080,22 @@ static void b43_nphy_tables_init_rev3(struct b43_wldev *dev)
static void b43_nphy_tables_init_rev0(struct b43_wldev *dev)
{
/* Static tables */
- ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
- ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
- ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
- ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
- ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
- ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
- ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
- ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
- ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
- ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
- ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
- ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
- ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
- ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
+ if (dev->phy.do_full_init) {
+ ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct);
+ ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup);
+ ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap);
+ ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
+ ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
+ ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
+ ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
+ ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
+ ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
+ ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
+ ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
+ ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
+ ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
+ ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
+ }
/* Volatile tables */
ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
diff --git a/drivers/net/wireless/b43/xmit.c b/drivers/net/wireless/b43/xmit.c
index 31adb8cf029..6e6ef3fc224 100644
--- a/drivers/net/wireless/b43/xmit.c
+++ b/drivers/net/wireless/b43/xmit.c
@@ -408,7 +408,7 @@ int b43_generate_txhdr(struct b43_wldev *dev,
mac_ctl |= B43_TXH_MAC_HWSEQ;
if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
mac_ctl |= B43_TXH_MAC_STMSDU;
- if (phy->type == B43_PHYTYPE_A)
+ if (!phy->gmode)
mac_ctl |= B43_TXH_MAC_5GHZ;
/* Overwrite rates[0].count to make the retry calculation
@@ -811,9 +811,13 @@ void b43_rx(struct b43_wldev *dev, struct sk_buff *skb, const void *_rxhdr)
break;
case B43_PHYTYPE_G:
status.band = IEEE80211_BAND_2GHZ;
- /* chanid is the radio channel cookie value as used
- * to tune the radio. */
- status.freq = chanid + 2400;
+ /* Somewhere between 478.104 and 508.1084 firmware for G-PHY
+ * has been modified to be compatible with N-PHY and others.
+ */
+ if (dev->fw.rev >= 508)
+ status.freq = ieee80211_channel_to_frequency(chanid, status.band);
+ else
+ status.freq = chanid + 2400;
break;
case B43_PHYTYPE_N:
case B43_PHYTYPE_LP:
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
index 1d2ceac3a22..98e67c18f27 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile
@@ -33,7 +33,7 @@ brcmfmac-objs += \
bcdc.o \
dhd_common.o \
dhd_linux.o \
- nvram.o \
+ firmware.o \
btcoex.o
brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \
dhd_sdio.o \
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/chip.c b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
index df130ef53d1..c7c9f15c0fe 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/chip.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/chip.c
@@ -303,10 +303,10 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
ci = core->chip;
- /* if core is already in reset, just return */
+ /* if core is already in reset, skip reset */
regdata = ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL);
if ((regdata & BCMA_RESET_CTL_RESET) != 0)
- return;
+ goto in_reset_configure;
/* configure reset */
ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
@@ -322,6 +322,7 @@ static void brcmf_chip_ai_coredisable(struct brcmf_core_priv *core,
SPINWAIT(ci->ops->read32(ci->ctx, core->wrapbase + BCMA_RESET_CTL) !=
BCMA_RESET_CTL_RESET, 300);
+in_reset_configure:
/* in-reset configure */
ci->ops->write32(ci->ctx, core->wrapbase + BCMA_IOCTL,
reset | BCMA_IOCTL_FGC | BCMA_IOCTL_CLK);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
index 939d6b13292..16f9ab2568a 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd.h
@@ -186,7 +186,7 @@ void brcmf_del_if(struct brcmf_pub *drvr, s32 bssidx);
void brcmf_txflowblock_if(struct brcmf_if *ifp,
enum brcmf_netif_stop_reason reason, bool state);
u32 brcmf_get_chip_info(struct brcmf_if *ifp);
-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
+void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success);
/* Sets dongle media info (drv_version, mac address). */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
index c4535616064..7735328fff2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_bus.h
@@ -63,7 +63,6 @@ struct brcmf_bus_dcmd {
*/
struct brcmf_bus_ops {
int (*preinit)(struct device *dev);
- int (*init)(struct device *dev);
void (*stop)(struct device *dev);
int (*txdata)(struct device *dev, struct sk_buff *skb);
int (*txctl)(struct device *dev, unsigned char *msg, uint len);
@@ -99,6 +98,7 @@ struct brcmf_bus {
unsigned long tx_realloc;
u32 chip;
u32 chiprev;
+ bool always_use_fws_queue;
struct brcmf_bus_ops *ops;
};
@@ -113,11 +113,6 @@ static inline int brcmf_bus_preinit(struct brcmf_bus *bus)
return bus->ops->preinit(bus->dev);
}
-static inline int brcmf_bus_init(struct brcmf_bus *bus)
-{
- return bus->ops->init(bus->dev);
-}
-
static inline void brcmf_bus_stop(struct brcmf_bus *bus)
{
bus->ops->stop(bus->dev);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
index 6a8983a1fb9..ed3e32ce8c2 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_common.c
@@ -32,6 +32,9 @@
#define BRCMF_DEFAULT_SCAN_UNASSOC_TIME 40
#define BRCMF_DEFAULT_PACKET_FILTER "100 0 0 0 0x01 0x00"
+/* boost value for RSSI_DELTA in preferred join selection */
+#define BRCMF_JOIN_PREF_RSSI_BOOST 8
+
bool brcmf_c_prec_enq(struct device *dev, struct pktq *q,
struct sk_buff *pkt, int prec)
@@ -246,6 +249,7 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
{
s8 eventmask[BRCMF_EVENTING_MASK_LEN];
u8 buf[BRCMF_DCMD_SMLEN];
+ struct brcmf_join_pref_params join_pref_params[2];
char *ptr;
s32 err;
@@ -298,6 +302,20 @@ int brcmf_c_preinit_dcmds(struct brcmf_if *ifp)
goto done;
}
+ /* Setup join_pref to select target by RSSI(with boost on 5GHz) */
+ join_pref_params[0].type = BRCMF_JOIN_PREF_RSSI_DELTA;
+ join_pref_params[0].len = 2;
+ join_pref_params[0].rssi_gain = BRCMF_JOIN_PREF_RSSI_BOOST;
+ join_pref_params[0].band = WLC_BAND_5G;
+ join_pref_params[1].type = BRCMF_JOIN_PREF_RSSI;
+ join_pref_params[1].len = 2;
+ join_pref_params[1].rssi_gain = 0;
+ join_pref_params[1].band = 0;
+ err = brcmf_fil_iovar_data_set(ifp, "join_pref", join_pref_params,
+ sizeof(join_pref_params));
+ if (err)
+ brcmf_err("Set join_pref error (%d)\n", err);
+
/* Setup event_msgs, enable E_IF */
err = brcmf_fil_iovar_data_get(ifp, "event_msgs", eventmask,
BRCMF_EVENTING_MASK_LEN);
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
index 7d28cd38509..09dd8c13d84 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_linux.c
@@ -190,7 +190,7 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
int ret;
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_pub *drvr = ifp->drvr;
- struct ethhdr *eh;
+ struct ethhdr *eh = (struct ethhdr *)(skb->data);
brcmf_dbg(DATA, "Enter, idx=%d\n", ifp->bssidx);
@@ -236,6 +236,9 @@ static netdev_tx_t brcmf_netdev_start_xmit(struct sk_buff *skb,
goto done;
}
+ if (eh->h_proto == htons(ETH_P_PAE))
+ atomic_inc(&ifp->pend_8021x_cnt);
+
ret = brcmf_fws_process_skb(ifp, skb);
done:
@@ -538,31 +541,26 @@ void brcmf_rx_frame(struct device *dev, struct sk_buff *skb)
brcmf_netif_rx(ifp, skb);
}
-void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp,
+void brcmf_txfinalize(struct brcmf_pub *drvr, struct sk_buff *txp, u8 ifidx,
bool success)
{
struct brcmf_if *ifp;
struct ethhdr *eh;
- u8 ifidx;
u16 type;
- int res;
-
- res = brcmf_proto_hdrpull(drvr, false, &ifidx, txp);
ifp = drvr->iflist[ifidx];
if (!ifp)
goto done;
- if (res == 0) {
- eh = (struct ethhdr *)(txp->data);
- type = ntohs(eh->h_proto);
+ eh = (struct ethhdr *)(txp->data);
+ type = ntohs(eh->h_proto);
- if (type == ETH_P_PAE) {
- atomic_dec(&ifp->pend_8021x_cnt);
- if (waitqueue_active(&ifp->pend_8021x_wait))
- wake_up(&ifp->pend_8021x_wait);
- }
+ if (type == ETH_P_PAE) {
+ atomic_dec(&ifp->pend_8021x_cnt);
+ if (waitqueue_active(&ifp->pend_8021x_wait))
+ wake_up(&ifp->pend_8021x_wait);
}
+
if (!success)
ifp->stats.tx_errors++;
done:
@@ -573,13 +571,17 @@ void brcmf_txcomplete(struct device *dev, struct sk_buff *txp, bool success)
{
struct brcmf_bus *bus_if = dev_get_drvdata(dev);
struct brcmf_pub *drvr = bus_if->drvr;
+ u8 ifidx;
/* await txstatus signal for firmware if active */
if (brcmf_fws_fc_active(drvr->fws)) {
if (!success)
brcmf_fws_bustxfail(drvr->fws, txp);
} else {
- brcmf_txfinalize(drvr, txp, success);
+ if (brcmf_proto_hdrpull(drvr, false, &ifidx, txp))
+ brcmu_pkt_buf_free_skb(txp);
+ else
+ brcmf_txfinalize(drvr, txp, ifidx, success);
}
}
@@ -914,13 +916,6 @@ int brcmf_bus_start(struct device *dev)
brcmf_dbg(TRACE, "\n");
- /* Bring up the bus */
- ret = brcmf_bus_init(bus_if);
- if (ret != 0) {
- brcmf_err("brcmf_sdbrcm_bus_init failed %d\n", ret);
- return ret;
- }
-
/* add primary networking interface */
ifp = brcmf_add_if(drvr, 0, 0, "wlan%d", NULL);
if (IS_ERR(ifp))
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
index 13c89a0c4ba..8fa0dbbbda7 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/dhd_sdio.c
@@ -42,7 +42,7 @@
#include <soc.h>
#include "sdio_host.h"
#include "chip.h"
-#include "nvram.h"
+#include "firmware.h"
#define DCMD_RESP_TIMEOUT 2000 /* In milli second */
@@ -632,43 +632,28 @@ static const struct brcmf_firmware_names brcmf_fwname_data[] = {
{ BCM4354_CHIP_ID, 0xFFFFFFFF, BRCMF_FIRMWARE_NVRAM(BCM4354) }
};
-
-static const struct firmware *brcmf_sdio_get_fw(struct brcmf_sdio *bus,
- enum brcmf_firmware_type type)
+static const char *brcmf_sdio_get_fwname(struct brcmf_chip *ci,
+ enum brcmf_firmware_type type)
{
- const struct firmware *fw;
- const char *name;
- int err, i;
+ int i;
for (i = 0; i < ARRAY_SIZE(brcmf_fwname_data); i++) {
- if (brcmf_fwname_data[i].chipid == bus->ci->chip &&
- brcmf_fwname_data[i].revmsk & BIT(bus->ci->chiprev)) {
+ if (brcmf_fwname_data[i].chipid == ci->chip &&
+ brcmf_fwname_data[i].revmsk & BIT(ci->chiprev)) {
switch (type) {
case BRCMF_FIRMWARE_BIN:
- name = brcmf_fwname_data[i].bin;
- break;
+ return brcmf_fwname_data[i].bin;
case BRCMF_FIRMWARE_NVRAM:
- name = brcmf_fwname_data[i].nv;
- break;
+ return brcmf_fwname_data[i].nv;
default:
brcmf_err("invalid firmware type (%d)\n", type);
return NULL;
}
- goto found;
}
}
brcmf_err("Unknown chipid %d [%d]\n",
- bus->ci->chip, bus->ci->chiprev);
+ ci->chip, ci->chiprev);
return NULL;
-
-found:
- err = request_firmware(&fw, name, &bus->sdiodev->func[2]->dev);
- if ((err) || (!fw)) {
- brcmf_err("fail to request firmware %s (%d)\n", name, err);
- return NULL;
- }
-
- return fw;
}
static void pkt_align(struct sk_buff *p, int len, int align)
@@ -3278,20 +3263,13 @@ static int brcmf_sdio_download_code_file(struct brcmf_sdio *bus,
}
static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
- const struct firmware *nv)
+ void *vars, u32 varsz)
{
- void *vars;
- u32 varsz;
int address;
int err;
brcmf_dbg(TRACE, "Enter\n");
- vars = brcmf_nvram_strip(nv, &varsz);
-
- if (vars == NULL)
- return -EINVAL;
-
address = bus->ci->ramsize - varsz + bus->ci->rambase;
err = brcmf_sdiod_ramrw(bus->sdiodev, true, address, vars, varsz);
if (err)
@@ -3300,15 +3278,14 @@ static int brcmf_sdio_download_nvram(struct brcmf_sdio *bus,
else if (!brcmf_sdio_verifymemory(bus->sdiodev, address, vars, varsz))
err = -EIO;
- brcmf_nvram_free(vars);
-
return err;
}
-static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
+static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus,
+ const struct firmware *fw,
+ void *nvram, u32 nvlen)
{
int bcmerror = -EFAULT;
- const struct firmware *fw;
u32 rstvec;
sdio_claim_host(bus->sdiodev->func[1]);
@@ -3317,12 +3294,6 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
/* Keep arm in reset */
brcmf_chip_enter_download(bus->ci);
- fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_BIN);
- if (fw == NULL) {
- bcmerror = -ENOENT;
- goto err;
- }
-
rstvec = get_unaligned_le32(fw->data);
brcmf_dbg(SDIO, "firmware rstvec: %x\n", rstvec);
@@ -3330,17 +3301,12 @@ static int brcmf_sdio_download_firmware(struct brcmf_sdio *bus)
release_firmware(fw);
if (bcmerror) {
brcmf_err("dongle image file download failed\n");
+ brcmf_fw_nvram_free(nvram);
goto err;
}
- fw = brcmf_sdio_get_fw(bus, BRCMF_FIRMWARE_NVRAM);
- if (fw == NULL) {
- bcmerror = -ENOENT;
- goto err;
- }
-
- bcmerror = brcmf_sdio_download_nvram(bus, fw);
- release_firmware(fw);
+ bcmerror = brcmf_sdio_download_nvram(bus, nvram, nvlen);
+ brcmf_fw_nvram_free(nvram);
if (bcmerror) {
brcmf_err("dongle nvram file download failed\n");
goto err;
@@ -3490,97 +3456,6 @@ done:
return err;
}
-static int brcmf_sdio_bus_init(struct device *dev)
-{
- struct brcmf_bus *bus_if = dev_get_drvdata(dev);
- struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
- struct brcmf_sdio *bus = sdiodev->bus;
- int err, ret = 0;
- u8 saveclk;
-
- brcmf_dbg(TRACE, "Enter\n");
-
- /* try to download image and nvram to the dongle */
- if (bus_if->state == BRCMF_BUS_DOWN) {
- bus->alp_only = true;
- err = brcmf_sdio_download_firmware(bus);
- if (err)
- return err;
- bus->alp_only = false;
- }
-
- if (!bus->sdiodev->bus_if->drvr)
- return 0;
-
- /* Start the watchdog timer */
- bus->sdcnt.tickcnt = 0;
- brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
-
- sdio_claim_host(bus->sdiodev->func[1]);
-
- /* Make sure backplane clock is on, needed to generate F2 interrupt */
- brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
- if (bus->clkstate != CLK_AVAIL)
- goto exit;
-
- /* Force clocks on backplane to be sure F2 interrupt propagates */
- saveclk = brcmf_sdiod_regrb(bus->sdiodev,
- SBSDIO_FUNC1_CHIPCLKCSR, &err);
- if (!err) {
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- (saveclk | SBSDIO_FORCE_HT), &err);
- }
- if (err) {
- brcmf_err("Failed to force clock for F2: err %d\n", err);
- goto exit;
- }
-
- /* Enable function 2 (frame transfers) */
- w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
- offsetof(struct sdpcmd_regs, tosbmailboxdata));
- err = sdio_enable_func(bus->sdiodev->func[SDIO_FUNC_2]);
-
-
- brcmf_dbg(INFO, "enable F2: err=%d\n", err);
-
- /* If F2 successfully enabled, set core and enable interrupts */
- if (!err) {
- /* Set up the interrupt mask and enable interrupts */
- bus->hostintmask = HOSTINTMASK;
- w_sdreg32(bus, bus->hostintmask,
- offsetof(struct sdpcmd_regs, hostintmask));
-
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_WATERMARK, 8, &err);
- } else {
- /* Disable F2 again */
- sdio_disable_func(bus->sdiodev->func[SDIO_FUNC_2]);
- ret = -ENODEV;
- }
-
- if (brcmf_chip_sr_capable(bus->ci)) {
- brcmf_sdio_sr_init(bus);
- } else {
- /* Restore previous clock setting */
- brcmf_sdiod_regwb(bus->sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
- saveclk, &err);
- }
-
- if (ret == 0) {
- ret = brcmf_sdiod_intr_register(bus->sdiodev);
- if (ret != 0)
- brcmf_err("intr register failed:%d\n", ret);
- }
-
- /* If we didn't come up, turn off backplane clock */
- if (ret != 0)
- brcmf_sdio_clkctl(bus, CLK_NONE, false);
-
-exit:
- sdio_release_host(bus->sdiodev->func[1]);
-
- return ret;
-}
-
void brcmf_sdio_isr(struct brcmf_sdio *bus)
{
brcmf_dbg(TRACE, "Enter\n");
@@ -4020,13 +3895,114 @@ brcmf_sdio_watchdog(unsigned long data)
static struct brcmf_bus_ops brcmf_sdio_bus_ops = {
.stop = brcmf_sdio_bus_stop,
.preinit = brcmf_sdio_bus_preinit,
- .init = brcmf_sdio_bus_init,
.txdata = brcmf_sdio_bus_txdata,
.txctl = brcmf_sdio_bus_txctl,
.rxctl = brcmf_sdio_bus_rxctl,
.gettxq = brcmf_sdio_bus_gettxq,
};
+static void brcmf_sdio_firmware_callback(struct device *dev,
+ const struct firmware *code,
+ void *nvram, u32 nvram_len)
+{
+ struct brcmf_bus *bus_if = dev_get_drvdata(dev);
+ struct brcmf_sdio_dev *sdiodev = bus_if->bus_priv.sdio;
+ struct brcmf_sdio *bus = sdiodev->bus;
+ int err = 0;
+ u8 saveclk;
+
+ brcmf_dbg(TRACE, "Enter: dev=%s\n", dev_name(dev));
+
+ /* try to download image and nvram to the dongle */
+ if (bus_if->state == BRCMF_BUS_DOWN) {
+ bus->alp_only = true;
+ err = brcmf_sdio_download_firmware(bus, code, nvram, nvram_len);
+ if (err)
+ goto fail;
+ bus->alp_only = false;
+ }
+
+ if (!bus_if->drvr)
+ return;
+
+ /* Start the watchdog timer */
+ bus->sdcnt.tickcnt = 0;
+ brcmf_sdio_wd_timer(bus, BRCMF_WD_POLL_MS);
+
+ sdio_claim_host(sdiodev->func[1]);
+
+ /* Make sure backplane clock is on, needed to generate F2 interrupt */
+ brcmf_sdio_clkctl(bus, CLK_AVAIL, false);
+ if (bus->clkstate != CLK_AVAIL)
+ goto release;
+
+ /* Force clocks on backplane to be sure F2 interrupt propagates */
+ saveclk = brcmf_sdiod_regrb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR, &err);
+ if (!err) {
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ (saveclk | SBSDIO_FORCE_HT), &err);
+ }
+ if (err) {
+ brcmf_err("Failed to force clock for F2: err %d\n", err);
+ goto release;
+ }
+
+ /* Enable function 2 (frame transfers) */
+ w_sdreg32(bus, SDPCM_PROT_VERSION << SMB_DATA_VERSION_SHIFT,
+ offsetof(struct sdpcmd_regs, tosbmailboxdata));
+ err = sdio_enable_func(sdiodev->func[SDIO_FUNC_2]);
+
+
+ brcmf_dbg(INFO, "enable F2: err=%d\n", err);
+
+ /* If F2 successfully enabled, set core and enable interrupts */
+ if (!err) {
+ /* Set up the interrupt mask and enable interrupts */
+ bus->hostintmask = HOSTINTMASK;
+ w_sdreg32(bus, bus->hostintmask,
+ offsetof(struct sdpcmd_regs, hostintmask));
+
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_WATERMARK, 8, &err);
+ } else {
+ /* Disable F2 again */
+ sdio_disable_func(sdiodev->func[SDIO_FUNC_2]);
+ goto release;
+ }
+
+ if (brcmf_chip_sr_capable(bus->ci)) {
+ brcmf_sdio_sr_init(bus);
+ } else {
+ /* Restore previous clock setting */
+ brcmf_sdiod_regwb(sdiodev, SBSDIO_FUNC1_CHIPCLKCSR,
+ saveclk, &err);
+ }
+
+ if (err == 0) {
+ err = brcmf_sdiod_intr_register(sdiodev);
+ if (err != 0)
+ brcmf_err("intr register failed:%d\n", err);
+ }
+
+ /* If we didn't come up, turn off backplane clock */
+ if (err != 0)
+ brcmf_sdio_clkctl(bus, CLK_NONE, false);
+
+ sdio_release_host(sdiodev->func[1]);
+
+ err = brcmf_bus_start(dev);
+ if (err != 0) {
+ brcmf_err("dongle is not responding\n");
+ goto fail;
+ }
+ return;
+
+release:
+ sdio_release_host(sdiodev->func[1]);
+fail:
+ brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), err);
+ device_release_driver(dev);
+}
+
struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
{
int ret;
@@ -4110,8 +4086,13 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
goto fail;
}
+ /* Query the F2 block size, set roundup accordingly */
+ bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
+ bus->roundup = min(max_roundup, bus->blocksize);
+
/* Allocate buffers */
if (bus->sdiodev->bus_if->maxctl) {
+ bus->sdiodev->bus_if->maxctl += bus->roundup;
bus->rxblen =
roundup((bus->sdiodev->bus_if->maxctl + SDPCM_HDRLEN),
ALIGNMENT) + bus->head_align;
@@ -4139,10 +4120,6 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
bus->idletime = BRCMF_IDLE_INTERVAL;
bus->idleclock = BRCMF_IDLE_ACTIVE;
- /* Query the F2 block size, set roundup accordingly */
- bus->blocksize = bus->sdiodev->func[2]->cur_blksize;
- bus->roundup = min(max_roundup, bus->blocksize);
-
/* SR state */
bus->sleeping = false;
bus->sr_enabled = false;
@@ -4150,10 +4127,14 @@ struct brcmf_sdio *brcmf_sdio_probe(struct brcmf_sdio_dev *sdiodev)
brcmf_sdio_debugfs_create(bus);
brcmf_dbg(INFO, "completed!!\n");
- /* if firmware path present try to download and bring up bus */
- ret = brcmf_bus_start(bus->sdiodev->dev);
+ ret = brcmf_fw_get_firmwares(sdiodev->dev, BRCMF_FW_REQUEST_NVRAM,
+ brcmf_sdio_get_fwname(bus->ci,
+ BRCMF_FIRMWARE_BIN),
+ brcmf_sdio_get_fwname(bus->ci,
+ BRCMF_FIRMWARE_NVRAM),
+ brcmf_sdio_firmware_callback);
if (ret != 0) {
- brcmf_err("dongle is not responding\n");
+ brcmf_err("async firmware request failed: %d\n", ret);
goto fail;
}
@@ -4173,9 +4154,7 @@ void brcmf_sdio_remove(struct brcmf_sdio *bus)
/* De-register interrupt handler */
brcmf_sdiod_intr_unregister(bus->sdiodev);
- if (bus->sdiodev->bus_if->drvr) {
- brcmf_detach(bus->sdiodev->dev);
- }
+ brcmf_detach(bus->sdiodev->dev);
cancel_work_sync(&bus->datawork);
if (bus->brcmf_wq)
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/firmware.c b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
new file mode 100644
index 00000000000..7b7d237c1dd
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.c
@@ -0,0 +1,332 @@
+/*
+ * Copyright (c) 2013 Broadcom Corporation
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
+ * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
+ * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/device.h>
+#include <linux/firmware.h>
+
+#include "dhd_dbg.h"
+#include "firmware.h"
+
+enum nvram_parser_state {
+ IDLE,
+ KEY,
+ VALUE,
+ COMMENT,
+ END
+};
+
+/**
+ * struct nvram_parser - internal info for parser.
+ *
+ * @state: current parser state.
+ * @fwnv: input buffer being parsed.
+ * @nvram: output buffer with parse result.
+ * @nvram_len: lenght of parse result.
+ * @line: current line.
+ * @column: current column in line.
+ * @pos: byte offset in input buffer.
+ * @entry: start position of key,value entry.
+ */
+struct nvram_parser {
+ enum nvram_parser_state state;
+ const struct firmware *fwnv;
+ u8 *nvram;
+ u32 nvram_len;
+ u32 line;
+ u32 column;
+ u32 pos;
+ u32 entry;
+};
+
+static bool is_nvram_char(char c)
+{
+ /* comment marker excluded */
+ if (c == '#')
+ return false;
+
+ /* key and value may have any other readable character */
+ return (c > 0x20 && c < 0x7f);
+}
+
+static bool is_whitespace(char c)
+{
+ return (c == ' ' || c == '\r' || c == '\n' || c == '\t');
+}
+
+static enum nvram_parser_state brcmf_nvram_handle_idle(struct nvram_parser *nvp)
+{
+ char c;
+
+ c = nvp->fwnv->data[nvp->pos];
+ if (c == '\n')
+ return COMMENT;
+ if (is_whitespace(c))
+ goto proceed;
+ if (c == '#')
+ return COMMENT;
+ if (is_nvram_char(c)) {
+ nvp->entry = nvp->pos;
+ return KEY;
+ }
+ brcmf_dbg(INFO, "warning: ln=%d:col=%d: ignoring invalid character\n",
+ nvp->line, nvp->column);
+proceed:
+ nvp->column++;
+ nvp->pos++;
+ return IDLE;
+}
+
+static enum nvram_parser_state brcmf_nvram_handle_key(struct nvram_parser *nvp)
+{
+ enum nvram_parser_state st = nvp->state;
+ char c;
+
+ c = nvp->fwnv->data[nvp->pos];
+ if (c == '=') {
+ st = VALUE;
+ } else if (!is_nvram_char(c)) {
+ brcmf_dbg(INFO, "warning: ln=%d:col=%d: '=' expected, skip invalid key entry\n",
+ nvp->line, nvp->column);
+ return COMMENT;
+ }
+
+ nvp->column++;
+ nvp->pos++;
+ return st;
+}
+
+static enum nvram_parser_state
+brcmf_nvram_handle_value(struct nvram_parser *nvp)
+{
+ char c;
+ char *skv;
+ char *ekv;
+ u32 cplen;
+
+ c = nvp->fwnv->data[nvp->pos];
+ if (!is_nvram_char(c)) {
+ /* key,value pair complete */
+ ekv = (u8 *)&nvp->fwnv->data[nvp->pos];
+ skv = (u8 *)&nvp->fwnv->data[nvp->entry];
+ cplen = ekv - skv;
+ /* copy to output buffer */
+ memcpy(&nvp->nvram[nvp->nvram_len], skv, cplen);
+ nvp->nvram_len += cplen;
+ nvp->nvram[nvp->nvram_len] = '\0';
+ nvp->nvram_len++;
+ return IDLE;
+ }
+ nvp->pos++;
+ nvp->column++;
+ return VALUE;
+}
+
+static enum nvram_parser_state
+brcmf_nvram_handle_comment(struct nvram_parser *nvp)
+{
+ char *eol, *sol;
+
+ sol = (char *)&nvp->fwnv->data[nvp->pos];
+ eol = strchr(sol, '\n');
+ if (eol == NULL)
+ return END;
+
+ /* eat all moving to next line */
+ nvp->line++;
+ nvp->column = 1;
+ nvp->pos += (eol - sol) + 1;
+ return IDLE;
+}
+
+static enum nvram_parser_state brcmf_nvram_handle_end(struct nvram_parser *nvp)
+{
+ /* final state */
+ return END;
+}
+
+static enum nvram_parser_state
+(*nv_parser_states[])(struct nvram_parser *nvp) = {
+ brcmf_nvram_handle_idle,
+ brcmf_nvram_handle_key,
+ brcmf_nvram_handle_value,
+ brcmf_nvram_handle_comment,
+ brcmf_nvram_handle_end
+};
+
+static int brcmf_init_nvram_parser(struct nvram_parser *nvp,
+ const struct firmware *nv)
+{
+ memset(nvp, 0, sizeof(*nvp));
+ nvp->fwnv = nv;
+ /* Alloc for extra 0 byte + roundup by 4 + length field */
+ nvp->nvram = kzalloc(nv->size + 1 + 3 + sizeof(u32), GFP_KERNEL);
+ if (!nvp->nvram)
+ return -ENOMEM;
+
+ nvp->line = 1;
+ nvp->column = 1;
+ return 0;
+}
+
+/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a fil
+ * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
+ * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
+ * End of buffer is completed with token identifying length of buffer.
+ */
+static void *brcmf_fw_nvram_strip(const struct firmware *nv, u32 *new_length)
+{
+ struct nvram_parser nvp;
+ u32 pad;
+ u32 token;
+ __le32 token_le;
+
+ if (brcmf_init_nvram_parser(&nvp, nv) < 0)
+ return NULL;
+
+ while (nvp.pos < nv->size) {
+ nvp.state = nv_parser_states[nvp.state](&nvp);
+ if (nvp.state == END)
+ break;
+ }
+ pad = nvp.nvram_len;
+ *new_length = roundup(nvp.nvram_len + 1, 4);
+ while (pad != *new_length) {
+ nvp.nvram[pad] = 0;
+ pad++;
+ }
+
+ token = *new_length / 4;
+ token = (~token << 16) | (token & 0x0000FFFF);
+ token_le = cpu_to_le32(token);
+
+ memcpy(&nvp.nvram[*new_length], &token_le, sizeof(token_le));
+ *new_length += sizeof(token_le);
+
+ return nvp.nvram;
+}
+
+void brcmf_fw_nvram_free(void *nvram)
+{
+ kfree(nvram);
+}
+
+struct brcmf_fw {
+ struct device *dev;
+ u16 flags;
+ const struct firmware *code;
+ const char *nvram_name;
+ void (*done)(struct device *dev, const struct firmware *fw,
+ void *nvram_image, u32 nvram_len);
+};
+
+static void brcmf_fw_request_nvram_done(const struct firmware *fw, void *ctx)
+{
+ struct brcmf_fw *fwctx = ctx;
+ u32 nvram_length = 0;
+ void *nvram = NULL;
+
+ brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
+ if (!fw && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
+ goto fail;
+
+ if (fw) {
+ nvram = brcmf_fw_nvram_strip(fw, &nvram_length);
+ release_firmware(fw);
+ if (!nvram && !(fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL))
+ goto fail;
+ }
+
+ fwctx->done(fwctx->dev, fwctx->code, nvram, nvram_length);
+ kfree(fwctx);
+ return;
+
+fail:
+ brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
+ if (fwctx->code)
+ release_firmware(fwctx->code);
+ device_release_driver(fwctx->dev);
+ kfree(fwctx);
+}
+
+static void brcmf_fw_request_code_done(const struct firmware *fw, void *ctx)
+{
+ struct brcmf_fw *fwctx = ctx;
+ int ret;
+
+ brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(fwctx->dev));
+ if (!fw)
+ goto fail;
+
+ /* only requested code so done here */
+ if (!(fwctx->flags & BRCMF_FW_REQUEST_NVRAM)) {
+ fwctx->done(fwctx->dev, fw, NULL, 0);
+ kfree(fwctx);
+ return;
+ }
+ fwctx->code = fw;
+ ret = request_firmware_nowait(THIS_MODULE, true, fwctx->nvram_name,
+ fwctx->dev, GFP_KERNEL, fwctx,
+ brcmf_fw_request_nvram_done);
+
+ if (!ret)
+ return;
+
+ /* when nvram is optional call .done() callback here */
+ if (fwctx->flags & BRCMF_FW_REQ_NV_OPTIONAL) {
+ fwctx->done(fwctx->dev, fw, NULL, 0);
+ kfree(fwctx);
+ return;
+ }
+
+ /* failed nvram request */
+ release_firmware(fw);
+fail:
+ brcmf_dbg(TRACE, "failed: dev=%s\n", dev_name(fwctx->dev));
+ device_release_driver(fwctx->dev);
+ kfree(fwctx);
+}
+
+int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
+ const char *code, const char *nvram,
+ void (*fw_cb)(struct device *dev,
+ const struct firmware *fw,
+ void *nvram_image, u32 nvram_len))
+{
+ struct brcmf_fw *fwctx;
+
+ brcmf_dbg(TRACE, "enter: dev=%s\n", dev_name(dev));
+ if (!fw_cb || !code)
+ return -EINVAL;
+
+ if ((flags & BRCMF_FW_REQUEST_NVRAM) && !nvram)
+ return -EINVAL;
+
+ fwctx = kzalloc(sizeof(*fwctx), GFP_KERNEL);
+ if (!fwctx)
+ return -ENOMEM;
+
+ fwctx->dev = dev;
+ fwctx->flags = flags;
+ fwctx->done = fw_cb;
+ if (flags & BRCMF_FW_REQUEST_NVRAM)
+ fwctx->nvram_name = nvram;
+
+ return request_firmware_nowait(THIS_MODULE, true, code, dev,
+ GFP_KERNEL, fwctx,
+ brcmf_fw_request_code_done);
+}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.h b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
index d454580928c..6431bfd7aff 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/nvram.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/firmware.h
@@ -13,12 +13,24 @@
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
-#ifndef BRCMFMAC_NVRAM_H
-#define BRCMFMAC_NVRAM_H
+#ifndef BRCMFMAC_FIRMWARE_H
+#define BRCMFMAC_FIRMWARE_H
+#define BRCMF_FW_REQUEST 0x000F
+#define BRCMF_FW_REQUEST_NVRAM 0x0001
+#define BRCMF_FW_REQ_FLAGS 0x00F0
+#define BRCMF_FW_REQ_NV_OPTIONAL 0x0010
-void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length);
-void brcmf_nvram_free(void *nvram);
-
+void brcmf_fw_nvram_free(void *nvram);
+/*
+ * Request firmware(s) asynchronously. When the asynchronous request
+ * fails it will not use the callback, but call device_release_driver()
+ * instead which will call the driver .remove() callback.
+ */
+int brcmf_fw_get_firmwares(struct device *dev, u16 flags,
+ const char *code, const char *nvram,
+ void (*fw_cb)(struct device *dev,
+ const struct firmware *fw,
+ void *nvram_image, u32 nvram_len));
-#endif /* BRCMFMAC_NVRAM_H */
+#endif /* BRCMFMAC_FIRMWARE_H */
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
index 614e4888504..2bc68a2137f 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwil_types.h
@@ -53,6 +53,14 @@
#define BRCMF_OBSS_COEX_OFF 0
#define BRCMF_OBSS_COEX_ON 1
+/* join preference types for join_pref iovar */
+enum brcmf_join_pref_types {
+ BRCMF_JOIN_PREF_RSSI = 1,
+ BRCMF_JOIN_PREF_WPA,
+ BRCMF_JOIN_PREF_BAND,
+ BRCMF_JOIN_PREF_RSSI_DELTA,
+};
+
enum brcmf_fil_p2p_if_types {
BRCMF_FIL_P2P_IF_CLIENT,
BRCMF_FIL_P2P_IF_GO,
@@ -282,6 +290,22 @@ struct brcmf_assoc_params_le {
__le16 chanspec_list[1];
};
+/**
+ * struct join_pref params - parameters for preferred join selection.
+ *
+ * @type: preference type (see enum brcmf_join_pref_types).
+ * @len: length of bytes following (currently always 2).
+ * @rssi_gain: signal gain for selection (only when @type is RSSI_DELTA).
+ * @band: band to which selection preference applies.
+ * This is used if @type is BAND or RSSI_DELTA.
+ */
+struct brcmf_join_pref_params {
+ u8 type;
+ u8 len;
+ u8 rssi_gain;
+ u8 band;
+};
+
/* used for join with or without a specific bssid and channel list */
struct brcmf_join_params {
struct brcmf_ssid_le ssid_le;
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
index c3e7d76dbf3..699908de314 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/fwsignal.c
@@ -476,6 +476,7 @@ struct brcmf_fws_info {
bool bus_flow_blocked;
bool creditmap_received;
u8 mode;
+ bool avoid_queueing;
};
/*
@@ -1369,13 +1370,12 @@ done:
}
static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
- struct sk_buff *skb, u32 genbit,
- u16 seq)
+ struct sk_buff *skb, u8 ifidx,
+ u32 genbit, u16 seq)
{
struct brcmf_fws_mac_descriptor *entry = brcmf_skbcb(skb)->mac;
u32 hslot;
int ret;
- u8 ifidx;
hslot = brcmf_skb_htod_tag_get_field(skb, HSLOT);
@@ -1389,29 +1389,21 @@ static int brcmf_fws_txstatus_suppressed(struct brcmf_fws_info *fws, int fifo,
entry->generation = genbit;
- ret = brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb);
- if (ret == 0) {
- brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
- brcmf_skbcb(skb)->htod_seq = seq;
- if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
- brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
- brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
- } else {
- brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
- }
- ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo,
- skb);
+ brcmf_skb_htod_tag_set_field(skb, GENERATION, genbit);
+ brcmf_skbcb(skb)->htod_seq = seq;
+ if (brcmf_skb_htod_seq_get_field(skb, FROMFW)) {
+ brcmf_skb_htod_seq_set_field(skb, FROMDRV, 1);
+ brcmf_skb_htod_seq_set_field(skb, FROMFW, 0);
+ } else {
+ brcmf_skb_htod_seq_set_field(skb, FROMDRV, 0);
}
+ ret = brcmf_fws_enq(fws, BRCMF_FWS_SKBSTATE_SUPPRESSED, fifo, skb);
if (ret != 0) {
- /* suppress q is full or hdrpull failed, drop this packet */
- brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb,
- true);
+ /* suppress q is full drop this packet */
+ brcmf_fws_hanger_poppkt(&fws->hanger, hslot, &skb, true);
} else {
- /*
- * Mark suppressed to avoid a double free during
- * wlfc cleanup
- */
+ /* Mark suppressed to avoid a double free during wlfc cleanup */
brcmf_fws_hanger_mark_suppressed(&fws->hanger, hslot);
}
@@ -1428,6 +1420,7 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
struct sk_buff *skb;
struct brcmf_skbuff_cb *skcb;
struct brcmf_fws_mac_descriptor *entry = NULL;
+ u8 ifidx;
brcmf_dbg(DATA, "flags %d\n", flags);
@@ -1476,12 +1469,15 @@ brcmf_fws_txs_process(struct brcmf_fws_info *fws, u8 flags, u32 hslot,
}
brcmf_fws_macdesc_return_req_credit(skb);
+ if (brcmf_proto_hdrpull(fws->drvr, false, &ifidx, skb)) {
+ brcmu_pkt_buf_free_skb(skb);
+ return -EINVAL;
+ }
if (!remove_from_hanger)
- ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, genbit,
- seq);
-
+ ret = brcmf_fws_txstatus_suppressed(fws, fifo, skb, ifidx,
+ genbit, seq);
if (remove_from_hanger || ret)
- brcmf_txfinalize(fws->drvr, skb, true);
+ brcmf_txfinalize(fws->drvr, skb, ifidx, true);
return 0;
}
@@ -1868,7 +1864,7 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
struct ethhdr *eh = (struct ethhdr *)(skb->data);
int fifo = BRCMF_FWS_FIFO_BCMC;
bool multicast = is_multicast_ether_addr(eh->h_dest);
- bool pae = eh->h_proto == htons(ETH_P_PAE);
+ int rc = 0;
brcmf_dbg(DATA, "tx proto=0x%X\n", ntohs(eh->h_proto));
/* determine the priority */
@@ -1876,8 +1872,13 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
skb->priority = cfg80211_classify8021d(skb, NULL);
drvr->tx_multicast += !!multicast;
- if (pae)
- atomic_inc(&ifp->pend_8021x_cnt);
+
+ if (fws->avoid_queueing) {
+ rc = brcmf_proto_txdata(drvr, ifp->ifidx, 0, skb);
+ if (rc < 0)
+ brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+ return rc;
+ }
/* set control buffer information */
skcb->if_flags = 0;
@@ -1899,15 +1900,12 @@ int brcmf_fws_process_skb(struct brcmf_if *ifp, struct sk_buff *skb)
brcmf_fws_schedule_deq(fws);
} else {
brcmf_err("drop skb: no hanger slot\n");
- if (pae) {
- atomic_dec(&ifp->pend_8021x_cnt);
- if (waitqueue_active(&ifp->pend_8021x_wait))
- wake_up(&ifp->pend_8021x_wait);
- }
- brcmu_pkt_buf_free_skb(skb);
+ brcmf_txfinalize(drvr, skb, ifp->ifidx, false);
+ rc = -ENOMEM;
}
brcmf_fws_unlock(fws);
- return 0;
+
+ return rc;
}
void brcmf_fws_reset_interface(struct brcmf_if *ifp)
@@ -1982,7 +1980,8 @@ static void brcmf_fws_dequeue_worker(struct work_struct *worker)
ret = brcmf_proto_txdata(drvr, ifidx, 0, skb);
brcmf_fws_lock(fws);
if (ret < 0)
- brcmf_txfinalize(drvr, skb, false);
+ brcmf_txfinalize(drvr, skb, ifidx,
+ false);
if (fws->bus_flow_blocked)
break;
}
@@ -2039,6 +2038,13 @@ int brcmf_fws_init(struct brcmf_pub *drvr)
fws->drvr = drvr;
fws->fcmode = fcmode;
+ if ((drvr->bus_if->always_use_fws_queue == false) &&
+ (fcmode == BRCMF_FWS_FCMODE_NONE)) {
+ fws->avoid_queueing = true;
+ brcmf_dbg(INFO, "FWS queueing will be avoided\n");
+ return 0;
+ }
+
fws->fws_wq = create_singlethread_workqueue("brcmf_fws_wq");
if (fws->fws_wq == NULL) {
brcmf_err("workqueue creation failed\n");
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/nvram.c b/drivers/net/wireless/brcm80211/brcmfmac/nvram.c
deleted file mode 100644
index d5ef86db631..00000000000
--- a/drivers/net/wireless/brcm80211/brcmfmac/nvram.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Copyright (c) 2013 Broadcom Corporation
- *
- * Permission to use, copy, modify, and/or distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
- * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-#include <linux/kernel.h>
-#include <linux/slab.h>
-#include <linux/firmware.h>
-
-#include "nvram.h"
-
-/* brcmf_nvram_strip :Takes a buffer of "<var>=<value>\n" lines read from a file
- * and ending in a NUL. Removes carriage returns, empty lines, comment lines,
- * and converts newlines to NULs. Shortens buffer as needed and pads with NULs.
- * End of buffer is completed with token identifying length of buffer.
- */
-void *brcmf_nvram_strip(const struct firmware *nv, u32 *new_length)
-{
- u8 *nvram;
- u32 i;
- u32 len;
- u32 column;
- u8 val;
- bool comment;
- u32 token;
- __le32 token_le;
-
- /* Alloc for extra 0 byte + roundup by 4 + length field */
- nvram = kmalloc(nv->size + 1 + 3 + sizeof(token_le), GFP_KERNEL);
- if (!nvram)
- return NULL;
-
- len = 0;
- column = 0;
- comment = false;
- for (i = 0; i < nv->size; i++) {
- val = nv->data[i];
- if (val == 0)
- break;
- if (val == '\r')
- continue;
- if (comment && (val != '\n'))
- continue;
- comment = false;
- if (val == '#') {
- comment = true;
- continue;
- }
- if (val == '\n') {
- if (column == 0)
- continue;
- nvram[len] = 0;
- len++;
- column = 0;
- continue;
- }
- nvram[len] = val;
- len++;
- column++;
- }
- column = len;
- *new_length = roundup(len + 1, 4);
- while (column != *new_length) {
- nvram[column] = 0;
- column++;
- }
-
- token = *new_length / 4;
- token = (~token << 16) | (token & 0x0000FFFF);
- token_le = cpu_to_le32(token);
-
- memcpy(&nvram[*new_length], &token_le, sizeof(token_le));
- *new_length += sizeof(token_le);
-
- return nvram;
-}
-
-void brcmf_nvram_free(void *nvram)
-{
- kfree(nvram);
-}
-
-
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/usb.c b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
index 24f65cd5385..d06fcb05adf 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/usb.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/usb.c
@@ -25,6 +25,7 @@
#include <dhd_bus.h>
#include <dhd_dbg.h>
+#include "firmware.h"
#include "usb_rdl.h"
#include "usb.h"
@@ -61,12 +62,6 @@ struct brcmf_usb_image {
u8 *image;
int image_len;
};
-static struct list_head fw_image_list;
-
-struct intr_transfer_buf {
- u32 notification;
- u32 reserved;
-};
struct brcmf_usbdev_info {
struct brcmf_usbdev bus_pub; /* MUST BE FIRST */
@@ -75,7 +70,7 @@ struct brcmf_usbdev_info {
struct list_head rx_postq;
struct list_head tx_freeq;
struct list_head tx_postq;
- uint rx_pipe, tx_pipe, intr_pipe, rx_pipe2;
+ uint rx_pipe, tx_pipe, rx_pipe2;
int rx_low_watermark;
int tx_low_watermark;
@@ -87,7 +82,7 @@ struct brcmf_usbdev_info {
struct brcmf_usbreq *tx_reqs;
struct brcmf_usbreq *rx_reqs;
- u8 *image; /* buffer for combine fw and nvram */
+ const u8 *image; /* buffer for combine fw and nvram */
int image_len;
struct usb_device *usbdev;
@@ -104,10 +99,6 @@ struct brcmf_usbdev_info {
ulong ctl_op;
struct urb *bulk_urb; /* used for FW download */
- struct urb *intr_urb; /* URB for interrupt endpoint */
- int intr_size; /* Size of interrupt message */
- int interval; /* Interrupt polling interval */
- struct intr_transfer_buf intr; /* Data buffer for interrupt endpoint */
};
static void brcmf_usb_rx_refill(struct brcmf_usbdev_info *devinfo,
@@ -531,39 +522,6 @@ brcmf_usb_state_change(struct brcmf_usbdev_info *devinfo, int state)
}
}
-static void
-brcmf_usb_intr_complete(struct urb *urb)
-{
- struct brcmf_usbdev_info *devinfo =
- (struct brcmf_usbdev_info *)urb->context;
- int err;
-
- brcmf_dbg(USB, "Enter, urb->status=%d\n", urb->status);
-
- if (devinfo == NULL)
- return;
-
- if (unlikely(urb->status)) {
- if (urb->status == -ENOENT ||
- urb->status == -ESHUTDOWN ||
- urb->status == -ENODEV) {
- brcmf_usb_state_change(devinfo,
- BRCMFMAC_USB_STATE_DOWN);
- }
- }
-
- if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_DOWN) {
- brcmf_err("intr cb when DBUS down, ignoring\n");
- return;
- }
-
- if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP) {
- err = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
- if (err)
- brcmf_err("usb_submit_urb, err=%d\n", err);
- }
-}
-
static int brcmf_usb_tx(struct device *dev, struct sk_buff *skb)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
@@ -619,7 +577,6 @@ static int brcmf_usb_up(struct device *dev)
{
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(dev);
u16 ifnum;
- int ret;
brcmf_dbg(USB, "Enter\n");
if (devinfo->bus_pub.state == BRCMFMAC_USB_STATE_UP)
@@ -628,23 +585,6 @@ static int brcmf_usb_up(struct device *dev)
/* Success, indicate devinfo is fully up */
brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_UP);
- if (devinfo->intr_urb) {
- usb_fill_int_urb(devinfo->intr_urb, devinfo->usbdev,
- devinfo->intr_pipe,
- &devinfo->intr,
- devinfo->intr_size,
- (usb_complete_t)brcmf_usb_intr_complete,
- devinfo,
- devinfo->interval);
-
- ret = usb_submit_urb(devinfo->intr_urb, GFP_ATOMIC);
- if (ret) {
- brcmf_err("USB_SUBMIT_URB failed with status %d\n",
- ret);
- return -EINVAL;
- }
- }
-
if (devinfo->ctl_urb) {
devinfo->ctl_in_pipe = usb_rcvctrlpipe(devinfo->usbdev, 0);
devinfo->ctl_out_pipe = usb_sndctrlpipe(devinfo->usbdev, 0);
@@ -681,8 +621,6 @@ static void brcmf_usb_down(struct device *dev)
return;
brcmf_usb_state_change(devinfo, BRCMFMAC_USB_STATE_DOWN);
- if (devinfo->intr_urb)
- usb_kill_urb(devinfo->intr_urb);
if (devinfo->ctl_urb)
usb_kill_urb(devinfo->ctl_urb);
@@ -1021,7 +959,7 @@ brcmf_usb_fw_download(struct brcmf_usbdev_info *devinfo)
}
err = brcmf_usb_dlstart(devinfo,
- devinfo->image, devinfo->image_len);
+ (u8 *)devinfo->image, devinfo->image_len);
if (err == 0)
err = brcmf_usb_dlrun(devinfo);
return err;
@@ -1036,7 +974,6 @@ static void brcmf_usb_detach(struct brcmf_usbdev_info *devinfo)
brcmf_usb_free_q(&devinfo->rx_freeq, false);
brcmf_usb_free_q(&devinfo->tx_freeq, false);
- usb_free_urb(devinfo->intr_urb);
usb_free_urb(devinfo->ctl_urb);
usb_free_urb(devinfo->bulk_urb);
@@ -1080,68 +1017,20 @@ static int check_file(const u8 *headers)
return -1;
}
-static int brcmf_usb_get_fw(struct brcmf_usbdev_info *devinfo)
+static const char *brcmf_usb_get_fwname(struct brcmf_usbdev_info *devinfo)
{
- s8 *fwname;
- const struct firmware *fw;
- struct brcmf_usb_image *fw_image;
- int err;
-
- brcmf_dbg(USB, "Enter\n");
switch (devinfo->bus_pub.devid) {
case 43143:
- fwname = BRCMF_USB_43143_FW_NAME;
- break;
+ return BRCMF_USB_43143_FW_NAME;
case 43235:
case 43236:
case 43238:
- fwname = BRCMF_USB_43236_FW_NAME;
- break;
+ return BRCMF_USB_43236_FW_NAME;
case 43242:
- fwname = BRCMF_USB_43242_FW_NAME;
- break;
+ return BRCMF_USB_43242_FW_NAME;
default:
- return -EINVAL;
- break;
- }
- brcmf_dbg(USB, "Loading FW %s\n", fwname);
- list_for_each_entry(fw_image, &fw_image_list, list) {
- if (fw_image->fwname == fwname) {
- devinfo->image = fw_image->image;
- devinfo->image_len = fw_image->image_len;
- return 0;
- }
- }
- /* fw image not yet loaded. Load it now and add to list */
- err = request_firmware(&fw, fwname, devinfo->dev);
- if (!fw) {
- brcmf_err("fail to request firmware %s\n", fwname);
- return err;
- }
- if (check_file(fw->data) < 0) {
- brcmf_err("invalid firmware %s\n", fwname);
- return -EINVAL;
+ return NULL;
}
-
- fw_image = kzalloc(sizeof(*fw_image), GFP_ATOMIC);
- if (!fw_image)
- return -ENOMEM;
- INIT_LIST_HEAD(&fw_image->list);
- list_add_tail(&fw_image->list, &fw_image_list);
- fw_image->fwname = fwname;
- fw_image->image = vmalloc(fw->size);
- if (!fw_image->image)
- return -ENOMEM;
-
- memcpy(fw_image->image, fw->data, fw->size);
- fw_image->image_len = fw->size;
-
- release_firmware(fw);
-
- devinfo->image = fw_image->image;
- devinfo->image_len = fw_image->image_len;
-
- return 0;
}
@@ -1186,11 +1075,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
goto error;
devinfo->tx_freecount = ntxq;
- devinfo->intr_urb = usb_alloc_urb(0, GFP_ATOMIC);
- if (!devinfo->intr_urb) {
- brcmf_err("usb_alloc_urb (intr) failed\n");
- goto error;
- }
devinfo->ctl_urb = usb_alloc_urb(0, GFP_ATOMIC);
if (!devinfo->ctl_urb) {
brcmf_err("usb_alloc_urb (ctl) failed\n");
@@ -1202,16 +1086,6 @@ struct brcmf_usbdev *brcmf_usb_attach(struct brcmf_usbdev_info *devinfo,
goto error;
}
- if (!brcmf_usb_dlneeded(devinfo))
- return &devinfo->bus_pub;
-
- brcmf_dbg(USB, "Start fw downloading\n");
- if (brcmf_usb_get_fw(devinfo))
- goto error;
-
- if (brcmf_usb_fw_download(devinfo))
- goto error;
-
return &devinfo->bus_pub;
error:
@@ -1222,18 +1096,77 @@ error:
static struct brcmf_bus_ops brcmf_usb_bus_ops = {
.txdata = brcmf_usb_tx,
- .init = brcmf_usb_up,
.stop = brcmf_usb_down,
.txctl = brcmf_usb_tx_ctlpkt,
.rxctl = brcmf_usb_rx_ctlpkt,
};
+static int brcmf_usb_bus_setup(struct brcmf_usbdev_info *devinfo)
+{
+ int ret;
+
+ /* Attach to the common driver interface */
+ ret = brcmf_attach(devinfo->dev);
+ if (ret) {
+ brcmf_err("brcmf_attach failed\n");
+ return ret;
+ }
+
+ ret = brcmf_usb_up(devinfo->dev);
+ if (ret)
+ goto fail;
+
+ ret = brcmf_bus_start(devinfo->dev);
+ if (ret)
+ goto fail;
+
+ return 0;
+fail:
+ brcmf_detach(devinfo->dev);
+ return ret;
+}
+
+static void brcmf_usb_probe_phase2(struct device *dev,
+ const struct firmware *fw,
+ void *nvram, u32 nvlen)
+{
+ struct brcmf_bus *bus = dev_get_drvdata(dev);
+ struct brcmf_usbdev_info *devinfo;
+ int ret;
+
+ brcmf_dbg(USB, "Start fw downloading\n");
+ ret = check_file(fw->data);
+ if (ret < 0) {
+ brcmf_err("invalid firmware\n");
+ release_firmware(fw);
+ goto error;
+ }
+
+ devinfo = bus->bus_priv.usb->devinfo;
+ devinfo->image = fw->data;
+ devinfo->image_len = fw->size;
+
+ ret = brcmf_usb_fw_download(devinfo);
+ release_firmware(fw);
+ if (ret)
+ goto error;
+
+ ret = brcmf_usb_bus_setup(devinfo);
+ if (ret)
+ goto error;
+
+ return;
+error:
+ brcmf_dbg(TRACE, "failed: dev=%s, err=%d\n", dev_name(dev), ret);
+ device_release_driver(dev);
+}
+
static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
{
struct brcmf_bus *bus = NULL;
struct brcmf_usbdev *bus_pub = NULL;
- int ret;
struct device *dev = devinfo->dev;
+ int ret;
brcmf_dbg(USB, "Enter\n");
bus_pub = brcmf_usb_attach(devinfo, BRCMF_USB_NRXQ, BRCMF_USB_NTXQ);
@@ -1251,25 +1184,22 @@ static int brcmf_usb_probe_cb(struct brcmf_usbdev_info *devinfo)
bus->bus_priv.usb = bus_pub;
dev_set_drvdata(dev, bus);
bus->ops = &brcmf_usb_bus_ops;
- bus->chip = bus_pub->devid;
- bus->chiprev = bus_pub->chiprev;
bus->proto_type = BRCMF_PROTO_BCDC;
+ bus->always_use_fws_queue = true;
- /* Attach to the common driver interface */
- ret = brcmf_attach(dev);
- if (ret) {
- brcmf_err("brcmf_attach failed\n");
- goto fail;
- }
-
- ret = brcmf_bus_start(dev);
- if (ret) {
- brcmf_err("dongle is not responding\n");
- brcmf_detach(dev);
- goto fail;
+ if (!brcmf_usb_dlneeded(devinfo)) {
+ ret = brcmf_usb_bus_setup(devinfo);
+ if (ret)
+ goto fail;
}
+ bus->chip = bus_pub->devid;
+ bus->chiprev = bus_pub->chiprev;
+ /* request firmware here */
+ brcmf_fw_get_firmwares(dev, 0, brcmf_usb_get_fwname(devinfo), NULL,
+ brcmf_usb_probe_phase2);
return 0;
+
fail:
/* Release resources in reverse order */
kfree(bus);
@@ -1357,9 +1287,6 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
goto fail;
}
- endpoint_num = endpoint->bEndpointAddress & USB_ENDPOINT_NUMBER_MASK;
- devinfo->intr_pipe = usb_rcvintpipe(usb, endpoint_num);
-
devinfo->rx_pipe = 0;
devinfo->rx_pipe2 = 0;
devinfo->tx_pipe = 0;
@@ -1391,16 +1318,9 @@ brcmf_usb_probe(struct usb_interface *intf, const struct usb_device_id *id)
}
}
- /* Allocate interrupt URB and data buffer */
- /* RNDIS says 8-byte intr, our old drivers used 4-byte */
- if (IFEPDESC(usb, CONTROL_IF, 0).wMaxPacketSize == cpu_to_le16(16))
- devinfo->intr_size = 8;
- else
- devinfo->intr_size = 4;
-
- devinfo->interval = IFEPDESC(usb, CONTROL_IF, 0).bInterval;
-
- if (usb->speed == USB_SPEED_HIGH)
+ if (usb->speed == USB_SPEED_SUPER)
+ brcmf_dbg(USB, "Broadcom super speed USB wireless device detected\n");
+ else if (usb->speed == USB_SPEED_HIGH)
brcmf_dbg(USB, "Broadcom high speed USB wireless device detected\n");
else
brcmf_dbg(USB, "Broadcom full speed USB wireless device detected\n");
@@ -1455,23 +1375,18 @@ static int brcmf_usb_resume(struct usb_interface *intf)
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
brcmf_dbg(USB, "Enter\n");
- if (!brcmf_attach(devinfo->dev))
- return brcmf_bus_start(&usb->dev);
-
- return 0;
+ return brcmf_usb_bus_setup(devinfo);
}
static int brcmf_usb_reset_resume(struct usb_interface *intf)
{
struct usb_device *usb = interface_to_usbdev(intf);
struct brcmf_usbdev_info *devinfo = brcmf_usb_get_businfo(&usb->dev);
-
brcmf_dbg(USB, "Enter\n");
- if (!brcmf_usb_fw_download(devinfo))
- return brcmf_usb_resume(intf);
-
- return -EIO;
+ return brcmf_fw_get_firmwares(&usb->dev, 0,
+ brcmf_usb_get_fwname(devinfo), NULL,
+ brcmf_usb_probe_phase2);
}
#define BRCMF_USB_VENDOR_ID_BROADCOM 0x0a5c
@@ -1506,16 +1421,6 @@ static struct usb_driver brcmf_usbdrvr = {
.disable_hub_initiated_lpm = 1,
};
-static void brcmf_release_fw(struct list_head *q)
-{
- struct brcmf_usb_image *fw_image, *next;
-
- list_for_each_entry_safe(fw_image, next, q, list) {
- vfree(fw_image->image);
- list_del_init(&fw_image->list);
- }
-}
-
static int brcmf_usb_reset_device(struct device *dev, void *notused)
{
/* device past is the usb interface so we
@@ -1534,12 +1439,10 @@ void brcmf_usb_exit(void)
ret = driver_for_each_device(drv, NULL, NULL,
brcmf_usb_reset_device);
usb_deregister(&brcmf_usbdrvr);
- brcmf_release_fw(&fw_image_list);
}
void brcmf_usb_register(void)
{
brcmf_dbg(USB, "Enter\n");
- INIT_LIST_HEAD(&fw_image_list);
usb_register(&brcmf_usbdrvr);
}
diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
index afb3d15e38f..d8fa276e368 100644
--- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
+++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c
@@ -221,9 +221,9 @@ static const struct ieee80211_regdomain brcmf_regdom = {
*/
REG_RULE(2484-10, 2484+10, 20, 6, 20, 0),
/* IEEE 802.11a, channel 36..64 */
- REG_RULE(5150-10, 5350+10, 40, 6, 20, 0),
+ REG_RULE(5150-10, 5350+10, 80, 6, 20, 0),
/* IEEE 802.11a, channel 100..165 */
- REG_RULE(5470-10, 5850+10, 40, 6, 20, 0), }
+ REG_RULE(5470-10, 5850+10, 80, 6, 20, 0), }
};
static const u32 __wl_cipher_suites[] = {
@@ -341,6 +341,60 @@ static u8 brcmf_mw_to_qdbm(u16 mw)
return qdbm;
}
+static u16 chandef_to_chanspec(struct brcmu_d11inf *d11inf,
+ struct cfg80211_chan_def *ch)
+{
+ struct brcmu_chan ch_inf;
+ s32 primary_offset;
+
+ brcmf_dbg(TRACE, "chandef: control %d center %d width %d\n",
+ ch->chan->center_freq, ch->center_freq1, ch->width);
+ ch_inf.chnum = ieee80211_frequency_to_channel(ch->center_freq1);
+ primary_offset = ch->center_freq1 - ch->chan->center_freq;
+ switch (ch->width) {
+ case NL80211_CHAN_WIDTH_20:
+ ch_inf.bw = BRCMU_CHAN_BW_20;
+ WARN_ON(primary_offset != 0);
+ break;
+ case NL80211_CHAN_WIDTH_40:
+ ch_inf.bw = BRCMU_CHAN_BW_40;
+ if (primary_offset < 0)
+ ch_inf.sb = BRCMU_CHAN_SB_U;
+ else
+ ch_inf.sb = BRCMU_CHAN_SB_L;
+ break;
+ case NL80211_CHAN_WIDTH_80:
+ ch_inf.bw = BRCMU_CHAN_BW_80;
+ if (primary_offset < 0) {
+ if (primary_offset < -CH_10MHZ_APART)
+ ch_inf.sb = BRCMU_CHAN_SB_UU;
+ else
+ ch_inf.sb = BRCMU_CHAN_SB_UL;
+ } else {
+ if (primary_offset > CH_10MHZ_APART)
+ ch_inf.sb = BRCMU_CHAN_SB_LL;
+ else
+ ch_inf.sb = BRCMU_CHAN_SB_LU;
+ }
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ }
+ switch (ch->chan->band) {
+ case IEEE80211_BAND_2GHZ:
+ ch_inf.band = BRCMU_CHAN_BAND_2G;
+ break;
+ case IEEE80211_BAND_5GHZ:
+ ch_inf.band = BRCMU_CHAN_BAND_5G;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ }
+ d11inf->encchspec(&ch_inf);
+
+ return ch_inf.chspec;
+}
+
u16 channel_to_chanspec(struct brcmu_d11inf *d11inf,
struct ieee80211_channel *ch)
{
@@ -586,6 +640,9 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
if (err)
brcmf_err("Scan abort failed\n");
}
+
+ brcmf_set_mpc(ifp, 1);
+
/*
* e-scan can be initiated by scheduled scan
* which takes precedence.
@@ -595,12 +652,10 @@ s32 brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
cfg->sched_escan = false;
if (!aborted)
cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
- brcmf_set_mpc(ifp, 1);
} else if (scan_request) {
brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
aborted ? "Aborted" : "Done");
cfg80211_scan_done(scan_request, aborted);
- brcmf_set_mpc(ifp, 1);
}
if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status))
brcmf_dbg(SCAN, "Scan complete, probably P2P scan\n");
@@ -1236,8 +1291,8 @@ brcmf_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *ndev,
params->chandef.chan->center_freq);
if (params->channel_fixed) {
/* adding chanspec */
- chanspec = channel_to_chanspec(&cfg->d11inf,
- params->chandef.chan);
+ chanspec = chandef_to_chanspec(&cfg->d11inf,
+ &params->chandef);
join_params.params_le.chanspec_list[0] =
cpu_to_le16(chanspec);
join_params.params_le.chanspec_num = cpu_to_le32(1);
@@ -2182,7 +2237,7 @@ brcmf_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
static s32
brcmf_cfg80211_get_station(struct wiphy *wiphy, struct net_device *ndev,
- u8 *mac, struct station_info *sinfo)
+ const u8 *mac, struct station_info *sinfo)
{
struct brcmf_if *ifp = netdev_priv(ndev);
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
@@ -3124,7 +3179,7 @@ brcmf_cfg80211_sched_scan_start(struct wiphy *wiphy,
}
if (!request->n_ssids || !request->n_match_sets) {
- brcmf_err("Invalid sched scan req!! n_ssids:%d\n",
+ brcmf_dbg(SCAN, "Invalid sched scan req!! n_ssids:%d\n",
request->n_ssids);
return -EINVAL;
}
@@ -3734,23 +3789,6 @@ brcmf_config_ap_mgmt_ie(struct brcmf_cfg80211_vif *vif,
}
static s32
-brcmf_cfg80211_set_channel(struct brcmf_cfg80211_info *cfg,
- struct brcmf_if *ifp,
- struct ieee80211_channel *channel)
-{
- u16 chanspec;
- s32 err;
-
- brcmf_dbg(TRACE, "band=%d, center_freq=%d\n", channel->band,
- channel->center_freq);
-
- chanspec = channel_to_chanspec(&cfg->d11inf, channel);
- err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
-
- return err;
-}
-
-static s32
brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct cfg80211_ap_settings *settings)
{
@@ -3765,11 +3803,12 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
struct brcmf_join_params join_params;
enum nl80211_iftype dev_role;
struct brcmf_fil_bss_enable_le bss_enable;
+ u16 chanspec;
- brcmf_dbg(TRACE, "channel_type=%d, beacon_interval=%d, dtim_period=%d,\n",
- cfg80211_get_chandef_type(&settings->chandef),
- settings->beacon_interval,
- settings->dtim_period);
+ brcmf_dbg(TRACE, "ctrlchn=%d, center=%d, bw=%d, beacon_interval=%d, dtim_period=%d,\n",
+ settings->chandef.chan->hw_value,
+ settings->chandef.center_freq1, settings->chandef.width,
+ settings->beacon_interval, settings->dtim_period);
brcmf_dbg(TRACE, "ssid=%s(%zu), auth_type=%d, inactivity_timeout=%d\n",
settings->ssid, settings->ssid_len, settings->auth_type,
settings->inactivity_timeout);
@@ -3826,9 +3865,10 @@ brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
brcmf_config_ap_mgmt_ie(ifp->vif, &settings->beacon);
- err = brcmf_cfg80211_set_channel(cfg, ifp, settings->chandef.chan);
+ chanspec = chandef_to_chanspec(&cfg->d11inf, &settings->chandef);
+ err = brcmf_fil_iovar_int_set(ifp, "chanspec", chanspec);
if (err < 0) {
- brcmf_err("Set Channel failed, %d\n", err);
+ brcmf_err("Set Channel failed: chspec=%d, %d\n", chanspec, err);
goto exit;
}
@@ -3975,7 +4015,7 @@ brcmf_cfg80211_change_beacon(struct wiphy *wiphy, struct net_device *ndev,
static int
brcmf_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev,
- u8 *mac)
+ const u8 *mac)
{
struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
struct brcmf_scb_val_le scbval;
@@ -4203,7 +4243,7 @@ static int brcmf_convert_nl80211_tdls_oper(enum nl80211_tdls_operation oper)
}
static int brcmf_cfg80211_tdls_oper(struct wiphy *wiphy,
- struct net_device *ndev, u8 *peer,
+ struct net_device *ndev, const u8 *peer,
enum nl80211_tdls_operation oper)
{
struct brcmf_if *ifp;
@@ -4364,6 +4404,8 @@ static struct wiphy *brcmf_setup_wiphy(struct device *phydev)
WIPHY_FLAG_OFFCHAN_TX |
WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL |
WIPHY_FLAG_SUPPORTS_TDLS;
+ if (!brcmf_roamoff)
+ wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM;
wiphy->mgmt_stypes = brcmf_txrx_stypes;
wiphy->max_remain_on_channel_duration = 5000;
brcmf_wiphy_pno_params(wiphy);
@@ -4685,7 +4727,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
struct brcmf_cfg80211_profile *profile = &ifp->vif->profile;
struct ieee80211_channel *chan;
s32 err = 0;
- u16 reason;
if (brcmf_is_apmode(ifp->vif)) {
err = brcmf_notify_connect_status_ap(cfg, ndev, e, data);
@@ -4706,16 +4747,6 @@ brcmf_notify_connect_status(struct brcmf_if *ifp,
brcmf_dbg(CONN, "Linkdown\n");
if (!brcmf_is_ibssmode(ifp->vif)) {
brcmf_bss_connect_done(cfg, ndev, e, false);
- if (test_and_clear_bit(BRCMF_VIF_STATUS_CONNECTED,
- &ifp->vif->sme_state)) {
- reason = 0;
- if (((e->event_code == BRCMF_E_DEAUTH_IND) ||
- (e->event_code == BRCMF_E_DISASSOC_IND)) &&
- (e->reason != WLAN_REASON_UNSPECIFIED))
- reason = e->reason;
- cfg80211_disconnected(ndev, reason, NULL, 0,
- GFP_KERNEL);
- }
}
brcmf_link_down(ifp->vif);
brcmf_init_prof(ndev_to_prof(ndev));
@@ -4948,7 +4979,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_if *ifp)
if (!err) {
/* only set 2G bandwidth using bw_cap command */
band_bwcap.band = cpu_to_le32(WLC_BAND_2G);
- band_bwcap.bw_cap = cpu_to_le32(WLC_BW_40MHZ_BIT);
+ band_bwcap.bw_cap = cpu_to_le32(WLC_BW_CAP_40MHZ);
err = brcmf_fil_iovar_data_set(ifp, "bw_cap", &band_bwcap,
sizeof(band_bwcap));
} else {
@@ -5215,6 +5246,9 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
if (!(bw_cap[band] & WLC_BW_40MHZ_BIT) &&
ch.bw == BRCMU_CHAN_BW_40)
continue;
+ if (!(bw_cap[band] & WLC_BW_80MHZ_BIT) &&
+ ch.bw == BRCMU_CHAN_BW_80)
+ continue;
update = false;
for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) {
if (band_chan_arr[j].hw_value == ch.chnum) {
@@ -5231,10 +5265,13 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
ieee80211_channel_to_frequency(ch.chnum, band);
band_chan_arr[index].hw_value = ch.chnum;
- if (ch.bw == BRCMU_CHAN_BW_40) {
- /* assuming the order is HT20, HT40 Upper,
- * HT40 lower from chanspecs
- */
+ /* assuming the chanspecs order is HT20,
+ * HT40 upper, HT40 lower, and VHT80.
+ */
+ if (ch.bw == BRCMU_CHAN_BW_80) {
+ band_chan_arr[index].flags &=
+ ~IEEE80211_CHAN_NO_80MHZ;
+ } else if (ch.bw == BRCMU_CHAN_BW_40) {
ht40_flag = band_chan_arr[index].flags &
IEEE80211_CHAN_NO_HT40;
if (ch.sb == BRCMU_CHAN_SB_U) {
@@ -5255,8 +5292,13 @@ static s32 brcmf_construct_reginfo(struct brcmf_cfg80211_info *cfg,
IEEE80211_CHAN_NO_HT40MINUS;
}
} else {
+ /* disable other bandwidths for now as mentioned
+ * order assure they are enabled for subsequent
+ * chanspecs.
+ */
band_chan_arr[index].flags =
- IEEE80211_CHAN_NO_HT40;
+ IEEE80211_CHAN_NO_HT40 |
+ IEEE80211_CHAN_NO_80MHZ;
ch.bw = BRCMU_CHAN_BW_20;
cfg->d11inf.encchspec(&ch);
channel = ch.chspec;
@@ -5323,13 +5365,63 @@ static void brcmf_get_bwcap(struct brcmf_if *ifp, u32 bw_cap[])
}
}
+static void brcmf_update_ht_cap(struct ieee80211_supported_band *band,
+ u32 bw_cap[2], u32 nchain)
+{
+ band->ht_cap.ht_supported = true;
+ if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
+ band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
+ band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
+ }
+ band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
+ band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
+ band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
+ band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
+ memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
+ band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+}
+
+static __le16 brcmf_get_mcs_map(u32 nchain, enum ieee80211_vht_mcs_support supp)
+{
+ u16 mcs_map;
+ int i;
+
+ for (i = 0, mcs_map = 0xFFFF; i < nchain; i++)
+ mcs_map = (mcs_map << 2) | supp;
+
+ return cpu_to_le16(mcs_map);
+}
+
+static void brcmf_update_vht_cap(struct ieee80211_supported_band *band,
+ u32 bw_cap[2], u32 nchain)
+{
+ __le16 mcs_map;
+
+ /* not allowed in 2.4G band */
+ if (band->band == IEEE80211_BAND_2GHZ)
+ return;
+
+ band->vht_cap.vht_supported = true;
+ /* 80MHz is mandatory */
+ band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_80;
+ if (bw_cap[band->band] & WLC_BW_160MHZ_BIT) {
+ band->vht_cap.cap |= IEEE80211_VHT_CAP_SUPP_CHAN_WIDTH_160MHZ;
+ band->vht_cap.cap |= IEEE80211_VHT_CAP_SHORT_GI_160;
+ }
+ /* all support 256-QAM */
+ mcs_map = brcmf_get_mcs_map(nchain, IEEE80211_VHT_MCS_SUPPORT_0_9);
+ band->vht_cap.vht_mcs.rx_mcs_map = mcs_map;
+ band->vht_cap.vht_mcs.tx_mcs_map = mcs_map;
+}
+
static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
{
struct brcmf_if *ifp = netdev_priv(cfg_to_ndev(cfg));
struct wiphy *wiphy;
s32 phy_list;
u32 band_list[3];
- u32 nmode;
+ u32 nmode = 0;
+ u32 vhtmode = 0;
u32 bw_cap[2] = { 0, 0 };
u32 rxchain;
u32 nchain;
@@ -5360,14 +5452,16 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
brcmf_dbg(INFO, "BRCMF_C_GET_BANDLIST reported: 0x%08x 0x%08x 0x%08x phy\n",
band_list[0], band_list[1], band_list[2]);
+ (void)brcmf_fil_iovar_int_get(ifp, "vhtmode", &vhtmode);
err = brcmf_fil_iovar_int_get(ifp, "nmode", &nmode);
if (err) {
brcmf_err("nmode error (%d)\n", err);
} else {
brcmf_get_bwcap(ifp, bw_cap);
}
- brcmf_dbg(INFO, "nmode=%d, bw_cap=(%d, %d)\n", nmode,
- bw_cap[IEEE80211_BAND_2GHZ], bw_cap[IEEE80211_BAND_5GHZ]);
+ brcmf_dbg(INFO, "nmode=%d, vhtmode=%d, bw_cap=(%d, %d)\n",
+ nmode, vhtmode, bw_cap[IEEE80211_BAND_2GHZ],
+ bw_cap[IEEE80211_BAND_5GHZ]);
err = brcmf_fil_iovar_int_get(ifp, "rxchain", &rxchain);
if (err) {
@@ -5398,17 +5492,10 @@ static s32 brcmf_update_wiphybands(struct brcmf_cfg80211_info *cfg)
else
continue;
- if (bw_cap[band->band] & WLC_BW_40MHZ_BIT) {
- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40;
- band->ht_cap.cap |= IEEE80211_HT_CAP_SUP_WIDTH_20_40;
- }
- band->ht_cap.cap |= IEEE80211_HT_CAP_SGI_20;
- band->ht_cap.cap |= IEEE80211_HT_CAP_DSSSCCK40;
- band->ht_cap.ht_supported = true;
- band->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K;
- band->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16;
- memset(band->ht_cap.mcs.rx_mask, 0xff, nchain);
- band->ht_cap.mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED;
+ if (nmode)
+ brcmf_update_ht_cap(band, bw_cap, nchain);
+ if (vhtmode)
+ brcmf_update_vht_cap(band, bw_cap, nchain);
bands[band->band] = band;
}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/main.c b/drivers/net/wireless/brcm80211/brcmsmac/main.c
index 9417cb5a255..af8ba64ace3 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/main.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/main.c
@@ -4870,14 +4870,11 @@ static void brcms_c_detach_module(struct brcms_c_info *wlc)
/*
* low level detach
*/
-static int brcms_b_detach(struct brcms_c_info *wlc)
+static void brcms_b_detach(struct brcms_c_info *wlc)
{
uint i;
struct brcms_hw_band *band;
struct brcms_hardware *wlc_hw = wlc->hw;
- int callbacks;
-
- callbacks = 0;
brcms_b_detach_dmapio(wlc_hw);
@@ -4900,9 +4897,6 @@ static int brcms_b_detach(struct brcms_c_info *wlc)
ai_detach(wlc_hw->sih);
wlc_hw->sih = NULL;
}
-
- return callbacks;
-
}
/*
@@ -4917,14 +4911,15 @@ static int brcms_b_detach(struct brcms_c_info *wlc)
*/
uint brcms_c_detach(struct brcms_c_info *wlc)
{
- uint callbacks = 0;
+ uint callbacks;
if (wlc == NULL)
return 0;
- callbacks += brcms_b_detach(wlc);
+ brcms_b_detach(wlc);
/* delete software timers */
+ callbacks = 0;
if (!brcms_c_radio_monitor_stop(wlc))
callbacks++;
diff --git a/drivers/net/wireless/brcm80211/brcmutil/d11.c b/drivers/net/wireless/brcm80211/brcmutil/d11.c
index 30e54e2c6c9..2b2522bdd8e 100644
--- a/drivers/net/wireless/brcm80211/brcmutil/d11.c
+++ b/drivers/net/wireless/brcm80211/brcmutil/d11.c
@@ -21,19 +21,46 @@
#include <brcmu_wifi.h>
#include <brcmu_d11.h>
-static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
+static u16 d11n_sb(enum brcmu_chan_sb sb)
{
- ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
+ switch (sb) {
+ case BRCMU_CHAN_SB_NONE:
+ return BRCMU_CHSPEC_D11N_SB_N;
+ case BRCMU_CHAN_SB_L:
+ return BRCMU_CHSPEC_D11N_SB_L;
+ case BRCMU_CHAN_SB_U:
+ return BRCMU_CHSPEC_D11N_SB_U;
+ default:
+ WARN_ON(1);
+ }
+ return 0;
+}
- switch (ch->bw) {
+static u16 d11n_bw(enum brcmu_chan_bw bw)
+{
+ switch (bw) {
case BRCMU_CHAN_BW_20:
- ch->chspec |= BRCMU_CHSPEC_D11N_BW_20 | BRCMU_CHSPEC_D11N_SB_N;
- break;
+ return BRCMU_CHSPEC_D11N_BW_20;
case BRCMU_CHAN_BW_40:
+ return BRCMU_CHSPEC_D11N_BW_40;
default:
- WARN_ON_ONCE(1);
- break;
+ WARN_ON(1);
}
+ return 0;
+}
+
+static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
+{
+ if (ch->bw == BRCMU_CHAN_BW_20)
+ ch->sb = BRCMU_CHAN_SB_NONE;
+
+ ch->chspec = 0;
+ brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
+ BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
+ brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_SB_MASK,
+ 0, d11n_sb(ch->sb));
+ brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11N_BW_MASK,
+ 0, d11n_bw(ch->bw));
if (ch->chnum <= CH_MAX_2G_CHANNEL)
ch->chspec |= BRCMU_CHSPEC_D11N_BND_2G;
@@ -41,23 +68,34 @@ static void brcmu_d11n_encchspec(struct brcmu_chan *ch)
ch->chspec |= BRCMU_CHSPEC_D11N_BND_5G;
}
-static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
+static u16 d11ac_bw(enum brcmu_chan_bw bw)
{
- ch->chspec = ch->chnum & BRCMU_CHSPEC_CH_MASK;
-
- switch (ch->bw) {
+ switch (bw) {
case BRCMU_CHAN_BW_20:
- ch->chspec |= BRCMU_CHSPEC_D11AC_BW_20;
- break;
+ return BRCMU_CHSPEC_D11AC_BW_20;
case BRCMU_CHAN_BW_40:
+ return BRCMU_CHSPEC_D11AC_BW_40;
case BRCMU_CHAN_BW_80:
- case BRCMU_CHAN_BW_80P80:
- case BRCMU_CHAN_BW_160:
+ return BRCMU_CHSPEC_D11AC_BW_80;
default:
- WARN_ON_ONCE(1);
- break;
+ WARN_ON(1);
}
+ return 0;
+}
+static void brcmu_d11ac_encchspec(struct brcmu_chan *ch)
+{
+ if (ch->bw == BRCMU_CHAN_BW_20 || ch->sb == BRCMU_CHAN_SB_NONE)
+ ch->sb = BRCMU_CHAN_SB_L;
+
+ brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_CH_MASK,
+ BRCMU_CHSPEC_CH_SHIFT, ch->chnum);
+ brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
+ BRCMU_CHSPEC_D11AC_SB_SHIFT, ch->sb);
+ brcmu_maskset16(&ch->chspec, BRCMU_CHSPEC_D11AC_BW_MASK,
+ 0, d11ac_bw(ch->bw));
+
+ ch->chspec &= ~BRCMU_CHSPEC_D11AC_BND_MASK;
if (ch->chnum <= CH_MAX_2G_CHANNEL)
ch->chspec |= BRCMU_CHSPEC_D11AC_BND_2G;
else
@@ -73,6 +111,7 @@ static void brcmu_d11n_decchspec(struct brcmu_chan *ch)
switch (ch->chspec & BRCMU_CHSPEC_D11N_BW_MASK) {
case BRCMU_CHSPEC_D11N_BW_20:
ch->bw = BRCMU_CHAN_BW_20;
+ ch->sb = BRCMU_CHAN_SB_NONE;
break;
case BRCMU_CHSPEC_D11N_BW_40:
ch->bw = BRCMU_CHAN_BW_40;
@@ -112,6 +151,7 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
switch (ch->chspec & BRCMU_CHSPEC_D11AC_BW_MASK) {
case BRCMU_CHSPEC_D11AC_BW_20:
ch->bw = BRCMU_CHAN_BW_20;
+ ch->sb = BRCMU_CHAN_SB_NONE;
break;
case BRCMU_CHSPEC_D11AC_BW_40:
ch->bw = BRCMU_CHAN_BW_40;
@@ -128,6 +168,25 @@ static void brcmu_d11ac_decchspec(struct brcmu_chan *ch)
break;
case BRCMU_CHSPEC_D11AC_BW_80:
ch->bw = BRCMU_CHAN_BW_80;
+ ch->sb = brcmu_maskget16(ch->chspec, BRCMU_CHSPEC_D11AC_SB_MASK,
+ BRCMU_CHSPEC_D11AC_SB_SHIFT);
+ switch (ch->sb) {
+ case BRCMU_CHAN_SB_LL:
+ ch->chnum -= CH_30MHZ_APART;
+ break;
+ case BRCMU_CHAN_SB_LU:
+ ch->chnum -= CH_10MHZ_APART;
+ break;
+ case BRCMU_CHAN_SB_UL:
+ ch->chnum += CH_10MHZ_APART;
+ break;
+ case BRCMU_CHAN_SB_UU:
+ ch->chnum += CH_30MHZ_APART;
+ break;
+ default:
+ WARN_ON_ONCE(1);
+ break;
+ }
break;
case BRCMU_CHSPEC_D11AC_BW_8080:
case BRCMU_CHSPEC_D11AC_BW_160:
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_d11.h b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
index 8660a2cba09..f9745ea8b3e 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_d11.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_d11.h
@@ -108,13 +108,7 @@ enum brcmu_chan_bw {
};
enum brcmu_chan_sb {
- BRCMU_CHAN_SB_NONE = 0,
- BRCMU_CHAN_SB_L,
- BRCMU_CHAN_SB_U,
- BRCMU_CHAN_SB_LL,
- BRCMU_CHAN_SB_LU,
- BRCMU_CHAN_SB_UL,
- BRCMU_CHAN_SB_UU,
+ BRCMU_CHAN_SB_NONE = -1,
BRCMU_CHAN_SB_LLL,
BRCMU_CHAN_SB_LLU,
BRCMU_CHAN_SB_LUL,
@@ -123,6 +117,12 @@ enum brcmu_chan_sb {
BRCMU_CHAN_SB_ULU,
BRCMU_CHAN_SB_UUL,
BRCMU_CHAN_SB_UUU,
+ BRCMU_CHAN_SB_L = BRCMU_CHAN_SB_LLL,
+ BRCMU_CHAN_SB_U = BRCMU_CHAN_SB_LLU,
+ BRCMU_CHAN_SB_LL = BRCMU_CHAN_SB_LLL,
+ BRCMU_CHAN_SB_LU = BRCMU_CHAN_SB_LLU,
+ BRCMU_CHAN_SB_UL = BRCMU_CHAN_SB_LUL,
+ BRCMU_CHAN_SB_UU = BRCMU_CHAN_SB_LUU,
};
struct brcmu_chan {
diff --git a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
index 74419d4bd12..76b5d3a8629 100644
--- a/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
+++ b/drivers/net/wireless/brcm80211/include/brcmu_wifi.h
@@ -29,6 +29,7 @@
#define CH_UPPER_SB 0x01
#define CH_LOWER_SB 0x02
#define CH_EWA_VALID 0x04
+#define CH_30MHZ_APART 6
#define CH_20MHZ_APART 4
#define CH_10MHZ_APART 2
#define CH_5MHZ_APART 1 /* 2G band channels are 5 Mhz apart */
diff --git a/drivers/net/wireless/hostap/hostap_main.c b/drivers/net/wireless/hostap/hostap_main.c
index 67db34e56d7..52919ad4272 100644
--- a/drivers/net/wireless/hostap/hostap_main.c
+++ b/drivers/net/wireless/hostap/hostap_main.c
@@ -882,7 +882,7 @@ void hostap_setup_dev(struct net_device *dev, local_info_t *local,
dev->mtu = local->mtu;
- SET_ETHTOOL_OPS(dev, &prism2_ethtool_ops);
+ dev->ethtool_ops = &prism2_ethtool_ops;
}
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index 74b3b4de7bb..7fd50428b93 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -2,10 +2,6 @@ config IWLWIFI
tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
depends on PCI && MAC80211 && HAS_IOMEM
select FW_LOADER
- select NEW_LEDS
- select LEDS_CLASS
- select LEDS_TRIGGERS
- select MAC80211_LEDS
---help---
Select to build the driver supporting the:
@@ -43,6 +39,14 @@ config IWLWIFI
say M here and read <file:Documentation/kbuild/modules.txt>. The
module will be called iwlwifi.
+config IWLWIFI_LEDS
+ bool
+ depends on IWLWIFI
+ depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
+ select LEDS_TRIGGERS
+ select MAC80211_LEDS
+ default y
+
config IWLDVM
tristate "Intel Wireless WiFi DVM Firmware support"
depends on IWLWIFI
@@ -124,7 +128,6 @@ config IWLWIFI_DEBUG_EXPERIMENTAL_UCODE
Enable use of experimental ucode for testing and debugging.
config IWLWIFI_DEVICE_TRACING
-
bool "iwlwifi device access tracing"
depends on IWLWIFI
depends on EVENT_TRACING
diff --git a/drivers/net/wireless/iwlwifi/dvm/Makefile b/drivers/net/wireless/iwlwifi/dvm/Makefile
index dce7ab2e0c4..4d19685f31c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/dvm/Makefile
@@ -4,9 +4,10 @@ iwldvm-objs += main.o rs.o mac80211.o ucode.o tx.o
iwldvm-objs += lib.o calib.o tt.o sta.o rx.o
iwldvm-objs += power.o
-iwldvm-objs += scan.o led.o
+iwldvm-objs += scan.o
iwldvm-objs += rxon.o devices.o
+iwldvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwldvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
diff --git a/drivers/net/wireless/iwlwifi/dvm/calib.c b/drivers/net/wireless/iwlwifi/dvm/calib.c
index be1086c8715..20e6aa91070 100644
--- a/drivers/net/wireless/iwlwifi/dvm/calib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/calib.c
@@ -94,7 +94,6 @@ int iwl_send_calib_results(struct iwl_priv *priv)
{
struct iwl_host_cmd hcmd = {
.id = REPLY_PHY_CALIBRATION_CMD,
- .flags = CMD_SYNC,
};
struct iwl_calib_result *res;
diff --git a/drivers/net/wireless/iwlwifi/dvm/debugfs.c b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
index d2fe2596d54..0ffb6ff1a25 100644
--- a/drivers/net/wireless/iwlwifi/dvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/debugfs.c
@@ -1481,7 +1481,7 @@ static ssize_t iwl_dbgfs_ucode_bt_stats_read(struct file *file,
/* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex);
- ret = iwl_send_statistics_request(priv, CMD_SYNC, false);
+ ret = iwl_send_statistics_request(priv, 0, false);
mutex_unlock(&priv->mutex);
if (ret)
@@ -1868,7 +1868,7 @@ static ssize_t iwl_dbgfs_clear_ucode_statistics_write(struct file *file,
/* make request to uCode to retrieve statistics information */
mutex_lock(&priv->mutex);
- iwl_send_statistics_request(priv, CMD_SYNC, true);
+ iwl_send_statistics_request(priv, 0, true);
mutex_unlock(&priv->mutex);
return count;
@@ -2188,7 +2188,6 @@ static int iwl_cmd_echo_test(struct iwl_priv *priv)
struct iwl_host_cmd cmd = {
.id = REPLY_ECHO,
.len = { 0 },
- .flags = CMD_SYNC,
};
ret = iwl_dvm_send_cmd(priv, &cmd);
@@ -2320,7 +2319,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct file *file,
mutex_lock(&priv->mutex);
/* take the return value to make compiler happy - it will fail anyway */
- ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, CMD_SYNC, 0, NULL);
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_ERROR, 0, 0, NULL);
mutex_unlock(&priv->mutex);
diff --git a/drivers/net/wireless/iwlwifi/dvm/dev.h b/drivers/net/wireless/iwlwifi/dvm/dev.h
index 3441f70d0ff..a6f22c32a27 100644
--- a/drivers/net/wireless/iwlwifi/dvm/dev.h
+++ b/drivers/net/wireless/iwlwifi/dvm/dev.h
@@ -888,9 +888,11 @@ struct iwl_priv {
struct iwl_event_log event_log;
+#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
unsigned long blink_on, blink_off;
bool led_registered;
+#endif
/* WoWLAN GTK rekey data */
u8 kck[NL80211_KCK_LEN], kek[NL80211_KEK_LEN];
diff --git a/drivers/net/wireless/iwlwifi/dvm/devices.c b/drivers/net/wireless/iwlwifi/dvm/devices.c
index 758c54eeb20..34b41e5f7cf 100644
--- a/drivers/net/wireless/iwlwifi/dvm/devices.c
+++ b/drivers/net/wireless/iwlwifi/dvm/devices.c
@@ -417,7 +417,6 @@ static int iwl5000_hw_channel_switch(struct iwl_priv *priv,
struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH,
.len = { sizeof(cmd), },
- .flags = CMD_SYNC,
.data = { &cmd, },
};
@@ -579,7 +578,6 @@ static int iwl6000_hw_channel_switch(struct iwl_priv *priv,
struct iwl_host_cmd hcmd = {
.id = REPLY_CHANNEL_SWITCH,
.len = { sizeof(*cmd), },
- .flags = CMD_SYNC,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
};
int err;
diff --git a/drivers/net/wireless/iwlwifi/dvm/led.h b/drivers/net/wireless/iwlwifi/dvm/led.h
index 6a0817d9c4f..1c6b2252d0f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/led.h
+++ b/drivers/net/wireless/iwlwifi/dvm/led.h
@@ -36,8 +36,20 @@ struct iwl_priv;
#define IWL_LED_ACTIVITY (0<<1)
#define IWL_LED_LINK (1<<1)
+#ifdef CONFIG_IWLWIFI_LEDS
void iwlagn_led_enable(struct iwl_priv *priv);
void iwl_leds_init(struct iwl_priv *priv);
void iwl_leds_exit(struct iwl_priv *priv);
+#else
+static inline void iwlagn_led_enable(struct iwl_priv *priv)
+{
+}
+static inline void iwl_leds_init(struct iwl_priv *priv)
+{
+}
+static inline void iwl_leds_exit(struct iwl_priv *priv)
+{
+}
+#endif
#endif /* __iwl_leds_h__ */
diff --git a/drivers/net/wireless/iwlwifi/dvm/lib.c b/drivers/net/wireless/iwlwifi/dvm/lib.c
index d169228f59e..2191621d69c 100644
--- a/drivers/net/wireless/iwlwifi/dvm/lib.c
+++ b/drivers/net/wireless/iwlwifi/dvm/lib.c
@@ -81,7 +81,7 @@ int iwlagn_send_tx_power(struct iwl_priv *priv)
else
tx_ant_cfg_cmd = REPLY_TX_POWER_DBM_CMD;
- return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, CMD_SYNC,
+ return iwl_dvm_send_cmd_pdu(priv, tx_ant_cfg_cmd, 0,
sizeof(tx_power_cmd), &tx_power_cmd);
}
@@ -141,7 +141,6 @@ int iwlagn_txfifo_flush(struct iwl_priv *priv, u32 scd_q_msk)
struct iwl_host_cmd cmd = {
.id = REPLY_TXFIFO_FLUSH,
.len = { sizeof(struct iwl_txfifo_flush_cmd), },
- .flags = CMD_SYNC,
.data = { &flush_cmd, },
};
@@ -333,12 +332,12 @@ void iwlagn_send_advance_bt_config(struct iwl_priv *priv)
memcpy(&bt_cmd_v2.basic, &basic,
sizeof(basic));
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- CMD_SYNC, sizeof(bt_cmd_v2), &bt_cmd_v2);
+ 0, sizeof(bt_cmd_v2), &bt_cmd_v2);
} else {
memcpy(&bt_cmd_v1.basic, &basic,
sizeof(basic));
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- CMD_SYNC, sizeof(bt_cmd_v1), &bt_cmd_v1);
+ 0, sizeof(bt_cmd_v1), &bt_cmd_v1);
}
if (ret)
IWL_ERR(priv, "failed to send BT Coex Config\n");
@@ -1044,7 +1043,6 @@ int iwlagn_send_patterns(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = REPLY_WOWLAN_PATTERNS,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
- .flags = CMD_SYNC,
};
int i, err;
@@ -1201,7 +1199,6 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
if (key_data.use_rsc_tsc) {
struct iwl_host_cmd rsc_tsc_cmd = {
.id = REPLY_WOWLAN_TSC_RSC_PARAMS,
- .flags = CMD_SYNC,
.data[0] = key_data.rsc_tsc,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
.len[0] = sizeof(*key_data.rsc_tsc),
@@ -1215,7 +1212,7 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
if (key_data.use_tkip) {
ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_WOWLAN_TKIP_PARAMS,
- CMD_SYNC, sizeof(tkip_cmd),
+ 0, sizeof(tkip_cmd),
&tkip_cmd);
if (ret)
goto out;
@@ -1231,20 +1228,20 @@ int iwlagn_suspend(struct iwl_priv *priv, struct cfg80211_wowlan *wowlan)
ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_WOWLAN_KEK_KCK_MATERIAL,
- CMD_SYNC, sizeof(kek_kck_cmd),
+ 0, sizeof(kek_kck_cmd),
&kek_kck_cmd);
if (ret)
goto out;
}
}
- ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_D3_CONFIG, 0,
sizeof(d3_cfg_cmd), &d3_cfg_cmd);
if (ret)
goto out;
ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WOWLAN_WAKEUP_FILTER,
- CMD_SYNC, sizeof(wakeup_filter_cmd),
+ 0, sizeof(wakeup_filter_cmd),
&wakeup_filter_cmd);
if (ret)
goto out;
diff --git a/drivers/net/wireless/iwlwifi/dvm/main.c b/drivers/net/wireless/iwlwifi/dvm/main.c
index 6a00353768f..0b7f46f0b07 100644
--- a/drivers/net/wireless/iwlwifi/dvm/main.c
+++ b/drivers/net/wireless/iwlwifi/dvm/main.c
@@ -128,7 +128,6 @@ int iwlagn_send_beacon_cmd(struct iwl_priv *priv)
struct iwl_tx_beacon_cmd *tx_beacon_cmd;
struct iwl_host_cmd cmd = {
.id = REPLY_TX_BEACON,
- .flags = CMD_SYNC,
};
struct ieee80211_tx_info *info;
u32 frame_size;
@@ -311,8 +310,7 @@ int iwl_send_statistics_request(struct iwl_priv *priv, u8 flags, bool clear)
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
else
- return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD,
- CMD_SYNC,
+ return iwl_dvm_send_cmd_pdu(priv, REPLY_STATISTICS_CMD, 0,
sizeof(struct iwl_statistics_cmd),
&statistics_cmd);
}
@@ -622,7 +620,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_CT_KILL_CONFIG_CMD,
- CMD_SYNC, sizeof(adv_cmd), &adv_cmd);
+ 0, sizeof(adv_cmd), &adv_cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
@@ -637,7 +635,7 @@ static void iwl_rf_kill_ct_config(struct iwl_priv *priv)
ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_CT_KILL_CONFIG_CMD,
- CMD_SYNC, sizeof(cmd), &cmd);
+ 0, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "REPLY_CT_KILL_CONFIG_CMD failed\n");
else
@@ -673,9 +671,7 @@ static int iwlagn_send_tx_ant_config(struct iwl_priv *priv, u8 valid_tx_ant)
if (IWL_UCODE_API(priv->fw->ucode_ver) > 1) {
IWL_DEBUG_HC(priv, "select valid tx ant: %u\n", valid_tx_ant);
- return iwl_dvm_send_cmd_pdu(priv,
- TX_ANT_CONFIGURATION_CMD,
- CMD_SYNC,
+ return iwl_dvm_send_cmd_pdu(priv, TX_ANT_CONFIGURATION_CMD, 0,
sizeof(struct iwl_tx_ant_config_cmd),
&tx_ant_cmd);
} else {
@@ -703,7 +699,7 @@ static void iwl_send_bt_config(struct iwl_priv *priv)
(bt_cmd.flags == BT_COEX_DISABLE) ? "disable" : "active");
if (iwl_dvm_send_cmd_pdu(priv, REPLY_BT_CONFIG,
- CMD_SYNC, sizeof(struct iwl_bt_cmd), &bt_cmd))
+ 0, sizeof(struct iwl_bt_cmd), &bt_cmd))
IWL_ERR(priv, "failed to send BT Coex Config\n");
}
@@ -987,7 +983,7 @@ static void iwl_bg_restart(struct work_struct *data)
ieee80211_restart_hw(priv->hw);
else
IWL_ERR(priv,
- "Cannot request restart before registrating with mac80211");
+ "Cannot request restart before registrating with mac80211\n");
} else {
WARN_ON(1);
}
@@ -1127,7 +1123,6 @@ static void iwl_option_config(struct iwl_priv *priv)
static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
{
struct iwl_nvm_data *data = priv->nvm_data;
- char *debug_msg;
if (data->sku_cap_11n_enable &&
!priv->cfg->ht_params) {
@@ -1141,8 +1136,8 @@ static int iwl_eeprom_init_hw_params(struct iwl_priv *priv)
return -EINVAL;
}
- debug_msg = "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n";
- IWL_DEBUG_INFO(priv, debug_msg,
+ IWL_DEBUG_INFO(priv,
+ "Device SKU: 24GHz %s %s, 52GHz %s %s, 11.n %s %s\n",
data->sku_cap_band_24GHz_enable ? "" : "NOT", "enabled",
data->sku_cap_band_52GHz_enable ? "" : "NOT", "enabled",
data->sku_cap_11n_enable ? "" : "NOT", "enabled");
@@ -1350,7 +1345,7 @@ static struct iwl_op_mode *iwl_op_mode_dvm_start(struct iwl_trans *trans,
iwl_set_hw_params(priv);
if (!(priv->nvm_data->sku_cap_ipan_enable)) {
- IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN");
+ IWL_DEBUG_INFO(priv, "Your EEPROM disabled PAN\n");
ucode_flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
/*
* if not PAN, then don't support P2P -- might be a uCode
@@ -2019,10 +2014,10 @@ void iwlagn_lift_passive_no_rx(struct iwl_priv *priv)
for (mq = 0; mq < IWLAGN_FIRST_AMPDU_QUEUE; mq++) {
if (!test_bit(mq, &priv->transport_queue_stop)) {
- IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d", mq);
+ IWL_DEBUG_TX_QUEUES(priv, "Wake queue %d\n", mq);
ieee80211_wake_queue(priv->hw, mq);
} else {
- IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d", mq);
+ IWL_DEBUG_TX_QUEUES(priv, "Don't wake queue %d\n", mq);
}
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c
index b4e61417013..f2c1439566b 100644
--- a/drivers/net/wireless/iwlwifi/dvm/power.c
+++ b/drivers/net/wireless/iwlwifi/dvm/power.c
@@ -278,7 +278,7 @@ static int iwl_set_power(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd)
le32_to_cpu(cmd->sleep_interval[3]),
le32_to_cpu(cmd->sleep_interval[4]));
- return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, CMD_SYNC,
+ return iwl_dvm_send_cmd_pdu(priv, POWER_TABLE_CMD, 0,
sizeof(struct iwl_powertable_cmd), cmd);
}
@@ -361,7 +361,7 @@ int iwl_power_set_mode(struct iwl_priv *priv, struct iwl_powertable_cmd *cmd,
memcpy(&priv->power_data.sleep_cmd, cmd, sizeof(*cmd));
} else
- IWL_ERR(priv, "set power fail, ret = %d", ret);
+ IWL_ERR(priv, "set power fail, ret = %d\n", ret);
return ret;
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/rs.c b/drivers/net/wireless/iwlwifi/dvm/rs.c
index aa773a2da4a..32b78a66536 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rs.c
@@ -1453,7 +1453,7 @@ static int rs_move_legacy_other(struct iwl_priv *priv,
tbl->action = IWL_LEGACY_SWITCH_SISO;
break;
default:
- IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load);
break;
}
@@ -1628,7 +1628,7 @@ static int rs_move_siso_to_other(struct iwl_priv *priv,
tbl->action = IWL_SISO_SWITCH_ANTENNA1;
break;
default:
- IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load);
break;
}
@@ -1799,7 +1799,7 @@ static int rs_move_mimo2_to_other(struct iwl_priv *priv,
tbl->action = IWL_MIMO2_SWITCH_SISO_A;
break;
default:
- IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load);
break;
}
@@ -1969,7 +1969,7 @@ static int rs_move_mimo3_to_other(struct iwl_priv *priv,
tbl->action = IWL_MIMO3_SWITCH_SISO_A;
break;
default:
- IWL_ERR(priv, "Invalid BT load %d", priv->bt_traffic_load);
+ IWL_ERR(priv, "Invalid BT load %d\n", priv->bt_traffic_load);
break;
}
@@ -2709,7 +2709,7 @@ static void rs_initialize_lq(struct iwl_priv *priv,
rs_set_expected_tpt_table(lq_sta, tbl);
rs_fill_link_cmd(NULL, lq_sta, rate);
priv->stations[lq_sta->lq.sta_id].lq = &lq_sta->lq;
- iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, CMD_SYNC, true);
+ iwl_send_lq_cmd(priv, ctx, &lq_sta->lq, 0, true);
}
static void rs_get_rate(void *priv_r, struct ieee80211_sta *sta, void *priv_sta,
diff --git a/drivers/net/wireless/iwlwifi/dvm/rx.c b/drivers/net/wireless/iwlwifi/dvm/rx.c
index cd8377346af..debec963c61 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rx.c
@@ -786,7 +786,7 @@ static void iwlagn_pass_packet_to_mac80211(struct iwl_priv *priv,
memcpy(IEEE80211_SKB_RXCB(skb), stats, sizeof(*stats));
- ieee80211_rx_ni(priv->hw, skb);
+ ieee80211_rx(priv->hw, skb);
}
static u32 iwlagn_translate_rx_status(struct iwl_priv *priv, u32 decrypt_in)
diff --git a/drivers/net/wireless/iwlwifi/dvm/rxon.c b/drivers/net/wireless/iwlwifi/dvm/rxon.c
index 503a81e5818..6dc5dd3ced4 100644
--- a/drivers/net/wireless/iwlwifi/dvm/rxon.c
+++ b/drivers/net/wireless/iwlwifi/dvm/rxon.c
@@ -104,7 +104,7 @@ static int iwlagn_disable_bss(struct iwl_priv *priv,
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
- CMD_SYNC, sizeof(*send), send);
+ 0, sizeof(*send), send);
send->filter_flags = old_filter;
@@ -134,7 +134,7 @@ static int iwlagn_disable_pan(struct iwl_priv *priv,
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
send->dev_type = RXON_DEV_TYPE_P2P;
ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd,
- CMD_SYNC, sizeof(*send), send);
+ 0, sizeof(*send), send);
send->filter_flags = old_filter;
send->dev_type = old_dev_type;
@@ -160,7 +160,7 @@ static int iwlagn_disconn_pan(struct iwl_priv *priv,
int ret;
send->filter_flags &= ~RXON_FILTER_ASSOC_MSK;
- ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, 0,
sizeof(*send), send);
send->filter_flags = old_filter;
@@ -189,7 +189,7 @@ static void iwlagn_update_qos(struct iwl_priv *priv,
ctx->qos_data.qos_active,
ctx->qos_data.def_qos_parm.qos_flags);
- ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->qos_cmd, 0,
sizeof(struct iwl_qosparam_cmd),
&ctx->qos_data.def_qos_parm);
if (ret)
@@ -353,7 +353,7 @@ static int iwl_send_rxon_timing(struct iwl_priv *priv,
le16_to_cpu(ctx->timing.atim_window));
return iwl_dvm_send_cmd_pdu(priv, ctx->rxon_timing_cmd,
- CMD_SYNC, sizeof(ctx->timing), &ctx->timing);
+ 0, sizeof(ctx->timing), &ctx->timing);
}
static int iwlagn_rxon_disconn(struct iwl_priv *priv,
@@ -495,7 +495,7 @@ static int iwlagn_rxon_connect(struct iwl_priv *priv,
* Associated RXON doesn't clear the station table in uCode,
* so we don't need to restore stations etc. after this.
*/
- ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, ctx->rxon_cmd, 0,
sizeof(struct iwl_rxon_cmd), &ctx->staging);
if (ret) {
IWL_ERR(priv, "Error setting new RXON (%d)\n", ret);
@@ -610,7 +610,7 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
cmd.slots[0].width = cpu_to_le16(slot0);
cmd.slots[1].width = cpu_to_le16(slot1);
- ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, CMD_SYNC,
+ ret = iwl_dvm_send_cmd_pdu(priv, REPLY_WIPAN_PARAMS, 0,
sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv, "Error setting PAN parameters (%d)\n", ret);
@@ -823,7 +823,7 @@ static int iwl_check_rxon_cmd(struct iwl_priv *priv,
if ((rxon->flags & (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK))
== (RXON_FLG_CCK_MSK | RXON_FLG_AUTO_DETECT_MSK)) {
- IWL_WARN(priv, "CCK and auto detect");
+ IWL_WARN(priv, "CCK and auto detect\n");
errors |= BIT(8);
}
@@ -1068,13 +1068,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
/* recalculate basic rates */
iwl_calc_basic_rates(priv, ctx);
- /*
- * force CTS-to-self frames protection if RTS-CTS is not preferred
- * one aggregation protection method
- */
- if (!priv->hw_params.use_rts_for_aggregation)
- ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
-
if ((ctx->vif && ctx->vif->bss_conf.use_short_slot) ||
!(ctx->staging.flags & RXON_FLG_BAND_24G_MSK))
ctx->staging.flags |= RXON_FLG_SHORT_SLOT_MSK;
@@ -1395,7 +1388,7 @@ static void iwlagn_chain_noise_reset(struct iwl_priv *priv)
priv->phy_calib_chain_noise_reset_cmd);
ret = iwl_dvm_send_cmd_pdu(priv,
REPLY_PHY_CALIBRATION_CMD,
- CMD_SYNC, sizeof(cmd), &cmd);
+ 0, sizeof(cmd), &cmd);
if (ret)
IWL_ERR(priv,
"Could not send REPLY_PHY_CALIBRATION_CMD\n");
@@ -1480,11 +1473,6 @@ void iwlagn_bss_info_changed(struct ieee80211_hw *hw,
else
ctx->staging.flags &= ~RXON_FLG_TGG_PROTECT_MSK;
- if (bss_conf->use_cts_prot)
- ctx->staging.flags |= RXON_FLG_SELF_CTS_EN;
- else
- ctx->staging.flags &= ~RXON_FLG_SELF_CTS_EN;
-
memcpy(ctx->staging.bssid_addr, bss_conf->bssid, ETH_ALEN);
if (vif->type == NL80211_IFTYPE_AP ||
diff --git a/drivers/net/wireless/iwlwifi/dvm/scan.c b/drivers/net/wireless/iwlwifi/dvm/scan.c
index be98b913ed5..43bef901e8f 100644
--- a/drivers/net/wireless/iwlwifi/dvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/dvm/scan.c
@@ -59,7 +59,7 @@ static int iwl_send_scan_abort(struct iwl_priv *priv)
int ret;
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_ABORT_CMD,
- .flags = CMD_SYNC | CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
__le32 *status;
@@ -639,7 +639,6 @@ static int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
struct iwl_host_cmd cmd = {
.id = REPLY_SCAN_CMD,
.len = { sizeof(struct iwl_scan_cmd), },
- .flags = CMD_SYNC,
};
struct iwl_scan_cmd *scan;
struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_BSS];
diff --git a/drivers/net/wireless/iwlwifi/dvm/sta.c b/drivers/net/wireless/iwlwifi/dvm/sta.c
index 9cdd91cdf66..6ec86adbe4a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/dvm/sta.c
@@ -39,7 +39,7 @@ static int iwl_sta_ucode_activate(struct iwl_priv *priv, u8 sta_id)
lockdep_assert_held(&priv->sta_lock);
if (sta_id >= IWLAGN_STATION_COUNT) {
- IWL_ERR(priv, "invalid sta_id %u", sta_id);
+ IWL_ERR(priv, "invalid sta_id %u\n", sta_id);
return -EINVAL;
}
if (!(priv->stations[sta_id].used & IWL_STA_DRIVER_ACTIVE))
@@ -165,7 +165,7 @@ int iwl_send_add_sta(struct iwl_priv *priv,
iwl_free_resp(&cmd);
if (cmd.handler_status)
- IWL_ERR(priv, "%s - error in the CMD response %d", __func__,
+ IWL_ERR(priv, "%s - error in the CMD response %d\n", __func__,
cmd.handler_status);
return cmd.handler_status;
@@ -261,7 +261,7 @@ int iwl_sta_update_ht(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
cmd.station_flags = flags;
cmd.sta.sta_id = sta_id;
- return iwl_send_add_sta(priv, &cmd, CMD_SYNC);
+ return iwl_send_add_sta(priv, &cmd, 0);
}
static void iwl_set_ht_add_station(struct iwl_priv *priv, u8 index,
@@ -413,7 +413,7 @@ int iwl_add_station_common(struct iwl_priv *priv, struct iwl_rxon_context *ctx,
spin_unlock_bh(&priv->sta_lock);
/* Add station to device's station table */
- ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ ret = iwl_send_add_sta(priv, &sta_cmd, 0);
if (ret) {
spin_lock_bh(&priv->sta_lock);
IWL_ERR(priv, "Adding station %pM failed.\n",
@@ -456,7 +456,6 @@ static int iwl_send_remove_station(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = REPLY_REMOVE_STA,
.len = { sizeof(struct iwl_rem_sta_cmd), },
- .flags = CMD_SYNC,
.data = { &rm_sta_cmd, },
};
@@ -740,7 +739,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
send_lq = true;
}
spin_unlock_bh(&priv->sta_lock);
- ret = iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ ret = iwl_send_add_sta(priv, &sta_cmd, 0);
if (ret) {
spin_lock_bh(&priv->sta_lock);
IWL_ERR(priv, "Adding station %pM failed.\n",
@@ -756,8 +755,7 @@ void iwl_restore_stations(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
* current LQ command
*/
if (send_lq)
- iwl_send_lq_cmd(priv, ctx, &lq,
- CMD_SYNC, true);
+ iwl_send_lq_cmd(priv, ctx, &lq, 0, true);
spin_lock_bh(&priv->sta_lock);
priv->stations[i].used &= ~IWL_STA_UCODE_INPROGRESS;
}
@@ -968,7 +966,7 @@ int iwlagn_add_bssid_station(struct iwl_priv *priv,
return -ENOMEM;
}
- ret = iwl_send_lq_cmd(priv, ctx, link_cmd, CMD_SYNC, true);
+ ret = iwl_send_lq_cmd(priv, ctx, link_cmd, 0, true);
if (ret)
IWL_ERR(priv, "Link quality command failed (%d)\n", ret);
@@ -999,7 +997,6 @@ static int iwl_send_static_wepkey_cmd(struct iwl_priv *priv,
struct iwl_host_cmd cmd = {
.id = ctx->wep_key_cmd,
.data = { wep_cmd, },
- .flags = CMD_SYNC,
};
might_sleep();
@@ -1248,7 +1245,7 @@ int iwl_remove_dynamic_key(struct iwl_priv *priv,
sta_cmd.sta.modify_mask = STA_MODIFY_KEY_MASK;
sta_cmd.mode = STA_CONTROL_MODIFY_MSK;
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ return iwl_send_add_sta(priv, &sta_cmd, 0);
}
int iwl_set_dynamic_key(struct iwl_priv *priv,
@@ -1284,13 +1281,13 @@ int iwl_set_dynamic_key(struct iwl_priv *priv,
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
- seq.tkip.iv32, p1k, CMD_SYNC);
+ seq.tkip.iv32, p1k, 0);
break;
case WLAN_CIPHER_SUITE_CCMP:
case WLAN_CIPHER_SUITE_WEP40:
case WLAN_CIPHER_SUITE_WEP104:
ret = iwlagn_send_sta_key(priv, keyconf, sta_id,
- 0, NULL, CMD_SYNC);
+ 0, NULL, 0);
break;
default:
IWL_ERR(priv, "Unknown cipher %x\n", keyconf->cipher);
@@ -1409,7 +1406,7 @@ int iwl_sta_tx_modify_enable_tid(struct iwl_priv *priv, int sta_id, int tid)
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_bh(&priv->sta_lock);
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ return iwl_send_add_sta(priv, &sta_cmd, 0);
}
int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
@@ -1433,7 +1430,7 @@ int iwl_sta_rx_agg_start(struct iwl_priv *priv, struct ieee80211_sta *sta,
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_bh(&priv->sta_lock);
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ return iwl_send_add_sta(priv, &sta_cmd, 0);
}
int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
@@ -1458,7 +1455,7 @@ int iwl_sta_rx_agg_stop(struct iwl_priv *priv, struct ieee80211_sta *sta,
memcpy(&sta_cmd, &priv->stations[sta_id].sta, sizeof(struct iwl_addsta_cmd));
spin_unlock_bh(&priv->sta_lock);
- return iwl_send_add_sta(priv, &sta_cmd, CMD_SYNC);
+ return iwl_send_add_sta(priv, &sta_cmd, 0);
}
diff --git a/drivers/net/wireless/iwlwifi/dvm/tt.c b/drivers/net/wireless/iwlwifi/dvm/tt.c
index 058c5892c42..acb981a0a0a 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tt.c
@@ -236,7 +236,7 @@ static void iwl_prepare_ct_kill_task(struct iwl_priv *priv)
{
IWL_DEBUG_TEMP(priv, "Prepare to enter IWL_TI_CT_KILL\n");
/* make request to retrieve statistics information */
- iwl_send_statistics_request(priv, CMD_SYNC, false);
+ iwl_send_statistics_request(priv, 0, false);
/* Reschedule the ct_kill wait timer */
mod_timer(&priv->thermal_throttle.ct_kill_waiting_tm,
jiffies + msecs_to_jiffies(CT_KILL_WAITING_DURATION));
diff --git a/drivers/net/wireless/iwlwifi/dvm/tx.c b/drivers/net/wireless/iwlwifi/dvm/tx.c
index 398dd096674..3255a1723d1 100644
--- a/drivers/net/wireless/iwlwifi/dvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/dvm/tx.c
@@ -402,10 +402,10 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
/* aggregation is on for this <sta,tid> */
if (info->flags & IEEE80211_TX_CTL_AMPDU &&
tid_data->agg.state != IWL_AGG_ON) {
- IWL_ERR(priv, "TX_CTL_AMPDU while not in AGG:"
- " Tx flags = 0x%08x, agg.state = %d",
+ IWL_ERR(priv,
+ "TX_CTL_AMPDU while not in AGG: Tx flags = 0x%08x, agg.state = %d\n",
info->flags, tid_data->agg.state);
- IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d",
+ IWL_ERR(priv, "sta_id = %d, tid = %d seq_num = %d\n",
sta_id, tid,
IEEE80211_SEQ_TO_SN(tid_data->seq_number));
goto drop_unlock_sta;
@@ -416,7 +416,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv,
*/
if (WARN_ONCE(tid_data->agg.state != IWL_AGG_ON &&
tid_data->agg.state != IWL_AGG_OFF,
- "Tx while agg.state = %d", tid_data->agg.state))
+ "Tx while agg.state = %d\n", tid_data->agg.state))
goto drop_unlock_sta;
seq_number = tid_data->seq_number;
@@ -778,8 +778,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
/* There are no packets for this RA / TID in the HW any more */
if (tid_data->agg.ssn == tid_data->next_reclaimed) {
IWL_DEBUG_TX_QUEUES(priv,
- "Can continue DELBA flow ssn = next_recl ="
- " %d", tid_data->next_reclaimed);
+ "Can continue DELBA flow ssn = next_recl = %d\n",
+ tid_data->next_reclaimed);
iwl_trans_txq_disable(priv->trans,
tid_data->agg.txq_id);
iwlagn_dealloc_agg_txq(priv, tid_data->agg.txq_id);
@@ -791,8 +791,8 @@ static void iwlagn_check_ratid_empty(struct iwl_priv *priv, int sta_id, u8 tid)
/* There are no packets for this RA / TID in the HW any more */
if (tid_data->agg.ssn == tid_data->next_reclaimed) {
IWL_DEBUG_TX_QUEUES(priv,
- "Can continue ADDBA flow ssn = next_recl ="
- " %d", tid_data->next_reclaimed);
+ "Can continue ADDBA flow ssn = next_recl = %d\n",
+ tid_data->next_reclaimed);
tid_data->agg.state = IWL_AGG_STARTING;
ieee80211_start_tx_ba_cb_irqsafe(vif, addr, tid);
}
@@ -1216,8 +1216,8 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
ctx->vif->type == NL80211_IFTYPE_STATION) {
/* block and stop all queues */
priv->passive_no_rx = true;
- IWL_DEBUG_TX_QUEUES(priv, "stop all queues: "
- "passive channel");
+ IWL_DEBUG_TX_QUEUES(priv,
+ "stop all queues: passive channel\n");
ieee80211_stop_queues(priv->hw);
IWL_DEBUG_TX_REPLY(priv,
@@ -1271,7 +1271,7 @@ int iwlagn_rx_reply_tx(struct iwl_priv *priv, struct iwl_rx_cmd_buffer *rxb,
while (!skb_queue_empty(&skbs)) {
skb = __skb_dequeue(&skbs);
- ieee80211_tx_status_ni(priv->hw, skb);
+ ieee80211_tx_status(priv->hw, skb);
}
return 0;
@@ -1411,7 +1411,7 @@ int iwlagn_rx_reply_compressed_ba(struct iwl_priv *priv,
while (!skb_queue_empty(&reclaimed_skbs)) {
skb = __skb_dequeue(&reclaimed_skbs);
- ieee80211_tx_status_ni(priv->hw, skb);
+ ieee80211_tx_status(priv->hw, skb);
}
return 0;
diff --git a/drivers/net/wireless/iwlwifi/dvm/ucode.c b/drivers/net/wireless/iwlwifi/dvm/ucode.c
index cf03ef5619d..d5cee153059 100644
--- a/drivers/net/wireless/iwlwifi/dvm/ucode.c
+++ b/drivers/net/wireless/iwlwifi/dvm/ucode.c
@@ -172,7 +172,7 @@ static int iwl_send_wimax_coex(struct iwl_priv *priv)
memset(&coex_cmd, 0, sizeof(coex_cmd));
return iwl_dvm_send_cmd_pdu(priv,
- COEX_PRIORITY_TABLE_CMD, CMD_SYNC,
+ COEX_PRIORITY_TABLE_CMD, 0,
sizeof(coex_cmd), &coex_cmd);
}
@@ -205,7 +205,7 @@ void iwl_send_prio_tbl(struct iwl_priv *priv)
memcpy(prio_tbl_cmd.prio_tbl, iwl_bt_prio_tbl,
sizeof(iwl_bt_prio_tbl));
if (iwl_dvm_send_cmd_pdu(priv,
- REPLY_BT_COEX_PRIO_TABLE, CMD_SYNC,
+ REPLY_BT_COEX_PRIO_TABLE, 0,
sizeof(prio_tbl_cmd), &prio_tbl_cmd))
IWL_ERR(priv, "failed to send BT prio tbl command\n");
}
@@ -218,7 +218,7 @@ int iwl_send_bt_env(struct iwl_priv *priv, u8 action, u8 type)
env_cmd.action = action;
env_cmd.type = type;
ret = iwl_dvm_send_cmd_pdu(priv,
- REPLY_BT_COEX_PROT_ENV, CMD_SYNC,
+ REPLY_BT_COEX_PROT_ENV, 0,
sizeof(env_cmd), &env_cmd);
if (ret)
IWL_ERR(priv, "failed to send BT env command\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c
index f73de239cdc..48730064da7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-7000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-7000.c
@@ -98,7 +98,7 @@
#define NVM_HW_SECTION_NUM_FAMILY_7000 0
static const struct iwl_base_params iwl7000_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_7000,
.num_of_queues = IWLAGN_NUM_QUEUES,
.pll_cfg_val = 0,
.shadow_ram_support = true,
diff --git a/drivers/net/wireless/iwlwifi/iwl-8000.c b/drivers/net/wireless/iwlwifi/iwl-8000.c
index f5bd82b8859..51c41531d81 100644
--- a/drivers/net/wireless/iwlwifi/iwl-8000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-8000.c
@@ -83,9 +83,10 @@
#define IWL8000_MODULE_FIRMWARE(api) IWL8000_FW_PRE __stringify(api) ".ucode"
#define NVM_HW_SECTION_NUM_FAMILY_8000 10
+#define DEFAULT_NVM_FILE_FAMILY_8000 "iwl_nvm_8000.bin"
static const struct iwl_base_params iwl8000_base_params = {
- .eeprom_size = OTP_LOW_IMAGE_SIZE,
+ .eeprom_size = OTP_LOW_IMAGE_SIZE_FAMILY_8000,
.num_of_queues = IWLAGN_NUM_QUEUES,
.pll_cfg_val = 0,
.shadow_ram_support = true,
@@ -118,6 +119,7 @@ const struct iwl_cfg iwl8260_2ac_cfg = {
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
+ .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
};
const struct iwl_cfg iwl8260_n_cfg = {
@@ -127,6 +129,7 @@ const struct iwl_cfg iwl8260_n_cfg = {
.ht_params = &iwl8000_ht_params,
.nvm_ver = IWL8000_NVM_VERSION,
.nvm_calib_ver = IWL8000_TX_POWER_VERSION,
+ .default_nvm_file = DEFAULT_NVM_FILE_FAMILY_8000,
};
MODULE_FIRMWARE(IWL8000_MODULE_FIRMWARE(IWL8000_UCODE_API_OK));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index 7f37fb86837..04a483d3865 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -102,9 +102,7 @@
/* EEPROM */
#define IWLAGN_EEPROM_IMG_SIZE 2048
-/* OTP */
-/* lower blocks contain EEPROM image and calibration data */
-#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
+
/* high blocks contain PAPD data */
#define OTP_HIGH_IMAGE_SIZE_6x00 (6 * 512 * sizeof(u16)) /* 6 KB */
#define OTP_HIGH_IMAGE_SIZE_1000 (0x200 * sizeof(u16)) /* 1024 bytes */
diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h
index 7ce82d9c722..b7047905f41 100644
--- a/drivers/net/wireless/iwlwifi/iwl-config.h
+++ b/drivers/net/wireless/iwlwifi/iwl-config.h
@@ -193,6 +193,11 @@ struct iwl_ht_params {
#define EEPROM_6000_REG_BAND_24_HT40_CHANNELS 0x80
#define EEPROM_REGULATORY_BAND_NO_HT40 0
+/* lower blocks contain EEPROM image and calibration data */
+#define OTP_LOW_IMAGE_SIZE (2 * 512 * sizeof(u16)) /* 2 KB */
+#define OTP_LOW_IMAGE_SIZE_FAMILY_7000 (16 * 512 * sizeof(u16)) /* 16 KB */
+#define OTP_LOW_IMAGE_SIZE_FAMILY_8000 (32 * 512 * sizeof(u16)) /* 32 KB */
+
struct iwl_eeprom_params {
const u8 regulatory_bands[7];
bool enhanced_txpower;
@@ -269,6 +274,8 @@ struct iwl_cfg {
u8 nvm_hw_section_num;
bool lp_xtal_workaround;
const struct iwl_pwr_tx_backoff *pwr_tx_backoffs;
+ bool no_power_up_nic_in_init;
+ const char *default_nvm_file;
};
/*
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.c b/drivers/net/wireless/iwlwifi/iwl-debug.c
index 8a44f594528..09feff4fa22 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.c
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.c
@@ -61,8 +61,6 @@
*
*****************************************************************************/
-#define DEBUG
-
#include <linux/device.h>
#include <linux/interrupt.h>
#include <linux/export.h>
@@ -128,8 +126,8 @@ void __iwl_dbg(struct device *dev,
#ifdef CONFIG_IWLWIFI_DEBUG
if (iwl_have_debug_level(level) &&
(!limit || net_ratelimit()))
- dev_dbg(dev, "%c %s %pV", in_interrupt() ? 'I' : 'U',
- function, &vaf);
+ dev_printk(KERN_DEBUG, dev, "%c %s %pV",
+ in_interrupt() ? 'I' : 'U', function, &vaf);
#endif
trace_iwlwifi_dbg(level, in_interrupt(), function, &vaf);
va_end(args);
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h
index c8cbdbe1592..295083510e7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-debug.h
+++ b/drivers/net/wireless/iwlwifi/iwl-debug.h
@@ -47,12 +47,32 @@ void __iwl_warn(struct device *dev, const char *fmt, ...) __printf(2, 3);
void __iwl_info(struct device *dev, const char *fmt, ...) __printf(2, 3);
void __iwl_crit(struct device *dev, const char *fmt, ...) __printf(2, 3);
+/* not all compilers can evaluate strlen() at compile time, so use sizeof() */
+#define CHECK_FOR_NEWLINE(f) BUILD_BUG_ON(f[sizeof(f) - 2] != '\n')
+
/* No matter what is m (priv, bus, trans), this will work */
-#define IWL_ERR(m, f, a...) __iwl_err((m)->dev, false, false, f, ## a)
-#define IWL_ERR_DEV(d, f, a...) __iwl_err((d), false, false, f, ## a)
-#define IWL_WARN(m, f, a...) __iwl_warn((m)->dev, f, ## a)
-#define IWL_INFO(m, f, a...) __iwl_info((m)->dev, f, ## a)
-#define IWL_CRIT(m, f, a...) __iwl_crit((m)->dev, f, ## a)
+#define IWL_ERR_DEV(d, f, a...) \
+ do { \
+ CHECK_FOR_NEWLINE(f); \
+ __iwl_err((d), false, false, f, ## a); \
+ } while (0)
+#define IWL_ERR(m, f, a...) \
+ IWL_ERR_DEV((m)->dev, f, ## a)
+#define IWL_WARN(m, f, a...) \
+ do { \
+ CHECK_FOR_NEWLINE(f); \
+ __iwl_warn((m)->dev, f, ## a); \
+ } while (0)
+#define IWL_INFO(m, f, a...) \
+ do { \
+ CHECK_FOR_NEWLINE(f); \
+ __iwl_info((m)->dev, f, ## a); \
+ } while (0)
+#define IWL_CRIT(m, f, a...) \
+ do { \
+ CHECK_FOR_NEWLINE(f); \
+ __iwl_crit((m)->dev, f, ## a); \
+ } while (0)
#if defined(CONFIG_IWLWIFI_DEBUG) || defined(CONFIG_IWLWIFI_DEVICE_TRACING)
void __iwl_dbg(struct device *dev,
@@ -72,12 +92,17 @@ do { \
DUMP_PREFIX_OFFSET, 16, 1, p, len, 1); \
} while (0)
+#define __IWL_DEBUG_DEV(dev, level, limit, fmt, args...) \
+ do { \
+ CHECK_FOR_NEWLINE(fmt); \
+ __iwl_dbg(dev, level, limit, __func__, fmt, ##args); \
+ } while (0)
#define IWL_DEBUG(m, level, fmt, args...) \
- __iwl_dbg((m)->dev, level, false, __func__, fmt, ##args)
+ __IWL_DEBUG_DEV((m)->dev, level, false, fmt, ##args)
#define IWL_DEBUG_DEV(dev, level, fmt, args...) \
- __iwl_dbg((dev), level, false, __func__, fmt, ##args)
+ __IWL_DEBUG_DEV(dev, level, false, fmt, ##args)
#define IWL_DEBUG_LIMIT(m, level, fmt, args...) \
- __iwl_dbg((m)->dev, level, true, __func__, fmt, ##args)
+ __IWL_DEBUG_DEV((m)->dev, level, true, fmt, ##args)
#ifdef CONFIG_IWLWIFI_DEBUG
#define iwl_print_hex_dump(m, level, p, len) \
diff --git a/drivers/net/wireless/iwlwifi/iwl-drv.c b/drivers/net/wireless/iwlwifi/iwl-drv.c
index 0a3e841b44a..f2a5c12269a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-drv.c
+++ b/drivers/net/wireless/iwlwifi/iwl-drv.c
@@ -1243,6 +1243,7 @@ struct iwl_mod_params iwlwifi_mod_params = {
.bt_coex_active = true,
.power_level = IWL_POWER_INDEX_1,
.wd_disable = true,
+ .uapsd_disable = false,
/* the rest are 0 by default */
};
IWL_EXPORT_SYMBOL(iwlwifi_mod_params);
@@ -1356,6 +1357,10 @@ MODULE_PARM_DESC(wd_disable,
module_param_named(nvm_file, iwlwifi_mod_params.nvm_file, charp, S_IRUGO);
MODULE_PARM_DESC(nvm_file, "NVM file name");
+module_param_named(uapsd_disable, iwlwifi_mod_params.uapsd_disable,
+ bool, S_IRUGO);
+MODULE_PARM_DESC(uapsd_disable, "disable U-APSD functionality (default: N)");
+
/*
* set bt_coex_active to true, uCode will do kill/defer
* every time the priority line is asserted (BT is sending signals on the
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
index f381908be7e..2953ffceda3 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-error-dump.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw-error-dump.h
@@ -72,11 +72,14 @@
* @IWL_FW_ERROR_DUMP_SRAM:
* @IWL_FW_ERROR_DUMP_REG:
* @IWL_FW_ERROR_DUMP_RXF:
+ * @IWL_FW_ERROR_DUMP_TXCMD: last TX command data, structured as
+ * &struct iwl_fw_error_dump_txcmd packets
*/
enum iwl_fw_error_dump_type {
IWL_FW_ERROR_DUMP_SRAM = 0,
IWL_FW_ERROR_DUMP_REG = 1,
IWL_FW_ERROR_DUMP_RXF = 2,
+ IWL_FW_ERROR_DUMP_TXCMD = 3,
IWL_FW_ERROR_DUMP_MAX,
};
@@ -105,4 +108,27 @@ struct iwl_fw_error_dump_file {
u8 data[0];
} __packed;
+/**
+ * struct iwl_fw_error_dump_txcmd - TX command data
+ * @cmdlen: original length of command
+ * @caplen: captured length of command (may be less)
+ * @data: captured command data, @caplen bytes
+ */
+struct iwl_fw_error_dump_txcmd {
+ __le32 cmdlen;
+ __le32 caplen;
+ u8 data[];
+} __packed;
+
+/**
+ * iwl_mvm_fw_error_next_data - advance fw error dump data pointer
+ * @data: previous data block
+ * Returns: next data block
+ */
+static inline struct iwl_fw_error_dump_data *
+iwl_mvm_fw_error_next_data(struct iwl_fw_error_dump_data *data)
+{
+ return (void *)(data->data + le32_to_cpu(data->len));
+}
+
#endif /* __fw_error_dump_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-fw.h b/drivers/net/wireless/iwlwifi/iwl-fw.h
index f5927d0cf9b..b1a33322b9b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-fw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-fw.h
@@ -74,7 +74,7 @@
* @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
* @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
* @IWL_UCODE_TLV_FLAGS_DW_BC_TABLE: The SCD byte count table is in DWORDS
- * @IWL_UCODE_TLV_FLAGS_UAPSD: This uCode image supports uAPSD
+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: This uCode image supports uAPSD
* @IWL_UCODE_TLV_FLAGS_SHORT_BL: 16 entries of black list instead of 64 in scan
* offload profile config command.
* @IWL_UCODE_TLV_FLAGS_D3_6_IPV6_ADDRS: D3 image supports up to six
@@ -88,6 +88,7 @@
* P2P client interfaces simultaneously if they are in different bindings.
* @IWL_UCODE_TLV_FLAGS_P2P_BSS_PS_SCM: support power save on BSS station and
* P2P client interfaces simultaneously if they are in same bindings.
+ * @IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT: General support for uAPSD
* @IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD: P2P client supports uAPSD power save
* @IWL_UCODE_TLV_FLAGS_BCAST_FILTERING: uCode supports broadcast filtering.
* @IWL_UCODE_TLV_FLAGS_GO_UAPSD: AP/GO interfaces support uAPSD clients
@@ -107,6 +108,7 @@ enum iwl_ucode_tlv_flag {
IWL_UCODE_TLV_FLAGS_P2P_PM = BIT(21),
IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM = BIT(22),
IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_SCM = BIT(23),
+ IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT = BIT(24),
IWL_UCODE_TLV_FLAGS_EBS_SUPPORT = BIT(25),
IWL_UCODE_TLV_FLAGS_P2P_PS_UAPSD = BIT(26),
IWL_UCODE_TLV_FLAGS_BCAST_FILTERING = BIT(29),
@@ -116,9 +118,11 @@ enum iwl_ucode_tlv_flag {
/**
* enum iwl_ucode_tlv_api - ucode api
* @IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID: wowlan config includes tid field.
+ * @IWL_UCODE_TLV_API_CSA_FLOW: ucode can do unbind-bind flow for CSA.
*/
enum iwl_ucode_tlv_api {
IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID = BIT(0),
+ IWL_UCODE_TLV_API_CSA_FLOW = BIT(4),
};
/**
@@ -194,6 +198,11 @@ struct fw_img {
bool is_dual_cpus;
};
+struct iwl_sf_region {
+ u32 addr;
+ u32 size;
+};
+
/* uCode version contains 4 values: Major/Minor/API/Serial */
#define IWL_UCODE_MAJOR(ver) (((ver) & 0xFF000000) >> 24)
#define IWL_UCODE_MINOR(ver) (((ver) & 0x00FF0000) >> 16)
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.c b/drivers/net/wireless/iwlwifi/iwl-io.c
index 44cc3cf4576..5eef4ae7333 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.c
+++ b/drivers/net/wireless/iwlwifi/iwl-io.c
@@ -33,6 +33,7 @@
#include "iwl-io.h"
#include "iwl-csr.h"
#include "iwl-debug.h"
+#include "iwl-prph.h"
#include "iwl-fh.h"
#define IWL_POLL_INTERVAL 10 /* microseconds */
@@ -183,6 +184,23 @@ void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask)
}
IWL_EXPORT_SYMBOL(iwl_clear_bits_prph);
+void iwl_force_nmi(struct iwl_trans *trans)
+{
+ /*
+ * In HW previous to the 8000 HW family, and in the 8000 HW family
+ * itself when the revision step==0, the DEVICE_SET_NMI_REG is used
+ * to force an NMI. Otherwise, a different register -
+ * DEVICE_SET_NMI_8000B_REG - is used.
+ */
+ if ((trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) ||
+ ((trans->hw_rev & 0xc) == 0x0))
+ iwl_write_prph(trans, DEVICE_SET_NMI_REG, DEVICE_SET_NMI_VAL);
+ else
+ iwl_write_prph(trans, DEVICE_SET_NMI_8000B_REG,
+ DEVICE_SET_NMI_8000B_VAL);
+}
+IWL_EXPORT_SYMBOL(iwl_force_nmi);
+
static const char *get_fh_string(int cmd)
{
#define IWL_CMD(x) case x: return #x
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h
index 665ddd9dbbc..705d12c079e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-io.h
+++ b/drivers/net/wireless/iwlwifi/iwl-io.h
@@ -80,6 +80,7 @@ void iwl_set_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
void iwl_set_bits_mask_prph(struct iwl_trans *trans, u32 ofs,
u32 bits, u32 mask);
void iwl_clear_bits_prph(struct iwl_trans *trans, u32 ofs, u32 mask);
+void iwl_force_nmi(struct iwl_trans *trans);
/* Error handling */
int iwl_dump_fh(struct iwl_trans *trans, char **buf);
diff --git a/drivers/net/wireless/iwlwifi/iwl-modparams.h b/drivers/net/wireless/iwlwifi/iwl-modparams.h
index d994317db85..d051857729a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-modparams.h
+++ b/drivers/net/wireless/iwlwifi/iwl-modparams.h
@@ -119,6 +119,7 @@ struct iwl_mod_params {
#endif
int ant_coupling;
char *nvm_file;
+ bool uapsd_disable;
};
#endif /* #__iwl_modparams_h__ */
diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
index 4049c0d626b..85eee79c495 100644
--- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
+++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c
@@ -62,6 +62,7 @@
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/export.h>
+#include <linux/etherdevice.h>
#include "iwl-drv.h"
#include "iwl-modparams.h"
#include "iwl-nvm-parse.h"
@@ -127,7 +128,7 @@ static const u8 iwl_nvm_channels[] = {
static const u8 iwl_nvm_channels_family_8000[] = {
/* 2.4 GHz */
- 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
/* 5 GHz */
36, 40, 44, 48, 52, 56, 60, 64, 68, 72, 76, 80, 84, 88, 92,
96, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 144,
@@ -137,7 +138,7 @@ static const u8 iwl_nvm_channels_family_8000[] = {
#define IWL_NUM_CHANNELS ARRAY_SIZE(iwl_nvm_channels)
#define IWL_NUM_CHANNELS_FAMILY_8000 ARRAY_SIZE(iwl_nvm_channels_family_8000)
#define NUM_2GHZ_CHANNELS 14
-#define NUM_2GHZ_CHANNELS_FAMILY_8000 13
+#define NUM_2GHZ_CHANNELS_FAMILY_8000 14
#define FIRST_2GHZ_HT_MINUS 5
#define LAST_2GHZ_HT_PLUS 9
#define LAST_5GHZ_HT 161
@@ -450,13 +451,7 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
struct iwl_nvm_data *data,
const __le16 *nvm_sec)
{
- u8 hw_addr[ETH_ALEN];
-
- if (cfg->device_family != IWL_DEVICE_FAMILY_8000)
- memcpy(hw_addr, nvm_sec + HW_ADDR, ETH_ALEN);
- else
- memcpy(hw_addr, nvm_sec + MAC_ADDRESS_OVERRIDE_FAMILY_8000,
- ETH_ALEN);
+ const u8 *hw_addr = (const u8 *)(nvm_sec + HW_ADDR);
/* The byte order is little endian 16 bit, meaning 214365 */
data->hw_addr[0] = hw_addr[1];
@@ -467,6 +462,41 @@ static void iwl_set_hw_address(const struct iwl_cfg *cfg,
data->hw_addr[5] = hw_addr[4];
}
+static void iwl_set_hw_address_family_8000(const struct iwl_cfg *cfg,
+ struct iwl_nvm_data *data,
+ const __le16 *mac_override,
+ const __le16 *nvm_hw)
+{
+ const u8 *hw_addr;
+
+ if (mac_override) {
+ hw_addr = (const u8 *)(mac_override +
+ MAC_ADDRESS_OVERRIDE_FAMILY_8000);
+
+ /* The byte order is little endian 16 bit, meaning 214365 */
+ data->hw_addr[0] = hw_addr[1];
+ data->hw_addr[1] = hw_addr[0];
+ data->hw_addr[2] = hw_addr[3];
+ data->hw_addr[3] = hw_addr[2];
+ data->hw_addr[4] = hw_addr[5];
+ data->hw_addr[5] = hw_addr[4];
+
+ if (is_valid_ether_addr(hw_addr))
+ return;
+ }
+
+ /* take the MAC address from the OTP */
+ hw_addr = (const u8 *)(nvm_hw + HW_ADDR0_FAMILY_8000);
+ data->hw_addr[0] = hw_addr[3];
+ data->hw_addr[1] = hw_addr[2];
+ data->hw_addr[2] = hw_addr[1];
+ data->hw_addr[3] = hw_addr[0];
+
+ hw_addr = (const u8 *)(nvm_hw + HW_ADDR1_FAMILY_8000);
+ data->hw_addr[4] = hw_addr[1];
+ data->hw_addr[5] = hw_addr[0];
+}
+
struct iwl_nvm_data *
iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
const __le16 *nvm_hw, const __le16 *nvm_sw,
@@ -526,7 +556,7 @@ iwl_parse_nvm_data(struct device *dev, const struct iwl_cfg *cfg,
rx_chains);
} else {
/* MAC address in family 8000 */
- iwl_set_hw_address(cfg, data, mac_override);
+ iwl_set_hw_address_family_8000(cfg, data, mac_override, nvm_hw);
iwl_init_sbands(dev, cfg, data, regulatory,
sku & NVM_SKU_CAP_11AC_ENABLE, tx_chains,
diff --git a/drivers/net/wireless/iwlwifi/iwl-phy-db.c b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
index b761ac4822a..d4fb5cad07e 100644
--- a/drivers/net/wireless/iwlwifi/iwl-phy-db.c
+++ b/drivers/net/wireless/iwlwifi/iwl-phy-db.c
@@ -345,7 +345,6 @@ static int iwl_send_phy_db_cmd(struct iwl_phy_db *phy_db, u16 type,
struct iwl_phy_db_cmd phy_db_cmd;
struct iwl_host_cmd cmd = {
.id = PHY_DB_CMD,
- .flags = CMD_SYNC,
};
IWL_DEBUG_INFO(phy_db->trans,
@@ -393,13 +392,13 @@ static int iwl_phy_db_send_all_channel_groups(
entry->data);
if (err) {
IWL_ERR(phy_db->trans,
- "Can't SEND phy_db section %d (%d), err %d",
+ "Can't SEND phy_db section %d (%d), err %d\n",
type, i, err);
return err;
}
IWL_DEBUG_INFO(phy_db->trans,
- "Sent PHY_DB HCMD, type = %d num = %d",
+ "Sent PHY_DB HCMD, type = %d num = %d\n",
type, i);
}
@@ -451,7 +450,7 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
IWL_NUM_PAPD_CH_GROUPS);
if (err) {
IWL_ERR(phy_db->trans,
- "Cannot send channel specific PAPD groups");
+ "Cannot send channel specific PAPD groups\n");
return err;
}
@@ -461,7 +460,7 @@ int iwl_send_phy_db_data(struct iwl_phy_db *phy_db)
IWL_NUM_TXP_CH_GROUPS);
if (err) {
IWL_ERR(phy_db->trans,
- "Cannot send channel specific TX power groups");
+ "Cannot send channel specific TX power groups\n");
return err;
}
diff --git a/drivers/net/wireless/iwlwifi/iwl-prph.h b/drivers/net/wireless/iwlwifi/iwl-prph.h
index 779311080a9..4997e27672b 100644
--- a/drivers/net/wireless/iwlwifi/iwl-prph.h
+++ b/drivers/net/wireless/iwlwifi/iwl-prph.h
@@ -105,6 +105,9 @@
/* Device NMI register */
#define DEVICE_SET_NMI_REG 0x00a01c30
+#define DEVICE_SET_NMI_VAL 0x1
+#define DEVICE_SET_NMI_8000B_REG 0x00a01c24
+#define DEVICE_SET_NMI_8000B_VAL 0x1000000
/* Shared registers (0x0..0x3ff, via target indirect or periphery */
#define SHR_BASE 0x00a10000
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.h b/drivers/net/wireless/iwlwifi/iwl-trans.h
index 22fd94ec804..34d49e171fb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.h
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.h
@@ -189,10 +189,9 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
/**
* enum CMD_MODE - how to send the host commands ?
*
- * @CMD_SYNC: The caller will be stalled until the fw responds to the command
* @CMD_ASYNC: Return right away and don't wait for the response
- * @CMD_WANT_SKB: valid only with CMD_SYNC. The caller needs the buffer of the
- * response. The caller needs to call iwl_free_resp when done.
+ * @CMD_WANT_SKB: Not valid with CMD_ASYNC. The caller needs the buffer of
+ * the response. The caller needs to call iwl_free_resp when done.
* @CMD_HIGH_PRIO: The command is high priority - it goes to the front of the
* command queue, but after other high priority commands. valid only
* with CMD_ASYNC.
@@ -202,7 +201,6 @@ static inline u32 iwl_rx_packet_payload_len(const struct iwl_rx_packet *pkt)
* (i.e. mark it as non-idle).
*/
enum CMD_MODE {
- CMD_SYNC = 0,
CMD_ASYNC = BIT(0),
CMD_WANT_SKB = BIT(1),
CMD_SEND_IN_RFKILL = BIT(2),
@@ -427,7 +425,7 @@ struct iwl_trans;
* @send_cmd:send a host command. Must return -ERFKILL if RFkill is asserted.
* If RFkill is asserted in the middle of a SYNC host command, it must
* return -ERFKILL straight away.
- * May sleep only if CMD_SYNC is set
+ * May sleep only if CMD_ASYNC is not set
* @tx: send an skb
* Must be atomic
* @reclaim: free packet until ssn. Returns a list of freed packets.
@@ -463,6 +461,11 @@ struct iwl_trans;
* @unref: release a reference previously taken with @ref. Note that
* initially the reference count is 1, making an initial @unref
* necessary to allow low power states.
+ * @dump_data: fill a data dump with debug data, maybe containing last
+ * TX'ed commands and similar. When called with a NULL buffer and
+ * zero buffer length, provide only the (estimated) required buffer
+ * length. Return the used buffer length.
+ * Note that the transport must fill in the proper file headers.
*/
struct iwl_trans_ops {
@@ -470,6 +473,8 @@ struct iwl_trans_ops {
void (*op_mode_leave)(struct iwl_trans *iwl_trans);
int (*start_fw)(struct iwl_trans *trans, const struct fw_img *fw,
bool run_in_rfkill);
+ int (*update_sf)(struct iwl_trans *trans,
+ struct iwl_sf_region *st_fwrd_space);
void (*fw_alive)(struct iwl_trans *trans, u32 scd_addr);
void (*stop_device)(struct iwl_trans *trans);
@@ -511,6 +516,10 @@ struct iwl_trans_ops {
u32 value);
void (*ref)(struct iwl_trans *trans);
void (*unref)(struct iwl_trans *trans);
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ u32 (*dump_data)(struct iwl_trans *trans, void *buf, u32 buflen);
+#endif
};
/**
@@ -629,6 +638,17 @@ static inline int iwl_trans_start_fw(struct iwl_trans *trans,
return trans->ops->start_fw(trans, fw, run_in_rfkill);
}
+static inline int iwl_trans_update_sf(struct iwl_trans *trans,
+ struct iwl_sf_region *st_fwrd_space)
+{
+ might_sleep();
+
+ if (trans->ops->update_sf)
+ return trans->ops->update_sf(trans, st_fwrd_space);
+
+ return 0;
+}
+
static inline void iwl_trans_stop_device(struct iwl_trans *trans)
{
might_sleep();
@@ -664,6 +684,16 @@ static inline void iwl_trans_unref(struct iwl_trans *trans)
trans->ops->unref(trans);
}
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+static inline u32 iwl_trans_dump_data(struct iwl_trans *trans,
+ void *buf, u32 buflen)
+{
+ if (!trans->ops->dump_data)
+ return 0;
+ return trans->ops->dump_data(trans, buf, buflen);
+}
+#endif
+
static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
struct iwl_host_cmd *cmd)
{
@@ -677,7 +707,7 @@ static inline int iwl_trans_send_cmd(struct iwl_trans *trans,
return -EIO;
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE)) {
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return -EIO;
}
@@ -719,7 +749,7 @@ static inline int iwl_trans_tx(struct iwl_trans *trans, struct sk_buff *skb,
return -EIO;
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return trans->ops->tx(trans, skb, dev_cmd, queue);
}
@@ -728,7 +758,7 @@ static inline void iwl_trans_reclaim(struct iwl_trans *trans, int queue,
int ssn, struct sk_buff_head *skbs)
{
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
trans->ops->reclaim(trans, queue, ssn, skbs);
}
@@ -745,7 +775,7 @@ static inline void iwl_trans_txq_enable(struct iwl_trans *trans, int queue,
might_sleep();
if (unlikely((trans->state != IWL_TRANS_FW_ALIVE)))
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
trans->ops->txq_enable(trans, queue, fifo, sta_id, tid,
frame_limit, ssn);
@@ -762,7 +792,7 @@ static inline int iwl_trans_wait_tx_queue_empty(struct iwl_trans *trans,
u32 txq_bm)
{
if (unlikely(trans->state != IWL_TRANS_FW_ALIVE))
- IWL_ERR(trans, "%s bad state = %d", __func__, trans->state);
+ IWL_ERR(trans, "%s bad state = %d\n", __func__, trans->state);
return trans->ops->wait_tx_queue_empty(trans, txq_bm);
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/Makefile b/drivers/net/wireless/iwlwifi/mvm/Makefile
index ccdd3b7c4cc..c30d7f64ec1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/Makefile
+++ b/drivers/net/wireless/iwlwifi/mvm/Makefile
@@ -3,8 +3,9 @@ iwlmvm-y += fw.o mac80211.o nvm.o ops.o phy-ctxt.o mac-ctxt.o
iwlmvm-y += utils.o rx.o tx.o binding.o quota.o sta.o sf.o
iwlmvm-y += scan.o time-event.o rs.o
iwlmvm-y += power.o coex.o
-iwlmvm-y += led.o tt.o offloading.o
+iwlmvm-y += tt.o offloading.o
iwlmvm-$(CONFIG_IWLWIFI_DEBUGFS) += debugfs.o debugfs-vif.o
+iwlmvm-$(CONFIG_IWLWIFI_LEDS) += led.o
iwlmvm-$(CONFIG_PM_SLEEP) += d3.o
ccflags-y += -D__CHECK_ENDIAN__ -I$(src)/../
diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c
index 8f4b03dbaf3..c8c3b38228f 100644
--- a/drivers/net/wireless/iwlwifi/mvm/coex.c
+++ b/drivers/net/wireless/iwlwifi/mvm/coex.c
@@ -106,7 +106,7 @@ static const u8 iwl_bt_prio_tbl[BT_COEX_PRIO_TBL_EVT_MAX] = {
static int iwl_send_bt_prio_tbl(struct iwl_mvm *mvm)
{
- return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, BT_COEX_PRIO_TABLE, 0,
sizeof(struct iwl_bt_coex_prio_tbl_cmd),
&iwl_bt_prio_tbl);
}
@@ -124,10 +124,10 @@ const u32 iwl_bt_cts_kill_msk[BT_KILL_MSK_MAX] = {
};
static const __le32 iwl_bt_prio_boost[BT_COEX_BOOST_SIZE] = {
- cpu_to_le32(0xf0f0f0f0),
- cpu_to_le32(0xc0c0c0c0),
- cpu_to_le32(0xfcfcfcfc),
- cpu_to_le32(0xff00ff00),
+ cpu_to_le32(0xf0f0f0f0), /* 50% */
+ cpu_to_le32(0xc0c0c0c0), /* 25% */
+ cpu_to_le32(0xfcfcfcfc), /* 75% */
+ cpu_to_le32(0xfefefefe), /* 87.5% */
};
static const __le32 iwl_single_shared_ant[BT_COEX_MAX_LUT][BT_COEX_LUT_SIZE] = {
@@ -300,8 +300,8 @@ static const __le64 iwl_ci_mask[][3] = {
};
static const __le32 iwl_bt_mprio_lut[BT_COEX_MULTI_PRIO_LUT_SIZE] = {
- cpu_to_le32(0x22002200),
- cpu_to_le32(0x33113311),
+ cpu_to_le32(0x28412201),
+ cpu_to_le32(0x11118451),
};
struct corunning_block_luts {
@@ -565,7 +565,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
.id = BT_CONFIG,
.len = { sizeof(*bt_cmd), },
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
- .flags = CMD_SYNC,
};
int ret;
u32 flags;
@@ -611,14 +610,14 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm)
bt_cmd->flags |= cpu_to_le32(BT_COEX_SYNC2SCO);
if (IWL_MVM_BT_COEX_CORUNNING) {
- bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_CORUN_LUT_20 |
- BT_VALID_CORUN_LUT_40);
+ bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_CORUN_LUT_20 |
+ BT_VALID_CORUN_LUT_40);
bt_cmd->flags |= cpu_to_le32(BT_COEX_CORUNNING);
}
if (IWL_MVM_BT_COEX_MPLUT) {
bt_cmd->flags |= cpu_to_le32(BT_COEX_MPLUT);
- bt_cmd->valid_bit_msk = cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
+ bt_cmd->valid_bit_msk |= cpu_to_le32(BT_VALID_MULTI_PRIO_LUT);
}
if (mvm->cfg->bt_shared_single_ant)
@@ -663,7 +662,6 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
.data[0] = &bt_cmd,
.len = { sizeof(*bt_cmd), },
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
- .flags = CMD_SYNC,
};
int ret = 0;
@@ -717,7 +715,8 @@ static int iwl_mvm_bt_udpate_ctrl_kill_msk(struct iwl_mvm *mvm,
return ret;
}
-int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable)
+static int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id,
+ bool enable)
{
struct iwl_bt_coex_cmd *bt_cmd;
/* Send ASYNC since this can be sent from an atomic context */
@@ -735,8 +734,7 @@ int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable)
return 0;
/* nothing to do */
- if (mvmsta->bt_reduced_txpower_dbg ||
- mvmsta->bt_reduced_txpower == enable)
+ if (mvmsta->bt_reduced_txpower == enable)
return 0;
bt_cmd = kzalloc(sizeof(*bt_cmd), GFP_ATOMIC);
@@ -803,23 +801,10 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
switch (vif->type) {
case NL80211_IFTYPE_STATION:
+ /* Count BSSes vifs */
+ data->num_bss_ifaces++;
/* default smps_mode for BSS / P2P client is AUTOMATIC */
smps_mode = IEEE80211_SMPS_AUTOMATIC;
- data->num_bss_ifaces++;
-
- /*
- * Count unassoc BSSes, relax SMSP constraints
- * and disable reduced Tx Power
- */
- if (!vif->bss_conf.assoc) {
- iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
- smps_mode);
- if (iwl_mvm_bt_coex_reduced_txp(mvm,
- mvmvif->ap_sta_id,
- false))
- IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
- return;
- }
break;
case NL80211_IFTYPE_AP:
/* default smps_mode for AP / GO is OFF */
@@ -845,8 +830,12 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* ... relax constraints and disable rssi events */
iwl_mvm_update_smps(mvm, vif, IWL_MVM_SMPS_REQ_BT_COEX,
smps_mode);
- if (vif->type == NL80211_IFTYPE_STATION)
+ data->reduced_tx_power = false;
+ if (vif->type == NL80211_IFTYPE_STATION) {
+ iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
+ false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
+ }
return;
}
@@ -857,6 +846,11 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
smps_mode = vif->type == NL80211_IFTYPE_AP ?
IEEE80211_SMPS_OFF :
IEEE80211_SMPS_DYNAMIC;
+
+ /* relax SMPS contraints for next association */
+ if (!vif->bss_conf.assoc)
+ smps_mode = IEEE80211_SMPS_AUTOMATIC;
+
IWL_DEBUG_COEX(data->mvm,
"mac %d: bt_status %d bt_activity_grading %d smps_req %d\n",
mvmvif->id, data->notif->bt_status, bt_activity_grading,
@@ -903,22 +897,18 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac,
/* if secondary is not NULL, it might be a GO */
data->secondary = chanctx_conf;
- /* don't reduce the Tx power if in loose scheme */
+ /*
+ * don't reduce the Tx power if one of these is true:
+ * we are in LOOSE
+ * single share antenna product
+ * BT is active
+ * we are associated
+ */
if (iwl_get_coex_type(mvm, vif) == BT_COEX_LOOSE_LUT ||
- mvm->cfg->bt_shared_single_ant) {
- data->reduced_tx_power = false;
- iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
- return;
- }
-
- /* reduced Txpower only if BT is on, so ...*/
- if (!data->notif->bt_status) {
- /* ... cancel reduced Tx power ... */
- if (iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false))
- IWL_ERR(mvm, "Couldn't send BT_CONFIG cmd\n");
+ mvm->cfg->bt_shared_single_ant || !vif->bss_conf.assoc ||
+ !data->notif->bt_status) {
data->reduced_tx_power = false;
-
- /* ... and there is no need to get reports on RSSI any more. */
+ iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id, false);
iwl_mvm_bt_coex_enable_rssi_event(mvm, vif, false, 0);
return;
}
@@ -1022,9 +1012,9 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
/* Don't spam the fw with the same command over and over */
if (memcmp(&cmd, &mvm->last_bt_ci_cmd, sizeof(cmd))) {
- if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, CMD_SYNC,
+ if (iwl_mvm_send_cmd_pdu(mvm, BT_COEX_CI, 0,
sizeof(cmd), &cmd))
- IWL_ERR(mvm, "Failed to send BT_CI cmd");
+ IWL_ERR(mvm, "Failed to send BT_CI cmd\n");
memcpy(&mvm->last_bt_ci_cmd, &cmd, sizeof(cmd));
}
@@ -1039,7 +1029,6 @@ static void iwl_mvm_bt_coex_notif_handle(struct iwl_mvm *mvm)
IWL_ERR(mvm, "Failed to update the ctrl_kill_msk\n");
}
-/* upon association, the fw will send in BT Coex notification */
int iwl_mvm_rx_bt_coex_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *dev_cmd)
@@ -1278,7 +1267,6 @@ int iwl_mvm_rx_ant_coupling_notif(struct iwl_mvm *mvm,
.id = BT_CONFIG,
.len = { sizeof(*bt_cmd), },
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
- .flags = CMD_SYNC,
};
if (!IWL_MVM_BT_COEX_CORUNNING)
diff --git a/drivers/net/wireless/iwlwifi/mvm/d3.c b/drivers/net/wireless/iwlwifi/mvm/d3.c
index 7694472a303..645b3cfc29a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/d3.c
+++ b/drivers/net/wireless/iwlwifi/mvm/d3.c
@@ -193,8 +193,7 @@ static void iwl_mvm_wowlan_program_keys(struct ieee80211_hw *hw,
wkc.wep_key.key_offset = data->wep_key_idx;
}
- ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, CMD_SYNC,
- sizeof(wkc), &wkc);
+ ret = iwl_mvm_send_cmd_pdu(mvm, WEP_KEY, 0, sizeof(wkc), &wkc);
data->error = ret != 0;
mvm->ptk_ivlen = key->iv_len;
@@ -341,7 +340,6 @@ static int iwl_mvm_send_patterns(struct iwl_mvm *mvm,
struct iwl_host_cmd cmd = {
.id = WOWLAN_PATTERNS,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
- .flags = CMD_SYNC,
};
int i, err;
@@ -518,7 +516,6 @@ static int iwl_mvm_send_remote_wake_cfg(struct iwl_mvm *mvm,
.id = REMOTE_WAKE_CONFIG_CMD,
.len = { sizeof(*cfg), },
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
- .flags = CMD_SYNC,
};
int ret;
@@ -666,10 +663,8 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
if (WARN_ON(!vif->bss_conf.assoc))
return -EINVAL;
- /* hack */
- vif->bss_conf.assoc = false;
+
ret = iwl_mvm_mac_ctxt_add(mvm, vif);
- vif->bss_conf.assoc = true;
if (ret)
return ret;
@@ -705,7 +700,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
return ret;
rcu_assign_pointer(mvm->fw_id_to_mac_id[mvmvif->ap_sta_id], ap_sta);
- ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);
if (ret)
return ret;
@@ -719,7 +714,7 @@ static int iwl_mvm_d3_reprogram(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
for (i = 1; i < MAX_BINDINGS; i++)
quota_cmd.quotas[i].id_and_color = cpu_to_le32(FW_CTXT_INVALID);
- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
sizeof(quota_cmd), &quota_cmd);
if (ret)
IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
@@ -739,7 +734,7 @@ static int iwl_mvm_get_last_nonqos_seq(struct iwl_mvm *mvm,
};
struct iwl_host_cmd cmd = {
.id = NON_QOS_TX_COUNTER_CMD,
- .flags = CMD_SYNC | CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
int err;
u32 size;
@@ -781,7 +776,7 @@ void iwl_mvm_set_last_nonqos_seq(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->seqno_valid = false;
- if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, CMD_SYNC,
+ if (iwl_mvm_send_cmd_pdu(mvm, NON_QOS_TX_COUNTER_CMD, 0,
sizeof(query_cmd), &query_cmd))
IWL_ERR(mvm, "failed to set non-QoS seqno\n");
}
@@ -796,7 +791,7 @@ iwl_mvm_send_wowlan_config_cmd(struct iwl_mvm *mvm,
if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_WOWLAN_CONFIG_TID)
cmd_len = sizeof(*cmd);
- return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, WOWLAN_CONFIGURATION, 0,
cmd_len, cmd);
}
@@ -825,7 +820,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
};
struct iwl_host_cmd d3_cfg_cmd = {
.id = D3_CONFIG_CMD,
- .flags = CMD_SYNC | CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
.data[0] = &d3_cfg_cmd_data,
.len[0] = sizeof(d3_cfg_cmd_data),
};
@@ -975,7 +970,6 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (key_data.use_rsc_tsc) {
struct iwl_host_cmd rsc_tsc_cmd = {
.id = WOWLAN_TSC_RSC_PARAM,
- .flags = CMD_SYNC,
.data[0] = key_data.rsc_tsc,
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
.len[0] = sizeof(*key_data.rsc_tsc),
@@ -989,7 +983,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (key_data.use_tkip) {
ret = iwl_mvm_send_cmd_pdu(mvm,
WOWLAN_TKIP_PARAM,
- CMD_SYNC, sizeof(tkip_cmd),
+ 0, sizeof(tkip_cmd),
&tkip_cmd);
if (ret)
goto out;
@@ -1006,8 +1000,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
kek_kck_cmd.replay_ctr = mvmvif->rekey_data.replay_ctr;
ret = iwl_mvm_send_cmd_pdu(mvm,
- WOWLAN_KEK_KCK_MATERIAL,
- CMD_SYNC,
+ WOWLAN_KEK_KCK_MATERIAL, 0,
sizeof(kek_kck_cmd),
&kek_kck_cmd);
if (ret)
@@ -1023,7 +1016,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (ret)
goto out;
- ret = iwl_mvm_send_proto_offload(mvm, vif, false, CMD_SYNC);
+ ret = iwl_mvm_send_proto_offload(mvm, vif, false, 0);
if (ret)
goto out;
@@ -1035,7 +1028,7 @@ static int __iwl_mvm_suspend(struct ieee80211_hw *hw,
if (ret)
goto out;
- ret = iwl_mvm_power_update_mac(mvm, vif);
+ ret = iwl_mvm_power_update_mac(mvm);
if (ret)
goto out;
@@ -1466,7 +1459,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
} err_info;
struct iwl_host_cmd cmd = {
.id = WOWLAN_GET_STATUSES,
- .flags = CMD_SYNC | CMD_WANT_SKB,
+ .flags = CMD_WANT_SKB,
};
struct iwl_wowlan_status_data status;
struct iwl_wowlan_status *fw_status;
@@ -1492,7 +1485,7 @@ static bool iwl_mvm_query_wakeup_reasons(struct iwl_mvm *mvm,
}
/* only for tracing for now */
- ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, CMD_SYNC, 0, NULL);
+ ret = iwl_mvm_send_cmd_pdu(mvm, OFFLOADS_QUERY_CMD, 0, 0, NULL);
if (ret)
IWL_ERR(mvm, "failed to query offload statistics (%d)\n", ret);
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
index 6047cfdafb9..2e90ff795c1 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c
@@ -175,7 +175,7 @@ static ssize_t iwl_dbgfs_pm_params_write(struct ieee80211_vif *vif, char *buf,
mutex_lock(&mvm->mutex);
iwl_dbgfs_update_pm(mvm, vif, param, val);
- ret = iwl_mvm_power_update_mac(mvm, vif);
+ ret = iwl_mvm_power_update_mac(mvm);
mutex_unlock(&mvm->mutex);
return ret ?: count;
@@ -262,10 +262,9 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
struct iwl_mvm_sta *mvm_sta = (void *)sta->drv_priv;
pos += scnprintf(buf+pos, bufsz-pos,
- "ap_sta_id %d - reduced Tx power %d force %d\n",
+ "ap_sta_id %d - reduced Tx power %d\n",
ap_sta_id,
- mvm_sta->bt_reduced_txpower,
- mvm_sta->bt_reduced_txpower_dbg);
+ mvm_sta->bt_reduced_txpower);
}
}
@@ -283,41 +282,6 @@ static ssize_t iwl_dbgfs_mac_params_read(struct file *file,
return simple_read_from_buffer(user_buf, count, ppos, buf, pos);
}
-static ssize_t iwl_dbgfs_reduced_txp_write(struct ieee80211_vif *vif,
- char *buf, size_t count,
- loff_t *ppos)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_mvm *mvm = mvmvif->mvm;
- struct iwl_mvm_sta *mvmsta;
- bool reduced_tx_power;
- int ret;
-
- if (mvmvif->ap_sta_id >= ARRAY_SIZE(mvm->fw_id_to_mac_id))
- return -ENOTCONN;
-
- if (strtobool(buf, &reduced_tx_power) != 0)
- return -EINVAL;
-
- mutex_lock(&mvm->mutex);
-
- mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
- if (IS_ERR_OR_NULL(mvmsta)) {
- mutex_unlock(&mvm->mutex);
- return -ENOTCONN;
- }
-
- mvmsta->bt_reduced_txpower_dbg = false;
- ret = iwl_mvm_bt_coex_reduced_txp(mvm, mvmvif->ap_sta_id,
- reduced_tx_power);
- if (!ret)
- mvmsta->bt_reduced_txpower_dbg = true;
-
- mutex_unlock(&mvm->mutex);
-
- return ret ? : count;
-}
-
static void iwl_dbgfs_update_bf(struct ieee80211_vif *vif,
enum iwl_dbgfs_bf_mask param, int value)
{
@@ -452,9 +416,9 @@ static ssize_t iwl_dbgfs_bf_params_write(struct ieee80211_vif *vif, char *buf,
mutex_lock(&mvm->mutex);
iwl_dbgfs_update_bf(vif, param, value);
if (param == MVM_DEBUGFS_BF_ENABLE_BEACON_FILTER && !value)
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
+ ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
else
- ret = iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC);
+ ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
mutex_unlock(&mvm->mutex);
return ret ?: count;
@@ -558,7 +522,6 @@ MVM_DEBUGFS_READ_FILE_OPS(mac_params);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(pm_params, 32);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(bf_params, 256);
MVM_DEBUGFS_READ_WRITE_FILE_OPS(low_latency, 10);
-MVM_DEBUGFS_WRITE_FILE_OPS(reduced_txp, 10);
void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
{
@@ -590,7 +553,6 @@ void iwl_mvm_vif_dbgfs_register(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
S_IRUSR);
MVM_DEBUGFS_ADD_FILE_VIF(mac_params, mvmvif->dbgfs_dir, S_IRUSR);
- MVM_DEBUGFS_ADD_FILE_VIF(reduced_txp, mvmvif->dbgfs_dir, S_IWUSR);
MVM_DEBUGFS_ADD_FILE_VIF(low_latency, mvmvif->dbgfs_dir,
S_IRUSR | S_IWUSR);
diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
index f462c9baa2b..29ca72695ea 100644
--- a/drivers/net/wireless/iwlwifi/mvm/debugfs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/debugfs.c
@@ -65,9 +65,8 @@
#include "mvm.h"
#include "sta.h"
#include "iwl-io.h"
-#include "iwl-prph.h"
#include "debugfs.h"
-#include "fw-error-dump.h"
+#include "iwl-fw-error-dump.h"
static ssize_t iwl_dbgfs_tx_flush_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
@@ -681,7 +680,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
mvm->restart_fw++;
/* take the return value to make compiler happy - it will fail anyway */
- ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, CMD_SYNC, 0, NULL);
+ ret = iwl_mvm_send_cmd_pdu(mvm, REPLY_ERROR, 0, 0, NULL);
mutex_unlock(&mvm->mutex);
@@ -691,7 +690,7 @@ static ssize_t iwl_dbgfs_fw_restart_write(struct iwl_mvm *mvm, char *buf,
static ssize_t iwl_dbgfs_fw_nmi_write(struct iwl_mvm *mvm, char *buf,
size_t count, loff_t *ppos)
{
- iwl_write_prph(mvm->trans, DEVICE_SET_NMI_REG, 1);
+ iwl_force_nmi(mvm->trans);
return count;
}
@@ -838,7 +837,7 @@ static ssize_t iwl_dbgfs_bcast_filters_write(struct iwl_mvm *mvm, char *buf,
/* send updated bcast filtering configuration */
if (mvm->dbgfs_bcast_filtering.override &&
iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
- err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
+ err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
mutex_unlock(&mvm->mutex);
@@ -910,7 +909,7 @@ static ssize_t iwl_dbgfs_bcast_filters_macs_write(struct iwl_mvm *mvm,
/* send updated bcast filtering configuration */
if (mvm->dbgfs_bcast_filtering.override &&
iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
- err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
+ err = iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
mutex_unlock(&mvm->mutex);
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
index 6174c027ff5..6959fda3fe0 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
+++ b/drivers/net/wireless/iwlwifi/mvm/fw-api-scan.h
@@ -187,9 +187,9 @@ enum iwl_scan_type {
* this number of packets were received (typically 1)
* @passive2active: is auto switching from passive to active during scan allowed
* @rxchain_sel_flags: RXON_RX_CHAIN_*
- * @max_out_time: in usecs, max out of serving channel time
+ * @max_out_time: in TUs, max out of serving channel time
* @suspend_time: how long to pause scan when returning to service channel:
- * bits 0-19: beacon interal in usecs (suspend before executing)
+ * bits 0-19: beacon interal in TUs (suspend before executing)
* bits 20-23: reserved
* bits 24-31: number of beacons (suspend between channels)
* @rxon_flags: RXON_FLG_*
@@ -387,8 +387,8 @@ enum scan_framework_client {
* @quiet_plcp_th: quiet channel num of packets threshold
* @good_CRC_th: passive to active promotion threshold
* @rx_chain: RXON rx chain.
- * @max_out_time: max uSec to be out of assoceated channel
- * @suspend_time: pause scan this long when returning to service channel
+ * @max_out_time: max TUs to be out of assoceated channel
+ * @suspend_time: pause scan this TUs when returning to service channel
* @flags: RXON flags
* @filter_flags: RXONfilter
* @tx_cmd: tx command for active scan; for 2GHz and for 5GHz.
diff --git a/drivers/net/wireless/iwlwifi/mvm/fw.c b/drivers/net/wireless/iwlwifi/mvm/fw.c
index 3d99cf564ba..883e702152d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/fw.c
+++ b/drivers/net/wireless/iwlwifi/mvm/fw.c
@@ -99,7 +99,7 @@ static int iwl_send_tx_ant_cfg(struct iwl_mvm *mvm, u8 valid_tx_ant)
};
IWL_DEBUG_FW(mvm, "select valid tx ant: %u\n", valid_tx_ant);
- return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, TX_ANT_CONFIGURATION_CMD, 0,
sizeof(tx_ant_cmd), &tx_ant_cmd);
}
@@ -137,6 +137,8 @@ static bool iwl_alive_fn(struct iwl_notif_wait_data *notif_wait,
alive_data->scd_base_addr = le32_to_cpu(palive2->scd_base_ptr);
mvm->umac_error_event_table =
le32_to_cpu(palive2->error_info_addr);
+ mvm->sf_space.addr = le32_to_cpu(palive2->st_fwrd_addr);
+ mvm->sf_space.size = le32_to_cpu(palive2->st_fwrd_size);
alive_data->valid = le16_to_cpu(palive2->status) ==
IWL_ALIVE_STATUS_OK;
@@ -180,6 +182,7 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
int ret, i;
enum iwl_ucode_type old_type = mvm->cur_ucode;
static const u8 alive_cmd[] = { MVM_ALIVE };
+ struct iwl_sf_region st_fwrd_space;
fw = iwl_get_ucode_image(mvm, ucode_type);
if (WARN_ON(!fw))
@@ -215,6 +218,14 @@ static int iwl_mvm_load_ucode_wait_alive(struct iwl_mvm *mvm,
return -EIO;
}
+ /*
+ * update the sdio allocation according to the pointer we get in the
+ * alive notification.
+ */
+ st_fwrd_space.addr = mvm->sf_space.addr;
+ st_fwrd_space.size = mvm->sf_space.size;
+ ret = iwl_trans_update_sf(mvm->trans, &st_fwrd_space);
+
iwl_trans_fw_alive(mvm->trans, alive_data.scd_base_addr);
/*
@@ -256,7 +267,7 @@ static int iwl_send_phy_cfg_cmd(struct iwl_mvm *mvm)
IWL_DEBUG_INFO(mvm, "Sending Phy CFG command: 0x%x\n",
phy_cfg_cmd.phy_cfg);
- return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, PHY_CONFIGURATION_CMD, 0,
sizeof(phy_cfg_cmd), &phy_cfg_cmd);
}
@@ -295,7 +306,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
/* Read the NVM only at driver load time, no need to do this twice */
if (read_nvm) {
/* Read nvm */
- ret = iwl_nvm_init(mvm);
+ ret = iwl_nvm_init(mvm, true);
if (ret) {
IWL_ERR(mvm, "Failed to read NVM: %d\n", ret);
goto error;
@@ -303,7 +314,7 @@ int iwl_run_init_mvm_ucode(struct iwl_mvm *mvm, bool read_nvm)
}
/* In case we read the NVM from external file, load it to the NIC */
- if (iwlwifi_mod_params.nvm_file)
+ if (mvm->nvm_file_name)
iwl_mvm_load_nvm_to_nic(mvm);
ret = iwl_nvm_check_version(mvm->nvm_data, mvm->trans);
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
index 7110ec2605d..8b79081d488 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c
@@ -667,10 +667,9 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
if (vif->bss_conf.qos)
cmd->qos_flags |= cpu_to_le32(MAC_QOS_FLG_UPDATE_EDCA);
- if (vif->bss_conf.use_cts_prot) {
+ if (vif->bss_conf.use_cts_prot)
cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_TGG_PROTECT);
- cmd->protection_flags |= cpu_to_le32(MAC_PROT_FLG_SELF_CTS_EN);
- }
+
IWL_DEBUG_RATE(mvm, "use_cts_prot %d, ht_operation_mode %d\n",
vif->bss_conf.use_cts_prot,
vif->bss_conf.ht_operation_mode);
@@ -685,7 +684,7 @@ static void iwl_mvm_mac_ctxt_cmd_common(struct iwl_mvm *mvm,
static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
struct iwl_mac_ctx_cmd *cmd)
{
- int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,
+ int ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
sizeof(*cmd), cmd);
if (ret)
IWL_ERR(mvm, "Failed to send MAC context (action:%d): %d\n",
@@ -693,19 +692,39 @@ static int iwl_mvm_mac_ctxt_send_cmd(struct iwl_mvm *mvm,
return ret;
}
-/*
- * Fill the specific data for mac context of type station or p2p client
- */
-static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- struct iwl_mac_data_sta *ctxt_sta,
- bool force_assoc_off)
+static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ u32 action, bool force_assoc_off)
{
+ struct iwl_mac_ctx_cmd cmd = {};
+ struct iwl_mac_data_sta *ctxt_sta;
+
+ WARN_ON(vif->type != NL80211_IFTYPE_STATION);
+
+ /* Fill the common data for all mac context types */
+ iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+
+ if (vif->p2p) {
+ struct ieee80211_p2p_noa_attr *noa =
+ &vif->bss_conf.p2p_noa_attr;
+
+ cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
+ IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
+ ctxt_sta = &cmd.p2p_sta.sta;
+ } else {
+ ctxt_sta = &cmd.sta;
+ }
+
/* We need the dtim_period to set the MAC as associated */
if (vif->bss_conf.assoc && vif->bss_conf.dtim_period &&
!force_assoc_off) {
u32 dtim_offs;
+ /* Allow beacons to pass through as long as we are not
+ * associated, or we do not have dtim period information.
+ */
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
+
/*
* The DTIM count counts down, so when it is N that means N
* more beacon intervals happen until the DTIM TBTT. Therefore
@@ -752,51 +771,6 @@ static void iwl_mvm_mac_ctxt_cmd_fill_sta(struct iwl_mvm *mvm,
ctxt_sta->listen_interval = cpu_to_le32(mvm->hw->conf.listen_interval);
ctxt_sta->assoc_id = cpu_to_le32(vif->bss_conf.aid);
-}
-
-static int iwl_mvm_mac_ctxt_cmd_station(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- u32 action)
-{
- struct iwl_mac_ctx_cmd cmd = {};
-
- WARN_ON(vif->type != NL80211_IFTYPE_STATION || vif->p2p);
-
- /* Fill the common data for all mac context types */
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
-
- /* Allow beacons to pass through as long as we are not associated,or we
- * do not have dtim period information */
- if (!vif->bss_conf.assoc || !vif->bss_conf.dtim_period)
- cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON);
- else
- cmd.filter_flags &= ~cpu_to_le32(MAC_FILTER_IN_BEACON);
-
- /* Fill the data specific for station mode */
- iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.sta,
- action == FW_CTXT_ACTION_ADD);
-
- return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
-}
-
-static int iwl_mvm_mac_ctxt_cmd_p2p_client(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- u32 action)
-{
- struct iwl_mac_ctx_cmd cmd = {};
- struct ieee80211_p2p_noa_attr *noa = &vif->bss_conf.p2p_noa_attr;
-
- WARN_ON(vif->type != NL80211_IFTYPE_STATION || !vif->p2p);
-
- /* Fill the common data for all mac context types */
- iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
-
- /* Fill the data specific for station mode */
- iwl_mvm_mac_ctxt_cmd_fill_sta(mvm, vif, &cmd.p2p_sta.sta,
- action == FW_CTXT_ACTION_ADD);
-
- cmd.p2p_sta.ctwin = cpu_to_le32(noa->oppps_ctwindow &
- IEEE80211_P2P_OPPPS_CTWINDOW_MASK);
return iwl_mvm_mac_ctxt_send_cmd(mvm, &cmd);
}
@@ -1098,8 +1072,12 @@ static int iwl_mvm_mac_ctxt_cmd_ap(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
- /* Also enable probe requests to pass */
- cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST);
+ /*
+ * pass probe requests and beacons from other APs (needed
+ * for ht protection)
+ */
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
+ MAC_FILTER_IN_BEACON);
/* Fill the data specific for ap mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.ap,
@@ -1120,6 +1098,13 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
/* Fill the common data for all mac context types */
iwl_mvm_mac_ctxt_cmd_common(mvm, vif, &cmd, action);
+ /*
+ * pass probe requests and beacons from other APs (needed
+ * for ht protection)
+ */
+ cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_PROBE_REQUEST |
+ MAC_FILTER_IN_BEACON);
+
/* Fill the data specific for GO mode */
iwl_mvm_mac_ctxt_cmd_fill_ap(mvm, vif, &cmd.go.ap,
action == FW_CTXT_ACTION_ADD);
@@ -1134,16 +1119,12 @@ static int iwl_mvm_mac_ctxt_cmd_go(struct iwl_mvm *mvm,
}
static int iwl_mvm_mac_ctx_send(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
- u32 action)
+ u32 action, bool force_assoc_off)
{
switch (vif->type) {
case NL80211_IFTYPE_STATION:
- if (!vif->p2p)
- return iwl_mvm_mac_ctxt_cmd_station(mvm, vif,
- action);
- else
- return iwl_mvm_mac_ctxt_cmd_p2p_client(mvm, vif,
- action);
+ return iwl_mvm_mac_ctxt_cmd_sta(mvm, vif, action,
+ force_assoc_off);
break;
case NL80211_IFTYPE_AP:
if (!vif->p2p)
@@ -1173,7 +1154,8 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
- ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD);
+ ret = iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_ADD,
+ true);
if (ret)
return ret;
@@ -1184,7 +1166,8 @@ int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
return 0;
}
-int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
+int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ bool force_assoc_off)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
@@ -1192,7 +1175,8 @@ int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
vif->addr, ieee80211_vif_type_p2p(vif)))
return -EIO;
- return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY);
+ return iwl_mvm_mac_ctx_send(mvm, vif, FW_CTXT_ACTION_MODIFY,
+ force_assoc_off);
}
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
@@ -1211,7 +1195,7 @@ int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
mvmvif->color));
cmd.action = cpu_to_le32(FW_CTXT_ACTION_REMOVE);
- ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, MAC_CONTEXT_CMD, 0,
sizeof(cmd), &cmd);
if (ret) {
IWL_ERR(mvm, "Failed to remove MAC context: %d\n", ret);
@@ -1237,11 +1221,23 @@ int iwl_mvm_rx_beacon_notif(struct iwl_mvm *mvm,
u32 rate __maybe_unused =
le32_to_cpu(beacon->beacon_notify_hdr.initial_rate);
+ lockdep_assert_held(&mvm->mutex);
+
IWL_DEBUG_RX(mvm, "beacon status %#x retries:%d tsf:0x%16llX rate:%d\n",
status & TX_STATUS_MSK,
beacon->beacon_notify_hdr.failure_frame,
le64_to_cpu(beacon->tsf),
rate);
+
+ if (unlikely(mvm->csa_vif && mvm->csa_vif->csa_active)) {
+ if (!ieee80211_csa_is_complete(mvm->csa_vif)) {
+ iwl_mvm_mac_ctxt_beacon_changed(mvm, mvm->csa_vif);
+ } else {
+ ieee80211_csa_finish(mvm->csa_vif);
+ mvm->csa_vif = NULL;
+ }
+ }
+
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
index 97c3deae655..98556d03c1e 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c
+++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c
@@ -276,7 +276,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_HW_AMPDU_AGGREGATION |
IEEE80211_HW_TIMING_BEACON_ONLY |
IEEE80211_HW_CONNECTION_MONITOR |
- IEEE80211_HW_SUPPORTS_UAPSD |
IEEE80211_HW_SUPPORTS_DYNAMIC_SMPS |
IEEE80211_HW_SUPPORTS_STATIC_SMPS;
@@ -286,8 +285,6 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
IEEE80211_RADIOTAP_MCS_HAVE_STBC;
hw->radiotap_vht_details |= IEEE80211_RADIOTAP_VHT_KNOWN_STBC;
hw->rate_control_algorithm = "iwl-mvm-rs";
- hw->uapsd_queues = IWL_UAPSD_AC_INFO;
- hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
/*
* Enable 11w if advertised by firmware and software crypto
@@ -298,9 +295,13 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
!iwlwifi_mod_params.sw_crypto)
hw->flags |= IEEE80211_HW_MFP_CAPABLE;
- /* Disable uAPSD due to firmware issues */
- if (true)
- hw->flags &= ~IEEE80211_HW_SUPPORTS_UAPSD;
+ if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_UAPSD_SUPPORT &&
+ IWL_UCODE_API(mvm->fw->ucode_ver) >= 9 &&
+ !iwlwifi_mod_params.uapsd_disable) {
+ hw->flags |= IEEE80211_HW_SUPPORTS_UAPSD;
+ hw->uapsd_queues = IWL_UAPSD_AC_INFO;
+ hw->uapsd_max_sp_len = IWL_UAPSD_MAX_SP;
+ }
hw->sta_data_size = sizeof(struct iwl_mvm_sta);
hw->vif_data_size = sizeof(struct iwl_mvm_vif);
@@ -320,6 +321,9 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm)
if (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_GO_UAPSD)
hw->wiphy->flags |= WIPHY_FLAG_AP_UAPSD;
+ if (mvm->fw->ucode_capa.api[0] & IWL_UCODE_TLV_API_CSA_FLOW)
+ hw->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
+
hw->wiphy->iface_combinations = iwl_mvm_iface_combinations;
hw->wiphy->n_iface_combinations =
ARRAY_SIZE(iwl_mvm_iface_combinations);
@@ -539,13 +543,22 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
return -EACCES;
/* return from D0i3 before starting a new Tx aggregation */
- if (action == IEEE80211_AMPDU_TX_START) {
+ switch (action) {
+ case IEEE80211_AMPDU_TX_START:
+ case IEEE80211_AMPDU_TX_STOP_CONT:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH:
+ case IEEE80211_AMPDU_TX_STOP_FLUSH_CONT:
+ case IEEE80211_AMPDU_TX_OPERATIONAL:
iwl_mvm_ref(mvm, IWL_MVM_REF_TX_AGG);
tx_agg_ref = true;
/*
- * wait synchronously until D0i3 exit to get the correct
- * sequence number for the tid
+ * for tx start, wait synchronously until D0i3 exit to
+ * get the correct sequence number for the tid.
+ * additionally, some other ampdu actions use direct
+ * target access, which is not handled automatically
+ * by the trans layer (unlike commands), so wait for
+ * d0i3 exit in these cases as well.
*/
if (!wait_event_timeout(mvm->d0i3_exit_waitq,
!test_bit(IWL_MVM_STATUS_IN_D0I3, &mvm->status), HZ)) {
@@ -553,6 +566,9 @@ static int iwl_mvm_mac_ampdu_action(struct ieee80211_hw *hw,
iwl_mvm_unref(mvm, IWL_MVM_REF_TX_AGG);
return -EIO;
}
+ break;
+ default:
+ break;
}
mutex_lock(&mvm->mutex);
@@ -757,7 +773,7 @@ static int iwl_mvm_set_tx_power(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
.pwr_restriction = cpu_to_le16(tx_power),
};
- return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, REDUCE_TX_POWER_CMD, 0,
sizeof(reduce_txpwr_cmd),
&reduce_txpwr_cmd);
}
@@ -816,12 +832,12 @@ static int iwl_mvm_mac_add_interface(struct ieee80211_hw *hw,
if (ret)
goto out_release;
- ret = iwl_mvm_power_update_mac(mvm, vif);
+ ret = iwl_mvm_power_update_mac(mvm);
if (ret)
goto out_release;
/* beacon filtering */
- ret = iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
+ ret = iwl_mvm_disable_beacon_filter(mvm, vif, 0);
if (ret)
goto out_remove_mac;
@@ -967,7 +983,7 @@ static void iwl_mvm_mac_remove_interface(struct ieee80211_hw *hw,
if (mvm->vif_count && vif->type != NL80211_IFTYPE_P2P_DEVICE)
mvm->vif_count--;
- iwl_mvm_power_update_mac(mvm, vif);
+ iwl_mvm_power_update_mac(mvm);
iwl_mvm_mac_ctxt_remove(mvm, vif);
out_release:
@@ -1005,7 +1021,7 @@ static void iwl_mvm_mc_iface_iterator(void *_data, u8 *mac,
memcpy(cmd->bssid, vif->bss_conf.bssid, ETH_ALEN);
len = roundup(sizeof(*cmd) + cmd->count * ETH_ALEN, 4);
- ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_SYNC, len, cmd);
+ ret = iwl_mvm_send_cmd_pdu(mvm, MCAST_FILTER_CMD, CMD_ASYNC, len, cmd);
if (ret)
IWL_ERR(mvm, "mcast filter cmd error. ret=%d\n", ret);
}
@@ -1021,7 +1037,7 @@ static void iwl_mvm_recalc_multicast(struct iwl_mvm *mvm)
if (WARN_ON_ONCE(!mvm->mcast_filter_cmd))
return;
- ieee80211_iterate_active_interfaces(
+ ieee80211_iterate_active_interfaces_atomic(
mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_mc_iface_iterator, &iter_data);
}
@@ -1143,8 +1159,12 @@ static void iwl_mvm_bcast_filter_iterator(void *_data, u8 *mac,
bcast_mac = &cmd->macs[mvmvif->id];
- /* enable filtering only for associated stations */
- if (vif->type != NL80211_IFTYPE_STATION || !vif->bss_conf.assoc)
+ /*
+ * enable filtering only for associated stations, but not for P2P
+ * Clients
+ */
+ if (vif->type != NL80211_IFTYPE_STATION || vif->p2p ||
+ !vif->bss_conf.assoc)
return;
bcast_mac->default_discard = 1;
@@ -1221,14 +1241,10 @@ static int iwl_mvm_configure_bcast_filter(struct iwl_mvm *mvm,
if (!(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BCAST_FILTERING))
return 0;
- /* bcast filtering isn't supported for P2P client */
- if (vif->p2p)
- return 0;
-
if (!iwl_mvm_bcast_filter_build_cmd(mvm, &cmd))
return 0;
- return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, BCAST_FILTER_CMD, 0,
sizeof(cmd), &cmd);
}
#else
@@ -1255,7 +1271,7 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
if (changes & BSS_CHANGED_ASSOC && bss_conf->assoc)
iwl_mvm_mac_ctxt_recalc_tsf_id(mvm, vif);
- ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);
if (ret)
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
@@ -1335,10 +1351,10 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
iwl_mvm_remove_time_event(mvm, mvmvif,
&mvmvif->time_event_data);
iwl_mvm_sf_update(mvm, vif, false);
- WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, CMD_SYNC));
+ WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
} else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS |
BSS_CHANGED_QOS)) {
- ret = iwl_mvm_power_update_mac(mvm, vif);
+ ret = iwl_mvm_power_update_mac(mvm);
if (ret)
IWL_ERR(mvm, "failed to update power mode\n");
}
@@ -1349,16 +1365,19 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm,
}
if (changes & BSS_CHANGED_CQM) {
- IWL_DEBUG_MAC80211(mvm, "cqm info_changed");
+ IWL_DEBUG_MAC80211(mvm, "cqm info_changed\n");
/* reset cqm events tracking */
mvmvif->bf_data.last_cqm_event = 0;
- ret = iwl_mvm_update_beacon_filter(mvm, vif, false, CMD_SYNC);
- if (ret)
- IWL_ERR(mvm, "failed to update CQM thresholds\n");
+ if (mvmvif->bf_data.bf_enabled) {
+ ret = iwl_mvm_enable_beacon_filter(mvm, vif, 0);
+ if (ret)
+ IWL_ERR(mvm,
+ "failed to update CQM thresholds\n");
+ }
}
if (changes & BSS_CHANGED_ARP_FILTER) {
- IWL_DEBUG_MAC80211(mvm, "arp filter changed");
+ IWL_DEBUG_MAC80211(mvm, "arp filter changed\n");
iwl_mvm_configure_bcast_filter(mvm, vif);
}
}
@@ -1404,7 +1423,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
mvmvif->ap_ibss_active = true;
/* power updated needs to be done before quotas */
- iwl_mvm_power_update_mac(mvm, vif);
+ iwl_mvm_power_update_mac(mvm);
ret = iwl_mvm_update_quotas(mvm, vif);
if (ret)
@@ -1412,7 +1431,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
if (vif->p2p && mvm->p2p_device_vif)
- iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);
+ iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
iwl_mvm_ref(mvm, IWL_MVM_REF_AP_IBSS);
@@ -1422,7 +1441,7 @@ static int iwl_mvm_start_ap_ibss(struct ieee80211_hw *hw,
return 0;
out_quota_failed:
- iwl_mvm_power_update_mac(mvm, vif);
+ iwl_mvm_power_update_mac(mvm);
mvmvif->ap_ibss_active = false;
iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
out_unbind:
@@ -1452,13 +1471,13 @@ static void iwl_mvm_stop_ap_ibss(struct ieee80211_hw *hw,
/* Need to update the P2P Device MAC (only GO, IBSS is single vif) */
if (vif->p2p && mvm->p2p_device_vif)
- iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif);
+ iwl_mvm_mac_ctxt_changed(mvm, mvm->p2p_device_vif, false);
iwl_mvm_update_quotas(mvm, NULL);
iwl_mvm_send_rm_bcast_sta(mvm, &mvmvif->bcast_sta);
iwl_mvm_binding_remove_vif(mvm, vif);
- iwl_mvm_power_update_mac(mvm, vif);
+ iwl_mvm_power_update_mac(mvm);
iwl_mvm_mac_ctxt_remove(mvm, vif);
@@ -1479,7 +1498,7 @@ iwl_mvm_bss_info_changed_ap_ibss(struct iwl_mvm *mvm,
if (changes & (BSS_CHANGED_ERP_CTS_PROT | BSS_CHANGED_HT |
BSS_CHANGED_BANDWIDTH) &&
- iwl_mvm_mac_ctxt_changed(mvm, vif))
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false))
IWL_ERR(mvm, "failed to update MAC %pM\n", vif->addr);
/* Need to send a new beacon template to the FW */
@@ -1497,6 +1516,9 @@ static void iwl_mvm_bss_info_changed(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
+ if (changes & BSS_CHANGED_IDLE && !bss_conf->idle)
+ iwl_mvm_sched_scan_stop(mvm, true);
+
switch (vif->type) {
case NL80211_IFTYPE_STATION:
iwl_mvm_bss_info_changed_station(mvm, vif, bss_conf, changes);
@@ -1527,7 +1549,7 @@ static int iwl_mvm_mac_hw_scan(struct ieee80211_hw *hw,
switch (mvm->scan_status) {
case IWL_MVM_SCAN_SCHED:
- ret = iwl_mvm_sched_scan_stop(mvm);
+ ret = iwl_mvm_sched_scan_stop(mvm, true);
if (ret) {
ret = -EBUSY;
goto out;
@@ -1715,14 +1737,12 @@ static int iwl_mvm_mac_sta_state(struct ieee80211_hw *hw,
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTHORIZED) {
/* enable beacon filtering */
- if (vif->bss_conf.dtim_period)
- WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif,
- CMD_SYNC));
+ WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0));
ret = 0;
} else if (old_state == IEEE80211_STA_AUTHORIZED &&
new_state == IEEE80211_STA_ASSOC) {
/* disable beacon filtering */
- WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC));
+ WARN_ON(iwl_mvm_disable_beacon_filter(mvm, vif, 0));
ret = 0;
} else if (old_state == IEEE80211_STA_ASSOC &&
new_state == IEEE80211_STA_AUTH) {
@@ -1779,7 +1799,7 @@ static int iwl_mvm_mac_conf_tx(struct ieee80211_hw *hw,
int ret;
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_mac_ctxt_changed(mvm, vif);
+ ret = iwl_mvm_mac_ctxt_changed(mvm, vif, false);
mutex_unlock(&mvm->mutex);
return ret;
}
@@ -1814,6 +1834,11 @@ static int iwl_mvm_mac_sched_scan_start(struct ieee80211_hw *hw,
mutex_lock(&mvm->mutex);
+ if (!iwl_mvm_is_idle(mvm)) {
+ ret = -EBUSY;
+ goto out;
+ }
+
switch (mvm->scan_status) {
case IWL_MVM_SCAN_OS:
IWL_DEBUG_SCAN(mvm, "Stopping previous scan for sched_scan\n");
@@ -1867,7 +1892,7 @@ static int iwl_mvm_mac_sched_scan_stop(struct ieee80211_hw *hw,
int ret;
mutex_lock(&mvm->mutex);
- ret = iwl_mvm_sched_scan_stop(mvm);
+ ret = iwl_mvm_sched_scan_stop(mvm, false);
mutex_unlock(&mvm->mutex);
iwl_mvm_wait_for_async_handlers(mvm);
@@ -2163,10 +2188,10 @@ static void iwl_mvm_change_chanctx(struct ieee80211_hw *hw,
return;
mutex_lock(&mvm->mutex);
+ iwl_mvm_bt_coex_vif_change(mvm);
iwl_mvm_phy_ctxt_changed(mvm, phy_ctxt, &ctx->min_def,
ctx->rx_chains_static,
ctx->rx_chains_dynamic);
- iwl_mvm_bt_coex_vif_change(mvm);
mutex_unlock(&mvm->mutex);
}
@@ -2186,6 +2211,11 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
switch (vif->type) {
case NL80211_IFTYPE_AP:
+ /* Unless it's a CSA flow we have nothing to do here */
+ if (vif->csa_active) {
+ mvmvif->ap_ibss_active = true;
+ break;
+ }
case NL80211_IFTYPE_ADHOC:
/*
* The AP binding flow is handled as part of the start_ap flow
@@ -2209,7 +2239,7 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
* Power state must be updated before quotas,
* otherwise fw will complain.
*/
- iwl_mvm_power_update_mac(mvm, vif);
+ iwl_mvm_power_update_mac(mvm);
/* Setting the quota at this stage is only required for monitor
* interfaces. For the other types, the bss_info changed flow
@@ -2222,11 +2252,17 @@ static int iwl_mvm_assign_vif_chanctx(struct ieee80211_hw *hw,
goto out_remove_binding;
}
+ /* Handle binding during CSA */
+ if (vif->type == NL80211_IFTYPE_AP) {
+ iwl_mvm_update_quotas(mvm, vif);
+ iwl_mvm_mac_ctxt_changed(mvm, vif, false);
+ }
+
goto out_unlock;
out_remove_binding:
iwl_mvm_binding_remove_vif(mvm, vif);
- iwl_mvm_power_update_mac(mvm, vif);
+ iwl_mvm_power_update_mac(mvm);
out_unlock:
mutex_unlock(&mvm->mutex);
if (ret)
@@ -2246,22 +2282,29 @@ static void iwl_mvm_unassign_vif_chanctx(struct ieee80211_hw *hw,
iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data);
switch (vif->type) {
- case NL80211_IFTYPE_AP:
case NL80211_IFTYPE_ADHOC:
goto out_unlock;
case NL80211_IFTYPE_MONITOR:
mvmvif->monitor_active = false;
iwl_mvm_update_quotas(mvm, NULL);
break;
+ case NL80211_IFTYPE_AP:
+ /* This part is triggered only during CSA */
+ if (!vif->csa_active || !mvmvif->ap_ibss_active)
+ goto out_unlock;
+
+ mvmvif->ap_ibss_active = false;
+ iwl_mvm_update_quotas(mvm, NULL);
+ /*TODO: bt_coex notification here? */
default:
break;
}
iwl_mvm_binding_remove_vif(mvm, vif);
- iwl_mvm_power_update_mac(mvm, vif);
out_unlock:
mvmvif->phy_ctxt = NULL;
+ iwl_mvm_power_update_mac(mvm);
mutex_unlock(&mvm->mutex);
}
@@ -2325,9 +2368,8 @@ static int __iwl_mvm_mac_testmode_cmd(struct iwl_mvm *mvm,
return -EINVAL;
if (nla_get_u32(tb[IWL_MVM_TM_ATTR_BEACON_FILTER_STATE]))
- return iwl_mvm_enable_beacon_filter(mvm, vif,
- CMD_SYNC);
- return iwl_mvm_disable_beacon_filter(mvm, vif, CMD_SYNC);
+ return iwl_mvm_enable_beacon_filter(mvm, vif, 0);
+ return iwl_mvm_disable_beacon_filter(mvm, vif, 0);
}
return -EOPNOTSUPP;
@@ -2348,6 +2390,53 @@ static int iwl_mvm_mac_testmode_cmd(struct ieee80211_hw *hw,
}
#endif
+static void iwl_mvm_channel_switch_beacon(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif,
+ struct cfg80211_chan_def *chandef)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+
+ mutex_lock(&mvm->mutex);
+ if (WARN(mvm->csa_vif && mvm->csa_vif->csa_active,
+ "Another CSA is already in progress"))
+ goto out_unlock;
+
+ IWL_DEBUG_MAC80211(mvm, "CSA started to freq %d\n",
+ chandef->center_freq1);
+ mvm->csa_vif = vif;
+
+out_unlock:
+ mutex_unlock(&mvm->mutex);
+}
+
+static void iwl_mvm_mac_flush(struct ieee80211_hw *hw,
+ struct ieee80211_vif *vif, u32 queues, bool drop)
+{
+ struct iwl_mvm *mvm = IWL_MAC80211_GET_MVM(hw);
+ struct iwl_mvm_vif *mvmvif;
+ struct iwl_mvm_sta *mvmsta;
+
+ if (!vif || vif->type != NL80211_IFTYPE_STATION)
+ return;
+
+ mutex_lock(&mvm->mutex);
+ mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ mvmsta = iwl_mvm_sta_from_staid_protected(mvm, mvmvif->ap_sta_id);
+
+ if (WARN_ON_ONCE(!mvmsta))
+ goto done;
+
+ if (drop) {
+ if (iwl_mvm_flush_tx_path(mvm, mvmsta->tfd_queue_msk, true))
+ IWL_ERR(mvm, "flush request fail\n");
+ } else {
+ iwl_trans_wait_tx_queue_empty(mvm->trans,
+ mvmsta->tfd_queue_msk);
+ }
+done:
+ mutex_unlock(&mvm->mutex);
+}
+
const struct ieee80211_ops iwl_mvm_hw_ops = {
.tx = iwl_mvm_mac_tx,
.ampdu_action = iwl_mvm_mac_ampdu_action,
@@ -2371,6 +2460,7 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.sta_rc_update = iwl_mvm_sta_rc_update,
.conf_tx = iwl_mvm_mac_conf_tx,
.mgd_prepare_tx = iwl_mvm_mac_mgd_prepare_tx,
+ .flush = iwl_mvm_mac_flush,
.sched_scan_start = iwl_mvm_mac_sched_scan_start,
.sched_scan_stop = iwl_mvm_mac_sched_scan_stop,
.set_key = iwl_mvm_mac_set_key,
@@ -2390,6 +2480,8 @@ const struct ieee80211_ops iwl_mvm_hw_ops = {
.set_tim = iwl_mvm_set_tim,
+ .channel_switch_beacon = iwl_mvm_channel_switch_beacon,
+
CFG80211_TESTMODE_CMD(iwl_mvm_mac_testmode_cmd)
#ifdef CONFIG_PM_SLEEP
diff --git a/drivers/net/wireless/iwlwifi/mvm/mvm.h b/drivers/net/wireless/iwlwifi/mvm/mvm.h
index 17c42da5f9f..fcc6c29482d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/mvm.h
+++ b/drivers/net/wireless/iwlwifi/mvm/mvm.h
@@ -490,6 +490,7 @@ struct iwl_mvm {
u32 log_event_table;
u32 umac_error_event_table;
bool support_umac_log;
+ struct iwl_sf_region sf_space;
u32 ampdu_ref;
@@ -501,6 +502,7 @@ struct iwl_mvm {
u8 queue_to_mac80211[IWL_MAX_HW_QUEUES];
atomic_t queue_stop_count[IWL_MAX_HW_QUEUES];
+ const char *nvm_file_name;
struct iwl_nvm_data *nvm_data;
/* NVM sections */
struct iwl_nvm_section nvm_sections[NVM_MAX_NUM_SECTIONS];
@@ -589,7 +591,9 @@ struct iwl_mvm {
u32 *fw_error_rxf;
u32 fw_error_rxf_len;
+#ifdef CONFIG_IWLWIFI_LEDS
struct led_classdev led;
+#endif
struct ieee80211_vif *p2p_device_vif;
@@ -642,6 +646,8 @@ struct iwl_mvm {
/* Indicate if device power save is allowed */
bool ps_disabled;
+
+ struct ieee80211_vif *csa_vif;
};
/* Extract MVM priv from op_mode and _hw */
@@ -757,7 +763,7 @@ int iwl_mvm_rx_statistics(struct iwl_mvm *mvm,
struct iwl_device_cmd *cmd);
/* NVM */
-int iwl_nvm_init(struct iwl_mvm *mvm);
+int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic);
int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm);
int iwl_mvm_up(struct iwl_mvm *mvm);
@@ -808,7 +814,8 @@ void iwl_mvm_phy_ctxt_unref(struct iwl_mvm *mvm,
int iwl_mvm_mac_ctxt_init(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
void iwl_mvm_mac_ctxt_release(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
int iwl_mvm_mac_ctxt_add(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
-int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_mac_ctxt_changed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ bool force_assoc_off);
int iwl_mvm_mac_ctxt_remove(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
u32 iwl_mvm_mac_get_queues_mask(struct iwl_mvm *mvm,
struct ieee80211_vif *vif);
@@ -852,7 +859,7 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req);
-int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm);
+int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify);
int iwl_mvm_rx_sched_scan_results(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
@@ -887,7 +894,7 @@ int rs_pretty_print_rate(char *buf, const u32 rate);
/* power management */
int iwl_mvm_power_update_device(struct iwl_mvm *mvm);
-int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif);
+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm);
int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
char *buf, int bufsz);
@@ -896,8 +903,18 @@ int iwl_mvm_power_uapsd_misbehaving_ap_notif(struct iwl_mvm *mvm,
struct iwl_rx_cmd_buffer *rxb,
struct iwl_device_cmd *cmd);
+#ifdef CONFIG_IWLWIFI_LEDS
int iwl_mvm_leds_init(struct iwl_mvm *mvm);
void iwl_mvm_leds_exit(struct iwl_mvm *mvm);
+#else
+static inline int iwl_mvm_leds_init(struct iwl_mvm *mvm)
+{
+ return 0;
+}
+static inline void iwl_mvm_leds_exit(struct iwl_mvm *mvm)
+{
+}
+#endif
/* D3 (WoWLAN, NetDetect) */
int iwl_mvm_suspend(struct ieee80211_hw *hw, struct cfg80211_wowlan *wowlan);
@@ -950,7 +967,6 @@ bool iwl_mvm_bt_coex_is_tpc_allowed(struct iwl_mvm *mvm,
enum ieee80211_band band);
u8 iwl_mvm_bt_coex_tx_prio(struct iwl_mvm *mvm, struct ieee80211_hdr *hdr,
struct ieee80211_tx_info *info, u8 ac);
-int iwl_mvm_bt_coex_reduced_txp(struct iwl_mvm *mvm, u8 sta_id, bool enable);
enum iwl_bt_kill_msk {
BT_KILL_MSK_DEFAULT,
@@ -981,17 +997,11 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 flags);
-int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif, bool enable);
-int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool force,
- u32 flags);
-
/* SMPS */
void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
enum iwl_mvm_smps_type_request req_type,
enum ieee80211_smps_mode smps_request);
+bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm);
/* Low latency */
int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
@@ -1015,6 +1025,9 @@ static inline bool iwl_mvm_vif_low_latency(struct iwl_mvm_vif *mvmvif)
return mvmvif->low_latency;
}
+/* Assoc status */
+bool iwl_mvm_is_idle(struct iwl_mvm *mvm);
+
/* Thermal management and CT-kill */
void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff);
void iwl_mvm_tt_handler(struct iwl_mvm *mvm);
diff --git a/drivers/net/wireless/iwlwifi/mvm/nvm.c b/drivers/net/wireless/iwlwifi/mvm/nvm.c
index cf2d09f5378..808f78f6fbf 100644
--- a/drivers/net/wireless/iwlwifi/mvm/nvm.c
+++ b/drivers/net/wireless/iwlwifi/mvm/nvm.c
@@ -74,6 +74,12 @@
#define NVM_WRITE_OPCODE 1
#define NVM_READ_OPCODE 0
+/* load nvm chunk response */
+enum {
+ READ_NVM_CHUNK_SUCCEED = 0,
+ READ_NVM_CHUNK_NOT_VALID_ADDRESS = 1
+};
+
/*
* prepare the NVM host command w/ the pointers to the nvm buffer
* and send it to fw
@@ -90,7 +96,7 @@ static int iwl_nvm_write_chunk(struct iwl_mvm *mvm, u16 section,
struct iwl_host_cmd cmd = {
.id = NVM_ACCESS_CMD,
.len = { sizeof(struct iwl_nvm_access_cmd), length },
- .flags = CMD_SYNC | CMD_SEND_IN_RFKILL,
+ .flags = CMD_SEND_IN_RFKILL,
.data = { &nvm_access_cmd, data },
/* data may come from vmalloc, so use _DUP */
.dataflags = { 0, IWL_HCMD_DFL_DUP },
@@ -112,7 +118,7 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
struct iwl_rx_packet *pkt;
struct iwl_host_cmd cmd = {
.id = NVM_ACCESS_CMD,
- .flags = CMD_SYNC | CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
+ .flags = CMD_WANT_SKB | CMD_SEND_IN_RFKILL,
.data = { &nvm_access_cmd, },
};
int ret, bytes_read, offset_read;
@@ -139,10 +145,26 @@ static int iwl_nvm_read_chunk(struct iwl_mvm *mvm, u16 section,
offset_read = le16_to_cpu(nvm_resp->offset);
resp_data = nvm_resp->data;
if (ret) {
- IWL_ERR(mvm,
- "NVM access command failed with status %d (device: %s)\n",
- ret, mvm->cfg->name);
- ret = -EINVAL;
+ if ((offset != 0) &&
+ (ret == READ_NVM_CHUNK_NOT_VALID_ADDRESS)) {
+ /*
+ * meaning of NOT_VALID_ADDRESS:
+ * driver try to read chunk from address that is
+ * multiple of 2K and got an error since addr is empty.
+ * meaning of (offset != 0): driver already
+ * read valid data from another chunk so this case
+ * is not an error.
+ */
+ IWL_DEBUG_EEPROM(mvm->trans->dev,
+ "NVM access command failed on offset 0x%x since that section size is multiple 2K\n",
+ offset);
+ ret = 0;
+ } else {
+ IWL_DEBUG_EEPROM(mvm->trans->dev,
+ "NVM access command failed with status %d (device: %s)\n",
+ ret, mvm->cfg->name);
+ ret = -EIO;
+ }
goto exit;
}
@@ -211,9 +233,9 @@ static int iwl_nvm_read_section(struct iwl_mvm *mvm, u16 section,
while (ret == length) {
ret = iwl_nvm_read_chunk(mvm, section, offset, length, data);
if (ret < 0) {
- IWL_ERR(mvm,
- "Cannot read NVM from section %d offset %d, length %d\n",
- section, offset, length);
+ IWL_DEBUG_EEPROM(mvm->trans->dev,
+ "Cannot read NVM from section %d offset %d, length %d\n",
+ section, offset, length);
return ret;
}
offset += ret;
@@ -238,13 +260,20 @@ iwl_parse_nvm_sections(struct iwl_mvm *mvm)
return NULL;
}
} else {
+ /* SW and REGULATORY sections are mandatory */
if (!mvm->nvm_sections[NVM_SECTION_TYPE_SW].data ||
- !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data ||
!mvm->nvm_sections[NVM_SECTION_TYPE_REGULATORY].data) {
IWL_ERR(mvm,
"Can't parse empty family 8000 NVM sections\n");
return NULL;
}
+ /* MAC_OVERRIDE or at least HW section must exist */
+ if (!mvm->nvm_sections[mvm->cfg->nvm_hw_section_num].data &&
+ !mvm->nvm_sections[NVM_SECTION_TYPE_MAC_OVERRIDE].data) {
+ IWL_ERR(mvm,
+ "Can't parse mac_address, empty sections\n");
+ return NULL;
+ }
}
if (WARN_ON(!mvm->cfg))
@@ -311,16 +340,16 @@ static int iwl_mvm_read_external_nvm(struct iwl_mvm *mvm)
* get here after that we assume the NVM request can be satisfied
* synchronously.
*/
- ret = request_firmware(&fw_entry, iwlwifi_mod_params.nvm_file,
+ ret = request_firmware(&fw_entry, mvm->nvm_file_name,
mvm->trans->dev);
if (ret) {
IWL_ERR(mvm, "ERROR: %s isn't available %d\n",
- iwlwifi_mod_params.nvm_file, ret);
+ mvm->nvm_file_name, ret);
return ret;
}
IWL_INFO(mvm, "Loaded NVM file %s (%zu bytes)\n",
- iwlwifi_mod_params.nvm_file, fw_entry->size);
+ mvm->nvm_file_name, fw_entry->size);
if (fw_entry->size < sizeof(*file_sec)) {
IWL_ERR(mvm, "NVM file too small\n");
@@ -427,53 +456,28 @@ int iwl_mvm_load_nvm_to_nic(struct iwl_mvm *mvm)
return ret;
}
-int iwl_nvm_init(struct iwl_mvm *mvm)
+int iwl_nvm_init(struct iwl_mvm *mvm, bool read_nvm_from_nic)
{
- int ret, i, section;
+ int ret, section;
u8 *nvm_buffer, *temp;
- int nvm_to_read[NVM_MAX_NUM_SECTIONS];
- int num_of_sections_to_read;
if (WARN_ON_ONCE(mvm->cfg->nvm_hw_section_num >= NVM_MAX_NUM_SECTIONS))
return -EINVAL;
- /* load external NVM if configured */
- if (iwlwifi_mod_params.nvm_file) {
- /* move to External NVM flow */
- ret = iwl_mvm_read_external_nvm(mvm);
- if (ret)
- return ret;
- } else {
- /* list of NVM sections we are allowed/need to read */
- if (mvm->trans->cfg->device_family != IWL_DEVICE_FAMILY_8000) {
- nvm_to_read[0] = mvm->cfg->nvm_hw_section_num;
- nvm_to_read[1] = NVM_SECTION_TYPE_SW;
- nvm_to_read[2] = NVM_SECTION_TYPE_CALIBRATION;
- nvm_to_read[3] = NVM_SECTION_TYPE_PRODUCTION;
- num_of_sections_to_read = 4;
- } else {
- nvm_to_read[0] = NVM_SECTION_TYPE_SW;
- nvm_to_read[1] = NVM_SECTION_TYPE_CALIBRATION;
- nvm_to_read[2] = NVM_SECTION_TYPE_PRODUCTION;
- nvm_to_read[3] = NVM_SECTION_TYPE_REGULATORY;
- nvm_to_read[4] = NVM_SECTION_TYPE_MAC_OVERRIDE;
- num_of_sections_to_read = 5;
- }
-
+ /* load NVM values from nic */
+ if (read_nvm_from_nic) {
/* Read From FW NVM */
IWL_DEBUG_EEPROM(mvm->trans->dev, "Read from NVM\n");
- /* TODO: find correct NVM max size for a section */
nvm_buffer = kmalloc(mvm->cfg->base_params->eeprom_size,
GFP_KERNEL);
if (!nvm_buffer)
return -ENOMEM;
- for (i = 0; i < num_of_sections_to_read; i++) {
- section = nvm_to_read[i];
+ for (section = 0; section < NVM_MAX_NUM_SECTIONS; section++) {
/* we override the constness for initial read */
ret = iwl_nvm_read_section(mvm, section, nvm_buffer);
if (ret < 0)
- break;
+ continue;
temp = kmemdup(nvm_buffer, ret, GFP_KERNEL);
if (!temp) {
ret = -ENOMEM;
@@ -502,15 +506,21 @@ int iwl_nvm_init(struct iwl_mvm *mvm)
mvm->nvm_hw_blob.size = ret;
break;
}
- WARN(1, "section: %d", section);
}
#endif
}
kfree(nvm_buffer);
- if (ret < 0)
+ }
+
+ /* load external NVM if configured */
+ if (mvm->nvm_file_name) {
+ /* move to External NVM flow */
+ ret = iwl_mvm_read_external_nvm(mvm);
+ if (ret)
return ret;
}
+ /* parse the relevant nvm sections */
mvm->nvm_data = iwl_parse_nvm_sections(mvm);
if (!mvm->nvm_data)
return -ENODATA;
diff --git a/drivers/net/wireless/iwlwifi/mvm/ops.c b/drivers/net/wireless/iwlwifi/mvm/ops.c
index 7a5a8bac5fd..cc2f7de396d 100644
--- a/drivers/net/wireless/iwlwifi/mvm/ops.c
+++ b/drivers/net/wireless/iwlwifi/mvm/ops.c
@@ -79,8 +79,8 @@
#include "iwl-prph.h"
#include "rs.h"
#include "fw-api-scan.h"
-#include "fw-error-dump.h"
#include "time-event.h"
+#include "iwl-fw-error-dump.h"
/*
* module name, copyright, version, etc.
@@ -220,7 +220,7 @@ static const struct iwl_rx_handlers iwl_mvm_rx_handlers[] = {
RX_HANDLER(BA_NOTIF, iwl_mvm_rx_ba_notif, false),
RX_HANDLER(BT_PROFILE_NOTIFICATION, iwl_mvm_rx_bt_coex_notif, true),
- RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, false),
+ RX_HANDLER(BEACON_NOTIFICATION, iwl_mvm_rx_beacon_notif, true),
RX_HANDLER(STATISTICS_NOTIFICATION, iwl_mvm_rx_statistics, true),
RX_HANDLER(ANTENNA_COUPLING_NOTIFICATION,
iwl_mvm_rx_ant_coupling_notif, true),
@@ -466,13 +466,24 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
min_backoff = calc_min_backoff(trans, cfg);
iwl_mvm_tt_initialize(mvm, min_backoff);
+ /* set the nvm_file_name according to priority */
+ if (iwlwifi_mod_params.nvm_file)
+ mvm->nvm_file_name = iwlwifi_mod_params.nvm_file;
+ else
+ mvm->nvm_file_name = mvm->cfg->default_nvm_file;
+
+ if (WARN(cfg->no_power_up_nic_in_init && !mvm->nvm_file_name,
+ "not allowing power-up and not having nvm_file\n"))
+ goto out_free;
/*
- * If the NVM exists in an external file,
- * there is no need to unnecessarily power up the NIC at driver load
+ * Even if nvm exists in the nvm_file driver should read agin the nvm
+ * from the nic because there might be entries that exist in the OTP
+ * and not in the file.
+ * for nics with no_power_up_nic_in_init: rely completley on nvm_file
*/
- if (iwlwifi_mod_params.nvm_file) {
- err = iwl_nvm_init(mvm);
+ if (cfg->no_power_up_nic_in_init && mvm->nvm_file_name) {
+ err = iwl_nvm_init(mvm, false);
if (err)
goto out_free;
} else {
@@ -519,7 +530,7 @@ iwl_op_mode_mvm_start(struct iwl_trans *trans, const struct iwl_cfg *cfg,
out_free:
iwl_phy_db_free(mvm->phy_db);
kfree(mvm->scan_cmd);
- if (!iwlwifi_mod_params.nvm_file)
+ if (!cfg->no_power_up_nic_in_init || !mvm->nvm_file_name)
iwl_trans_op_mode_leave(trans);
ieee80211_free_hw(mvm->hw);
return NULL;
@@ -816,6 +827,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
struct iwl_fw_error_dump_file *dump_file;
struct iwl_fw_error_dump_data *dump_data;
u32 file_len;
+ u32 trans_len;
lockdep_assert_held(&mvm->mutex);
@@ -827,6 +839,10 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
sizeof(*dump_file) +
sizeof(*dump_data) * 2;
+ trans_len = iwl_trans_dump_data(mvm->trans, NULL, 0);
+ if (trans_len)
+ file_len += trans_len;
+
dump_file = vmalloc(file_len);
if (!dump_file)
return;
@@ -840,7 +856,7 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
dump_data->len = cpu_to_le32(mvm->fw_error_rxf_len);
memcpy(dump_data->data, mvm->fw_error_rxf, mvm->fw_error_rxf_len);
- dump_data = (void *)((u8 *)dump_data->data + mvm->fw_error_rxf_len);
+ dump_data = iwl_mvm_fw_error_next_data(dump_data);
dump_data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_SRAM);
dump_data->len = cpu_to_le32(mvm->fw_error_sram_len);
@@ -858,6 +874,15 @@ void iwl_mvm_fw_error_dump(struct iwl_mvm *mvm)
kfree(mvm->fw_error_sram);
mvm->fw_error_sram = NULL;
mvm->fw_error_sram_len = 0;
+
+ if (trans_len) {
+ void *buf = iwl_mvm_fw_error_next_data(dump_data);
+ u32 real_trans_len = iwl_trans_dump_data(mvm->trans, buf,
+ trans_len);
+ dump_data = (void *)((u8 *)buf + real_trans_len);
+ dump_file->file_len =
+ cpu_to_le32(file_len - trans_len + real_trans_len);
+ }
}
#endif
@@ -1143,7 +1168,7 @@ static void iwl_mvm_d0i3_exit_work(struct work_struct *wk)
struct iwl_mvm *mvm = container_of(wk, struct iwl_mvm, d0i3_exit_work);
struct iwl_host_cmd get_status_cmd = {
.id = WOWLAN_GET_STATUSES,
- .flags = CMD_SYNC | CMD_HIGH_PRIO | CMD_WANT_SKB,
+ .flags = CMD_HIGH_PRIO | CMD_WANT_SKB,
};
struct iwl_wowlan_status *status;
int ret;
diff --git a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
index 237efe0ac1c..539f3a942d4 100644
--- a/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/phy-ctxt.c
@@ -156,6 +156,18 @@ static void iwl_mvm_phy_ctxt_cmd_data(struct iwl_mvm *mvm,
idle_cnt = chains_static;
active_cnt = chains_dynamic;
+ /* In scenarios where we only ever use a single-stream rates,
+ * i.e. legacy 11b/g/a associations, single-stream APs or even
+ * static SMPS, enable both chains to get diversity, improving
+ * the case where we're far enough from the AP that attenuation
+ * between the two antennas is sufficiently different to impact
+ * performance.
+ */
+ if (active_cnt == 1 && iwl_mvm_rx_diversity_allowed(mvm)) {
+ idle_cnt = 2;
+ active_cnt = 2;
+ }
+
cmd->rxchain_info = cpu_to_le32(mvm->fw->valid_rx_ant <<
PHY_RX_CHAIN_VALID_POS);
cmd->rxchain_info |= cpu_to_le32(idle_cnt << PHY_RX_CHAIN_CNT_POS);
@@ -187,7 +199,7 @@ static int iwl_mvm_phy_ctxt_apply(struct iwl_mvm *mvm,
iwl_mvm_phy_ctxt_cmd_data(mvm, &cmd, chandef,
chains_static, chains_dynamic);
- ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, PHY_CONTEXT_CMD, 0,
sizeof(struct iwl_phy_context_cmd),
&cmd);
if (ret)
@@ -202,18 +214,15 @@ int iwl_mvm_phy_ctxt_add(struct iwl_mvm *mvm, struct iwl_mvm_phy_ctxt *ctxt,
struct cfg80211_chan_def *chandef,
u8 chains_static, u8 chains_dynamic)
{
- int ret;
-
WARN_ON(!test_bit(IWL_MVM_STATUS_IN_HW_RESTART, &mvm->status) &&
ctxt->ref);
lockdep_assert_held(&mvm->mutex);
ctxt->channel = chandef->chan;
- ret = iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
- chains_static, chains_dynamic,
- FW_CTXT_ACTION_ADD, 0);
- return ret;
+ return iwl_mvm_phy_ctxt_apply(mvm, ctxt, chandef,
+ chains_static, chains_dynamic,
+ FW_CTXT_ACTION_ADD, 0);
}
/*
diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c
index 78309f7d0b7..c182a8baf68 100644
--- a/drivers/net/wireless/iwlwifi/mvm/power.c
+++ b/drivers/net/wireless/iwlwifi/mvm/power.c
@@ -123,28 +123,6 @@ void iwl_mvm_beacon_filter_set_cqm_params(struct iwl_mvm *mvm,
cmd->ba_enable_beacon_abort = cpu_to_le32(mvmvif->bf_data.ba_enabled);
}
-int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif, bool enable)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
- struct iwl_beacon_filter_cmd cmd = {
- IWL_BF_CMD_CONFIG_DEFAULTS,
- .bf_enable_beacon_filter = cpu_to_le32(1),
- .ba_enable_beacon_abort = cpu_to_le32(enable),
- };
-
- if (!mvmvif->bf_data.bf_enabled)
- return 0;
-
- if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
- cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
-
- mvmvif->bf_data.ba_enabled = enable;
- iwl_mvm_beacon_filter_set_cqm_params(mvm, vif, &cmd);
- iwl_mvm_beacon_filter_debugfs_parameters(vif, &cmd);
- return iwl_mvm_beacon_filter_send_cmd(mvm, &cmd, CMD_SYNC);
-}
-
static void iwl_mvm_power_log(struct iwl_mvm *mvm,
struct iwl_mac_power_cmd *cmd)
{
@@ -268,10 +246,30 @@ static void iwl_mvm_power_configure_uapsd(struct iwl_mvm *mvm,
IWL_MVM_PS_HEAVY_RX_THLD_PERCENT;
}
+static void iwl_mvm_binding_iterator(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ unsigned long *data = _data;
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+
+ if (!mvmvif->phy_ctxt)
+ return;
+
+ if (vif->type == NL80211_IFTYPE_STATION ||
+ vif->type == NL80211_IFTYPE_AP)
+ __set_bit(mvmvif->phy_ctxt->id, data);
+}
+
static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
struct ieee80211_vif *vif)
{
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ unsigned long phy_ctxt_counter = 0;
+
+ ieee80211_iterate_active_interfaces_atomic(mvm->hw,
+ IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_binding_iterator,
+ &phy_ctxt_counter);
if (!memcmp(mvmvif->uapsd_misbehaving_bssid, vif->bss_conf.bssid,
ETH_ALEN))
@@ -289,6 +287,13 @@ static bool iwl_mvm_power_allow_uapsd(struct iwl_mvm *mvm,
IEEE80211_P2P_OPPPS_ENABLE_BIT))
return false;
+ /*
+ * Avoid using uAPSD if client is in DCM -
+ * low latency issue in Miracast
+ */
+ if (hweight8(phy_ctxt_counter) >= 2)
+ return false;
+
return true;
}
@@ -429,7 +434,7 @@ static int iwl_mvm_power_send_cmd(struct iwl_mvm *mvm,
memcpy(&iwl_mvm_vif_from_mac80211(vif)->mac_pwr_cmd, &cmd, sizeof(cmd));
#endif
- return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, MAC_PM_POWER_TABLE, 0,
sizeof(cmd), &cmd);
}
@@ -455,7 +460,7 @@ int iwl_mvm_power_update_device(struct iwl_mvm *mvm)
"Sending device power command with flags = 0x%X\n",
cmd.flags);
- return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, CMD_SYNC, sizeof(cmd),
+ return iwl_mvm_send_cmd_pdu(mvm, POWER_TABLE_CMD, 0, sizeof(cmd),
&cmd);
}
@@ -613,11 +618,15 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
ap_same_channel = (bss_mvmvif->phy_ctxt->id ==
ap_mvmvif->phy_ctxt->id);
- /* bss is not stand alone: enable PM if alone on its channel */
- if (vifs->bss_active && !(client_same_channel || ap_same_channel) &&
+ /* clients are not stand alone: enable PM if DCM */
+ if (!(client_same_channel || ap_same_channel) &&
(mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_BSS_P2P_PS_DCM)) {
+ if (vifs->bss_active)
bss_mvmvif->pm_enabled = true;
- return;
+ if (vifs->p2p_active &&
+ (mvm->fw->ucode_capa.flags & IWL_UCODE_TLV_FLAGS_P2P_PM))
+ p2p_mvmvif->pm_enabled = true;
+ return;
}
/*
@@ -633,55 +642,6 @@ iwl_mvm_power_set_pm(struct iwl_mvm *mvm,
}
}
-int iwl_mvm_power_update_mac(struct iwl_mvm *mvm, struct ieee80211_vif *vif)
-{
- struct iwl_mvm_vif *mvmvif;
- struct iwl_power_vifs vifs = {};
- bool ba_enable;
- int ret;
-
- lockdep_assert_held(&mvm->mutex);
-
- iwl_mvm_power_set_pm(mvm, &vifs);
-
- /* disable PS if CAM */
- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {
- mvm->ps_disabled = true;
- } else {
- /* don't update device power state unless we add / remove monitor */
- if (vifs.monitor_vif) {
- if (vifs.monitor_active)
- mvm->ps_disabled = true;
- ret = iwl_mvm_power_update_device(mvm);
- if (ret)
- return ret;
- }
- }
-
- if (vifs.bss_vif) {
- ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
- if (ret)
- return ret;
- }
-
- if (vifs.p2p_vif) {
- ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
- if (ret)
- return ret;
- }
-
- if (!vifs.bf_vif)
- return 0;
-
- vif = vifs.bf_vif;
- mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||
- !vif->bss_conf.ps || iwl_mvm_vif_low_latency(mvmvif));
-
- return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable);
-}
-
#ifdef CONFIG_IWLWIFI_DEBUGFS
int iwl_mvm_power_mac_dbgfs_read(struct iwl_mvm *mvm,
struct ieee80211_vif *vif, char *buf,
@@ -801,7 +761,7 @@ static int _iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
int ret;
- if (mvmvif != mvm->bf_allowed_vif ||
+ if (mvmvif != mvm->bf_allowed_vif || !vif->bss_conf.dtim_period ||
vif->type != NL80211_IFTYPE_STATION || vif->p2p)
return 0;
@@ -829,6 +789,26 @@ int iwl_mvm_enable_beacon_filter(struct iwl_mvm *mvm,
return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, flags, false);
}
+static int iwl_mvm_update_beacon_abort(struct iwl_mvm *mvm,
+ struct ieee80211_vif *vif,
+ bool enable)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ struct iwl_beacon_filter_cmd cmd = {
+ IWL_BF_CMD_CONFIG_DEFAULTS,
+ .bf_enable_beacon_filter = cpu_to_le32(1),
+ };
+
+ if (!mvmvif->bf_data.bf_enabled)
+ return 0;
+
+ if (mvm->cur_ucode == IWL_UCODE_WOWLAN)
+ cmd.ba_escape_timer = cpu_to_le32(IWL_BA_ESCAPE_TIMER_D3);
+
+ mvmvif->bf_data.ba_enabled = enable;
+ return _iwl_mvm_enable_beacon_filter(mvm, vif, &cmd, 0, false);
+}
+
int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
u32 flags)
@@ -848,6 +828,55 @@ int iwl_mvm_disable_beacon_filter(struct iwl_mvm *mvm,
return ret;
}
+int iwl_mvm_power_update_mac(struct iwl_mvm *mvm)
+{
+ struct iwl_mvm_vif *mvmvif;
+ struct iwl_power_vifs vifs = {};
+ bool ba_enable;
+ int ret;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ iwl_mvm_power_set_pm(mvm, &vifs);
+
+ /* disable PS if CAM */
+ if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM) {
+ mvm->ps_disabled = true;
+ } else {
+ /* don't update device power state unless we add / remove monitor */
+ if (vifs.monitor_vif) {
+ if (vifs.monitor_active)
+ mvm->ps_disabled = true;
+ ret = iwl_mvm_power_update_device(mvm);
+ if (ret)
+ return ret;
+ }
+ }
+
+ if (vifs.bss_vif) {
+ ret = iwl_mvm_power_send_cmd(mvm, vifs.bss_vif);
+ if (ret)
+ return ret;
+ }
+
+ if (vifs.p2p_vif) {
+ ret = iwl_mvm_power_send_cmd(mvm, vifs.p2p_vif);
+ if (ret)
+ return ret;
+ }
+
+ if (!vifs.bf_vif)
+ return 0;
+
+ mvmvif = iwl_mvm_vif_from_mac80211(vifs.bf_vif);
+
+ ba_enable = !(!mvmvif->pm_enabled || mvm->ps_disabled ||
+ !vifs.bf_vif->bss_conf.ps ||
+ iwl_mvm_vif_low_latency(mvmvif));
+
+ return iwl_mvm_update_beacon_abort(mvm, vifs.bf_vif, ba_enable);
+}
+
int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
struct ieee80211_vif *vif,
bool enable, u32 flags)
@@ -871,9 +900,10 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
if (WARN_ON(!dtimper_msec))
return 0;
- cmd.flags |=
- cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
cmd.skip_dtim_periods = 300 / dtimper_msec;
+ if (cmd.skip_dtim_periods)
+ cmd.flags |=
+ cpu_to_le16(POWER_FLAGS_SKIP_OVER_DTIM_MSK);
}
iwl_mvm_power_log(mvm, &cmd);
#ifdef CONFIG_IWLWIFI_DEBUGFS
@@ -904,23 +934,3 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm,
return ret;
}
-
-int iwl_mvm_update_beacon_filter(struct iwl_mvm *mvm,
- struct ieee80211_vif *vif,
- bool force,
- u32 flags)
-{
- struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
-
- if (mvmvif != mvm->bf_allowed_vif)
- return 0;
-
- if (!mvmvif->bf_data.bf_enabled) {
- /* disable beacon filtering explicitly if force is true */
- if (force)
- return iwl_mvm_disable_beacon_filter(mvm, vif, flags);
- return 0;
- }
-
- return iwl_mvm_enable_beacon_filter(mvm, vif, flags);
-}
diff --git a/drivers/net/wireless/iwlwifi/mvm/quota.c b/drivers/net/wireless/iwlwifi/mvm/quota.c
index 35e86e06dff..ba68d7b8450 100644
--- a/drivers/net/wireless/iwlwifi/mvm/quota.c
+++ b/drivers/net/wireless/iwlwifi/mvm/quota.c
@@ -285,7 +285,7 @@ int iwl_mvm_update_quotas(struct iwl_mvm *mvm, struct ieee80211_vif *newvif)
iwl_mvm_adjust_quota_for_noa(mvm, &cmd);
- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_QUOTA_CMD, 0,
sizeof(cmd), &cmd);
if (ret)
IWL_ERR(mvm, "Failed to send quota: %d\n", ret);
diff --git a/drivers/net/wireless/iwlwifi/mvm/rs.c b/drivers/net/wireless/iwlwifi/mvm/rs.c
index d44b2b33b5c..306a6caa486 100644
--- a/drivers/net/wireless/iwlwifi/mvm/rs.c
+++ b/drivers/net/wireless/iwlwifi/mvm/rs.c
@@ -211,7 +211,7 @@ static const struct rs_tx_column rs_tx_columns[] = {
.next_columns = {
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_SISO_ANT_A,
- RS_COLUMN_SISO_ANT_B,
+ RS_COLUMN_MIMO2,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
@@ -223,8 +223,8 @@ static const struct rs_tx_column rs_tx_columns[] = {
.ant = ANT_B,
.next_columns = {
RS_COLUMN_LEGACY_ANT_A,
- RS_COLUMN_SISO_ANT_A,
RS_COLUMN_SISO_ANT_B,
+ RS_COLUMN_MIMO2,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
RS_COLUMN_INVALID,
@@ -238,10 +238,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_A_SGI,
- RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -254,10 +254,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A,
RS_COLUMN_MIMO2,
RS_COLUMN_SISO_ANT_B_SGI,
- RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -271,10 +271,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI,
RS_COLUMN_SISO_ANT_A,
- RS_COLUMN_SISO_ANT_B,
- RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -289,10 +289,10 @@ static const struct rs_tx_column rs_tx_columns[] = {
RS_COLUMN_SISO_ANT_A_SGI,
RS_COLUMN_MIMO2_SGI,
RS_COLUMN_SISO_ANT_B,
- RS_COLUMN_SISO_ANT_A,
- RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_siso_allow,
@@ -304,12 +304,12 @@ static const struct rs_tx_column rs_tx_columns[] = {
.ant = ANT_AB,
.next_columns = {
RS_COLUMN_SISO_ANT_A,
- RS_COLUMN_SISO_ANT_B,
- RS_COLUMN_SISO_ANT_A_SGI,
- RS_COLUMN_SISO_ANT_B_SGI,
RS_COLUMN_MIMO2_SGI,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_mimo_allow,
@@ -321,12 +321,12 @@ static const struct rs_tx_column rs_tx_columns[] = {
.sgi = true,
.next_columns = {
RS_COLUMN_SISO_ANT_A_SGI,
- RS_COLUMN_SISO_ANT_B_SGI,
- RS_COLUMN_SISO_ANT_A,
- RS_COLUMN_SISO_ANT_B,
RS_COLUMN_MIMO2,
RS_COLUMN_LEGACY_ANT_A,
RS_COLUMN_LEGACY_ANT_B,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
+ RS_COLUMN_INVALID,
},
.checks = {
rs_mimo_allow,
@@ -1031,7 +1031,7 @@ static void rs_tx_status(void *mvm_r, struct ieee80211_supported_band *sband,
return;
}
-#ifdef CPTCFG_MAC80211_DEBUGFS
+#ifdef CONFIG_MAC80211_DEBUGFS
/* Disable last tx check if we are debugging with fixed rate */
if (lq_sta->dbg_fixed_rate) {
IWL_DEBUG_RATE(mvm, "Fixed rate. avoid rate scaling\n");
@@ -1335,105 +1335,50 @@ static void rs_set_expected_tpt_table(struct iwl_lq_sta *lq_sta,
tbl->expected_tpt = rs_get_expected_tpt_table(lq_sta, column, rate->bw);
}
-/*
- * Find starting rate for new "search" high-throughput mode of modulation.
- * Goal is to find lowest expected rate (under perfect conditions) that is
- * above the current measured throughput of "active" mode, to give new mode
- * a fair chance to prove itself without too many challenges.
- *
- * This gets called when transitioning to more aggressive modulation
- * (i.e. legacy to SISO or MIMO, or SISO to MIMO), as well as less aggressive
- * (i.e. MIMO to SISO). When moving to MIMO, bit rate will typically need
- * to decrease to match "active" throughput. When moving from MIMO to SISO,
- * bit rate will typically need to increase, but not if performance was bad.
- */
static s32 rs_get_best_rate(struct iwl_mvm *mvm,
struct iwl_lq_sta *lq_sta,
struct iwl_scale_tbl_info *tbl, /* "search" */
- u16 rate_mask, s8 index)
+ unsigned long rate_mask, s8 index)
{
- /* "active" values */
struct iwl_scale_tbl_info *active_tbl =
&(lq_sta->lq_info[lq_sta->active_tbl]);
- s32 active_sr = active_tbl->win[index].success_ratio;
- s32 active_tpt = active_tbl->expected_tpt[index];
- /* expected "search" throughput */
+ s32 success_ratio = active_tbl->win[index].success_ratio;
+ u16 expected_current_tpt = active_tbl->expected_tpt[index];
const u16 *tpt_tbl = tbl->expected_tpt;
-
- s32 new_rate, high, low, start_hi;
u16 high_low;
- s8 rate = index;
-
- new_rate = high = low = start_hi = IWL_RATE_INVALID;
-
- while (1) {
- high_low = rs_get_adjacent_rate(mvm, rate, rate_mask,
- tbl->rate.type);
-
- low = high_low & 0xff;
- high = (high_low >> 8) & 0xff;
+ u32 target_tpt;
+ int rate_idx;
- /*
- * Lower the "search" bit rate, to give new "search" mode
- * approximately the same throughput as "active" if:
- *
- * 1) "Active" mode has been working modestly well (but not
- * great), and expected "search" throughput (under perfect
- * conditions) at candidate rate is above the actual
- * measured "active" throughput (but less than expected
- * "active" throughput under perfect conditions).
- * OR
- * 2) "Active" mode has been working perfectly or very well
- * and expected "search" throughput (under perfect
- * conditions) at candidate rate is above expected
- * "active" throughput (under perfect conditions).
- */
- if ((((100 * tpt_tbl[rate]) > lq_sta->last_tpt) &&
- ((active_sr > RS_SR_FORCE_DECREASE) &&
- (active_sr <= IWL_RATE_HIGH_TH) &&
- (tpt_tbl[rate] <= active_tpt))) ||
- ((active_sr >= IWL_RATE_SCALE_SWITCH) &&
- (tpt_tbl[rate] > active_tpt))) {
- /* (2nd or later pass)
- * If we've already tried to raise the rate, and are
- * now trying to lower it, use the higher rate. */
- if (start_hi != IWL_RATE_INVALID) {
- new_rate = start_hi;
- break;
- }
-
- new_rate = rate;
-
- /* Loop again with lower rate */
- if (low != IWL_RATE_INVALID)
- rate = low;
+ if (success_ratio > RS_SR_NO_DECREASE) {
+ target_tpt = 100 * expected_current_tpt;
+ IWL_DEBUG_RATE(mvm,
+ "SR %d high. Find rate exceeding EXPECTED_CURRENT %d\n",
+ success_ratio, target_tpt);
+ } else {
+ target_tpt = lq_sta->last_tpt;
+ IWL_DEBUG_RATE(mvm,
+ "SR %d not thag good. Find rate exceeding ACTUAL_TPT %d\n",
+ success_ratio, target_tpt);
+ }
- /* Lower rate not available, use the original */
- else
- break;
+ rate_idx = find_first_bit(&rate_mask, BITS_PER_LONG);
- /* Else try to raise the "search" rate to match "active" */
- } else {
- /* (2nd or later pass)
- * If we've already tried to lower the rate, and are
- * now trying to raise it, use the lower rate. */
- if (new_rate != IWL_RATE_INVALID)
- break;
+ while (rate_idx != IWL_RATE_INVALID) {
+ if (target_tpt < (100 * tpt_tbl[rate_idx]))
+ break;
- /* Loop again with higher rate */
- else if (high != IWL_RATE_INVALID) {
- start_hi = high;
- rate = high;
+ high_low = rs_get_adjacent_rate(mvm, rate_idx, rate_mask,
+ tbl->rate.type);
- /* Higher rate not available, use the original */
- } else {
- new_rate = rate;
- break;
- }
- }
+ rate_idx = (high_low >> 8) & 0xff;
}
- return new_rate;
+ IWL_DEBUG_RATE(mvm, "Best rate found %d target_tp %d expected_new %d\n",
+ rate_idx, target_tpt,
+ rate_idx != IWL_RATE_INVALID ?
+ 100 * tpt_tbl[rate_idx] : IWL_INVALID_VALUE);
+
+ return rate_idx;
}
static u32 rs_bw_from_sta_bw(struct ieee80211_sta *sta)
@@ -1608,7 +1553,7 @@ static enum rs_column rs_get_next_column(struct iwl_mvm *mvm,
tpt = lq_sta->last_tpt / 100;
expected_tpt_tbl = rs_get_expected_tpt_table(lq_sta, next_col,
- tbl->rate.bw);
+ rs_bw_from_sta_bw(sta));
if (WARN_ON_ONCE(!expected_tpt_tbl))
continue;
@@ -1649,7 +1594,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
const struct rs_tx_column *curr_column = &rs_tx_columns[tbl->column];
u32 sz = (sizeof(struct iwl_scale_tbl_info) -
(sizeof(struct iwl_rate_scale_data) * IWL_RATE_COUNT));
- u16 rate_mask = 0;
+ unsigned long rate_mask = 0;
u32 rate_idx = 0;
memcpy(search_tbl, tbl, sz);
@@ -1691,7 +1636,7 @@ static int rs_switch_to_column(struct iwl_mvm *mvm,
!(BIT(rate_idx) & rate_mask)) {
IWL_DEBUG_RATE(mvm,
"can not switch with index %d"
- " rate mask %x\n",
+ " rate mask %lx\n",
rate_idx, rate_mask);
goto err;
@@ -1805,16 +1750,21 @@ static void rs_get_adjacent_txp(struct iwl_mvm *mvm, int index,
*stronger = TPC_INVALID;
}
-static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct rs_rate *rate,
- enum ieee80211_band band)
+static bool rs_tpc_allowed(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
+ struct rs_rate *rate, enum ieee80211_band band)
{
int index = rate->index;
+ bool cam = (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM);
+ bool sta_ps_disabled = (vif->type == NL80211_IFTYPE_STATION &&
+ !vif->bss_conf.ps);
+ IWL_DEBUG_RATE(mvm, "cam: %d sta_ps_disabled %d\n",
+ cam, sta_ps_disabled);
/*
* allow tpc only if power management is enabled, or bt coex
* activity grade allows it and we are on 2.4Ghz.
*/
- if (iwlmvm_mod_params.power_scheme == IWL_POWER_SCHEME_CAM &&
+ if ((cam || sta_ps_disabled) &&
!iwl_mvm_bt_coex_is_tpc_allowed(mvm, band))
return false;
@@ -1916,7 +1866,7 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
#ifdef CONFIG_MAC80211_DEBUGFS
if (lq_sta->dbg_fixed_txp_reduction <= TPC_MAX_REDUCTION) {
- IWL_DEBUG_RATE(mvm, "fixed tpc: %d",
+ IWL_DEBUG_RATE(mvm, "fixed tpc: %d\n",
lq_sta->dbg_fixed_txp_reduction);
lq_sta->lq.reduced_tpc = lq_sta->dbg_fixed_txp_reduction;
return cur != lq_sta->dbg_fixed_txp_reduction;
@@ -1931,9 +1881,9 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
band = chanctx_conf->def.chan->band;
rcu_read_unlock();
- if (!rs_tpc_allowed(mvm, rate, band)) {
+ if (!rs_tpc_allowed(mvm, vif, rate, band)) {
IWL_DEBUG_RATE(mvm,
- "tpc is not allowed. remove txp restrictions");
+ "tpc is not allowed. remove txp restrictions\n");
lq_sta->lq.reduced_tpc = TPC_NO_REDUCTION;
return cur != TPC_NO_REDUCTION;
}
@@ -1959,12 +1909,12 @@ static bool rs_tpc_perform(struct iwl_mvm *mvm,
/* override actions if we are on the edge */
if (weak == TPC_INVALID && action == TPC_ACTION_DECREASE) {
- IWL_DEBUG_RATE(mvm, "already in lowest txp, stay");
+ IWL_DEBUG_RATE(mvm, "already in lowest txp, stay\n");
action = TPC_ACTION_STAY;
} else if (strong == TPC_INVALID &&
(action == TPC_ACTION_INCREASE ||
action == TPC_ACTION_NO_RESTIRCTION)) {
- IWL_DEBUG_RATE(mvm, "already in highest txp, stay");
+ IWL_DEBUG_RATE(mvm, "already in highest txp, stay\n");
action = TPC_ACTION_STAY;
}
@@ -2235,7 +2185,8 @@ static void rs_rate_scale_perform(struct iwl_mvm *mvm,
break;
case RS_ACTION_STAY:
/* No change */
- update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);
+ if (lq_sta->rs_state == RS_STATE_STAY_IN_COLUMN)
+ update_lq = rs_tpc_perform(mvm, sta, lq_sta, tbl);
break;
default:
break;
@@ -2489,10 +2440,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
if (i == IWL_RATE_9M_INDEX)
continue;
- /* Disable MCS9 as a workaround */
- if (i == IWL_RATE_MCS_9_INDEX)
- continue;
-
/* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
if (i == IWL_RATE_MCS_9_INDEX &&
sta->bandwidth == IEEE80211_STA_RX_BW_20)
@@ -2511,10 +2458,6 @@ static void rs_vht_set_enabled_rates(struct ieee80211_sta *sta,
if (i == IWL_RATE_9M_INDEX)
continue;
- /* Disable MCS9 as a workaround */
- if (i == IWL_RATE_MCS_9_INDEX)
- continue;
-
/* VHT MCS9 isn't valid for 20Mhz for NSS=1,2 */
if (i == IWL_RATE_MCS_9_INDEX &&
sta->bandwidth == IEEE80211_STA_RX_BW_20)
diff --git a/drivers/net/wireless/iwlwifi/mvm/scan.c b/drivers/net/wireless/iwlwifi/mvm/scan.c
index 63e7b16edb5..eac2b424f6a 100644
--- a/drivers/net/wireless/iwlwifi/mvm/scan.c
+++ b/drivers/net/wireless/iwlwifi/mvm/scan.c
@@ -277,51 +277,22 @@ static void iwl_mvm_scan_calc_params(struct iwl_mvm *mvm,
IEEE80211_IFACE_ITER_NORMAL,
iwl_mvm_scan_condition_iterator,
&global_bound);
- /*
- * Under low latency traffic passive scan is fragmented meaning
- * that dwell on a particular channel will be fragmented. Each fragment
- * dwell time is 20ms and fragments period is 105ms. Skipping to next
- * channel will be delayed by the same period - 105ms. So suspend_time
- * parameter describing both fragments and channels skipping periods is
- * set to 105ms. This value is chosen so that overall passive scan
- * duration will not be too long. Max_out_time in this case is set to
- * 70ms, so for active scanning operating channel will be left for 70ms
- * while for passive still for 20ms (fragment dwell).
- */
- if (global_bound) {
- if (!iwl_mvm_low_latency(mvm)) {
- params->suspend_time = ieee80211_tu_to_usec(100);
- params->max_out_time = ieee80211_tu_to_usec(600);
- } else {
- params->suspend_time = ieee80211_tu_to_usec(105);
- /* P2P doesn't support fragmented passive scan, so
- * configure max_out_time to be at least longest dwell
- * time for passive scan.
- */
- if (vif->type == NL80211_IFTYPE_STATION && !vif->p2p) {
- params->max_out_time = ieee80211_tu_to_usec(70);
- params->passive_fragmented = true;
- } else {
- u32 passive_dwell;
-
- /*
- * Use band G so that passive channel dwell time
- * will be assigned with maximum value.
- */
- band = IEEE80211_BAND_2GHZ;
- passive_dwell = iwl_mvm_get_passive_dwell(band);
- params->max_out_time =
- ieee80211_tu_to_usec(passive_dwell);
- }
- }
+
+ if (!global_bound)
+ goto not_bound;
+
+ params->suspend_time = 100;
+ params->max_out_time = 600;
+
+ if (iwl_mvm_low_latency(mvm)) {
+ params->suspend_time = 250;
+ params->max_out_time = 250;
}
+not_bound:
+
for (band = IEEE80211_BAND_2GHZ; band < IEEE80211_NUM_BANDS; band++) {
- if (params->passive_fragmented)
- params->dwell[band].passive = 20;
- else
- params->dwell[band].passive =
- iwl_mvm_get_passive_dwell(band);
+ params->dwell[band].passive = iwl_mvm_get_passive_dwell(band);
params->dwell[band].active = iwl_mvm_get_active_dwell(band,
n_ssids);
}
@@ -335,7 +306,6 @@ int iwl_mvm_scan_request(struct iwl_mvm *mvm,
.id = SCAN_REQUEST_CMD,
.len = { 0, },
.data = { mvm->scan_cmd, },
- .flags = CMD_SYNC,
.dataflags = { IWL_HCMD_DFL_NOCOPY, },
};
struct iwl_scan_cmd *cmd = mvm->scan_cmd;
@@ -546,7 +516,7 @@ int iwl_mvm_cancel_scan(struct iwl_mvm *mvm)
ARRAY_SIZE(scan_abort_notif),
iwl_mvm_scan_abort_notif, NULL);
- ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, CMD_SYNC, 0, NULL);
+ ret = iwl_mvm_send_cmd_pdu(mvm, SCAN_ABORT_CMD, 0, 0, NULL);
if (ret) {
IWL_ERR(mvm, "Couldn't send SCAN_ABORT_CMD: %d\n", ret);
/* mac80211's state will be cleaned in the nic_restart flow */
@@ -618,9 +588,7 @@ static void iwl_build_scan_cmd(struct iwl_mvm *mvm,
struct iwl_scan_offload_cmd *scan,
struct iwl_mvm_scan_params *params)
{
- scan->channel_count =
- mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels +
- mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
+ scan->channel_count = req->n_channels;
scan->quiet_time = cpu_to_le16(IWL_ACTIVE_QUIET_TIME);
scan->quiet_plcp_th = cpu_to_le16(IWL_PLCP_QUIET_THRESH);
scan->good_CRC_th = IWL_GOOD_CRC_TH_DEFAULT;
@@ -699,61 +667,37 @@ static void iwl_build_channel_cfg(struct iwl_mvm *mvm,
struct cfg80211_sched_scan_request *req,
struct iwl_scan_channel_cfg *channels,
enum ieee80211_band band,
- int *head, int *tail,
+ int *head,
u32 ssid_bitmap,
struct iwl_mvm_scan_params *params)
{
- struct ieee80211_supported_band *s_band;
- int n_channels = req->n_channels;
- int i, j, index = 0;
- bool partial;
+ int i, index = 0;
- /*
- * We have to configure all supported channels, even if we don't want to
- * scan on them, but we have to send channels in the order that we want
- * to scan. So add requested channels to head of the list and others to
- * the end.
- */
- s_band = &mvm->nvm_data->bands[band];
-
- for (i = 0; i < s_band->n_channels && *head <= *tail; i++) {
- partial = false;
- for (j = 0; j < n_channels; j++)
- if (s_band->channels[i].center_freq ==
- req->channels[j]->center_freq) {
- index = *head;
- (*head)++;
- /*
- * Channels that came with the request will be
- * in partial scan .
- */
- partial = true;
- break;
- }
- if (!partial) {
- index = *tail;
- (*tail)--;
- }
- channels->channel_number[index] =
- cpu_to_le16(ieee80211_frequency_to_channel(
- s_band->channels[i].center_freq));
+ for (i = 0; i < req->n_channels; i++) {
+ struct ieee80211_channel *chan = req->channels[i];
+
+ if (chan->band != band)
+ continue;
+
+ index = *head;
+ (*head)++;
+
+ channels->channel_number[index] = cpu_to_le16(chan->hw_value);
channels->dwell_time[index][0] = params->dwell[band].active;
channels->dwell_time[index][1] = params->dwell[band].passive;
channels->iter_count[index] = cpu_to_le16(1);
channels->iter_interval[index] = 0;
- if (!(s_band->channels[i].flags & IEEE80211_CHAN_NO_IR))
+ if (!(chan->flags & IEEE80211_CHAN_NO_IR))
channels->type[index] |=
cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_ACTIVE);
channels->type[index] |=
- cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL);
- if (partial)
- channels->type[index] |=
- cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
+ cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_FULL |
+ IWL_SCAN_OFFLOAD_CHANNEL_PARTIAL);
- if (s_band->channels[i].flags & IEEE80211_CHAN_NO_HT40)
+ if (chan->flags & IEEE80211_CHAN_NO_HT40)
channels->type[index] |=
cpu_to_le32(IWL_SCAN_OFFLOAD_CHANNEL_NARROW);
@@ -770,7 +714,6 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
int band_2ghz = mvm->nvm_data->bands[IEEE80211_BAND_2GHZ].n_channels;
int band_5ghz = mvm->nvm_data->bands[IEEE80211_BAND_5GHZ].n_channels;
int head = 0;
- int tail = band_2ghz + band_5ghz;
u32 ssid_bitmap;
int cmd_len;
int ret;
@@ -778,7 +721,6 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
struct iwl_scan_offload_cfg *scan_cfg;
struct iwl_host_cmd cmd = {
.id = SCAN_OFFLOAD_CONFIG_CMD,
- .flags = CMD_SYNC,
};
struct iwl_mvm_scan_params params = {};
@@ -803,7 +745,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
&scan_cfg->scan_cmd.tx_cmd[0],
scan_cfg->data);
iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
- IEEE80211_BAND_2GHZ, &head, &tail,
+ IEEE80211_BAND_2GHZ, &head,
ssid_bitmap, &params);
}
if (band_5ghz) {
@@ -813,7 +755,7 @@ int iwl_mvm_config_sched_scan(struct iwl_mvm *mvm,
scan_cfg->data +
SCAN_OFFLOAD_PROBE_REQ_SIZE);
iwl_build_channel_cfg(mvm, req, &scan_cfg->channel_cfg,
- IEEE80211_BAND_5GHZ, &head, &tail,
+ IEEE80211_BAND_5GHZ, &head,
ssid_bitmap, &params);
}
@@ -836,7 +778,6 @@ int iwl_mvm_config_sched_scan_profiles(struct iwl_mvm *mvm,
struct iwl_scan_offload_blacklist *blacklist;
struct iwl_host_cmd cmd = {
.id = SCAN_OFFLOAD_UPDATE_PROFILES_CMD,
- .flags = CMD_SYNC,
.len[1] = sizeof(*profile_cfg),
.dataflags[0] = IWL_HCMD_DFL_NOCOPY,
.dataflags[1] = IWL_HCMD_DFL_NOCOPY,
@@ -927,7 +868,7 @@ int iwl_mvm_sched_scan_start(struct iwl_mvm *mvm,
scan_req.flags |=
cpu_to_le16(IWL_SCAN_OFFLOAD_FLAG_EBS_ACCURATE_MODE);
- return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, SCAN_OFFLOAD_REQUEST_CMD, 0,
sizeof(scan_req), &scan_req);
}
@@ -936,7 +877,6 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
int ret;
struct iwl_host_cmd cmd = {
.id = SCAN_OFFLOAD_ABORT_CMD,
- .flags = CMD_SYNC,
};
u32 status;
@@ -965,7 +905,7 @@ static int iwl_mvm_send_sched_scan_abort(struct iwl_mvm *mvm)
return ret;
}
-int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm)
+int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm, bool notify)
{
int ret;
struct iwl_notification_wait wait_scan_done;
@@ -1003,5 +943,8 @@ int iwl_mvm_sched_scan_stop(struct iwl_mvm *mvm)
*/
mvm->scan_status = IWL_MVM_SCAN_NONE;
+ if (notify)
+ ieee80211_sched_scan_stopped(mvm->hw);
+
return 0;
}
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.c b/drivers/net/wireless/iwlwifi/mvm/sta.c
index 3e11b9d802e..1fb01ea2e70 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.c
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.c
@@ -327,7 +327,7 @@ static int iwl_mvm_rm_sta_common(struct iwl_mvm *mvm, u8 sta_id)
return -EINVAL;
}
- ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, REMOVE_STA, 0,
sizeof(rm_sta_cmd), &rm_sta_cmd);
if (ret) {
IWL_ERR(mvm, "Failed to remove station. Id=%d\n", sta_id);
@@ -1053,12 +1053,12 @@ static int iwl_mvm_send_sta_key(struct iwl_mvm *mvm,
cmd.sta_id = sta_id;
status = ADD_STA_SUCCESS;
- if (cmd_flags == CMD_SYNC)
- ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
- &cmd, &status);
- else
+ if (cmd_flags & CMD_ASYNC)
ret = iwl_mvm_send_cmd_pdu(mvm, ADD_STA_KEY, CMD_ASYNC,
sizeof(cmd), &cmd);
+ else
+ ret = iwl_mvm_send_cmd_pdu_status(mvm, ADD_STA_KEY, sizeof(cmd),
+ &cmd, &status);
switch (status) {
case ADD_STA_SUCCESS:
@@ -1111,7 +1111,7 @@ static int iwl_mvm_send_sta_igtk(struct iwl_mvm *mvm,
remove_key ? "removing" : "installing",
igtk_cmd.sta_id);
- return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, CMD_SYNC,
+ return iwl_mvm_send_cmd_pdu(mvm, MGMT_MCAST_KEY, 0,
sizeof(igtk_cmd), &igtk_cmd);
}
@@ -1198,15 +1198,15 @@ int iwl_mvm_set_sta_key(struct iwl_mvm *mvm,
ieee80211_get_key_rx_seq(keyconf, 0, &seq);
ieee80211_get_tkip_rx_p1k(keyconf, addr, seq.tkip.iv32, p1k);
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
- seq.tkip.iv32, p1k, CMD_SYNC);
+ seq.tkip.iv32, p1k, 0);
break;
case WLAN_CIPHER_SUITE_CCMP:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf, sta_id,
- 0, NULL, CMD_SYNC);
+ 0, NULL, 0);
break;
default:
ret = iwl_mvm_send_sta_key(mvm, mvm_sta, keyconf,
- sta_id, 0, NULL, CMD_SYNC);
+ sta_id, 0, NULL, 0);
}
if (ret)
diff --git a/drivers/net/wireless/iwlwifi/mvm/sta.h b/drivers/net/wireless/iwlwifi/mvm/sta.h
index e5e3071ff25..d98e8a2142b 100644
--- a/drivers/net/wireless/iwlwifi/mvm/sta.h
+++ b/drivers/net/wireless/iwlwifi/mvm/sta.h
@@ -287,8 +287,6 @@ static inline u16 iwl_mvm_tid_queued(struct iwl_mvm_tid_data *tid_data)
* @tid_disable_agg: bitmap: if bit(tid) is set, the fw won't send ampdus for
* tid.
* @max_agg_bufsize: the maximal size of the AGG buffer for this station
- * @bt_reduced_txpower_dbg: debug mode in which %bt_reduced_txpower is forced
- * by debugfs.
* @bt_reduced_txpower: is reduced tx power enabled for this station
* @next_status_eosp: the next reclaimed packet is a PS-Poll response and
* we need to signal the EOSP
@@ -309,7 +307,6 @@ struct iwl_mvm_sta {
u32 mac_id_n_color;
u16 tid_disable_agg;
u8 max_agg_bufsize;
- bool bt_reduced_txpower_dbg;
bool bt_reduced_txpower;
bool next_status_eosp;
spinlock_t lock;
diff --git a/drivers/net/wireless/iwlwifi/mvm/time-event.c b/drivers/net/wireless/iwlwifi/mvm/time-event.c
index a9402937f76..80100f6cc12 100644
--- a/drivers/net/wireless/iwlwifi/mvm/time-event.c
+++ b/drivers/net/wireless/iwlwifi/mvm/time-event.c
@@ -312,7 +312,7 @@ static int iwl_mvm_time_event_send_add(struct iwl_mvm *mvm,
ARRAY_SIZE(time_event_response),
iwl_mvm_time_event_response, te_data);
- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0,
sizeof(*te_cmd), te_cmd);
if (ret) {
IWL_ERR(mvm, "Couldn't send TIME_EVENT_CMD: %d\n", ret);
@@ -434,7 +434,7 @@ void iwl_mvm_remove_time_event(struct iwl_mvm *mvm,
cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color));
IWL_DEBUG_TE(mvm, "Removing TE 0x%x\n", le32_to_cpu(time_cmd.id));
- ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, CMD_SYNC,
+ ret = iwl_mvm_send_cmd_pdu(mvm, TIME_EVENT_CMD, 0,
sizeof(time_cmd), &time_cmd);
if (WARN_ON(ret))
return;
diff --git a/drivers/net/wireless/iwlwifi/mvm/tt.c b/drivers/net/wireless/iwlwifi/mvm/tt.c
index 39a3e03a0ac..86856151278 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tt.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tt.c
@@ -409,7 +409,6 @@ void iwl_mvm_tt_tx_backoff(struct iwl_mvm *mvm, u32 backoff)
.id = REPLY_THERMAL_MNG_BACKOFF,
.len = { sizeof(u32), },
.data = { &backoff, },
- .flags = CMD_SYNC,
};
backoff = max(backoff, mvm->thermal_throttle.min_backoff);
diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c
index ff1b630e130..3846a6c41eb 100644
--- a/drivers/net/wireless/iwlwifi/mvm/tx.c
+++ b/drivers/net/wireless/iwlwifi/mvm/tx.c
@@ -958,7 +958,7 @@ int iwl_mvm_flush_tx_path(struct iwl_mvm *mvm, u32 tfd_msk, bool sync)
.flush_ctl = cpu_to_le16(DUMP_TX_FIFO_FLUSH),
};
- u32 flags = sync ? CMD_SYNC : CMD_ASYNC;
+ u32 flags = sync ? 0 : CMD_ASYNC;
ret = iwl_mvm_send_cmd_pdu(mvm, TXPATH_FLUSH, flags,
sizeof(flush_cmd), &flush_cmd);
diff --git a/drivers/net/wireless/iwlwifi/mvm/utils.c b/drivers/net/wireless/iwlwifi/mvm/utils.c
index c5f4532cafa..aa9fc77e841 100644
--- a/drivers/net/wireless/iwlwifi/mvm/utils.c
+++ b/drivers/net/wireless/iwlwifi/mvm/utils.c
@@ -144,7 +144,7 @@ int iwl_mvm_send_cmd_status(struct iwl_mvm *mvm, struct iwl_host_cmd *cmd,
"cmd flags %x", cmd->flags))
return -EINVAL;
- cmd->flags |= CMD_SYNC | CMD_WANT_SKB;
+ cmd->flags |= CMD_WANT_SKB;
ret = iwl_trans_send_cmd(mvm->trans, cmd);
if (ret == -ERFKILL) {
@@ -519,6 +519,7 @@ void iwl_mvm_dump_nic_error_log(struct iwl_mvm *mvm)
iwl_mvm_dump_umac_error_log(mvm);
}
+#ifdef CONFIG_IWLWIFI_DEBUGFS
void iwl_mvm_fw_error_sram_dump(struct iwl_mvm *mvm)
{
const struct fw_img *img;
@@ -581,6 +582,7 @@ void iwl_mvm_fw_error_rxf_dump(struct iwl_mvm *mvm)
}
iwl_trans_release_nic_access(mvm->trans, &flags);
}
+#endif
/**
* iwl_mvm_send_lq_cmd() - Send link quality command
@@ -597,7 +599,7 @@ int iwl_mvm_send_lq_cmd(struct iwl_mvm *mvm, struct iwl_lq_cmd *lq, bool init)
struct iwl_host_cmd cmd = {
.id = LQ_CMD,
.len = { sizeof(struct iwl_lq_cmd), },
- .flags = init ? CMD_SYNC : CMD_ASYNC,
+ .flags = init ? 0 : CMD_ASYNC,
.data = { lq, },
};
@@ -648,6 +650,39 @@ void iwl_mvm_update_smps(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
ieee80211_request_smps(vif, smps_mode);
}
+static void iwl_mvm_diversity_iter(void *_data, u8 *mac,
+ struct ieee80211_vif *vif)
+{
+ struct iwl_mvm_vif *mvmvif = iwl_mvm_vif_from_mac80211(vif);
+ bool *result = _data;
+ int i;
+
+ for (i = 0; i < NUM_IWL_MVM_SMPS_REQ; i++) {
+ if (mvmvif->smps_requests[i] == IEEE80211_SMPS_STATIC ||
+ mvmvif->smps_requests[i] == IEEE80211_SMPS_DYNAMIC)
+ *result = false;
+ }
+}
+
+bool iwl_mvm_rx_diversity_allowed(struct iwl_mvm *mvm)
+{
+ bool result = true;
+
+ lockdep_assert_held(&mvm->mutex);
+
+ if (num_of_ant(mvm->fw->valid_rx_ant) == 1)
+ return false;
+
+ if (!mvm->cfg->rx_with_siso_diversity)
+ return false;
+
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_diversity_iter, &result);
+
+ return result;
+}
+
int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
bool value)
{
@@ -667,7 +702,7 @@ int iwl_mvm_update_low_latency(struct iwl_mvm *mvm, struct ieee80211_vif *vif,
iwl_mvm_bt_coex_vif_change(mvm);
- return iwl_mvm_power_update_mac(mvm, vif);
+ return iwl_mvm_power_update_mac(mvm);
}
static void iwl_mvm_ll_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
@@ -688,3 +723,22 @@ bool iwl_mvm_low_latency(struct iwl_mvm *mvm)
return result;
}
+
+static void iwl_mvm_idle_iter(void *_data, u8 *mac, struct ieee80211_vif *vif)
+{
+ bool *idle = _data;
+
+ if (!vif->bss_conf.idle)
+ *idle = false;
+}
+
+bool iwl_mvm_is_idle(struct iwl_mvm *mvm)
+{
+ bool idle = true;
+
+ ieee80211_iterate_active_interfaces_atomic(
+ mvm->hw, IEEE80211_IFACE_ITER_NORMAL,
+ iwl_mvm_idle_iter, &idle);
+
+ return idle;
+}
diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c
index 3d1d57f9f5b..98950e45c7b 100644
--- a/drivers/net/wireless/iwlwifi/pcie/drv.c
+++ b/drivers/net/wireless/iwlwifi/pcie/drv.c
@@ -367,6 +367,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x095A, 0x5012, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5412, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5410, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095A, 0x5510, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5400, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x1010, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x5000, iwl7265_2n_cfg)},
@@ -380,7 +381,7 @@ static DEFINE_PCI_DEVICE_TABLE(iwl_hw_card_ids) = {
{IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)},
- {IWL_PCI_DEVICE(0x095A, 0x9200, iwl7265_2ac_cfg)},
+ {IWL_PCI_DEVICE(0x095B, 0x9200, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9510, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9310, iwl7265_2ac_cfg)},
{IWL_PCI_DEVICE(0x095A, 0x9410, iwl7265_2ac_cfg)},
@@ -417,7 +418,7 @@ static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
splx->package.count != 2 ||
splx->package.elements[0].type != ACPI_TYPE_INTEGER ||
splx->package.elements[0].integer.value != 0) {
- IWL_ERR(trans, "Unsupported splx structure");
+ IWL_ERR(trans, "Unsupported splx structure\n");
return 0;
}
@@ -426,14 +427,14 @@ static u64 splx_get_pwr_limit(struct iwl_trans *trans, union acpi_object *splx)
limits->package.count < 2 ||
limits->package.elements[0].type != ACPI_TYPE_INTEGER ||
limits->package.elements[1].type != ACPI_TYPE_INTEGER) {
- IWL_ERR(trans, "Invalid limits element");
+ IWL_ERR(trans, "Invalid limits element\n");
return 0;
}
domain_type = &limits->package.elements[0];
power_limit = &limits->package.elements[1];
if (!(domain_type->integer.value & SPL_DOMAINTYPE_WIFI)) {
- IWL_DEBUG_INFO(trans, "WiFi power is not limited");
+ IWL_DEBUG_INFO(trans, "WiFi power is not limited\n");
return 0;
}
@@ -450,26 +451,26 @@ static void set_dflt_pwr_limit(struct iwl_trans *trans, struct pci_dev *pdev)
pxsx_handle = ACPI_HANDLE(&pdev->dev);
if (!pxsx_handle) {
IWL_DEBUG_INFO(trans,
- "Could not retrieve root port ACPI handle");
+ "Could not retrieve root port ACPI handle\n");
return;
}
/* Get the method's handle */
status = acpi_get_handle(pxsx_handle, (acpi_string)SPL_METHOD, &handle);
if (ACPI_FAILURE(status)) {
- IWL_DEBUG_INFO(trans, "SPL method not found");
+ IWL_DEBUG_INFO(trans, "SPL method not found\n");
return;
}
/* Call SPLC with no arguments */
status = acpi_evaluate_object(handle, NULL, NULL, &splx);
if (ACPI_FAILURE(status)) {
- IWL_ERR(trans, "SPLC invocation failed (0x%x)", status);
+ IWL_ERR(trans, "SPLC invocation failed (0x%x)\n", status);
return;
}
trans->dflt_pwr_limit = splx_get_pwr_limit(trans, splx.pointer);
- IWL_DEBUG_INFO(trans, "Default power limit set to %lld",
+ IWL_DEBUG_INFO(trans, "Default power limit set to %lld\n",
trans->dflt_pwr_limit);
kfree(splx.pointer);
}
diff --git a/drivers/net/wireless/iwlwifi/pcie/internal.h b/drivers/net/wireless/iwlwifi/pcie/internal.h
index 1b95d856dfd..6c22b23a284 100644
--- a/drivers/net/wireless/iwlwifi/pcie/internal.h
+++ b/drivers/net/wireless/iwlwifi/pcie/internal.h
@@ -117,21 +117,19 @@ struct iwl_dma_ptr {
/**
* iwl_queue_inc_wrap - increment queue index, wrap back to beginning
* @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
*/
-static inline int iwl_queue_inc_wrap(int index, int n_bd)
+static inline int iwl_queue_inc_wrap(int index)
{
- return ++index & (n_bd - 1);
+ return ++index & (TFD_QUEUE_SIZE_MAX - 1);
}
/**
* iwl_queue_dec_wrap - decrement queue index, wrap back to end
* @index -- current index
- * @n_bd -- total number of entries in queue (must be power of 2)
*/
-static inline int iwl_queue_dec_wrap(int index, int n_bd)
+static inline int iwl_queue_dec_wrap(int index)
{
- return --index & (n_bd - 1);
+ return --index & (TFD_QUEUE_SIZE_MAX - 1);
}
struct iwl_cmd_meta {
@@ -145,13 +143,13 @@ struct iwl_cmd_meta {
*
* Contains common data for Rx and Tx queues.
*
- * Note the difference between n_bd and n_window: the hardware
- * always assumes 256 descriptors, so n_bd is always 256 (unless
+ * Note the difference between TFD_QUEUE_SIZE_MAX and n_window: the hardware
+ * always assumes 256 descriptors, so TFD_QUEUE_SIZE_MAX is always 256 (unless
* there might be HW changes in the future). For the normal TX
* queues, n_window, which is the size of the software queue data
* is also 256; however, for the command queue, n_window is only
* 32 since we don't need so many commands pending. Since the HW
- * still uses 256 BDs for DMA though, n_bd stays 256. As a result,
+ * still uses 256 BDs for DMA though, TFD_QUEUE_SIZE_MAX stays 256. As a result,
* the software buffers (in the variables @meta, @txb in struct
* iwl_txq) only have 32 entries, while the HW buffers (@tfds in
* the same struct) have 256.
@@ -162,7 +160,6 @@ struct iwl_cmd_meta {
* data is a window overlayed over the HW queue.
*/
struct iwl_queue {
- int n_bd; /* number of BDs in this queue */
int write_ptr; /* 1-st empty entry (index) host_w*/
int read_ptr; /* last used entry (index) host_r*/
/* use for monitoring and recovering the stuck queue */
@@ -373,6 +370,13 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
struct sk_buff_head *skbs);
void iwl_trans_pcie_tx_reset(struct iwl_trans *trans);
+static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
+{
+ struct iwl_tfd_tb *tb = &tfd->tbs[idx];
+
+ return le16_to_cpu(tb->hi_n_len) >> 4;
+}
+
/*****************************************************
* Error handling
******************************************************/
diff --git a/drivers/net/wireless/iwlwifi/pcie/rx.c b/drivers/net/wireless/iwlwifi/pcie/rx.c
index 4a26a082a1b..a2698e5e062 100644
--- a/drivers/net/wireless/iwlwifi/pcie/rx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/rx.c
@@ -850,7 +850,7 @@ static u32 iwl_pcie_int_cause_ict(struct iwl_trans *trans)
trans_pcie->ict_index, read);
trans_pcie->ict_tbl[trans_pcie->ict_index] = 0;
trans_pcie->ict_index =
- iwl_queue_inc_wrap(trans_pcie->ict_index, ICT_COUNT);
+ ((trans_pcie->ict_index + 1) & (ICT_COUNT - 1));
read = le32_to_cpu(trans_pcie->ict_tbl[trans_pcie->ict_index]);
trace_iwlwifi_dev_ict_read(trans->dev, trans_pcie->ict_index,
diff --git a/drivers/net/wireless/iwlwifi/pcie/trans.c b/drivers/net/wireless/iwlwifi/pcie/trans.c
index f98ef1e62eb..788085bc65d 100644
--- a/drivers/net/wireless/iwlwifi/pcie/trans.c
+++ b/drivers/net/wireless/iwlwifi/pcie/trans.c
@@ -73,6 +73,7 @@
#include "iwl-csr.h"
#include "iwl-prph.h"
#include "iwl-agn-hw.h"
+#include "iwl-fw-error-dump.h"
#include "internal.h"
static u32 iwl_trans_pcie_read_shr(struct iwl_trans *trans, u32 reg)
@@ -453,6 +454,7 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
{
int ret;
int t = 0;
+ int iter;
IWL_DEBUG_INFO(trans, "iwl_trans_prepare_card_hw enter\n");
@@ -461,18 +463,23 @@ static int iwl_pcie_prepare_card_hw(struct iwl_trans *trans)
if (ret >= 0)
return 0;
- /* If HW is not ready, prepare the conditions to check again */
- iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
- CSR_HW_IF_CONFIG_REG_PREPARE);
+ for (iter = 0; iter < 10; iter++) {
+ /* If HW is not ready, prepare the conditions to check again */
+ iwl_set_bit(trans, CSR_HW_IF_CONFIG_REG,
+ CSR_HW_IF_CONFIG_REG_PREPARE);
+
+ do {
+ ret = iwl_pcie_set_hw_ready(trans);
+ if (ret >= 0)
+ return 0;
- do {
- ret = iwl_pcie_set_hw_ready(trans);
- if (ret >= 0)
- return 0;
+ usleep_range(200, 1000);
+ t += 200;
+ } while (t < 150000);
+ msleep(25);
+ }
- usleep_range(200, 1000);
- t += 200;
- } while (t < 150000);
+ IWL_DEBUG_INFO(trans, "got NIC after %d iterations\n", iter);
return ret;
}
@@ -1337,8 +1344,8 @@ static int iwl_trans_pcie_wait_txq_empty(struct iwl_trans *trans, u32 txq_bm)
IWL_ERR(trans,
"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
cnt, active ? "" : "in", fifo, tbl_dw,
- iwl_read_prph(trans,
- SCD_QUEUE_RDPTR(cnt)) & (txq->q.n_bd - 1),
+ iwl_read_prph(trans, SCD_QUEUE_RDPTR(cnt)) &
+ (TFD_QUEUE_SIZE_MAX - 1),
iwl_read_prph(trans, SCD_QUEUE_WRPTR(cnt)));
}
@@ -1669,6 +1676,61 @@ err:
IWL_ERR(trans, "failed to create the trans debugfs entry\n");
return -ENOMEM;
}
+
+static u32 iwl_trans_pcie_get_cmdlen(struct iwl_tfd *tfd)
+{
+ u32 cmdlen = 0;
+ int i;
+
+ for (i = 0; i < IWL_NUM_OF_TBS; i++)
+ cmdlen += iwl_pcie_tfd_tb_get_len(tfd, i);
+
+ return cmdlen;
+}
+
+static u32 iwl_trans_pcie_dump_data(struct iwl_trans *trans,
+ void *buf, u32 buflen)
+{
+ struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
+ struct iwl_fw_error_dump_data *data;
+ struct iwl_txq *cmdq = &trans_pcie->txq[trans_pcie->cmd_queue];
+ struct iwl_fw_error_dump_txcmd *txcmd;
+ u32 len;
+ int i, ptr;
+
+ if (!buf)
+ return sizeof(*data) +
+ cmdq->q.n_window * (sizeof(*txcmd) +
+ TFD_MAX_PAYLOAD_SIZE);
+
+ len = 0;
+ data = buf;
+ data->type = cpu_to_le32(IWL_FW_ERROR_DUMP_TXCMD);
+ txcmd = (void *)data->data;
+ spin_lock_bh(&cmdq->lock);
+ ptr = cmdq->q.write_ptr;
+ for (i = 0; i < cmdq->q.n_window; i++) {
+ u8 idx = get_cmd_index(&cmdq->q, ptr);
+ u32 caplen, cmdlen;
+
+ cmdlen = iwl_trans_pcie_get_cmdlen(&cmdq->tfds[ptr]);
+ caplen = min_t(u32, TFD_MAX_PAYLOAD_SIZE, cmdlen);
+
+ if (cmdlen) {
+ len += sizeof(*txcmd) + caplen;
+ txcmd->cmdlen = cpu_to_le32(cmdlen);
+ txcmd->caplen = cpu_to_le32(caplen);
+ memcpy(txcmd->data, cmdq->entries[idx].cmd, caplen);
+ txcmd = (void *)((u8 *)txcmd->data + caplen);
+ }
+
+ ptr = iwl_queue_dec_wrap(ptr);
+ }
+ spin_unlock_bh(&cmdq->lock);
+
+ data->len = cpu_to_le32(len);
+ return sizeof(*data) + len;
+}
#else
static int iwl_trans_pcie_dbgfs_register(struct iwl_trans *trans,
struct dentry *dir)
@@ -1711,6 +1773,10 @@ static const struct iwl_trans_ops trans_ops_pcie = {
.grab_nic_access = iwl_trans_pcie_grab_nic_access,
.release_nic_access = iwl_trans_pcie_release_nic_access,
.set_bits_mask = iwl_trans_pcie_set_bits_mask,
+
+#ifdef CONFIG_IWLWIFI_DEBUGFS
+ .dump_data = iwl_trans_pcie_dump_data,
+#endif
};
struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
@@ -1788,6 +1854,10 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
* PCI Tx retries from interfering with C3 CPU state */
pci_write_config_byte(pdev, PCI_CFG_RETRY_TIMEOUT, 0x00);
+ trans->dev = &pdev->dev;
+ trans_pcie->pci_dev = pdev;
+ iwl_disable_interrupts(trans);
+
err = pci_enable_msi(pdev);
if (err) {
dev_err(&pdev->dev, "pci_enable_msi failed(0X%x)\n", err);
@@ -1799,8 +1869,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
}
}
- trans->dev = &pdev->dev;
- trans_pcie->pci_dev = pdev;
trans->hw_rev = iwl_read32(trans, CSR_HW_REV);
trans->hw_id = (pdev->device << 16) + pdev->subsystem_device;
snprintf(trans->hw_id_str, sizeof(trans->hw_id_str),
@@ -1826,8 +1894,6 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
goto out_pci_disable_msi;
}
- trans_pcie->inta_mask = CSR_INI_SET_MASK;
-
if (iwl_pcie_alloc_ict(trans))
goto out_free_cmd_pool;
@@ -1839,6 +1905,8 @@ struct iwl_trans *iwl_trans_pcie_alloc(struct pci_dev *pdev,
goto out_free_ict;
}
+ trans_pcie->inta_mask = CSR_INI_SET_MASK;
+
return trans;
out_free_ict:
diff --git a/drivers/net/wireless/iwlwifi/pcie/tx.c b/drivers/net/wireless/iwlwifi/pcie/tx.c
index dde6031f425..038940afbdc 100644
--- a/drivers/net/wireless/iwlwifi/pcie/tx.c
+++ b/drivers/net/wireless/iwlwifi/pcie/tx.c
@@ -70,20 +70,20 @@ static int iwl_queue_space(const struct iwl_queue *q)
/*
* To avoid ambiguity between empty and completely full queues, there
- * should always be less than q->n_bd elements in the queue.
- * If q->n_window is smaller than q->n_bd, there is no need to reserve
- * any queue entries for this purpose.
+ * should always be less than TFD_QUEUE_SIZE_MAX elements in the queue.
+ * If q->n_window is smaller than TFD_QUEUE_SIZE_MAX, there is no need
+ * to reserve any queue entries for this purpose.
*/
- if (q->n_window < q->n_bd)
+ if (q->n_window < TFD_QUEUE_SIZE_MAX)
max = q->n_window;
else
- max = q->n_bd - 1;
+ max = TFD_QUEUE_SIZE_MAX - 1;
/*
- * q->n_bd is a power of 2, so the following is equivalent to modulo by
- * q->n_bd and is well defined for negative dividends.
+ * TFD_QUEUE_SIZE_MAX is a power of 2, so the following is equivalent to
+ * modulo by TFD_QUEUE_SIZE_MAX and is well defined.
*/
- used = (q->write_ptr - q->read_ptr) & (q->n_bd - 1);
+ used = (q->write_ptr - q->read_ptr) & (TFD_QUEUE_SIZE_MAX - 1);
if (WARN_ON(used > max))
return 0;
@@ -94,17 +94,11 @@ static int iwl_queue_space(const struct iwl_queue *q)
/*
* iwl_queue_init - Initialize queue's high/low-water and read/write indexes
*/
-static int iwl_queue_init(struct iwl_queue *q, int count, int slots_num, u32 id)
+static int iwl_queue_init(struct iwl_queue *q, int slots_num, u32 id)
{
- q->n_bd = count;
q->n_window = slots_num;
q->id = id;
- /* count must be power-of-two size, otherwise iwl_queue_inc_wrap
- * and iwl_queue_dec_wrap are broken. */
- if (WARN_ON(!is_power_of_2(count)))
- return -EINVAL;
-
/* slots_num must be power-of-two size, otherwise
* get_cmd_index is broken. */
if (WARN_ON(!is_power_of_2(slots_num)))
@@ -197,17 +191,17 @@ static void iwl_pcie_txq_stuck_timer(unsigned long data)
IWL_ERR(trans,
"Q %d is %sactive and mapped to fifo %d ra_tid 0x%04x [%d,%d]\n",
i, active ? "" : "in", fifo, tbl_dw,
- iwl_read_prph(trans,
- SCD_QUEUE_RDPTR(i)) & (txq->q.n_bd - 1),
+ iwl_read_prph(trans, SCD_QUEUE_RDPTR(i)) &
+ (TFD_QUEUE_SIZE_MAX - 1),
iwl_read_prph(trans, SCD_QUEUE_WRPTR(i)));
}
for (i = q->read_ptr; i != q->write_ptr;
- i = iwl_queue_inc_wrap(i, q->n_bd))
+ i = iwl_queue_inc_wrap(i))
IWL_ERR(trans, "scratch %d = 0x%08x\n", i,
le32_to_cpu(txq->scratchbufs[i].scratch));
- iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
+ iwl_force_nmi(trans);
}
/*
@@ -338,12 +332,12 @@ void iwl_pcie_txq_check_wrptrs(struct iwl_trans *trans)
for (i = 0; i < trans->cfg->base_params->num_of_queues; i++) {
struct iwl_txq *txq = &trans_pcie->txq[i];
- spin_lock(&txq->lock);
+ spin_lock_bh(&txq->lock);
if (trans_pcie->txq[i].need_update) {
iwl_pcie_txq_inc_wr_ptr(trans, txq);
trans_pcie->txq[i].need_update = false;
}
- spin_unlock(&txq->lock);
+ spin_unlock_bh(&txq->lock);
}
}
@@ -359,13 +353,6 @@ static inline dma_addr_t iwl_pcie_tfd_tb_get_addr(struct iwl_tfd *tfd, u8 idx)
return addr;
}
-static inline u16 iwl_pcie_tfd_tb_get_len(struct iwl_tfd *tfd, u8 idx)
-{
- struct iwl_tfd_tb *tb = &tfd->tbs[idx];
-
- return le16_to_cpu(tb->hi_n_len) >> 4;
-}
-
static inline void iwl_pcie_tfd_set_tb(struct iwl_tfd *tfd, u8 idx,
dma_addr_t addr, u16 len)
{
@@ -425,13 +412,17 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
{
struct iwl_tfd *tfd_tmp = txq->tfds;
- /* rd_ptr is bounded by n_bd and idx is bounded by n_window */
+ /* rd_ptr is bounded by TFD_QUEUE_SIZE_MAX and
+ * idx is bounded by n_window
+ */
int rd_ptr = txq->q.read_ptr;
int idx = get_cmd_index(&txq->q, rd_ptr);
lockdep_assert_held(&txq->lock);
- /* We have only q->n_window txq->entries, but we use q->n_bd tfds */
+ /* We have only q->n_window txq->entries, but we use
+ * TFD_QUEUE_SIZE_MAX tfds
+ */
iwl_pcie_tfd_unmap(trans, &txq->entries[idx].meta, &tfd_tmp[rd_ptr]);
/* free SKB */
@@ -452,7 +443,7 @@ static void iwl_pcie_txq_free_tfd(struct iwl_trans *trans, struct iwl_txq *txq)
}
static int iwl_pcie_txq_build_tfd(struct iwl_trans *trans, struct iwl_txq *txq,
- dma_addr_t addr, u16 len, u8 reset)
+ dma_addr_t addr, u16 len, bool reset)
{
struct iwl_queue *q;
struct iwl_tfd *tfd, *tfd_tmp;
@@ -565,8 +556,7 @@ static int iwl_pcie_txq_init(struct iwl_trans *trans, struct iwl_txq *txq,
BUILD_BUG_ON(TFD_QUEUE_SIZE_MAX & (TFD_QUEUE_SIZE_MAX - 1));
/* Initialize queue's high/low-water marks, and head/tail indexes */
- ret = iwl_queue_init(&txq->q, TFD_QUEUE_SIZE_MAX, slots_num,
- txq_id);
+ ret = iwl_queue_init(&txq->q, slots_num, txq_id);
if (ret)
return ret;
@@ -591,15 +581,12 @@ static void iwl_pcie_txq_unmap(struct iwl_trans *trans, int txq_id)
struct iwl_txq *txq = &trans_pcie->txq[txq_id];
struct iwl_queue *q = &txq->q;
- if (!q->n_bd)
- return;
-
spin_lock_bh(&txq->lock);
while (q->write_ptr != q->read_ptr) {
IWL_DEBUG_TX_REPLY(trans, "Q %d Free %d\n",
txq_id, q->read_ptr);
iwl_pcie_txq_free_tfd(trans, txq);
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd);
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr);
}
txq->active = false;
spin_unlock_bh(&txq->lock);
@@ -636,10 +623,12 @@ static void iwl_pcie_txq_free(struct iwl_trans *trans, int txq_id)
}
/* De-alloc circular buffer of TFDs */
- if (txq->q.n_bd) {
- dma_free_coherent(dev, sizeof(struct iwl_tfd) *
- txq->q.n_bd, txq->tfds, txq->q.dma_addr);
+ if (txq->tfds) {
+ dma_free_coherent(dev,
+ sizeof(struct iwl_tfd) * TFD_QUEUE_SIZE_MAX,
+ txq->tfds, txq->q.dma_addr);
txq->q.dma_addr = 0;
+ txq->tfds = NULL;
dma_free_coherent(dev,
sizeof(*txq->scratchbufs) * txq->q.n_window,
@@ -948,8 +937,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
{
struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
struct iwl_txq *txq = &trans_pcie->txq[txq_id];
- /* n_bd is usually 256 => n_bd - 1 = 0xff */
- int tfd_num = ssn & (txq->q.n_bd - 1);
+ int tfd_num = ssn & (TFD_QUEUE_SIZE_MAX - 1);
struct iwl_queue *q = &txq->q;
int last_to_free;
@@ -973,12 +961,12 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
/*Since we free until index _not_ inclusive, the one before index is
* the last we will free. This one must be used */
- last_to_free = iwl_queue_dec_wrap(tfd_num, q->n_bd);
+ last_to_free = iwl_queue_dec_wrap(tfd_num);
if (!iwl_queue_used(q, last_to_free)) {
IWL_ERR(trans,
"%s: Read index for DMA queue txq id (%d), last_to_free %d is out of range [0-%d] %d %d.\n",
- __func__, txq_id, last_to_free, q->n_bd,
+ __func__, txq_id, last_to_free, TFD_QUEUE_SIZE_MAX,
q->write_ptr, q->read_ptr);
goto out;
}
@@ -988,7 +976,7 @@ void iwl_trans_pcie_reclaim(struct iwl_trans *trans, int txq_id, int ssn,
for (;
q->read_ptr != tfd_num;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) {
if (WARN_ON_ONCE(txq->entries[txq->q.read_ptr].skb == NULL))
continue;
@@ -1027,21 +1015,21 @@ static void iwl_pcie_cmdq_reclaim(struct iwl_trans *trans, int txq_id, int idx)
lockdep_assert_held(&txq->lock);
- if ((idx >= q->n_bd) || (!iwl_queue_used(q, idx))) {
+ if ((idx >= TFD_QUEUE_SIZE_MAX) || (!iwl_queue_used(q, idx))) {
IWL_ERR(trans,
"%s: Read index for DMA queue txq id (%d), index %d is out of range [0-%d] %d %d.\n",
- __func__, txq_id, idx, q->n_bd,
+ __func__, txq_id, idx, TFD_QUEUE_SIZE_MAX,
q->write_ptr, q->read_ptr);
return;
}
- for (idx = iwl_queue_inc_wrap(idx, q->n_bd); q->read_ptr != idx;
- q->read_ptr = iwl_queue_inc_wrap(q->read_ptr, q->n_bd)) {
+ for (idx = iwl_queue_inc_wrap(idx); q->read_ptr != idx;
+ q->read_ptr = iwl_queue_inc_wrap(q->read_ptr)) {
if (nfreed++ > 0) {
IWL_ERR(trans, "HCMD skipped: index (%d) %d %d\n",
idx, q->write_ptr, q->read_ptr);
- iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
+ iwl_force_nmi(trans);
}
}
@@ -1327,28 +1315,39 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
cmd_pos = offsetof(struct iwl_device_cmd, payload);
copy_size = sizeof(out_cmd->hdr);
for (i = 0; i < IWL_MAX_CMD_TBS_PER_TFD; i++) {
- int copy = 0;
+ int copy;
if (!cmd->len[i])
continue;
- /* need at least IWL_HCMD_SCRATCHBUF_SIZE copied */
- if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
- copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
-
- if (copy > cmd->len[i])
- copy = cmd->len[i];
- }
-
/* copy everything if not nocopy/dup */
if (!(cmd->dataflags[i] & (IWL_HCMD_DFL_NOCOPY |
- IWL_HCMD_DFL_DUP)))
+ IWL_HCMD_DFL_DUP))) {
copy = cmd->len[i];
- if (copy) {
memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
cmd_pos += copy;
copy_size += copy;
+ continue;
+ }
+
+ /*
+ * Otherwise we need at least IWL_HCMD_SCRATCHBUF_SIZE copied
+ * in total (for the scratchbuf handling), but copy up to what
+ * we can fit into the payload for debug dump purposes.
+ */
+ copy = min_t(int, TFD_MAX_PAYLOAD_SIZE - cmd_pos, cmd->len[i]);
+
+ memcpy((u8 *)out_cmd + cmd_pos, cmd->data[i], copy);
+ cmd_pos += copy;
+
+ /* However, treat copy_size the proper way, we need it below */
+ if (copy_size < IWL_HCMD_SCRATCHBUF_SIZE) {
+ copy = IWL_HCMD_SCRATCHBUF_SIZE - copy_size;
+
+ if (copy > cmd->len[i])
+ copy = cmd->len[i];
+ copy_size += copy;
}
}
@@ -1363,7 +1362,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
memcpy(&txq->scratchbufs[q->write_ptr], &out_cmd->hdr, scratch_size);
iwl_pcie_txq_build_tfd(trans, txq,
iwl_pcie_get_scratchbuf_dma(txq, q->write_ptr),
- scratch_size, 1);
+ scratch_size, true);
/* map first command fragment, if any remains */
if (copy_size > scratch_size) {
@@ -1379,7 +1378,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
}
iwl_pcie_txq_build_tfd(trans, txq, phys_addr,
- copy_size - scratch_size, 0);
+ copy_size - scratch_size, false);
}
/* map the remaining (adjusted) nocopy/dup fragments */
@@ -1402,7 +1401,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
goto out;
}
- iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], 0);
+ iwl_pcie_txq_build_tfd(trans, txq, phys_addr, cmdlen[i], false);
}
out_meta->flags = cmd->flags;
@@ -1445,7 +1444,7 @@ static int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans,
}
/* Increment and update queue's write index */
- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);
iwl_pcie_txq_inc_wr_ptr(trans, txq);
spin_unlock_irqrestore(&trans_pcie->reg_lock, flags);
@@ -1601,7 +1600,7 @@ static int iwl_pcie_send_hcmd_sync(struct iwl_trans *trans,
get_cmd_string(trans_pcie, cmd->id));
ret = -ETIMEDOUT;
- iwl_write_prph(trans, DEVICE_SET_NMI_REG, 1);
+ iwl_force_nmi(trans);
iwl_trans_fw_error(trans);
goto cancel;
@@ -1740,7 +1739,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
memcpy(&txq->scratchbufs[q->write_ptr], &dev_cmd->hdr,
IWL_HCMD_SCRATCHBUF_SIZE);
iwl_pcie_txq_build_tfd(trans, txq, tb0_phys,
- IWL_HCMD_SCRATCHBUF_SIZE, 1);
+ IWL_HCMD_SCRATCHBUF_SIZE, true);
/* there must be data left over for TB1 or this code must be changed */
BUILD_BUG_ON(sizeof(struct iwl_tx_cmd) < IWL_HCMD_SCRATCHBUF_SIZE);
@@ -1750,7 +1749,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
tb1_phys = dma_map_single(trans->dev, tb1_addr, tb1_len, DMA_TO_DEVICE);
if (unlikely(dma_mapping_error(trans->dev, tb1_phys)))
goto out_err;
- iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, 0);
+ iwl_pcie_txq_build_tfd(trans, txq, tb1_phys, tb1_len, false);
/*
* Set up TFD's third entry to point directly to remainder
@@ -1766,7 +1765,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
&txq->tfds[q->write_ptr]);
goto out_err;
}
- iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, 0);
+ iwl_pcie_txq_build_tfd(trans, txq, tb2_phys, tb2_len, false);
}
/* Set up entry for this TFD in Tx byte-count array */
@@ -1788,7 +1787,7 @@ int iwl_trans_pcie_tx(struct iwl_trans *trans, struct sk_buff *skb,
mod_timer(&txq->stuck_timer, jiffies + trans_pcie->wd_timeout);
/* Tell device the write index *just past* this latest filled TFD */
- q->write_ptr = iwl_queue_inc_wrap(q->write_ptr, q->n_bd);
+ q->write_ptr = iwl_queue_inc_wrap(q->write_ptr);
if (!wait_write_ptr)
iwl_pcie_txq_inc_wr_ptr(trans, txq);
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index 54e344aed6e..47a998d8f99 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -1006,9 +1006,8 @@ struct cmd_key_material {
} __packed;
static int lbs_set_key_material(struct lbs_private *priv,
- int key_type,
- int key_info,
- u8 *key, u16 key_len)
+ int key_type, int key_info,
+ const u8 *key, u16 key_len)
{
struct cmd_key_material cmd;
int ret;
@@ -1610,7 +1609,7 @@ static int lbs_cfg_del_key(struct wiphy *wiphy, struct net_device *netdev,
*/
static int lbs_cfg_get_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_info *sinfo)
+ const u8 *mac, struct station_info *sinfo)
{
struct lbs_private *priv = wiphy_priv(wiphy);
s8 signal, noise;
diff --git a/drivers/net/wireless/libertas/defs.h b/drivers/net/wireless/libertas/defs.h
index ab966f08024..407784aca62 100644
--- a/drivers/net/wireless/libertas/defs.h
+++ b/drivers/net/wireless/libertas/defs.h
@@ -90,7 +90,8 @@ do { if ((lbs_debug & (grp)) == (grp)) \
#define lbs_deb_cfg80211(fmt, args...) LBS_DEB_LL(LBS_DEB_CFG80211, " cfg80211", fmt, ##args)
#ifdef DEBUG
-static inline void lbs_deb_hex(unsigned int grp, const char *prompt, u8 *buf, int len)
+static inline void lbs_deb_hex(unsigned int grp, const char *prompt,
+ const u8 *buf, int len)
{
int i = 0;
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index c7366b07b56..e446fed7b34 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -71,8 +71,10 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
skb->ip_summed = CHECKSUM_NONE;
- if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR)
- return process_rxed_802_11_packet(priv, skb);
+ if (priv->wdev->iftype == NL80211_IFTYPE_MONITOR) {
+ ret = process_rxed_802_11_packet(priv, skb);
+ goto done;
+ }
p_rx_pd = (struct rxpd *) skb->data;
p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
@@ -86,7 +88,7 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
if (skb->len < (ETH_HLEN + 8 + sizeof(struct rxpd))) {
lbs_deb_rx("rx err: frame received with bad length\n");
dev->stats.rx_length_errors++;
- ret = 0;
+ ret = -EINVAL;
dev_kfree_skb(skb);
goto done;
}
diff --git a/drivers/net/wireless/mwifiex/11n.c b/drivers/net/wireless/mwifiex/11n.c
index 2bd07d681c5..e1c2f67ae85 100644
--- a/drivers/net/wireless/mwifiex/11n.c
+++ b/drivers/net/wireless/mwifiex/11n.c
@@ -749,3 +749,45 @@ void mwifiex_set_ba_params(struct mwifiex_private *priv)
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;
+}
diff --git a/drivers/net/wireless/mwifiex/11n.h b/drivers/net/wireless/mwifiex/11n.h
index 40b007a00f4..0b73fa08f5d 100644
--- a/drivers/net/wireless/mwifiex/11n.h
+++ b/drivers/net/wireless/mwifiex/11n.h
@@ -63,6 +63,7 @@ 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,
@@ -199,7 +200,7 @@ static inline int mwifiex_is_sta_11n_enabled(struct mwifiex_private *priv,
}
static inline u8
-mwifiex_tdls_peer_11n_enabled(struct mwifiex_private *priv, u8 *ra)
+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)
diff --git a/drivers/net/wireless/mwifiex/11n_aggr.c b/drivers/net/wireless/mwifiex/11n_aggr.c
index 860dfe71cf9..fe0f66f7350 100644
--- a/drivers/net/wireless/mwifiex/11n_aggr.c
+++ b/drivers/net/wireless/mwifiex/11n_aggr.c
@@ -100,6 +100,7 @@ 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);
skb_push(skb, sizeof(*local_tx_pd));
@@ -118,6 +119,9 @@ mwifiex_11n_form_amsdu_txpd(struct mwifiex_private *priv,
local_tx_pd->tx_pkt_length = cpu_to_le16(skb->len -
sizeof(*local_tx_pd));
+ 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);
@@ -181,8 +185,12 @@ mwifiex_11n_aggregate_pkt(struct mwifiex_private *priv,
skb_reserve(skb_aggr, headroom + sizeof(struct txpd));
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;
skb_aggr->priority = skb_src->priority;
do_gettimeofday(&tv);
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 21ee27ab7b7..b511613bba2 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -220,6 +220,7 @@ mwifiex_cfg80211_mgmt_tx(struct wiphy *wiphy, struct wireless_dev *wdev,
}
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;
@@ -994,7 +995,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
*/
static int
mwifiex_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_info *sinfo)
+ const u8 *mac, struct station_info *sinfo)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
@@ -1270,7 +1271,7 @@ static int mwifiex_cfg80211_change_beacon(struct wiphy *wiphy,
*/
static int
mwifiex_cfg80211_del_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac)
+ const u8 *mac)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
struct mwifiex_sta_node *sta_node;
@@ -2629,7 +2630,7 @@ static int mwifiex_cfg80211_set_coalesce(struct wiphy *wiphy,
*/
static int
mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
- u8 *peer, u8 action_code, u8 dialog_token,
+ const u8 *peer, u8 action_code, u8 dialog_token,
u16 status_code, u32 peer_capability,
const u8 *extra_ies, size_t extra_ies_len)
{
@@ -2701,7 +2702,7 @@ mwifiex_cfg80211_tdls_mgmt(struct wiphy *wiphy, struct net_device *dev,
static int
mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
- u8 *peer, enum nl80211_tdls_operation action)
+ const u8 *peer, enum nl80211_tdls_operation action)
{
struct mwifiex_private *priv = mwifiex_netdev_get_priv(dev);
@@ -2748,9 +2749,8 @@ mwifiex_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev,
}
static int
-mwifiex_cfg80211_add_station(struct wiphy *wiphy,
- struct net_device *dev,
- u8 *mac, struct station_parameters *params)
+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);
@@ -2765,9 +2765,9 @@ mwifiex_cfg80211_add_station(struct wiphy *wiphy,
}
static int
-mwifiex_cfg80211_change_station(struct wiphy *wiphy,
- struct net_device *dev,
- u8 *mac, struct station_parameters *params)
+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);
diff --git a/drivers/net/wireless/mwifiex/cmdevt.c b/drivers/net/wireless/mwifiex/cmdevt.c
index 8dee6c86f4f..c161141f6c3 100644
--- a/drivers/net/wireless/mwifiex/cmdevt.c
+++ b/drivers/net/wireless/mwifiex/cmdevt.c
@@ -453,6 +453,7 @@ int mwifiex_process_event(struct mwifiex_adapter *adapter)
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;
}
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index b485dc1ae5e..3175dd04834 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -169,6 +169,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#define TLV_TYPE_GWK_CIPHER (PROPRIETARY_TLV_BASE_ID + 146)
#define TLV_TYPE_COALESCE_RULE (PROPRIETARY_TLV_BASE_ID + 154)
#define TLV_TYPE_KEY_PARAM_V2 (PROPRIETARY_TLV_BASE_ID + 156)
+#define TLV_TYPE_TDLS_IDLE_TIMEOUT (PROPRIETARY_TLV_BASE_ID + 194)
#define TLV_TYPE_FW_API_REV (PROPRIETARY_TLV_BASE_ID + 199)
#define MWIFIEX_TX_DATA_BUF_SIZE_2K 2048
@@ -229,6 +230,7 @@ enum MWIFIEX_802_11_PRIVACY_FILTER {
#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))
/* httxcfg bitmap
* 0 reserved
@@ -403,7 +405,7 @@ enum P2P_MODES {
#define HS_CFG_CANCEL 0xffffffff
#define HS_CFG_COND_DEF 0x00000000
#define HS_CFG_GPIO_DEF 0xff
-#define HS_CFG_GAP_DEF 0
+#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
@@ -487,6 +489,7 @@ enum P2P_MODES {
#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_EXT_SCAN_REPORT 0x00000058
#define EVENT_REMAIN_ON_CHAN_EXPIRED 0x0000005f
@@ -519,6 +522,7 @@ enum P2P_MODES {
#define ACT_TDLS_DELETE 0x00
#define ACT_TDLS_CREATE 0x01
#define ACT_TDLS_CONFIG 0x02
+#define TDLS_EVENT_LINK_TEAR_DOWN 3
#define MWIFIEX_FW_V15 15
@@ -535,6 +539,7 @@ struct mwifiex_ie_types_data {
#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
struct txpd {
u8 bss_type;
@@ -577,7 +582,7 @@ struct rxpd {
* [Bit 7] Reserved
*/
u8 ht_info;
- u8 reserved;
+ u8 flags;
} __packed;
struct uap_txpd {
@@ -708,6 +713,13 @@ struct mwifiex_ie_types_vendor_param_set {
u8 ie[MWIFIEX_MAX_VSIE_LEN];
};
+#define MWIFIEX_TDLS_IDLE_TIMEOUT 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];
@@ -1745,6 +1757,15 @@ struct host_cmd_ds_802_11_subsc_evt {
__le16 events;
} __packed;
+struct mwifiex_tdls_generic_event {
+ __le16 type;
+ u8 peer_mac[ETH_ALEN];
+ union {
+ __le16 reason_code;
+ __le16 reserved;
+ } u;
+} __packed;
+
struct mwifiex_ie {
__le16 ie_index;
__le16 mgmt_subtype_mask;
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index cbabc12fbda..e91cd0fa5ca 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -645,6 +645,7 @@ mwifiex_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
}
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;
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 34181192a66..1398afa8406 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -910,8 +910,6 @@ 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 *);
-struct mwifiex_sta_node *
-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
void mwifiex_delete_all_station_list(struct mwifiex_private *priv);
void *mwifiex_process_sta_txpd(struct mwifiex_private *, struct sk_buff *skb);
void *mwifiex_process_uap_txpd(struct mwifiex_private *, struct sk_buff *skb);
@@ -1101,7 +1099,7 @@ mwifiex_11h_get_csa_closed_channel(struct mwifiex_private *priv)
return 0;
/* Clear csa channel, if DFS channel move time has passed */
- if (jiffies > priv->csa_expire_time) {
+ if (time_after(jiffies, priv->csa_expire_time)) {
priv->csa_chan = 0;
priv->csa_expire_time = 0;
}
@@ -1220,26 +1218,26 @@ 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, u8 *mac);
+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, u8 *mac);
+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac);
struct mwifiex_sta_node *
-mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac);
-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv, u8 *peer,
+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac);
+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,
- 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, u8 *peer, u8 action);
-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac);
+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);
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,
diff --git a/drivers/net/wireless/mwifiex/pcie.c b/drivers/net/wireless/mwifiex/pcie.c
index c2cfeec466d..2cc9b6fca49 100644
--- a/drivers/net/wireless/mwifiex/pcie.c
+++ b/drivers/net/wireless/mwifiex/pcie.c
@@ -50,7 +50,7 @@ mwifiex_map_pci_memory(struct mwifiex_adapter *adapter, struct sk_buff *skb,
return -1;
}
mapping.len = size;
- memcpy(skb->cb, &mapping, sizeof(mapping));
+ mwifiex_store_mapping(skb, &mapping);
return 0;
}
@@ -60,7 +60,7 @@ static void mwifiex_unmap_pci_memory(struct mwifiex_adapter *adapter,
struct pcie_service_card *card = adapter->card;
struct mwifiex_dma_mapping mapping;
- MWIFIEX_SKB_PACB(skb, &mapping);
+ mwifiex_get_mapping(skb, &mapping);
pci_unmap_single(card->dev, mapping.addr, mapping.len, flags);
}
@@ -1071,6 +1071,7 @@ static int mwifiex_pcie_send_data_complete(struct mwifiex_adapter *adapter)
* 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,
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index d75f4ebd4bd..45c5b3450cf 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -1738,6 +1738,19 @@ mwifiex_parse_single_response_buf(struct mwifiex_private *priv, u8 **bss_info,
return 0;
}
+static void mwifiex_complete_scan(struct mwifiex_private *priv)
+{
+ struct mwifiex_adapter *adapter = priv->adapter;
+
+ if (adapter->curr_cmd->wait_q_enabled) {
+ adapter->cmd_wait_q.status = 0;
+ if (!priv->scan_request) {
+ dev_dbg(adapter->dev, "complete internal scan\n");
+ mwifiex_complete_cmd(adapter, adapter->curr_cmd);
+ }
+ }
+}
+
static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
{
struct mwifiex_adapter *adapter = priv->adapter;
@@ -1751,16 +1764,9 @@ static void mwifiex_check_next_scan_command(struct mwifiex_private *priv)
adapter->scan_processing = false;
spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
- /* Need to indicate IOCTL complete */
- if (adapter->curr_cmd->wait_q_enabled) {
- adapter->cmd_wait_q.status = 0;
- if (!priv->scan_request) {
- dev_dbg(adapter->dev,
- "complete internal scan\n");
- mwifiex_complete_cmd(adapter,
- adapter->curr_cmd);
- }
- }
+ if (!adapter->ext_scan)
+ mwifiex_complete_scan(priv);
+
if (priv->report_scan_result)
priv->report_scan_result = false;
@@ -1965,6 +1971,9 @@ int mwifiex_cmd_802_11_scan_ext(struct mwifiex_private *priv,
int mwifiex_ret_802_11_scan_ext(struct mwifiex_private *priv)
{
dev_dbg(priv->adapter->dev, "info: EXT scan returns successfully\n");
+
+ mwifiex_complete_scan(priv);
+
return 0;
}
diff --git a/drivers/net/wireless/mwifiex/sdio.c b/drivers/net/wireless/mwifiex/sdio.c
index a1773d3cb49..4ce3d7b3399 100644
--- a/drivers/net/wireless/mwifiex/sdio.c
+++ b/drivers/net/wireless/mwifiex/sdio.c
@@ -1678,8 +1678,12 @@ static int mwifiex_sdio_host_to_card(struct mwifiex_adapter *adapter,
if (ret) {
if (type == MWIFIEX_TYPE_CMD)
adapter->cmd_sent = false;
- if (type == MWIFIEX_TYPE_DATA)
+ 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)))
diff --git a/drivers/net/wireless/mwifiex/sta_cmd.c b/drivers/net/wireless/mwifiex/sta_cmd.c
index e3cac1495cc..88202ce0c13 100644
--- a/drivers/net/wireless/mwifiex/sta_cmd.c
+++ b/drivers/net/wireless/mwifiex/sta_cmd.c
@@ -1546,6 +1546,7 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
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;
@@ -1643,6 +1644,12 @@ mwifiex_cmd_tdls_oper(struct mwifiex_private *priv,
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);
+ config_len += sizeof(struct mwifiex_ie_types_tdls_idle_timeout);
+
break;
default:
dev_err(priv->adapter->dev, "Unknown TDLS operation\n");
diff --git a/drivers/net/wireless/mwifiex/sta_cmdresp.c b/drivers/net/wireless/mwifiex/sta_cmdresp.c
index bfebb0144df..577f2979ed8 100644
--- a/drivers/net/wireless/mwifiex/sta_cmdresp.c
+++ b/drivers/net/wireless/mwifiex/sta_cmdresp.c
@@ -865,14 +865,20 @@ static int mwifiex_ret_tdls_oper(struct mwifiex_private *priv,
switch (action) {
case ACT_TDLS_DELETE:
- if (reason)
- dev_err(priv->adapter->dev,
- "TDLS link delete for %pM failed: reason %d\n",
- cmd_tdls_oper->peer_mac, reason);
- else
+ if (reason) {
+ if (!node || reason == TDLS_ERR_LINK_NONEXISTENT)
+ dev_dbg(priv->adapter->dev,
+ "TDLS link delete for %pM failed: reason %d\n",
+ cmd_tdls_oper->peer_mac, reason);
+ else
+ dev_err(priv->adapter->dev,
+ "TDLS link delete for %pM failed: reason %d\n",
+ cmd_tdls_oper->peer_mac, reason);
+ } else {
dev_dbg(priv->adapter->dev,
- "TDLS link config for %pM successful\n",
+ "TDLS link delete for %pM successful\n",
cmd_tdls_oper->peer_mac);
+ }
break;
case ACT_TDLS_CREATE:
if (reason) {
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index 368450cc56c..f6395ef11a7 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -134,6 +134,46 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv, u16 reason_code)
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);
+
+ /* 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))) {
+ dev_err(adapter->dev, "Invalid event length!\n");
+ return -1;
+ }
+
+ sta_ptr = mwifiex_get_sta_entry(priv, tdls_evt->peer_mac);
+ if (!sta_ptr) {
+ dev_err(adapter->dev, "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);
+ ret = mwifiex_tdls_oper(priv, tdls_evt->peer_mac,
+ MWIFIEX_TDLS_DISABLE_LINK);
+ queue_work(adapter->workqueue, &adapter->main_work);
+ break;
+ default:
+ break;
+ }
+
+ return ret;
+}
+
/*
* This function handles events generated by firmware.
*
@@ -459,6 +499,10 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
false);
break;
+ case EVENT_TDLS_GENERIC_EVENT:
+ ret = mwifiex_parse_tdls_event(priv, adapter->event_skb);
+ break;
+
default:
dev_dbg(adapter->dev, "event: unknown event id: %#x\n",
eventcause);
diff --git a/drivers/net/wireless/mwifiex/sta_rx.c b/drivers/net/wireless/mwifiex/sta_rx.c
index ed26387eccf..8b639d7fe6d 100644
--- a/drivers/net/wireless/mwifiex/sta_rx.c
+++ b/drivers/net/wireless/mwifiex/sta_rx.c
@@ -183,6 +183,7 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
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);
@@ -213,14 +214,25 @@ int mwifiex_process_sta_rx_packet(struct mwifiex_private *priv,
* 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) ||
+ 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)) {
+ 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);
+ }
} else {
if (rx_pkt_type != PKT_TYPE_BAR)
priv->rx_seq[local_rx_pd->priority] = seq_num;
diff --git a/drivers/net/wireless/mwifiex/sta_tx.c b/drivers/net/wireless/mwifiex/sta_tx.c
index 1236a5de7bc..70eb863c724 100644
--- a/drivers/net/wireless/mwifiex/sta_tx.c
+++ b/drivers/net/wireless/mwifiex/sta_tx.c
@@ -128,6 +128,7 @@ 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;
@@ -149,6 +150,7 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
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);
@@ -168,8 +170,9 @@ int mwifiex_send_null_packet(struct mwifiex_private *priv, u8 flags)
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, NULL);
+ skb, &tx_param);
}
switch (ret) {
case -EBUSY:
diff --git a/drivers/net/wireless/mwifiex/tdls.c b/drivers/net/wireless/mwifiex/tdls.c
index 97662a1ba58..0e88364e0c6 100644
--- a/drivers/net/wireless/mwifiex/tdls.c
+++ b/drivers/net/wireless/mwifiex/tdls.c
@@ -25,8 +25,8 @@
#define TDLS_RESP_FIX_LEN 8
#define TDLS_CONFIRM_FIX_LEN 6
-static void
-mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
+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;
@@ -84,7 +84,8 @@ mwifiex_restore_tdls_packets(struct mwifiex_private *priv, u8 *mac, u8 status)
return;
}
-static void mwifiex_hold_tdls_packets(struct mwifiex_private *priv, u8 *mac)
+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;
@@ -185,8 +186,50 @@ static int mwifiex_tdls_add_vht_capab(struct mwifiex_private *priv,
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)) {
+ dev_warn(priv->adapter->dev,
+ "TDLS peer station not found in list\n");
+ return -1;
+ }
+
+ 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,
- u8 *mac, struct sk_buff *skb)
+ const u8 *mac, struct sk_buff *skb)
{
struct mwifiex_bssdescriptor *bss_desc;
struct ieee80211_vht_operation *vht_oper;
@@ -325,8 +368,9 @@ static void mwifiex_tdls_add_qos_capab(struct sk_buff *skb)
}
static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
- u8 *peer, u8 action_code, u8 dialog_token,
- u16 status_code, struct sk_buff *skb)
+ const u8 *peer, u8 action_code,
+ u8 dialog_token,
+ u16 status_code, struct sk_buff *skb)
{
struct ieee80211_tdls_data *tf;
int ret;
@@ -428,6 +472,17 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
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;
@@ -453,7 +508,8 @@ static int mwifiex_prep_tdls_encap_data(struct mwifiex_private *priv,
}
static void
-mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
+mwifiex_tdls_add_link_ie(struct sk_buff *skb, const u8 *src_addr,
+ const u8 *peer, const u8 *bssid)
{
struct ieee80211_tdls_lnkie *lnkid;
@@ -467,8 +523,8 @@ mwifiex_tdls_add_link_ie(struct sk_buff *skb, u8 *src_addr, u8 *peer, u8 *bssid)
memcpy(lnkid->resp_sta, peer, ETH_ALEN);
}
-int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
- u8 *peer, u8 action_code, u8 dialog_token,
+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)
{
@@ -549,6 +605,7 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
}
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;
@@ -560,7 +617,8 @@ int mwifiex_send_tdls_data_frame(struct mwifiex_private *priv,
}
static int
-mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
+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)
{
@@ -638,10 +696,10 @@ mwifiex_construct_tdls_action_frame(struct mwifiex_private *priv, u8 *peer,
return 0;
}
-int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
- 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)
{
struct sk_buff *skb;
struct mwifiex_txinfo *tx_info;
@@ -703,6 +761,7 @@ int mwifiex_send_tdls_action_frame(struct mwifiex_private *priv,
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;
@@ -848,7 +907,7 @@ void mwifiex_process_tdls_action_frame(struct mwifiex_private *priv,
}
static int
-mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
+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;
@@ -869,7 +928,7 @@ mwifiex_tdls_process_config_link(struct mwifiex_private *priv, u8 *peer)
}
static int
-mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
+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;
@@ -896,7 +955,7 @@ mwifiex_tdls_process_create_link(struct mwifiex_private *priv, u8 *peer)
}
static int
-mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
+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;
@@ -925,7 +984,7 @@ mwifiex_tdls_process_disable_link(struct mwifiex_private *priv, u8 *peer)
}
static int
-mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
+mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, const u8 *peer)
{
struct mwifiex_sta_node *sta_ptr;
struct ieee80211_mcs_info mcs;
@@ -982,7 +1041,7 @@ mwifiex_tdls_process_enable_link(struct mwifiex_private *priv, u8 *peer)
return 0;
}
-int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
+int mwifiex_tdls_oper(struct mwifiex_private *priv, const u8 *peer, u8 action)
{
switch (action) {
case MWIFIEX_TDLS_ENABLE_LINK:
@@ -997,7 +1056,7 @@ int mwifiex_tdls_oper(struct mwifiex_private *priv, u8 *peer, u8 action)
return 0;
}
-int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, u8 *mac)
+int mwifiex_get_tdls_link_status(struct mwifiex_private *priv, const u8 *mac)
{
struct mwifiex_sta_node *sta_ptr;
diff --git a/drivers/net/wireless/mwifiex/txrx.c b/drivers/net/wireless/mwifiex/txrx.c
index 37f26afd431..fd7e5b9b458 100644
--- a/drivers/net/wireless/mwifiex/txrx.c
+++ b/drivers/net/wireless/mwifiex/txrx.c
@@ -55,6 +55,7 @@ int mwifiex_handle_rx_packet(struct mwifiex_adapter *adapter,
return -1;
}
+ memset(rx_info, 0, sizeof(*rx_info));
rx_info->bss_num = priv->bss_num;
rx_info->bss_type = priv->bss_type;
diff --git a/drivers/net/wireless/mwifiex/uap_txrx.c b/drivers/net/wireless/mwifiex/uap_txrx.c
index 9a56bc61cb1..b0601b91cc4 100644
--- a/drivers/net/wireless/mwifiex/uap_txrx.c
+++ b/drivers/net/wireless/mwifiex/uap_txrx.c
@@ -175,6 +175,7 @@ static void mwifiex_uap_queue_bridged_pkt(struct mwifiex_private *priv,
}
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;
diff --git a/drivers/net/wireless/mwifiex/util.c b/drivers/net/wireless/mwifiex/util.c
index c3824e37f3f..6da5abf52e6 100644
--- a/drivers/net/wireless/mwifiex/util.c
+++ b/drivers/net/wireless/mwifiex/util.c
@@ -259,7 +259,7 @@ int mwifiex_complete_cmd(struct mwifiex_adapter *adapter,
* 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, u8 *mac)
+mwifiex_get_sta_entry(struct mwifiex_private *priv, const u8 *mac)
{
struct mwifiex_sta_node *node;
@@ -280,7 +280,7 @@ mwifiex_get_sta_entry(struct mwifiex_private *priv, u8 *mac)
* If received mac address is NULL, NULL is returned.
*/
struct mwifiex_sta_node *
-mwifiex_add_sta_entry(struct mwifiex_private *priv, u8 *mac)
+mwifiex_add_sta_entry(struct mwifiex_private *priv, const u8 *mac)
{
struct mwifiex_sta_node *node;
unsigned long flags;
@@ -332,7 +332,7 @@ mwifiex_set_sta_ht_cap(struct mwifiex_private *priv, const u8 *ies,
}
/* This function will delete a station entry from station list */
-void mwifiex_del_sta_entry(struct mwifiex_private *priv, u8 *mac)
+void mwifiex_del_sta_entry(struct mwifiex_private *priv, const u8 *mac)
{
struct mwifiex_sta_node *node;
unsigned long flags;
diff --git a/drivers/net/wireless/mwifiex/util.h b/drivers/net/wireless/mwifiex/util.h
index ddae5702139..caadb3737b9 100644
--- a/drivers/net/wireless/mwifiex/util.h
+++ b/drivers/net/wireless/mwifiex/util.h
@@ -20,32 +20,55 @@
#ifndef _MWIFIEX_UTIL_H_
#define _MWIFIEX_UTIL_H_
+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;
+ };
+};
+
static inline struct mwifiex_rxinfo *MWIFIEX_SKB_RXCB(struct sk_buff *skb)
{
- return (struct mwifiex_rxinfo *)(skb->cb + sizeof(dma_addr_t));
+ 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)
{
- return (struct mwifiex_txinfo *)(skb->cb + sizeof(dma_addr_t));
+ struct mwifiex_cb *cb = (struct mwifiex_cb *)skb->cb;
+
+ return &cb->tx_info;
}
-struct mwifiex_dma_mapping {
- dma_addr_t addr;
- size_t len;
-};
+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_SKB_PACB(struct sk_buff *skb,
- struct mwifiex_dma_mapping *mapping)
+static inline void mwifiex_get_mapping(struct sk_buff *skb,
+ struct mwifiex_dma_mapping *mapping)
{
- memcpy(mapping, skb->cb, sizeof(*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_SKB_PACB(skb, &mapping);
+ mwifiex_get_mapping(skb, &mapping);
return mapping.addr;
}
diff --git a/drivers/net/wireless/mwifiex/wmm.c b/drivers/net/wireless/mwifiex/wmm.c
index 94b6c74ba72..d3671d009f6 100644
--- a/drivers/net/wireless/mwifiex/wmm.c
+++ b/drivers/net/wireless/mwifiex/wmm.c
@@ -92,7 +92,7 @@ mwifiex_wmm_ac_debug_print(const struct ieee_types_wmm_ac_parameters *ac_param)
* 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, u8 *ra)
+mwifiex_wmm_allocate_ralist_node(struct mwifiex_adapter *adapter, const u8 *ra)
{
struct mwifiex_ra_list_tbl *ra_list;
@@ -139,8 +139,7 @@ static u8 mwifiex_get_random_ba_threshold(void)
* This function allocates and adds a RA list for all TIDs
* with the given RA.
*/
-void
-mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
+void mwifiex_ralist_add(struct mwifiex_private *priv, const u8 *ra)
{
int i;
struct mwifiex_ra_list_tbl *ra_list;
@@ -164,6 +163,7 @@ mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra)
if (!mwifiex_queuing_ra_based(priv)) {
if (mwifiex_get_tdls_link_status(priv, ra) ==
TDLS_SETUP_COMPLETE) {
+ ra_list->tdls_link = true;
ra_list->is_11n_enabled =
mwifiex_tdls_peer_11n_enabled(priv, ra);
} else {
@@ -566,7 +566,7 @@ mwifiex_clean_txrx(struct mwifiex_private *priv)
*/
static struct mwifiex_ra_list_tbl *
mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
- u8 *ra_addr)
+ const u8 *ra_addr)
{
struct mwifiex_ra_list_tbl *ra_list;
@@ -587,7 +587,8 @@ mwifiex_wmm_get_ralist_node(struct mwifiex_private *priv, u8 tid,
* retrieved.
*/
struct mwifiex_ra_list_tbl *
-mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid, u8 *ra_addr)
+mwifiex_wmm_get_queue_raptr(struct mwifiex_private *priv, u8 tid,
+ const u8 *ra_addr)
{
struct mwifiex_ra_list_tbl *ra_list;
@@ -648,7 +649,7 @@ mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
if (ntohs(eth_hdr->h_proto) == ETH_P_TDLS)
dev_dbg(adapter->dev,
"TDLS setup packet for %pM. Don't block\n", ra);
- else
+ else if (memcmp(priv->cfg_bssid, ra, ETH_ALEN))
tdls_status = mwifiex_get_tdls_link_status(priv, ra);
}
diff --git a/drivers/net/wireless/mwifiex/wmm.h b/drivers/net/wireless/mwifiex/wmm.h
index 83e42083ebf..eca56e371a5 100644
--- a/drivers/net/wireless/mwifiex/wmm.h
+++ b/drivers/net/wireless/mwifiex/wmm.h
@@ -99,7 +99,7 @@ mwifiex_wmm_is_ra_list_empty(struct list_head *ra_list_hhead)
void mwifiex_wmm_add_buf_txqueue(struct mwifiex_private *priv,
struct sk_buff *skb);
-void mwifiex_ralist_add(struct mwifiex_private *priv, u8 *ra);
+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);
@@ -123,7 +123,8 @@ 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, u8 *ra_addr);
+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);
#endif /* !_MWIFIEX_WMM_H_ */
diff --git a/drivers/net/wireless/orinoco/hw.c b/drivers/net/wireless/orinoco/hw.c
index 49300d04efd..e27e32851f1 100644
--- a/drivers/net/wireless/orinoco/hw.c
+++ b/drivers/net/wireless/orinoco/hw.c
@@ -988,8 +988,8 @@ int __orinoco_hw_setup_enc(struct orinoco_private *priv)
* tsc must be NULL or up to 8 bytes
*/
int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
- int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
- u8 *tsc, size_t tsc_len)
+ int set_tx, const u8 *key, const u8 *rsc,
+ size_t rsc_len, const u8 *tsc, size_t tsc_len)
{
struct {
__le16 idx;
diff --git a/drivers/net/wireless/orinoco/hw.h b/drivers/net/wireless/orinoco/hw.h
index 8f6831f4e32..466d1ede76f 100644
--- a/drivers/net/wireless/orinoco/hw.h
+++ b/drivers/net/wireless/orinoco/hw.h
@@ -38,8 +38,8 @@ int __orinoco_hw_set_wap(struct orinoco_private *priv);
int __orinoco_hw_setup_wepkeys(struct orinoco_private *priv);
int __orinoco_hw_setup_enc(struct orinoco_private *priv);
int __orinoco_hw_set_tkip_key(struct orinoco_private *priv, int key_idx,
- int set_tx, u8 *key, u8 *rsc, size_t rsc_len,
- u8 *tsc, size_t tsc_len);
+ int set_tx, const u8 *key, const u8 *rsc,
+ size_t rsc_len, const u8 *tsc, size_t tsc_len);
int orinoco_clear_tkip_key(struct orinoco_private *priv, int key_idx);
int __orinoco_hw_set_multicast_list(struct orinoco_private *priv,
struct net_device *dev,
diff --git a/drivers/net/wireless/orinoco/orinoco_usb.c b/drivers/net/wireless/orinoco/orinoco_usb.c
index f9805c9353d..c90939ced0e 100644
--- a/drivers/net/wireless/orinoco/orinoco_usb.c
+++ b/drivers/net/wireless/orinoco/orinoco_usb.c
@@ -100,25 +100,11 @@ static struct ez_usb_fw firmware = {
.code = NULL,
};
-#ifdef CONFIG_USB_DEBUG
-static int debug = 1;
-#else
-static int debug;
-#endif
-
/* Debugging macros */
-#undef dbg
-#define dbg(format, arg...) \
- do { if (debug) printk(KERN_DEBUG PFX "%s: " format "\n", \
- __func__ , ## arg); } while (0)
#undef err
#define err(format, arg...) \
do { printk(KERN_ERR PFX format "\n", ## arg); } while (0)
-/* Module paramaters */
-module_param(debug, int, 0644);
-MODULE_PARM_DESC(debug, "Debug enabled or not");
-
MODULE_FIRMWARE("orinoco_ezusb_fw");
/*
@@ -341,7 +327,7 @@ static void ezusb_request_timerfn(u_long _ctx)
ctx->state = EZUSB_CTX_REQ_TIMEOUT;
} else {
ctx->state = EZUSB_CTX_RESP_TIMEOUT;
- dbg("couldn't unlink");
+ dev_dbg(&ctx->outurb->dev->dev, "couldn't unlink\n");
atomic_inc(&ctx->refcount);
ctx->killed = 1;
ezusb_ctx_complete(ctx);
@@ -634,9 +620,9 @@ static void ezusb_request_in_callback(struct ezusb_priv *upriv,
ctx = c;
break;
}
- dbg("Skipped (0x%x/0x%x) (%d/%d)",
- le16_to_cpu(ans->hermes_rid),
- c->in_rid, ans->ans_reply_count, reply_count);
+ netdev_dbg(upriv->dev, "Skipped (0x%x/0x%x) (%d/%d)\n",
+ le16_to_cpu(ans->hermes_rid), c->in_rid,
+ ans->ans_reply_count, reply_count);
}
}
@@ -768,7 +754,7 @@ static int ezusb_submit_in_urb(struct ezusb_priv *upriv)
void *cur_buf = upriv->read_urb->transfer_buffer;
if (upriv->read_urb->status == -EINPROGRESS) {
- dbg("urb busy, not resubmiting");
+ netdev_dbg(upriv->dev, "urb busy, not resubmiting\n");
retval = -EBUSY;
goto exit;
}
@@ -838,8 +824,9 @@ static int ezusb_firmware_download(struct ezusb_priv *upriv,
memcpy(fw_buffer, &fw->code[addr], FW_BUF_SIZE);
if (variant_offset >= addr &&
variant_offset < addr + FW_BUF_SIZE) {
- dbg("Patching card_variant byte at 0x%04X",
- variant_offset);
+ netdev_dbg(upriv->dev,
+ "Patching card_variant byte at 0x%04X\n",
+ variant_offset);
fw_buffer[variant_offset - addr] = FW_VAR_VALUE;
}
retval = usb_control_msg(upriv->udev,
@@ -879,7 +866,6 @@ static int ezusb_access_ltv(struct ezusb_priv *upriv,
BUG_ON(in_irq());
if (!upriv->udev) {
- dbg("Device disconnected");
retval = -ENODEV;
goto exit;
}
@@ -1023,8 +1009,9 @@ static int ezusb_doicmd_wait(struct hermes *hw, u16 cmd, u16 parm0, u16 parm1,
cpu_to_le16(parm1),
cpu_to_le16(parm2),
};
- dbg("0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X",
- cmd, parm0, parm1, parm2);
+ netdev_dbg(upriv->dev,
+ "0x%04X, parm0 0x%04X, parm1 0x%04X, parm2 0x%04X\n", cmd,
+ parm0, parm1, parm2);
ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
if (!ctx)
return -ENOMEM;
@@ -1045,7 +1032,7 @@ static int ezusb_docmd_wait(struct hermes *hw, u16 cmd, u16 parm0,
0,
0,
};
- dbg("0x%04X, parm0 0x%04X", cmd, parm0);
+ netdev_dbg(upriv->dev, "0x%04X, parm0 0x%04X\n", cmd, parm0);
ctx = ezusb_alloc_ctx(upriv, EZUSB_RID_DOCMD, EZUSB_RID_ACK);
if (!ctx)
return -ENOMEM;
@@ -1332,7 +1319,7 @@ static int ezusb_hard_reset(struct orinoco_private *priv)
return retval;
}
- dbg("sending control message");
+ netdev_dbg(upriv->dev, "sending control message\n");
retval = usb_control_msg(upriv->udev,
usb_sndctrlpipe(upriv->udev, 0),
EZUSB_REQUEST_TRIGER,
@@ -1401,10 +1388,8 @@ static void ezusb_bulk_in_callback(struct urb *urb)
u16 crc;
u16 hermes_rid;
- if (upriv->udev == NULL) {
- dbg("disconnected");
+ if (upriv->udev == NULL)
return;
- }
if (urb->status == -ETIMEDOUT) {
/* When a device gets unplugged we get this every time
@@ -1421,12 +1406,13 @@ static void ezusb_bulk_in_callback(struct urb *urb)
if ((urb->status == -EILSEQ)
|| (urb->status == -ENOENT)
|| (urb->status == -ECONNRESET)) {
- dbg("status %d, not resubmiting", urb->status);
+ netdev_dbg(upriv->dev, "status %d, not resubmiting\n",
+ urb->status);
return;
}
if (urb->status)
- dbg("status: %d length: %d",
- urb->status, urb->actual_length);
+ netdev_dbg(upriv->dev, "status: %d length: %d\n",
+ urb->status, urb->actual_length);
if (urb->actual_length < sizeof(*ans)) {
err("%s: short read, ignoring", __func__);
goto resubmit;
@@ -1687,7 +1673,7 @@ static int ezusb_probe(struct usb_interface *interface,
firmware.code = fw_entry->data;
}
if (firmware.size && firmware.code) {
- if (ezusb_firmware_download(upriv, &firmware))
+ if (ezusb_firmware_download(upriv, &firmware) < 0)
goto error;
} else {
err("No firmware to download");
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index b7a867b50b9..6abdaf0aa05 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -52,9 +52,9 @@ static int orinoco_set_key(struct orinoco_private *priv, int index,
priv->keys[index].seq_len = seq_len;
if (key_len)
- memcpy(priv->keys[index].key, key, key_len);
+ memcpy((void *)priv->keys[index].key, key, key_len);
if (seq_len)
- memcpy(priv->keys[index].seq, seq, seq_len);
+ memcpy((void *)priv->keys[index].seq, seq, seq_len);
switch (alg) {
case ORINOCO_ALG_TKIP:
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 39d22a15434..d2a9a08210b 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -517,7 +517,7 @@ static int rndis_set_default_key(struct wiphy *wiphy, struct net_device *netdev,
u8 key_index, bool unicast, bool multicast);
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_info *sinfo);
+ const u8 *mac, struct station_info *sinfo);
static int rndis_dump_station(struct wiphy *wiphy, struct net_device *dev,
int idx, u8 *mac, struct station_info *sinfo);
@@ -2490,7 +2490,7 @@ static void rndis_fill_station_info(struct usbnet *usbdev,
}
static int rndis_get_station(struct wiphy *wiphy, struct net_device *dev,
- u8 *mac, struct station_info *sinfo)
+ const u8 *mac, struct station_info *sinfo)
{
struct rndis_wlan_private *priv = wiphy_priv(wiphy);
struct usbnet *usbdev = priv->usbdev;
diff --git a/drivers/net/wireless/rsi/rsi_91x_mac80211.c b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
index 84164747ace..54aaeb09deb 100644
--- a/drivers/net/wireless/rsi/rsi_91x_mac80211.c
+++ b/drivers/net/wireless/rsi/rsi_91x_mac80211.c
@@ -656,6 +656,7 @@ static int rsi_mac80211_ampdu_action(struct ieee80211_hw *hw,
case IEEE80211_AMPDU_TX_START:
common->vif_info[ii].seq_start = seq_no;
ieee80211_start_tx_ba_cb_irqsafe(vif, sta->addr, tid);
+ status = 0;
break;
case IEEE80211_AMPDU_TX_STOP_CONT:
diff --git a/drivers/net/wireless/rsi/rsi_91x_sdio.c b/drivers/net/wireless/rsi/rsi_91x_sdio.c
index 2e39d38d6a9..46e7af446f0 100644
--- a/drivers/net/wireless/rsi/rsi_91x_sdio.c
+++ b/drivers/net/wireless/rsi/rsi_91x_sdio.c
@@ -285,7 +285,6 @@ static void rsi_reset_card(struct sdio_func *pfunction)
if (err) {
rsi_dbg(ERR_ZONE, "%s: CCCR speed reg read failed: %d\n",
__func__, err);
- card->state &= ~MMC_STATE_HIGHSPEED;
} else {
err = rsi_cmd52writebyte(card,
SDIO_CCCR_SPEED,
@@ -296,14 +295,13 @@ static void rsi_reset_card(struct sdio_func *pfunction)
__func__, err);
return;
}
- mmc_card_set_highspeed(card);
host->ios.timing = MMC_TIMING_SD_HS;
host->ops->set_ios(host, &host->ios);
}
}
/* Set clock */
- if (mmc_card_highspeed(card))
+ if (mmc_card_hs(card))
clock = 50000000;
else
clock = card->cis.max_dtr;
diff --git a/drivers/net/wireless/rsi/rsi_common.h b/drivers/net/wireless/rsi/rsi_common.h
index f2f70784d4a..d3fbe33d232 100644
--- a/drivers/net/wireless/rsi/rsi_common.h
+++ b/drivers/net/wireless/rsi/rsi_common.h
@@ -63,7 +63,7 @@ static inline int rsi_create_kthread(struct rsi_common *common,
u8 *name)
{
init_completion(&thread->completion);
- thread->task = kthread_run(func_ptr, common, name);
+ thread->task = kthread_run(func_ptr, common, "%s", name);
if (IS_ERR(thread->task))
return (int)PTR_ERR(thread->task);
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 2f1cd929c6f..a511cccc9f0 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1681,8 +1681,13 @@ static int rt2500pci_init_eeprom(struct rt2x00_dev *rt2x00dev)
/*
* Detect if this device has an hardware controlled radio.
*/
- if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO))
+ if (rt2x00_get_field16(eeprom, EEPROM_ANTENNA_HARDWARE_RADIO)) {
__set_bit(CAPABILITY_HW_BUTTON, &rt2x00dev->cap_flags);
+ /*
+ * On this device RFKILL initialized during probe does not work.
+ */
+ __set_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags);
+ }
/*
* Check if the BBP tuning should be enabled.
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index a49c3d73ea2..832006b5aab 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -229,6 +229,31 @@ static enum hrtimer_restart rt2800usb_tx_sta_fifo_timeout(struct hrtimer *timer)
/*
* Firmware functions
*/
+static int rt2800usb_autorun_detect(struct rt2x00_dev *rt2x00dev)
+{
+ __le32 *reg;
+ u32 fw_mode;
+
+ reg = kmalloc(sizeof(*reg), GFP_KERNEL);
+ if (reg == NULL)
+ return -ENOMEM;
+ /* cannot use rt2x00usb_register_read here as it uses different
+ * mode (MULTI_READ vs. DEVICE_MODE) and does not pass the
+ * magic value USB_MODE_AUTORUN (0x11) to the device, thus the
+ * returned value would be invalid.
+ */
+ rt2x00usb_vendor_request(rt2x00dev, USB_DEVICE_MODE,
+ USB_VENDOR_REQUEST_IN, 0, USB_MODE_AUTORUN,
+ reg, sizeof(*reg), REGISTER_TIMEOUT_FIRMWARE);
+ fw_mode = le32_to_cpu(*reg);
+ kfree(reg);
+
+ if ((fw_mode & 0x00000003) == 2)
+ return 1;
+
+ return 0;
+}
+
static char *rt2800usb_get_firmware_name(struct rt2x00_dev *rt2x00dev)
{
return FIRMWARE_RT2870;
@@ -240,6 +265,7 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
int status;
u32 offset;
u32 length;
+ int retval;
/*
* Check which section of the firmware we need.
@@ -257,8 +283,16 @@ static int rt2800usb_write_firmware(struct rt2x00_dev *rt2x00dev,
/*
* Write firmware to device.
*/
- rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
- data + offset, length);
+ retval = rt2800usb_autorun_detect(rt2x00dev);
+ if (retval < 0)
+ return retval;
+ if (retval) {
+ rt2x00_info(rt2x00dev,
+ "Firmware loading not required - NIC in AutoRun mode\n");
+ } else {
+ rt2x00usb_register_multiwrite(rt2x00dev, FIRMWARE_IMAGE_BASE,
+ data + offset, length);
+ }
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_CID, ~0);
rt2x00usb_register_write(rt2x00dev, H2M_MAILBOX_STATUS, ~0);
@@ -735,11 +769,26 @@ static void rt2800usb_fill_rxdone(struct queue_entry *entry,
/*
* Device probe functions.
*/
+static int rt2800usb_efuse_detect(struct rt2x00_dev *rt2x00dev)
+{
+ int retval;
+
+ retval = rt2800usb_autorun_detect(rt2x00dev);
+ if (retval < 0)
+ return retval;
+ if (retval)
+ return 1;
+ return rt2800_efuse_detect(rt2x00dev);
+}
+
static int rt2800usb_read_eeprom(struct rt2x00_dev *rt2x00dev)
{
int retval;
- if (rt2800_efuse_detect(rt2x00dev))
+ retval = rt2800usb_efuse_detect(rt2x00dev);
+ if (retval < 0)
+ return retval;
+ if (retval)
retval = rt2800_read_eeprom_efuse(rt2x00dev);
else
retval = rt2x00usb_eeprom_read(rt2x00dev, rt2x00dev->eeprom,
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 010b7650524..d13f25cd70d 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -693,6 +693,7 @@ enum rt2x00_capability_flags {
REQUIRE_SW_SEQNO,
REQUIRE_HT_TX_DESC,
REQUIRE_PS_AUTOWAKE,
+ REQUIRE_DELAYED_RFKILL,
/*
* Capabilities
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 2bde6729f5e..4fa43a2eeb7 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -1126,9 +1126,10 @@ static void rt2x00lib_uninitialize(struct rt2x00_dev *rt2x00dev)
return;
/*
- * Unregister extra components.
+ * Stop rfkill polling.
*/
- rt2x00rfkill_unregister(rt2x00dev);
+ if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
+ rt2x00rfkill_unregister(rt2x00dev);
/*
* Allow the HW to uninitialize.
@@ -1166,6 +1167,12 @@ static int rt2x00lib_initialize(struct rt2x00_dev *rt2x00dev)
set_bit(DEVICE_STATE_INITIALIZED, &rt2x00dev->flags);
+ /*
+ * Start rfkill polling.
+ */
+ if (test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
+ rt2x00rfkill_register(rt2x00dev);
+
return 0;
}
@@ -1375,7 +1382,12 @@ int rt2x00lib_probe_dev(struct rt2x00_dev *rt2x00dev)
rt2x00link_register(rt2x00dev);
rt2x00leds_register(rt2x00dev);
rt2x00debug_register(rt2x00dev);
- rt2x00rfkill_register(rt2x00dev);
+
+ /*
+ * Start rfkill polling.
+ */
+ if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
+ rt2x00rfkill_register(rt2x00dev);
return 0;
@@ -1391,6 +1403,12 @@ void rt2x00lib_remove_dev(struct rt2x00_dev *rt2x00dev)
clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
/*
+ * Stop rfkill polling.
+ */
+ if (!test_bit(REQUIRE_DELAYED_RFKILL, &rt2x00dev->cap_flags))
+ rt2x00rfkill_unregister(rt2x00dev);
+
+ /*
* Disable radio.
*/
rt2x00lib_disable_radio(rt2x00dev);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 30a2367ba8d..004dff9b962 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -487,6 +487,8 @@ int rt2x00mac_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd,
crypto.cipher = rt2x00crypto_key_to_cipher(key);
if (crypto.cipher == CIPHER_NONE)
return -EOPNOTSUPP;
+ if (crypto.cipher == CIPHER_TKIP && rt2x00_is_usb(rt2x00dev))
+ return -EOPNOTSUPP;
crypto.cmd = cmd;
@@ -621,20 +623,18 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
bss_conf->bssid);
/*
- * Update the beacon. This is only required on USB devices. PCI
- * devices fetch beacons periodically.
- */
- if (changes & BSS_CHANGED_BEACON && rt2x00_is_usb(rt2x00dev))
- rt2x00queue_update_beacon(rt2x00dev, vif);
-
- /*
* Start/stop beaconing.
*/
if (changes & BSS_CHANGED_BEACON_ENABLED) {
if (!bss_conf->enable_beacon && intf->enable_beacon) {
- rt2x00queue_clear_beacon(rt2x00dev, vif);
rt2x00dev->intf_beaconing--;
intf->enable_beacon = false;
+ /*
+ * Clear beacon in the H/W for this vif. This is needed
+ * to disable beaconing on this particular interface
+ * and keep it running on other interfaces.
+ */
+ rt2x00queue_clear_beacon(rt2x00dev, vif);
if (rt2x00dev->intf_beaconing == 0) {
/*
@@ -645,11 +645,15 @@ void rt2x00mac_bss_info_changed(struct ieee80211_hw *hw,
rt2x00queue_stop_queue(rt2x00dev->bcn);
mutex_unlock(&intf->beacon_skb_mutex);
}
-
-
} else if (bss_conf->enable_beacon && !intf->enable_beacon) {
rt2x00dev->intf_beaconing++;
intf->enable_beacon = true;
+ /*
+ * Upload beacon to the H/W. This is only required on
+ * USB devices. PCI devices fetch beacons periodically.
+ */
+ if (rt2x00_is_usb(rt2x00dev))
+ rt2x00queue_update_beacon(rt2x00dev, vif);
if (rt2x00dev->intf_beaconing == 1) {
/*
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.c b/drivers/net/wireless/rt2x00/rt2x00usb.c
index 10572452cc2..86c43d112a4 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.c
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.c
@@ -68,6 +68,12 @@ int rt2x00usb_vendor_request(struct rt2x00_dev *rt2x00dev,
}
}
+ /* If the port is powered down, we get a -EPROTO error, and this
+ * leads to a endless loop. So just say that the device is gone.
+ */
+ if (status == -EPROTO)
+ clear_bit(DEVICE_STATE_PRESENT, &rt2x00dev->flags);
+
rt2x00_err(rt2x00dev,
"Vendor Request 0x%02x failed for offset 0x%04x with error %d\n",
request, offset, status);
diff --git a/drivers/net/wireless/rt2x00/rt2x00usb.h b/drivers/net/wireless/rt2x00/rt2x00usb.h
index e7bcf62347d..831b65f93fe 100644
--- a/drivers/net/wireless/rt2x00/rt2x00usb.h
+++ b/drivers/net/wireless/rt2x00/rt2x00usb.h
@@ -93,6 +93,7 @@ enum rt2x00usb_mode_offset {
USB_MODE_SLEEP = 7, /* RT73USB */
USB_MODE_FIRMWARE = 8, /* RT73USB */
USB_MODE_WAKEUP = 9, /* RT73USB */
+ USB_MODE_AUTORUN = 17, /* RT2800USB */
};
/**
diff --git a/drivers/net/wireless/rtl818x/rtl8180/dev.c b/drivers/net/wireless/rtl818x/rtl8180/dev.c
index 50d69b13f98..2c1c02bafa1 100644
--- a/drivers/net/wireless/rtl818x/rtl8180/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8180/dev.c
@@ -284,6 +284,8 @@ static void rtl8180_handle_rx(struct ieee80211_hw *dev)
rx_status.band = dev->conf.chandef.chan->band;
rx_status.mactime = tsft;
rx_status.flag |= RX_FLAG_MACTIME_START;
+ if (flags & RTL818X_RX_DESC_FLAG_SPLCP)
+ rx_status.flag |= RX_FLAG_SHORTPRE;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
@@ -461,18 +463,23 @@ static void rtl8180_tx(struct ieee80211_hw *dev,
RTL818X_TX_DESC_FLAG_NO_ENC;
rc_flags = info->control.rates[0].flags;
+
+ /* HW will perform RTS-CTS when only RTS flags is set.
+ * HW will perform CTS-to-self when both RTS and CTS flags are set.
+ * RTS rate and RTS duration will be used also for CTS-to-self.
+ */
if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS) {
tx_flags |= RTL818X_TX_DESC_FLAG_RTS;
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
+ rts_duration = ieee80211_rts_duration(dev, priv->vif,
+ skb->len, info);
} else if (rc_flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- tx_flags |= RTL818X_TX_DESC_FLAG_CTS;
+ tx_flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS;
tx_flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
+ rts_duration = ieee80211_ctstoself_duration(dev, priv->vif,
+ skb->len, info);
}
- if (rc_flags & IEEE80211_TX_RC_USE_RTS_CTS)
- rts_duration = ieee80211_rts_duration(dev, priv->vif, skb->len,
- info);
-
if (priv->chip_family == RTL818X_CHIP_FAMILY_RTL8180) {
unsigned int remainder;
diff --git a/drivers/net/wireless/rtl818x/rtl8187/dev.c b/drivers/net/wireless/rtl818x/rtl8187/dev.c
index 0ca17cda48f..629ad8cfa17 100644
--- a/drivers/net/wireless/rtl818x/rtl8187/dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187/dev.c
@@ -253,14 +253,21 @@ static void rtl8187_tx(struct ieee80211_hw *dev,
flags |= ieee80211_get_tx_rate(dev, info)->hw_value << 24;
if (ieee80211_has_morefrags(tx_hdr->frame_control))
flags |= RTL818X_TX_DESC_FLAG_MOREFRAG;
+
+ /* HW will perform RTS-CTS when only RTS flags is set.
+ * HW will perform CTS-to-self when both RTS and CTS flags are set.
+ * RTS rate and RTS duration will be used also for CTS-to-self.
+ */
if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_RTS_CTS) {
flags |= RTL818X_TX_DESC_FLAG_RTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
rts_dur = ieee80211_rts_duration(dev, priv->vif,
skb->len, info);
} else if (info->control.rates[0].flags & IEEE80211_TX_RC_USE_CTS_PROTECT) {
- flags |= RTL818X_TX_DESC_FLAG_CTS;
+ flags |= RTL818X_TX_DESC_FLAG_RTS | RTL818X_TX_DESC_FLAG_CTS;
flags |= ieee80211_get_rts_cts_rate(dev, info)->hw_value << 19;
+ rts_dur = ieee80211_ctstoself_duration(dev, priv->vif,
+ skb->len, info);
}
if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
@@ -381,6 +388,8 @@ static void rtl8187_rx_cb(struct urb *urb)
rx_status.freq = dev->conf.chandef.chan->center_freq;
rx_status.band = dev->conf.chandef.chan->band;
rx_status.flag |= RX_FLAG_MACTIME_START;
+ if (flags & RTL818X_RX_DESC_FLAG_SPLCP)
+ rx_status.flag |= RX_FLAG_SHORTPRE;
if (flags & RTL818X_RX_DESC_FLAG_CRC32_ERR)
rx_status.flag |= RX_FLAG_FAILED_FCS_CRC;
memcpy(IEEE80211_SKB_RXCB(skb), &rx_status, sizeof(rx_status));
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
index 94cd9df9838..b14cf5a10f4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.c
@@ -2515,23 +2515,3 @@ void rtl88ee_suspend(struct ieee80211_hw *hw)
void rtl88ee_resume(struct ieee80211_hw *hw)
{
}
-
-/* Turn on AAP (RCR:bit 0) for promicuous mode. */
-void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-
- if (allow_all_da) /* Set BIT0 */
- rtlpci->receive_config |= RCR_AAP;
- else /* Clear BIT0 */
- rtlpci->receive_config &= ~RCR_AAP;
-
- if (write_into_reg)
- rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
-
- RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
- "receive_config = 0x%08X, write_into_reg =%d\n",
- rtlpci->receive_config, write_into_reg);
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
index b4460a41bd0..1850fde881b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/hw.h
@@ -61,8 +61,6 @@ void rtl8188ee_bt_reg_init(struct ieee80211_hw *hw);
void rtl8188ee_bt_hw_init(struct ieee80211_hw *hw);
void rtl88ee_suspend(struct ieee80211_hw *hw);
void rtl88ee_resume(struct ieee80211_hw *hw);
-void rtl88ee_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg);
void rtl88ee_fw_clk_off_timer_callback(unsigned long data);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
index 347af1e4f43..842d69349a3 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/sw.c
@@ -93,6 +93,7 @@ int rtl88e_init_sw_vars(struct ieee80211_hw *hw)
u8 tid;
rtl8188ee_bt_reg_init(hw);
+ rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
rtlpriv->dm.dm_initialgain_enable = 1;
rtlpriv->dm.dm_flag = 0;
@@ -254,7 +255,6 @@ static struct rtl_hal_ops rtl8188ee_hal_ops = {
.enable_hw_sec = rtl88ee_enable_hw_security_config,
.set_key = rtl88ee_set_key,
.init_sw_leds = rtl88ee_init_sw_leds,
- .allow_all_destaddr = rtl88ee_allow_all_destaddr,
.get_bbreg = rtl88e_phy_query_bb_reg,
.set_bbreg = rtl88e_phy_set_bb_reg,
.get_rfreg = rtl88e_phy_query_rf_reg,
@@ -266,6 +266,7 @@ static struct rtl_mod_params rtl88ee_mod_params = {
.inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
+ .msi_support = false,
.debug = DBG_EMERG,
};
@@ -382,10 +383,12 @@ module_param_named(debug, rtl88ee_mod_params.debug, int, 0444);
module_param_named(ips, rtl88ee_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl88ee_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl88ee_mod_params.fwctrl_lps, bool, 0444);
+module_param_named(msi, rtl88ee_mod_params.msi_support, bool, 0444);
MODULE_PARM_DESC(swenc, "Set to 1 for software crypto (default 0)\n");
MODULE_PARM_DESC(ips, "Set to 0 to not use link power save (default 1)\n");
MODULE_PARM_DESC(swlps, "Set to 1 to use SW control power save (default 0)\n");
MODULE_PARM_DESC(fwlps, "Set to 1 to use FW control power save (default 1)\n");
+MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
index 06ef47cd620..5b4c225396f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8188ee/trx.c
@@ -293,7 +293,7 @@ static void _rtl88ee_translate_rx_signal_stuff(struct ieee80211_hw *hw,
u8 *psaddr;
__le16 fc;
u16 type, ufc;
- bool match_bssid, packet_toself, packet_beacon, addr;
+ bool match_bssid, packet_toself, packet_beacon = false, addr;
tmp_buf = skb->data + pstatus->rx_drvinfo_size + pstatus->rx_bufshift;
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
index 55adf043aef..cdecb0fd4d8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.c
@@ -2423,24 +2423,3 @@ void rtl92ce_suspend(struct ieee80211_hw *hw)
void rtl92ce_resume(struct ieee80211_hw *hw)
{
}
-
-/* Turn on AAP (RCR:bit 0) for promicuous mode. */
-void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-
- if (allow_all_da) {/* Set BIT0 */
- rtlpci->receive_config |= RCR_AAP;
- } else {/* Clear BIT0 */
- rtlpci->receive_config &= ~RCR_AAP;
- }
-
- if (write_into_reg)
- rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
-
- RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
- "receive_config=0x%08X, write_into_reg=%d\n",
- rtlpci->receive_config, write_into_reg);
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
index 2d063b0c776..5533070f266 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/hw.h
@@ -76,7 +76,5 @@ void rtl8192ce_bt_reg_init(struct ieee80211_hw *hw);
void rtl8192ce_bt_hw_init(struct ieee80211_hw *hw);
void rtl92ce_suspend(struct ieee80211_hw *hw);
void rtl92ce_resume(struct ieee80211_hw *hw);
-void rtl92ce_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
index b790320d203..12f21f4073e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192ce/sw.c
@@ -229,7 +229,6 @@ static struct rtl_hal_ops rtl8192ce_hal_ops = {
.enable_hw_sec = rtl92ce_enable_hw_security_config,
.set_key = rtl92ce_set_key,
.init_sw_leds = rtl92ce_init_sw_leds,
- .allow_all_destaddr = rtl92ce_allow_all_destaddr,
.get_bbreg = rtl92c_phy_query_bb_reg,
.set_bbreg = rtl92c_phy_set_bb_reg,
.set_rfreg = rtl92ce_phy_set_rf_reg,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
index 68b5c7e92cf..a903c2671b4 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/hw.c
@@ -511,7 +511,7 @@ static int _rtl92cu_init_power_on(struct ieee80211_hw *hw)
pr_info("MAC auto ON okay!\n");
break;
}
- if (pollingCount++ > 100) {
+ if (pollingCount++ > 1000) {
RT_TRACE(rtlpriv, COMP_INIT, DBG_EMERG,
"Failed to polling REG_APS_FSMCO[APFM_ONMAC] done!\n");
return -ENODEV;
@@ -1001,7 +1001,7 @@ int rtl92cu_hw_init(struct ieee80211_hw *hw)
err = _rtl92cu_init_mac(hw);
if (err) {
RT_TRACE(rtlpriv, COMP_ERR, DBG_EMERG, "init mac failed!\n");
- return err;
+ goto exit;
}
err = rtl92c_download_fw(hw);
if (err) {
diff --git a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
index c61311084d7..361435f8608 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192cu/sw.c
@@ -395,9 +395,6 @@ static struct usb_driver rtl8192cu_driver = {
/* .resume = rtl_usb_resume, */
/* .reset_resume = rtl8192c_resume, */
#endif /* CONFIG_PM */
-#ifdef CONFIG_AUTOSUSPEND
- .supports_autosuspend = 1,
-#endif
.disable_hub_initiated_lpm = 1,
};
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
index 9098558d916..1c7101bcd79 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.c
@@ -2544,23 +2544,3 @@ void rtl92se_resume(struct ieee80211_hw *hw)
pci_write_config_dword(rtlpci->pdev, 0x40,
val & 0xffff00ff);
}
-
-/* Turn on AAP (RCR:bit 0) for promicuous mode. */
-void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-
- if (allow_all_da) /* Set BIT0 */
- rtlpci->receive_config |= RCR_AAP;
- else /* Clear BIT0 */
- rtlpci->receive_config &= ~RCR_AAP;
-
- if (write_into_reg)
- rtl_write_dword(rtlpriv, RCR, rtlpci->receive_config);
-
- RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
- "receive_config=0x%08X, write_into_reg=%d\n",
- rtlpci->receive_config, write_into_reg);
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
index da48aa8cbe6..4cacee10f31 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/hw.h
@@ -74,7 +74,5 @@ void rtl92se_set_key(struct ieee80211_hw *hw,
u8 enc_algo, bool is_wepkey, bool clear_all);
void rtl92se_suspend(struct ieee80211_hw *hw);
void rtl92se_resume(struct ieee80211_hw *hw);
-void rtl92se_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
index 2e8e6f8d2d5..1bff2a0f760 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/sw.c
@@ -290,7 +290,6 @@ static struct rtl_hal_ops rtl8192se_hal_ops = {
.enable_hw_sec = rtl92se_enable_hw_security_config,
.set_key = rtl92se_set_key,
.init_sw_leds = rtl92se_init_sw_leds,
- .allow_all_destaddr = rtl92se_allow_all_destaddr,
.get_bbreg = rtl92s_phy_query_bb_reg,
.set_bbreg = rtl92s_phy_set_bb_reg,
.get_rfreg = rtl92s_phy_query_rf_reg,
diff --git a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
index 36b48be8329..2b3c78baa9f 100644
--- a/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8192se/trx.c
@@ -49,6 +49,12 @@ static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 skb_queue)
if (ieee80211_is_nullfunc(fc))
return QSLT_HIGH;
+ /* Kernel commit 1bf4bbb4024dcdab changed EAPOL packets to use
+ * queue V0 at priority 7; however, the RTL8192SE appears to have
+ * that queue at priority 6
+ */
+ if (skb->priority == 7)
+ return QSLT_VO;
return skb->priority;
}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
index 48fee1be78c..5b4a714f3c8 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hal_bt_coexist.c
@@ -32,7 +32,6 @@
#include "dm.h"
#include "fw.h"
#include "../rtl8723com/fw_common.h"
-#include "../rtl8723com/fw_common.h"
#include "phy.h"
#include "reg.h"
#include "hal_btc.h"
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
index 65c9e80e1f7..87f69166a7e 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.c
@@ -2383,24 +2383,3 @@ void rtl8723ae_suspend(struct ieee80211_hw *hw)
void rtl8723ae_resume(struct ieee80211_hw *hw)
{
}
-
-/* Turn on AAP (RCR:bit 0) for promicuous mode. */
-void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-
- if (allow_all_da) /* Set BIT0 */
- rtlpci->receive_config |= RCR_AAP;
- else /* Clear BIT0 */
- rtlpci->receive_config &= ~RCR_AAP;
-
- if (write_into_reg)
- rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
-
-
- RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
- "receive_config=0x%08X, write_into_reg=%d\n",
- rtlpci->receive_config, write_into_reg);
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
index 6fa24f79b1d..d3bc39fb27a 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/hw.h
@@ -67,7 +67,5 @@ void rtl8723ae_bt_reg_init(struct ieee80211_hw *hw);
void rtl8723ae_bt_hw_init(struct ieee80211_hw *hw);
void rtl8723ae_suspend(struct ieee80211_hw *hw);
void rtl8723ae_resume(struct ieee80211_hw *hw);
-void rtl8723ae_allow_all_destaddr(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
index 1087a3bd07f..73cba1eec8c 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723ae/sw.c
@@ -238,7 +238,6 @@ static struct rtl_hal_ops rtl8723ae_hal_ops = {
.enable_hw_sec = rtl8723ae_enable_hw_security_config,
.set_key = rtl8723ae_set_key,
.init_sw_leds = rtl8723ae_init_sw_leds,
- .allow_all_destaddr = rtl8723ae_allow_all_destaddr,
.get_bbreg = rtl8723_phy_query_bb_reg,
.set_bbreg = rtl8723_phy_set_bb_reg,
.get_rfreg = rtl8723ae_phy_query_rf_reg,
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
index 0fdf0909321..3d555495b45 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.c
@@ -2501,23 +2501,3 @@ void rtl8723be_suspend(struct ieee80211_hw *hw)
void rtl8723be_resume(struct ieee80211_hw *hw)
{
}
-
-/* Turn on AAP (RCR:bit 0) for promicuous mode. */
-void rtl8723be_allow_all_destaddr(struct ieee80211_hw *hw, bool allow_all_da,
- bool write_into_reg)
-{
- struct rtl_priv *rtlpriv = rtl_priv(hw);
- struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
-
- if (allow_all_da) /* Set BIT0 */
- rtlpci->receive_config |= RCR_AAP;
- else /* Clear BIT0 */
- rtlpci->receive_config &= ~RCR_AAP;
-
- if (write_into_reg)
- rtl_write_dword(rtlpriv, REG_RCR, rtlpci->receive_config);
-
- RT_TRACE(rtlpriv, COMP_TURBO | COMP_INIT, DBG_LOUD,
- "receive_config = 0x%08X, write_into_reg =%d\n",
- rtlpci->receive_config, write_into_reg);
-}
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h b/drivers/net/wireless/rtlwifi/rtl8723be/hw.h
index b7449a9b57e..64c7551af6b 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/hw.h
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/hw.h
@@ -59,6 +59,4 @@ void rtl8723be_bt_reg_init(struct ieee80211_hw *hw);
void rtl8723be_bt_hw_init(struct ieee80211_hw *hw);
void rtl8723be_suspend(struct ieee80211_hw *hw);
void rtl8723be_resume(struct ieee80211_hw *hw);
-void rtl8723be_allow_all_destaddr(struct ieee80211_hw *hw, bool allow_all_da,
- bool write_into_reg);
#endif
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
index a07213645da..ff12bf41644 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/sw.c
@@ -92,7 +92,7 @@ int rtl8723be_init_sw_vars(struct ieee80211_hw *hw)
struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
rtl8723be_bt_reg_init(hw);
- rtlpci->msi_support = false;
+ rtlpci->msi_support = rtlpriv->cfg->mod_params->msi_support;
rtlpriv->btcoexist.btc_ops = rtl_btc_get_ops_pointer();
rtlpriv->dm.dm_initialgain_enable = 1;
@@ -253,6 +253,7 @@ static struct rtl_mod_params rtl8723be_mod_params = {
.inactiveps = true,
.swctrl_lps = false,
.fwctrl_lps = true,
+ .msi_support = false,
.debug = DBG_EMERG,
};
@@ -365,9 +366,11 @@ module_param_named(debug, rtl8723be_mod_params.debug, int, 0444);
module_param_named(ips, rtl8723be_mod_params.inactiveps, bool, 0444);
module_param_named(swlps, rtl8723be_mod_params.swctrl_lps, bool, 0444);
module_param_named(fwlps, rtl8723be_mod_params.fwctrl_lps, bool, 0444);
+module_param_named(msi, rtl8723be_mod_params.msi_support, bool, 0444);
MODULE_PARM_DESC(swenc, "using hardware crypto (default 0 [hardware])\n");
MODULE_PARM_DESC(ips, "using no link power save (default 1 is open)\n");
MODULE_PARM_DESC(fwlps, "using linked fw control power save (default 1 is open)\n");
+MODULE_PARM_DESC(msi, "Set to 1 to use MSI interrupts mode (default 0)\n");
MODULE_PARM_DESC(debug, "Set debug level (0-5) (default 0)");
static SIMPLE_DEV_PM_OPS(rtlwifi_pm_ops, rtl_pci_suspend, rtl_pci_resume);
diff --git a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c b/drivers/net/wireless/rtlwifi/rtl8723be/trx.c
index e0a0d8c8fed..969eaea5edd 100644
--- a/drivers/net/wireless/rtlwifi/rtl8723be/trx.c
+++ b/drivers/net/wireless/rtlwifi/rtl8723be/trx.c
@@ -33,7 +33,6 @@
#include "trx.h"
#include "led.h"
#include "dm.h"
-#include "phy.h"
static u8 _rtl8723be_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
{
diff --git a/drivers/net/wireless/rtlwifi/wifi.h b/drivers/net/wireless/rtlwifi/wifi.h
index 6965afdf572..407a7936d36 100644
--- a/drivers/net/wireless/rtlwifi/wifi.h
+++ b/drivers/net/wireless/rtlwifi/wifi.h
@@ -1960,8 +1960,6 @@ struct rtl_hal_ops {
u32 regaddr, u32 bitmask);
void (*set_rfreg) (struct ieee80211_hw *hw, enum radio_path rfpath,
u32 regaddr, u32 bitmask, u32 data);
- void (*allow_all_destaddr)(struct ieee80211_hw *hw,
- bool allow_all_da, bool write_into_reg);
void (*linked_set_reg) (struct ieee80211_hw *hw);
void (*chk_switch_dmdp) (struct ieee80211_hw *hw);
void (*dualmac_easy_concurrent) (struct ieee80211_hw *hw);
@@ -2030,6 +2028,10 @@ struct rtl_mod_params {
/* default: 1 = using linked fw power save */
bool fwctrl_lps;
+
+ /* default: 0 = not using MSI interrupts mode */
+ /* submodules should set their own defalut value */
+ bool msi_support;
};
struct rtl_hal_usbint_cfg {
diff --git a/drivers/net/wireless/ti/wl1251/acx.c b/drivers/net/wireless/ti/wl1251/acx.c
index 5a4ec56c83d..5695628757e 100644
--- a/drivers/net/wireless/ti/wl1251/acx.c
+++ b/drivers/net/wireless/ti/wl1251/acx.c
@@ -2,7 +2,6 @@
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/crc7.h>
#include "wl1251.h"
#include "reg.h"
diff --git a/drivers/net/wireless/ti/wl1251/cmd.c b/drivers/net/wireless/ti/wl1251/cmd.c
index bf1fa18b978..ede31f048ef 100644
--- a/drivers/net/wireless/ti/wl1251/cmd.c
+++ b/drivers/net/wireless/ti/wl1251/cmd.c
@@ -2,7 +2,6 @@
#include <linux/module.h>
#include <linux/slab.h>
-#include <linux/crc7.h>
#include <linux/etherdevice.h>
#include "wl1251.h"
diff --git a/drivers/net/wireless/ti/wl1251/event.c b/drivers/net/wireless/ti/wl1251/event.c
index db010531374..c98630394a1 100644
--- a/drivers/net/wireless/ti/wl1251/event.c
+++ b/drivers/net/wireless/ti/wl1251/event.c
@@ -124,11 +124,12 @@ static int wl1251_event_process(struct wl1251 *wl, struct event_mailbox *mbox)
return ret;
}
- if (wl->vif && vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
+ if (vector & SYNCHRONIZATION_TIMEOUT_EVENT_ID) {
wl1251_debug(DEBUG_EVENT, "SYNCHRONIZATION_TIMEOUT_EVENT");
/* indicate to the stack, that beacons have been lost */
- ieee80211_beacon_loss(wl->vif);
+ if (wl->vif && wl->vif->type == NL80211_IFTYPE_STATION)
+ ieee80211_beacon_loss(wl->vif);
}
if (vector & REGAINED_BSS_EVENT_ID) {
diff --git a/drivers/net/wireless/ti/wl1251/main.c b/drivers/net/wireless/ti/wl1251/main.c
index 757e25784a8..4e782f18ae3 100644
--- a/drivers/net/wireless/ti/wl1251/main.c
+++ b/drivers/net/wireless/ti/wl1251/main.c
@@ -550,6 +550,34 @@ static void wl1251_op_remove_interface(struct ieee80211_hw *hw,
mutex_unlock(&wl->mutex);
}
+static int wl1251_build_null_data(struct wl1251 *wl)
+{
+ struct sk_buff *skb = NULL;
+ int size;
+ void *ptr;
+ int ret = -ENOMEM;
+
+ if (wl->bss_type == BSS_TYPE_IBSS) {
+ size = sizeof(struct wl12xx_null_data_template);
+ ptr = NULL;
+ } else {
+ skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
+ if (!skb)
+ goto out;
+ size = skb->len;
+ ptr = skb->data;
+ }
+
+ ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA, ptr, size);
+
+out:
+ dev_kfree_skb(skb);
+ if (ret)
+ wl1251_warning("cmd buld null data failed: %d", ret);
+
+ return ret;
+}
+
static int wl1251_build_qos_null_data(struct wl1251 *wl)
{
struct ieee80211_qos_hdr template;
@@ -687,16 +715,6 @@ static int wl1251_op_config(struct ieee80211_hw *hw, u32 changed)
wl->power_level = conf->power_level;
}
- /*
- * Tell stack that connection is lost because hw encryption isn't
- * supported in monitor mode.
- * This requires temporary enabling of the hw connection monitor flag
- */
- if ((changed & IEEE80211_CONF_CHANGE_MONITOR) && wl->vif) {
- wl->hw->flags |= IEEE80211_HW_CONNECTION_MONITOR;
- ieee80211_connection_loss(wl->vif);
- }
-
out_sleep:
wl1251_ps_elp_sleep(wl);
@@ -1103,24 +1121,19 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
wl->rssi_thold = bss_conf->cqm_rssi_thold;
}
- if (changed & BSS_CHANGED_BSSID) {
+ if ((changed & BSS_CHANGED_BSSID) &&
+ memcmp(wl->bssid, bss_conf->bssid, ETH_ALEN)) {
memcpy(wl->bssid, bss_conf->bssid, ETH_ALEN);
- skb = ieee80211_nullfunc_get(wl->hw, wl->vif);
- if (!skb)
- goto out_sleep;
-
- ret = wl1251_cmd_template_set(wl, CMD_NULL_DATA,
- skb->data, skb->len);
- dev_kfree_skb(skb);
- if (ret < 0)
- goto out_sleep;
+ if (!is_zero_ether_addr(wl->bssid)) {
+ ret = wl1251_build_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
- ret = wl1251_build_qos_null_data(wl);
- if (ret < 0)
- goto out;
+ ret = wl1251_build_qos_null_data(wl);
+ if (ret < 0)
+ goto out_sleep;
- if (wl->bss_type != BSS_TYPE_IBSS) {
ret = wl1251_join(wl, wl->bss_type, wl->channel,
wl->beacon_int, wl->dtim_period);
if (ret < 0)
@@ -1129,9 +1142,6 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
}
if (changed & BSS_CHANGED_ASSOC) {
- /* Disable temporary enabled hw connection monitor flag */
- wl->hw->flags &= ~IEEE80211_HW_CONNECTION_MONITOR;
-
if (bss_conf->assoc) {
wl->beacon_int = bss_conf->beacon_int;
@@ -1216,8 +1226,8 @@ static void wl1251_op_bss_info_changed(struct ieee80211_hw *hw,
if (ret < 0)
goto out_sleep;
- ret = wl1251_join(wl, wl->bss_type, wl->beacon_int,
- wl->channel, wl->dtim_period);
+ ret = wl1251_join(wl, wl->bss_type, wl->channel,
+ wl->beacon_int, wl->dtim_period);
if (ret < 0)
goto out_sleep;
diff --git a/drivers/net/wireless/ti/wl1251/spi.c b/drivers/net/wireless/ti/wl1251/spi.c
index b06d36d9936..a0aa8fa7239 100644
--- a/drivers/net/wireless/ti/wl1251/spi.c
+++ b/drivers/net/wireless/ti/wl1251/spi.c
@@ -23,6 +23,7 @@
#include <linux/irq.h>
#include <linux/module.h>
#include <linux/slab.h>
+#include <linux/swab.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/wl12xx.h>
@@ -83,47 +84,44 @@ static void wl1251_spi_reset(struct wl1251 *wl)
static void wl1251_spi_wake(struct wl1251 *wl)
{
- u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
struct spi_transfer t;
struct spi_message m;
+ u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
- cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
if (!cmd) {
wl1251_error("could not allocate cmd for spi init");
return;
}
- memset(crc, 0, sizeof(crc));
memset(&t, 0, sizeof(t));
spi_message_init(&m);
/* Set WSPI_INIT_COMMAND
* the data is being send from the MSB to LSB
*/
- cmd[2] = 0xff;
- cmd[3] = 0xff;
- cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
- cmd[0] = 0;
- cmd[7] = 0;
- cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
- cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
+ cmd[0] = 0xff;
+ cmd[1] = 0xff;
+ cmd[2] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
+ cmd[3] = 0;
+ cmd[4] = 0;
+ cmd[5] = HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
+ cmd[5] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
+
+ cmd[6] = WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
+ | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
- cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
+ cmd[6] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
else
- cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
-
- cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
- | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
-
- crc[0] = cmd[1];
- crc[1] = cmd[0];
- crc[2] = cmd[7];
- crc[3] = cmd[6];
- crc[4] = cmd[5];
+ cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
- cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
- cmd[4] |= WSPI_INIT_CMD_END;
+ cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END;
+ /*
+ * The above is the logical order; it must actually be stored
+ * in the buffer byte-swapped.
+ */
+ __swab32s((u32 *)cmd);
+ __swab32s((u32 *)cmd+1);
t.tx_buf = cmd;
t.len = WSPI_INIT_CMD_LEN;
diff --git a/drivers/net/wireless/ti/wlcore/debugfs.h b/drivers/net/wireless/ti/wlcore/debugfs.h
index f7381dd6900..0f2cfb0d2a9 100644
--- a/drivers/net/wireless/ti/wlcore/debugfs.h
+++ b/drivers/net/wireless/ti/wlcore/debugfs.h
@@ -57,7 +57,7 @@ static const struct file_operations name## _ops = { \
wl, &name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
- } while (0);
+ } while (0)
#define DEBUGFS_ADD_PREFIX(prefix, name, parent) \
@@ -66,7 +66,7 @@ static const struct file_operations name## _ops = { \
wl, &prefix## _## name## _ops); \
if (!entry || IS_ERR(entry)) \
goto err; \
- } while (0);
+ } while (0)
#define DEBUGFS_FWSTATS_FILE(sub, name, fmt, struct_type) \
static ssize_t sub## _ ##name## _read(struct file *file, \
diff --git a/drivers/net/wireless/ti/wlcore/main.c b/drivers/net/wireless/ti/wlcore/main.c
index 077eb5b9cd7..3d6028e6275 100644
--- a/drivers/net/wireless/ti/wlcore/main.c
+++ b/drivers/net/wireless/ti/wlcore/main.c
@@ -543,7 +543,7 @@ static int wlcore_irq_locked(struct wl1271 *wl)
* wl1271_ps_elp_wakeup cannot be called concurrently.
*/
clear_bit(WL1271_FLAG_IRQ_RUNNING, &wl->flags);
- smp_mb__after_clear_bit();
+ smp_mb__after_atomic();
ret = wlcore_fw_status(wl, wl->fw_status);
if (ret < 0)
@@ -1416,7 +1416,7 @@ void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter)
int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
u16 offset, u8 flags,
- u8 *pattern, u8 len)
+ const u8 *pattern, u8 len)
{
struct wl12xx_rx_filter_field *field;
diff --git a/drivers/net/wireless/ti/wlcore/spi.c b/drivers/net/wireless/ti/wlcore/spi.c
index 5f3a389dd74..392c882b28f 100644
--- a/drivers/net/wireless/ti/wlcore/spi.c
+++ b/drivers/net/wireless/ti/wlcore/spi.c
@@ -24,11 +24,12 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/swab.h>
#include <linux/crc7.h>
#include <linux/spi/spi.h>
#include <linux/wl12xx.h>
#include <linux/platform_device.h>
-#include <linux/slab.h>
#include "wlcore.h"
#include "wl12xx_80211.h"
@@ -110,18 +111,16 @@ static void wl12xx_spi_reset(struct device *child)
static void wl12xx_spi_init(struct device *child)
{
struct wl12xx_spi_glue *glue = dev_get_drvdata(child->parent);
- u8 crc[WSPI_INIT_CMD_CRC_LEN], *cmd;
struct spi_transfer t;
struct spi_message m;
+ u8 *cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
- cmd = kzalloc(WSPI_INIT_CMD_LEN, GFP_KERNEL);
if (!cmd) {
dev_err(child->parent,
"could not allocate cmd for spi init\n");
return;
}
- memset(crc, 0, sizeof(crc));
memset(&t, 0, sizeof(t));
spi_message_init(&m);
@@ -129,30 +128,29 @@ static void wl12xx_spi_init(struct device *child)
* Set WSPI_INIT_COMMAND
* the data is being send from the MSB to LSB
*/
- cmd[2] = 0xff;
- cmd[3] = 0xff;
- cmd[1] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
- cmd[0] = 0;
- cmd[7] = 0;
- cmd[6] |= HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
- cmd[6] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
+ cmd[0] = 0xff;
+ cmd[1] = 0xff;
+ cmd[2] = WSPI_INIT_CMD_START | WSPI_INIT_CMD_TX;
+ cmd[3] = 0;
+ cmd[4] = 0;
+ cmd[5] = HW_ACCESS_WSPI_INIT_CMD_MASK << 3;
+ cmd[5] |= HW_ACCESS_WSPI_FIXED_BUSY_LEN & WSPI_INIT_CMD_FIXEDBUSY_LEN;
+
+ cmd[6] = WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
+ | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
if (HW_ACCESS_WSPI_FIXED_BUSY_LEN == 0)
- cmd[5] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
+ cmd[6] |= WSPI_INIT_CMD_DIS_FIXEDBUSY;
else
- cmd[5] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
+ cmd[6] |= WSPI_INIT_CMD_EN_FIXEDBUSY;
- cmd[5] |= WSPI_INIT_CMD_IOD | WSPI_INIT_CMD_IP | WSPI_INIT_CMD_CS
- | WSPI_INIT_CMD_WSPI | WSPI_INIT_CMD_WS;
-
- crc[0] = cmd[1];
- crc[1] = cmd[0];
- crc[2] = cmd[7];
- crc[3] = cmd[6];
- crc[4] = cmd[5];
-
- cmd[4] |= crc7(0, crc, WSPI_INIT_CMD_CRC_LEN) << 1;
- cmd[4] |= WSPI_INIT_CMD_END;
+ cmd[7] = crc7_be(0, cmd+2, WSPI_INIT_CMD_CRC_LEN) | WSPI_INIT_CMD_END;
+ /*
+ * The above is the logical order; it must actually be stored
+ * in the buffer byte-swapped.
+ */
+ __swab32s((u32 *)cmd);
+ __swab32s((u32 *)cmd+1);
t.tx_buf = cmd;
t.len = WSPI_INIT_CMD_LEN;
diff --git a/drivers/net/wireless/ti/wlcore/wlcore_i.h b/drivers/net/wireless/ti/wlcore/wlcore_i.h
index 756e890bc5e..c2c34a84ff3 100644
--- a/drivers/net/wireless/ti/wlcore/wlcore_i.h
+++ b/drivers/net/wireless/ti/wlcore/wlcore_i.h
@@ -512,8 +512,8 @@ int wl1271_recalc_rx_streaming(struct wl1271 *wl, struct wl12xx_vif *wlvif);
void wl12xx_queue_recovery_work(struct wl1271 *wl);
size_t wl12xx_copy_fwlog(struct wl1271 *wl, u8 *memblock, size_t maxlen);
int wl1271_rx_filter_alloc_field(struct wl12xx_rx_filter *filter,
- u16 offset, u8 flags,
- u8 *pattern, u8 len);
+ u16 offset, u8 flags,
+ const u8 *pattern, u8 len);
void wl1271_rx_filter_free(struct wl12xx_rx_filter *filter);
struct wl12xx_rx_filter *wl1271_rx_filter_alloc(void);
int wl1271_rx_filter_get_fields_size(struct wl12xx_rx_filter *filter);