aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless')
-rw-r--r--drivers/net/wireless/ath/Kconfig1
-rw-r--r--drivers/net/wireless/ath/Makefile1
-rw-r--r--drivers/net/wireless/ath/ath5k/ahb.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/ani.h4
-rw-r--r--drivers/net/wireless/ath/ath5k/ath5k.h98
-rw-r--r--drivers/net/wireless/ath/ath5k/attach.c18
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c31
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h55
-rw-r--r--drivers/net/wireless/ath/ath5k/caps.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/debug.c15
-rw-r--r--drivers/net/wireless/ath/ath5k/desc.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/dma.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/eeprom.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/gpio.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/initvals.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/led.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c5
-rw-r--r--drivers/net/wireless/ath/ath5k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath5k/pcu.c5
-rw-r--r--drivers/net/wireless/ath/ath5k/phy.c91
-rw-r--r--drivers/net/wireless/ath/ath5k/qcu.c10
-rw-r--r--drivers/net/wireless/ath/ath5k/reset.c79
-rw-r--r--drivers/net/wireless/ath/ath5k/rfkill.c2
-rw-r--r--drivers/net/wireless/ath/ath5k/sysfs.c1
-rw-r--r--drivers/net/wireless/ath/ath5k/trace.h3
-rw-r--r--drivers/net/wireless/ath/ath6kl/Kconfig15
-rw-r--r--drivers/net/wireless/ath/ath6kl/Makefile35
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.c692
-rw-r--r--drivers/net/wireless/ath/ath6kl/bmi.h250
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.c1538
-rw-r--r--drivers/net/wireless/ath/ath6kl/cfg80211.h39
-rw-r--r--drivers/net/wireless/ath/ath6kl/common.h180
-rw-r--r--drivers/net/wireless/ath/ath6kl/core.h544
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.c150
-rw-r--r--drivers/net/wireless/ath/ath6kl/debug.h105
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif-ops.h72
-rw-r--r--drivers/net/wireless/ath/ath6kl/hif.h207
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.c2457
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc.h607
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_hif.c641
-rw-r--r--drivers/net/wireless/ath/ath6kl/htc_hif.h92
-rw-r--r--drivers/net/wireless/ath/ath6kl/init.c1303
-rw-r--r--drivers/net/wireless/ath/ath6kl/main.c1337
-rw-r--r--drivers/net/wireless/ath/ath6kl/node.c234
-rw-r--r--drivers/net/wireless/ath/ath6kl/sdio.c912
-rw-r--r--drivers/net/wireless/ath/ath6kl/target.h331
-rw-r--r--drivers/net/wireless/ath/ath6kl/txrx.c1457
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.c2743
-rw-r--r--drivers/net/wireless/ath/ath6kl/wmi.h2018
-rw-r--r--drivers/net/wireless/ath/ath9k/ahb.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h190
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_eeprom.c150
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_mac.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9003_phy.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c18
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c15
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c60
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_4k.c135
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_9287.c122
-rw-r--r--drivers/net/wireless/ath/ath9k/eeprom_def.c150
-rw-r--r--drivers/net/wireless/ath/ath9k/gpio.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/htc.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/htc_drv_init.c1
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h9
-rw-r--r--drivers/net/wireless/ath/ath9k/init.c8
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c16
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/pci.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h6
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c10
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c12
-rw-r--r--drivers/net/wireless/ath/regd.h2
-rw-r--r--drivers/net/wireless/ath/regd_common.h2
-rw-r--r--drivers/net/wireless/b43/Kconfig6
-rw-r--r--drivers/net/wireless/b43/main.c2
-rw-r--r--drivers/net/wireless/b43legacy/b43legacy.h1
-rw-r--r--drivers/net/wireless/b43legacy/dma.c374
-rw-r--r--drivers/net/wireless/b43legacy/dma.h107
-rw-r--r--drivers/net/wireless/b43legacy/main.c4
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2200.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945-rs.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-3945.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965-rs.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-4965.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl-led.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl3945-base.c1
-rw-r--r--drivers/net/wireless/iwlegacy/iwl4965-base.c1
-rw-r--r--drivers/net/wireless/iwlwifi/Kconfig17
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-1000.c16
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-2000.c24
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-5000.c13
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-6000.c20
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-calib.c69
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-hw.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c47
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rs.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-rxon.c23
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-tx.c30
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c388
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.h1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h34
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.c5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h5
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h29
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-led.c1
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c19
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-trans.c10
-rw-r--r--drivers/net/wireless/libertas/cfg.c69
-rw-r--r--drivers/net/wireless/libertas/cfg.h1
-rw-r--r--drivers/net/wireless/libertas/cmd.c6
-rw-r--r--drivers/net/wireless/libertas/decl.h4
-rw-r--r--drivers/net/wireless/libertas/dev.h28
-rw-r--r--drivers/net/wireless/libertas/ethtool.c1
-rw-r--r--drivers/net/wireless/libertas/if_sdio.c277
-rw-r--r--drivers/net/wireless/libertas/if_spi.c4
-rw-r--r--drivers/net/wireless/libertas/if_usb.c13
-rw-r--r--drivers/net/wireless/libertas/main.c180
-rw-r--r--drivers/net/wireless/libertas/mesh.c77
-rw-r--r--drivers/net/wireless/libertas/mesh.h27
-rw-r--r--drivers/net/wireless/libertas/rx.c1
-rw-r--r--drivers/net/wireless/libertas/tx.c1
-rw-r--r--drivers/net/wireless/mac80211_hwsim.c6
-rw-r--r--drivers/net/wireless/mwifiex/cfg80211.c209
-rw-r--r--drivers/net/wireless/mwifiex/fw.h15
-rw-r--r--drivers/net/wireless/mwifiex/init.c21
-rw-r--r--drivers/net/wireless/mwifiex/ioctl.h5
-rw-r--r--drivers/net/wireless/mwifiex/join.c32
-rw-r--r--drivers/net/wireless/mwifiex/main.c4
-rw-r--r--drivers/net/wireless/mwifiex/main.h55
-rw-r--r--drivers/net/wireless/mwifiex/scan.c1578
-rw-r--r--drivers/net/wireless/mwifiex/sta_event.c9
-rw-r--r--drivers/net/wireless/mwifiex/sta_ioctl.c230
-rw-r--r--drivers/net/wireless/orinoco/wext.c1
-rw-r--r--drivers/net/wireless/rndis_wlan.c2
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c39
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c39
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c46
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c1
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c34
-rw-r--r--drivers/net/wireless/rtlwifi/pci.c37
-rw-r--r--drivers/net/wireless/rtlwifi/pci.h26
-rw-r--r--drivers/net/wireless/wl1251/cmd.h2
-rw-r--r--drivers/net/wireless/wl1251/wl12xx_80211.h2
-rw-r--r--drivers/net/wireless/wl12xx/cmd.h4
-rw-r--r--drivers/net/wireless/wl12xx/main.c2
-rw-r--r--drivers/net/wireless/wl12xx/scan.h6
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx.h4
-rw-r--r--drivers/net/wireless/wl12xx/wl12xx_80211.h2
156 files changed, 20353 insertions, 3380 deletions
diff --git a/drivers/net/wireless/ath/Kconfig b/drivers/net/wireless/ath/Kconfig
index d1b23067619f..073548836413 100644
--- a/drivers/net/wireless/ath/Kconfig
+++ b/drivers/net/wireless/ath/Kconfig
@@ -25,5 +25,6 @@ config ATH_DEBUG
25source "drivers/net/wireless/ath/ath5k/Kconfig" 25source "drivers/net/wireless/ath/ath5k/Kconfig"
26source "drivers/net/wireless/ath/ath9k/Kconfig" 26source "drivers/net/wireless/ath/ath9k/Kconfig"
27source "drivers/net/wireless/ath/carl9170/Kconfig" 27source "drivers/net/wireless/ath/carl9170/Kconfig"
28source "drivers/net/wireless/ath/ath6kl/Kconfig"
28 29
29endif 30endif
diff --git a/drivers/net/wireless/ath/Makefile b/drivers/net/wireless/ath/Makefile
index 0e8f528c81c0..d1214696a35b 100644
--- a/drivers/net/wireless/ath/Makefile
+++ b/drivers/net/wireless/ath/Makefile
@@ -1,6 +1,7 @@
1obj-$(CONFIG_ATH5K) += ath5k/ 1obj-$(CONFIG_ATH5K) += ath5k/
2obj-$(CONFIG_ATH9K_HW) += ath9k/ 2obj-$(CONFIG_ATH9K_HW) += ath9k/
3obj-$(CONFIG_CARL9170) += carl9170/ 3obj-$(CONFIG_CARL9170) += carl9170/
4obj-$(CONFIG_ATH6KL) += ath6kl/
4 5
5obj-$(CONFIG_ATH_COMMON) += ath.o 6obj-$(CONFIG_ATH_COMMON) += ath.o
6 7
diff --git a/drivers/net/wireless/ath/ath5k/ahb.c b/drivers/net/wireless/ath/ath5k/ahb.c
index a2a167363dbf..e5be7e701816 100644
--- a/drivers/net/wireless/ath/ath5k/ahb.c
+++ b/drivers/net/wireless/ath/ath5k/ahb.c
@@ -169,7 +169,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
169 __set_bit(ATH_STAT_2G_DISABLED, ah->status); 169 __set_bit(ATH_STAT_2G_DISABLED, ah->status);
170 } 170 }
171 171
172 ret = ath5k_init_softc(ah, &ath_ahb_bus_ops); 172 ret = ath5k_init_ah(ah, &ath_ahb_bus_ops);
173 if (ret != 0) { 173 if (ret != 0) {
174 dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret); 174 dev_err(&pdev->dev, "failed to attach device, err=%d\n", ret);
175 ret = -ENODEV; 175 ret = -ENODEV;
@@ -214,7 +214,7 @@ static int ath_ahb_remove(struct platform_device *pdev)
214 __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE); 214 __raw_writel(reg, (void __iomem *) AR5K_AR5312_ENABLE);
215 } 215 }
216 216
217 ath5k_deinit_softc(ah); 217 ath5k_deinit_ah(ah);
218 platform_set_drvdata(pdev, NULL); 218 platform_set_drvdata(pdev, NULL);
219 ieee80211_free_hw(hw); 219 ieee80211_free_hw(hw);
220 220
diff --git a/drivers/net/wireless/ath/ath5k/ani.c b/drivers/net/wireless/ath/ath5k/ani.c
index 603ae15f139b..bea90e6be70e 100644
--- a/drivers/net/wireless/ath/ath5k/ani.c
+++ b/drivers/net/wireless/ath/ath5k/ani.c
@@ -15,7 +15,6 @@
15 */ 15 */
16 16
17#include "ath5k.h" 17#include "ath5k.h"
18#include "base.h"
19#include "reg.h" 18#include "reg.h"
20#include "debug.h" 19#include "debug.h"
21#include "ani.h" 20#include "ani.h"
diff --git a/drivers/net/wireless/ath/ath5k/ani.h b/drivers/net/wireless/ath/ath5k/ani.h
index 034015397093..7358b6c83c6c 100644
--- a/drivers/net/wireless/ath/ath5k/ani.h
+++ b/drivers/net/wireless/ath/ath5k/ani.h
@@ -16,6 +16,10 @@
16#ifndef ANI_H 16#ifndef ANI_H
17#define ANI_H 17#define ANI_H
18 18
19#include "../ath.h"
20
21enum ath5k_phy_error_code;
22
19/* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */ 23/* these thresholds are relative to the ATH5K_ANI_LISTEN_PERIOD */
20#define ATH5K_ANI_LISTEN_PERIOD 100 24#define ATH5K_ANI_LISTEN_PERIOD 100
21#define ATH5K_ANI_OFDM_TRIG_HIGH 500 25#define ATH5K_ANI_OFDM_TRIG_HIGH 500
diff --git a/drivers/net/wireless/ath/ath5k/ath5k.h b/drivers/net/wireless/ath/ath5k/ath5k.h
index 277d5cbe0068..fecbcd9a4259 100644
--- a/drivers/net/wireless/ath/ath5k/ath5k.h
+++ b/drivers/net/wireless/ath/ath5k/ath5k.h
@@ -131,13 +131,6 @@
131#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \ 131#define AR5K_REG_DISABLE_BITS(ah, _reg, _flags) \
132 ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg) 132 ath5k_hw_reg_write(ah, ath5k_hw_reg_read(ah, _reg) & ~(_flags), _reg)
133 133
134/* Access to PHY registers */
135#define AR5K_PHY_READ(ah, _reg) \
136 ath5k_hw_reg_read(ah, (ah)->ah_phy + ((_reg) << 2))
137
138#define AR5K_PHY_WRITE(ah, _reg, _val) \
139 ath5k_hw_reg_write(ah, _val, (ah)->ah_phy + ((_reg) << 2))
140
141/* Access QCU registers per queue */ 134/* Access QCU registers per queue */
142#define AR5K_REG_READ_Q(ah, _reg, _queue) \ 135#define AR5K_REG_READ_Q(ah, _reg, _queue) \
143 (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \ 136 (ath5k_hw_reg_read(ah, _reg) & (1 << _queue)) \
@@ -166,7 +159,6 @@
166#define AR5K_TUNE_DMA_BEACON_RESP 2 159#define AR5K_TUNE_DMA_BEACON_RESP 2
167#define AR5K_TUNE_SW_BEACON_RESP 10 160#define AR5K_TUNE_SW_BEACON_RESP 10
168#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0 161#define AR5K_TUNE_ADDITIONAL_SWBA_BACKOFF 0
169#define AR5K_TUNE_RADAR_ALERT false
170#define AR5K_TUNE_MIN_TX_FIFO_THRES 1 162#define AR5K_TUNE_MIN_TX_FIFO_THRES 1
171#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1) 163#define AR5K_TUNE_MAX_TX_FIFO_THRES ((IEEE80211_MAX_FRAME_LEN / 64) + 1)
172#define AR5K_TUNE_REGISTER_TIMEOUT 20000 164#define AR5K_TUNE_REGISTER_TIMEOUT 20000
@@ -295,17 +287,6 @@ enum ath5k_radio {
295 * Common silicon revision/version values 287 * Common silicon revision/version values
296 */ 288 */
297 289
298enum ath5k_srev_type {
299 AR5K_VERSION_MAC,
300 AR5K_VERSION_RAD,
301};
302
303struct ath5k_srev_name {
304 const char *sr_name;
305 enum ath5k_srev_type sr_type;
306 u_int sr_val;
307};
308
309#define AR5K_SREV_UNKNOWN 0xffff 290#define AR5K_SREV_UNKNOWN 0xffff
310 291
311#define AR5K_SREV_AR5210 0x00 /* Crete */ 292#define AR5K_SREV_AR5210 0x00 /* Crete */
@@ -424,7 +405,6 @@ enum ath5k_driver_mode {
424 AR5K_MODE_11A = 0, 405 AR5K_MODE_11A = 0,
425 AR5K_MODE_11B = 1, 406 AR5K_MODE_11B = 1,
426 AR5K_MODE_11G = 2, 407 AR5K_MODE_11G = 2,
427 AR5K_MODE_XR = 0,
428 AR5K_MODE_MAX = 3 408 AR5K_MODE_MAX = 3
429}; 409};
430 410
@@ -694,33 +674,6 @@ struct ath5k_gain {
694#define AR5K_SLOT_TIME_20 880 674#define AR5K_SLOT_TIME_20 880
695#define AR5K_SLOT_TIME_MAX 0xffff 675#define AR5K_SLOT_TIME_MAX 0xffff
696 676
697/* channel_flags */
698#define CHANNEL_CW_INT 0x0008 /* Contention Window interference detected */
699#define CHANNEL_CCK 0x0020 /* CCK channel */
700#define CHANNEL_OFDM 0x0040 /* OFDM channel */
701#define CHANNEL_2GHZ 0x0080 /* 2GHz channel. */
702#define CHANNEL_5GHZ 0x0100 /* 5GHz channel */
703#define CHANNEL_PASSIVE 0x0200 /* Only passive scan allowed */
704#define CHANNEL_DYN 0x0400 /* Dynamic CCK-OFDM channel (for g operation) */
705#define CHANNEL_XR 0x0800 /* XR channel */
706
707#define CHANNEL_A (CHANNEL_5GHZ | CHANNEL_OFDM)
708#define CHANNEL_B (CHANNEL_2GHZ | CHANNEL_CCK)
709#define CHANNEL_G (CHANNEL_2GHZ | CHANNEL_OFDM)
710#define CHANNEL_X (CHANNEL_5GHZ | CHANNEL_OFDM | CHANNEL_XR)
711
712#define CHANNEL_ALL (CHANNEL_OFDM | CHANNEL_CCK | \
713 CHANNEL_2GHZ | CHANNEL_5GHZ)
714
715#define CHANNEL_MODES CHANNEL_ALL
716
717/*
718 * Used internally for ath5k_hw_reset_tx_queue().
719 * Also see struct struct ieee80211_channel.
720 */
721#define IS_CHAN_XR(_c) ((_c->hw_value & CHANNEL_XR) != 0)
722#define IS_CHAN_B(_c) ((_c->hw_value & CHANNEL_B) != 0)
723
724/* 677/*
725 * The following structure is used to map 2GHz channels to 678 * The following structure is used to map 2GHz channels to
726 * 5GHz Atheros channels. 679 * 5GHz Atheros channels.
@@ -977,7 +930,7 @@ enum ath5k_power_mode {
977struct ath5k_capabilities { 930struct ath5k_capabilities {
978 /* 931 /*
979 * Supported PHY modes 932 * Supported PHY modes
980 * (ie. CHANNEL_A, CHANNEL_B, ...) 933 * (ie. AR5K_MODE_11A, AR5K_MODE_11B, ...)
981 */ 934 */
982 DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX); 935 DECLARE_BITMAP(cap_mode, AR5K_MODE_MAX);
983 936
@@ -1013,16 +966,6 @@ struct ath5k_nfcal_hist {
1013 s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */ 966 s16 nfval[ATH5K_NF_CAL_HIST_MAX]; /* last few noise floors */
1014}; 967};
1015 968
1016/**
1017 * struct avg_val - Helper structure for average calculation
1018 * @avg: contains the actual average value
1019 * @avg_weight: is used internally during calculation to prevent rounding errors
1020 */
1021struct ath5k_avg_val {
1022 int avg;
1023 int avg_weight;
1024};
1025
1026#define ATH5K_LED_MAX_NAME_LEN 31 969#define ATH5K_LED_MAX_NAME_LEN 31
1027 970
1028/* 971/*
@@ -1148,7 +1091,6 @@ struct ath5k_hw {
1148 bool rx_pending; /* rx tasklet pending */ 1091 bool rx_pending; /* rx tasklet pending */
1149 bool tx_pending; /* tx tasklet pending */ 1092 bool tx_pending; /* tx tasklet pending */
1150 1093
1151 u8 lladdr[ETH_ALEN];
1152 u8 bssidmask[ETH_ALEN]; 1094 u8 bssidmask[ETH_ALEN];
1153 1095
1154 unsigned int led_pin, /* GPIO pin for driving LED */ 1096 unsigned int led_pin, /* GPIO pin for driving LED */
@@ -1156,7 +1098,6 @@ struct ath5k_hw {
1156 1098
1157 struct work_struct reset_work; /* deferred chip reset */ 1099 struct work_struct reset_work; /* deferred chip reset */
1158 1100
1159 unsigned int rxbufsize; /* rx size based on mtu */
1160 struct list_head rxbuf; /* receive buffer */ 1101 struct list_head rxbuf; /* receive buffer */
1161 spinlock_t rxbuflock; 1102 spinlock_t rxbuflock;
1162 u32 *rxlink; /* link ptr in last RX desc */ 1103 u32 *rxlink; /* link ptr in last RX desc */
@@ -1208,10 +1149,8 @@ struct ath5k_hw {
1208 1149
1209 enum ath5k_version ah_version; 1150 enum ath5k_version ah_version;
1210 enum ath5k_radio ah_radio; 1151 enum ath5k_radio ah_radio;
1211 u32 ah_phy;
1212 u32 ah_mac_srev; 1152 u32 ah_mac_srev;
1213 u16 ah_mac_version; 1153 u16 ah_mac_version;
1214 u16 ah_mac_revision;
1215 u16 ah_phy_revision; 1154 u16 ah_phy_revision;
1216 u16 ah_radio_5ghz_revision; 1155 u16 ah_radio_5ghz_revision;
1217 u16 ah_radio_2ghz_revision; 1156 u16 ah_radio_2ghz_revision;
@@ -1279,12 +1218,6 @@ struct ath5k_hw {
1279 bool txp_setup; 1218 bool txp_setup;
1280 } ah_txpower; 1219 } ah_txpower;
1281 1220
1282 struct {
1283 bool r_enabled;
1284 int r_last_alert;
1285 struct ieee80211_channel r_last_channel;
1286 } ah_radar;
1287
1288 struct ath5k_nfcal_hist ah_nfcal_hist; 1221 struct ath5k_nfcal_hist ah_nfcal_hist;
1289 1222
1290 /* average beacon RSSI in our BSS (used by ANI) */ 1223 /* average beacon RSSI in our BSS (used by ANI) */
@@ -1327,36 +1260,13 @@ struct ath_bus_ops {
1327extern const struct ieee80211_ops ath5k_hw_ops; 1260extern const struct ieee80211_ops ath5k_hw_ops;
1328 1261
1329/* Initialization and detach functions */ 1262/* Initialization and detach functions */
1330int ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops);
1331void ath5k_deinit_softc(struct ath5k_hw *ah);
1332int ath5k_hw_init(struct ath5k_hw *ah); 1263int ath5k_hw_init(struct ath5k_hw *ah);
1333void ath5k_hw_deinit(struct ath5k_hw *ah); 1264void ath5k_hw_deinit(struct ath5k_hw *ah);
1334 1265
1335int ath5k_sysfs_register(struct ath5k_hw *ah); 1266int ath5k_sysfs_register(struct ath5k_hw *ah);
1336void ath5k_sysfs_unregister(struct ath5k_hw *ah); 1267void ath5k_sysfs_unregister(struct ath5k_hw *ah);
1337 1268
1338/* base.c */
1339struct ath5k_buf;
1340struct ath5k_txq;
1341
1342void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
1343bool ath5k_any_vif_assoc(struct ath5k_hw *ah);
1344void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
1345 struct ath5k_txq *txq);
1346int ath5k_start(struct ieee80211_hw *hw);
1347void ath5k_stop(struct ieee80211_hw *hw);
1348void ath5k_mode_setup(struct ath5k_hw *ah, struct ieee80211_vif *vif);
1349void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
1350 struct ieee80211_vif *vif);
1351int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
1352void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf);
1353int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
1354void ath5k_beacon_config(struct ath5k_hw *ah);
1355void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
1356void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
1357
1358/*Chip id helper functions */ 1269/*Chip id helper functions */
1359const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
1360int ath5k_hw_read_srev(struct ath5k_hw *ah); 1270int ath5k_hw_read_srev(struct ath5k_hw *ah);
1361 1271
1362/* LED functions */ 1272/* LED functions */
@@ -1367,7 +1277,7 @@ void ath5k_unregister_leds(struct ath5k_hw *ah);
1367 1277
1368 1278
1369/* Reset Functions */ 1279/* Reset Functions */
1370int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial); 1280int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel);
1371int ath5k_hw_on_hold(struct ath5k_hw *ah); 1281int ath5k_hw_on_hold(struct ath5k_hw *ah);
1372int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode, 1282int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1373 struct ieee80211_channel *channel, bool fast, bool skip_pcu); 1283 struct ieee80211_channel *channel, bool fast, bool skip_pcu);
@@ -1487,13 +1397,13 @@ int ath5k_hw_write_initvals(struct ath5k_hw *ah, u8 mode, bool change_channel);
1487 1397
1488/* PHY functions */ 1398/* PHY functions */
1489/* Misc PHY functions */ 1399/* Misc PHY functions */
1490u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan); 1400u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band);
1491int ath5k_hw_phy_disable(struct ath5k_hw *ah); 1401int ath5k_hw_phy_disable(struct ath5k_hw *ah);
1492/* Gain_F optimization */ 1402/* Gain_F optimization */
1493enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah); 1403enum ath5k_rfgain ath5k_hw_gainf_calibrate(struct ath5k_hw *ah);
1494int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah); 1404int ath5k_hw_rfgain_opt_init(struct ath5k_hw *ah);
1495/* PHY/RF channel functions */ 1405/* PHY/RF channel functions */
1496bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags); 1406bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel);
1497/* PHY calibration */ 1407/* PHY calibration */
1498void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah); 1408void ath5k_hw_init_nfcal_hist(struct ath5k_hw *ah);
1499int ath5k_hw_phy_calibrate(struct ath5k_hw *ah, 1409int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
diff --git a/drivers/net/wireless/ath/ath5k/attach.c b/drivers/net/wireless/ath/ath5k/attach.c
index f8a6b380d96d..91627dd2c26a 100644
--- a/drivers/net/wireless/ath/ath5k/attach.c
+++ b/drivers/net/wireless/ath/ath5k/attach.c
@@ -25,7 +25,6 @@
25#include "ath5k.h" 25#include "ath5k.h"
26#include "reg.h" 26#include "reg.h"
27#include "debug.h" 27#include "debug.h"
28#include "base.h"
29 28
30/** 29/**
31 * ath5k_hw_post - Power On Self Test helper function 30 * ath5k_hw_post - Power On Self Test helper function
@@ -95,7 +94,7 @@ static int ath5k_hw_post(struct ath5k_hw *ah)
95/** 94/**
96 * ath5k_hw_init - Check if hw is supported and init the needed structs 95 * ath5k_hw_init - Check if hw is supported and init the needed structs
97 * 96 *
98 * @ah: The &struct ath5k_hw we got from the driver's init_softc function 97 * @ah: The &struct ath5k_hw associated with the device
99 * 98 *
100 * Check if the device is supported, perform a POST and initialize the needed 99 * Check if the device is supported, perform a POST and initialize the needed
101 * structs. Returns -ENOMEM if we don't have memory for the needed structs, 100 * structs. Returns -ENOMEM if we don't have memory for the needed structs,
@@ -114,7 +113,6 @@ int ath5k_hw_init(struct ath5k_hw *ah)
114 /* 113 /*
115 * HW information 114 * HW information
116 */ 115 */
117 ah->ah_radar.r_enabled = AR5K_TUNE_RADAR_ALERT;
118 ah->ah_bwmode = AR5K_BWMODE_DEFAULT; 116 ah->ah_bwmode = AR5K_BWMODE_DEFAULT;
119 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER; 117 ah->ah_txpower.txp_tpc = AR5K_TUNE_TPC_TXPOWER;
120 ah->ah_imr = 0; 118 ah->ah_imr = 0;
@@ -137,9 +135,8 @@ int ath5k_hw_init(struct ath5k_hw *ah)
137 else 135 else
138 ah->ah_version = AR5K_AR5212; 136 ah->ah_version = AR5K_AR5212;
139 137
140 /* Get the MAC revision */ 138 /* Get the MAC version */
141 ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER); 139 ah->ah_mac_version = AR5K_REG_MS(srev, AR5K_SREV_VER);
142 ah->ah_mac_revision = AR5K_REG_MS(srev, AR5K_SREV_REV);
143 140
144 /* Fill the ath5k_hw struct with the needed functions */ 141 /* Fill the ath5k_hw struct with the needed functions */
145 ret = ath5k_hw_init_desc_functions(ah); 142 ret = ath5k_hw_init_desc_functions(ah);
@@ -147,7 +144,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
147 goto err; 144 goto err;
148 145
149 /* Bring device out of sleep and reset its units */ 146 /* Bring device out of sleep and reset its units */
150 ret = ath5k_hw_nic_wakeup(ah, 0, true); 147 ret = ath5k_hw_nic_wakeup(ah, NULL);
151 if (ret) 148 if (ret)
152 goto err; 149 goto err;
153 150
@@ -155,8 +152,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
155 ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) & 152 ah->ah_phy_revision = ath5k_hw_reg_read(ah, AR5K_PHY_CHIP_ID) &
156 0xffffffff; 153 0xffffffff;
157 ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah, 154 ah->ah_radio_5ghz_revision = ath5k_hw_radio_revision(ah,
158 CHANNEL_5GHZ); 155 IEEE80211_BAND_5GHZ);
159 ah->ah_phy = AR5K_PHY(0);
160 156
161 /* Try to identify radio chip based on its srev */ 157 /* Try to identify radio chip based on its srev */
162 switch (ah->ah_radio_5ghz_revision & 0xf0) { 158 switch (ah->ah_radio_5ghz_revision & 0xf0) {
@@ -164,14 +160,14 @@ int ath5k_hw_init(struct ath5k_hw *ah)
164 ah->ah_radio = AR5K_RF5111; 160 ah->ah_radio = AR5K_RF5111;
165 ah->ah_single_chip = false; 161 ah->ah_single_chip = false;
166 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, 162 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
167 CHANNEL_2GHZ); 163 IEEE80211_BAND_2GHZ);
168 break; 164 break;
169 case AR5K_SREV_RAD_5112: 165 case AR5K_SREV_RAD_5112:
170 case AR5K_SREV_RAD_2112: 166 case AR5K_SREV_RAD_2112:
171 ah->ah_radio = AR5K_RF5112; 167 ah->ah_radio = AR5K_RF5112;
172 ah->ah_single_chip = false; 168 ah->ah_single_chip = false;
173 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, 169 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
174 CHANNEL_2GHZ); 170 IEEE80211_BAND_2GHZ);
175 break; 171 break;
176 case AR5K_SREV_RAD_2413: 172 case AR5K_SREV_RAD_2413:
177 ah->ah_radio = AR5K_RF2413; 173 ah->ah_radio = AR5K_RF2413;
@@ -208,7 +204,7 @@ int ath5k_hw_init(struct ath5k_hw *ah)
208 ah->ah_radio = AR5K_RF5111; 204 ah->ah_radio = AR5K_RF5111;
209 ah->ah_single_chip = false; 205 ah->ah_single_chip = false;
210 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah, 206 ah->ah_radio_2ghz_revision = ath5k_hw_radio_revision(ah,
211 CHANNEL_2GHZ); 207 IEEE80211_BAND_2GHZ);
212 } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) || 208 } else if (ah->ah_mac_version == (AR5K_SREV_AR2425 >> 4) ||
213 ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) || 209 ah->ah_mac_version == (AR5K_SREV_AR2417 >> 4) ||
214 ah->ah_phy_revision == AR5K_SREV_PHY_2425) { 210 ah->ah_phy_revision == AR5K_SREV_PHY_2425) {
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index c3119a6caace..e9ea38d0fff6 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -52,6 +52,7 @@
52#include <linux/uaccess.h> 52#include <linux/uaccess.h>
53#include <linux/slab.h> 53#include <linux/slab.h>
54#include <linux/etherdevice.h> 54#include <linux/etherdevice.h>
55#include <linux/nl80211.h>
55 56
56#include <net/ieee80211_radiotap.h> 57#include <net/ieee80211_radiotap.h>
57 58
@@ -61,6 +62,8 @@
61#include "reg.h" 62#include "reg.h"
62#include "debug.h" 63#include "debug.h"
63#include "ani.h" 64#include "ani.h"
65#include "ath5k.h"
66#include "../regd.h"
64 67
65#define CREATE_TRACE_POINTS 68#define CREATE_TRACE_POINTS
66#include "trace.h" 69#include "trace.h"
@@ -272,20 +275,18 @@ static unsigned int
272ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels, 275ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
273 unsigned int mode, unsigned int max) 276 unsigned int mode, unsigned int max)
274{ 277{
275 unsigned int count, size, chfreq, freq, ch; 278 unsigned int count, size, freq, ch;
276 enum ieee80211_band band; 279 enum ieee80211_band band;
277 280
278 switch (mode) { 281 switch (mode) {
279 case AR5K_MODE_11A: 282 case AR5K_MODE_11A:
280 /* 1..220, but 2GHz frequencies are filtered by check_channel */ 283 /* 1..220, but 2GHz frequencies are filtered by check_channel */
281 size = 220; 284 size = 220;
282 chfreq = CHANNEL_5GHZ;
283 band = IEEE80211_BAND_5GHZ; 285 band = IEEE80211_BAND_5GHZ;
284 break; 286 break;
285 case AR5K_MODE_11B: 287 case AR5K_MODE_11B:
286 case AR5K_MODE_11G: 288 case AR5K_MODE_11G:
287 size = 26; 289 size = 26;
288 chfreq = CHANNEL_2GHZ;
289 band = IEEE80211_BAND_2GHZ; 290 band = IEEE80211_BAND_2GHZ;
290 break; 291 break;
291 default: 292 default:
@@ -300,26 +301,19 @@ ath5k_setup_channels(struct ath5k_hw *ah, struct ieee80211_channel *channels,
300 if (freq == 0) /* mapping failed - not a standard channel */ 301 if (freq == 0) /* mapping failed - not a standard channel */
301 continue; 302 continue;
302 303
304 /* Write channel info, needed for ath5k_channel_ok() */
305 channels[count].center_freq = freq;
306 channels[count].band = band;
307 channels[count].hw_value = mode;
308
303 /* Check if channel is supported by the chipset */ 309 /* Check if channel is supported by the chipset */
304 if (!ath5k_channel_ok(ah, freq, chfreq)) 310 if (!ath5k_channel_ok(ah, &channels[count]))
305 continue; 311 continue;
306 312
307 if (!modparam_all_channels && 313 if (!modparam_all_channels &&
308 !ath5k_is_standard_channel(ch, band)) 314 !ath5k_is_standard_channel(ch, band))
309 continue; 315 continue;
310 316
311 /* Write channel info and increment counter */
312 channels[count].center_freq = freq;
313 channels[count].band = band;
314 switch (mode) {
315 case AR5K_MODE_11A:
316 case AR5K_MODE_11G:
317 channels[count].hw_value = chfreq | CHANNEL_OFDM;
318 break;
319 case AR5K_MODE_11B:
320 channels[count].hw_value = CHANNEL_B;
321 }
322
323 count++; 317 count++;
324 } 318 }
325 319
@@ -2349,7 +2343,7 @@ ath5k_tx_complete_poll_work(struct work_struct *work)
2349\*************************/ 2343\*************************/
2350 2344
2351int __devinit 2345int __devinit
2352ath5k_init_softc(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops) 2346ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops)
2353{ 2347{
2354 struct ieee80211_hw *hw = ah->hw; 2348 struct ieee80211_hw *hw = ah->hw;
2355 struct ath_common *common; 2349 struct ath_common *common;
@@ -2867,7 +2861,6 @@ ath5k_init(struct ieee80211_hw *hw)
2867 } 2861 }
2868 2862
2869 SET_IEEE80211_PERM_ADDR(hw, mac); 2863 SET_IEEE80211_PERM_ADDR(hw, mac);
2870 memcpy(&ah->lladdr, mac, ETH_ALEN);
2871 /* All MAC address bits matter for ACKs */ 2864 /* All MAC address bits matter for ACKs */
2872 ath5k_update_bssid_mask_and_opmode(ah, NULL); 2865 ath5k_update_bssid_mask_and_opmode(ah, NULL);
2873 2866
@@ -2903,7 +2896,7 @@ err:
2903} 2896}
2904 2897
2905void 2898void
2906ath5k_deinit_softc(struct ath5k_hw *ah) 2899ath5k_deinit_ah(struct ath5k_hw *ah)
2907{ 2900{
2908 struct ieee80211_hw *hw = ah->hw; 2901 struct ieee80211_hw *hw = ah->hw;
2909 2902
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index a81f28d5bddc..6c94c7ff2350 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -38,19 +38,27 @@
38/* 38/*
39 * Definitions for the Atheros Wireless LAN controller driver. 39 * Definitions for the Atheros Wireless LAN controller driver.
40 */ 40 */
41#ifndef _DEV_ATH_ATHVAR_H 41#ifndef _DEV_ATH5K_BASE_H
42#define _DEV_ATH_ATHVAR_H 42#define _DEV_ATH5K_BASE_H
43 43
44#include <linux/interrupt.h> 44struct ieee80211_vif;
45#include <linux/list.h> 45struct ieee80211_hw;
46#include <linux/wireless.h> 46struct ath5k_hw;
47#include <linux/if_ether.h> 47struct ath5k_txq;
48#include <linux/rfkill.h> 48struct ieee80211_channel;
49#include <linux/workqueue.h> 49struct ath_bus_ops;
50enum nl80211_iftype;
50 51
51#include "ath5k.h" 52enum ath5k_srev_type {
52#include "../regd.h" 53 AR5K_VERSION_MAC,
53#include "../ath.h" 54 AR5K_VERSION_RAD,
55};
56
57struct ath5k_srev_name {
58 const char *sr_name;
59 enum ath5k_srev_type sr_type;
60 u_int sr_val;
61};
54 62
55struct ath5k_buf { 63struct ath5k_buf {
56 struct list_head list; 64 struct list_head list;
@@ -65,7 +73,6 @@ struct ath5k_vif {
65 enum nl80211_iftype opmode; 73 enum nl80211_iftype opmode;
66 int bslot; 74 int bslot;
67 struct ath5k_buf *bbuf; /* beacon buffer */ 75 struct ath5k_buf *bbuf; /* beacon buffer */
68 u8 lladdr[ETH_ALEN];
69}; 76};
70 77
71struct ath5k_vif_iter_data { 78struct ath5k_vif_iter_data {
@@ -78,8 +85,30 @@ struct ath5k_vif_iter_data {
78 enum nl80211_iftype opmode; 85 enum nl80211_iftype opmode;
79 int n_stas; 86 int n_stas;
80}; 87};
88
81void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif); 89void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
90bool ath5k_any_vif_assoc(struct ath5k_hw *ah);
91
92int ath5k_start(struct ieee80211_hw *hw);
93void ath5k_stop(struct ieee80211_hw *hw);
94
95void ath5k_beacon_update_timers(struct ath5k_hw *ah, u64 bc_tsf);
96int ath5k_beacon_update(struct ieee80211_hw *hw, struct ieee80211_vif *vif);
97void ath5k_beacon_config(struct ath5k_hw *ah);
98void ath5k_set_beacon_filter(struct ieee80211_hw *hw, bool enable);
99
100void ath5k_update_bssid_mask_and_opmode(struct ath5k_hw *ah,
101 struct ieee80211_vif *vif);
102int ath5k_chan_set(struct ath5k_hw *ah, struct ieee80211_channel *chan);
103void ath5k_txbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
104void ath5k_rxbuf_free_skb(struct ath5k_hw *ah, struct ath5k_buf *bf);
105void ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
106 struct ath5k_txq *txq);
107
108const char *ath5k_chip_name(enum ath5k_srev_type type, u_int16_t val);
82 109
110int ath5k_init_ah(struct ath5k_hw *ah, const struct ath_bus_ops *bus_ops);
111void ath5k_deinit_ah(struct ath5k_hw *ah);
83 112
84/* Check whether BSSID mask is supported */ 113/* Check whether BSSID mask is supported */
85#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212) 114#define ath5k_hw_hasbssidmask(_ah) (ah->ah_version == AR5K_AR5212)
@@ -87,4 +116,4 @@ void ath5k_vif_iter(void *data, u8 *mac, struct ieee80211_vif *vif);
87/* Check whether virtual EOL is supported */ 116/* Check whether virtual EOL is supported */
88#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210) 117#define ath5k_hw_hasveol(_ah) (ah->ah_version != AR5K_AR5210)
89 118
90#endif 119#endif /* _DEV_ATH5K_BASE_H */
diff --git a/drivers/net/wireless/ath/ath5k/caps.c b/drivers/net/wireless/ath/ath5k/caps.c
index eefe670e28a7..810fba96702b 100644
--- a/drivers/net/wireless/ath/ath5k/caps.c
+++ b/drivers/net/wireless/ath/ath5k/caps.c
@@ -24,7 +24,7 @@
24#include "ath5k.h" 24#include "ath5k.h"
25#include "reg.h" 25#include "reg.h"
26#include "debug.h" 26#include "debug.h"
27#include "base.h" 27#include "../regd.h"
28 28
29/* 29/*
30 * Fill the capabilities struct 30 * Fill the capabilities struct
diff --git a/drivers/net/wireless/ath/ath5k/debug.c b/drivers/net/wireless/ath/ath5k/debug.c
index ccca724de173..fce8c904eea9 100644
--- a/drivers/net/wireless/ath/ath5k/debug.c
+++ b/drivers/net/wireless/ath/ath5k/debug.c
@@ -58,19 +58,18 @@
58 * THE POSSIBILITY OF SUCH DAMAGES. 58 * THE POSSIBILITY OF SUCH DAMAGES.
59 */ 59 */
60 60
61#include "base.h" 61#include <linux/module.h>
62#include <linux/seq_file.h>
63#include <linux/list.h>
62#include "debug.h" 64#include "debug.h"
65#include "ath5k.h"
66#include "reg.h"
67#include "base.h"
63 68
64static unsigned int ath5k_debug; 69static unsigned int ath5k_debug;
65module_param_named(debug, ath5k_debug, uint, 0); 70module_param_named(debug, ath5k_debug, uint, 0);
66 71
67 72
68#ifdef CONFIG_ATH5K_DEBUG
69
70#include <linux/seq_file.h>
71#include "reg.h"
72#include "ani.h"
73
74static int ath5k_debugfs_open(struct inode *inode, struct file *file) 73static int ath5k_debugfs_open(struct inode *inode, struct file *file)
75{ 74{
76 file->private_data = inode->i_private; 75 file->private_data = inode->i_private;
@@ -1031,5 +1030,3 @@ ath5k_debug_printtxbuf(struct ath5k_hw *ah, struct ath5k_buf *bf)
1031 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1, 1030 td->tx_stat.tx_status_0, td->tx_stat.tx_status_1,
1032 done ? ' ' : (ts.ts_status == 0) ? '*' : '!'); 1031 done ? ' ' : (ts.ts_status == 0) ? '*' : '!');
1033} 1032}
1034
1035#endif /* ifdef CONFIG_ATH5K_DEBUG */
diff --git a/drivers/net/wireless/ath/ath5k/desc.c b/drivers/net/wireless/ath/ath5k/desc.c
index 846535f59efc..7e88dda82221 100644
--- a/drivers/net/wireless/ath/ath5k/desc.c
+++ b/drivers/net/wireless/ath/ath5k/desc.c
@@ -24,7 +24,6 @@
24#include "ath5k.h" 24#include "ath5k.h"
25#include "reg.h" 25#include "reg.h"
26#include "debug.h" 26#include "debug.h"
27#include "base.h"
28 27
29 28
30/************************\ 29/************************\
diff --git a/drivers/net/wireless/ath/ath5k/dma.c b/drivers/net/wireless/ath/ath5k/dma.c
index 0d5d4033f12a..2481f9c7f4b6 100644
--- a/drivers/net/wireless/ath/ath5k/dma.c
+++ b/drivers/net/wireless/ath/ath5k/dma.c
@@ -35,7 +35,6 @@
35#include "ath5k.h" 35#include "ath5k.h"
36#include "reg.h" 36#include "reg.h"
37#include "debug.h" 37#include "debug.h"
38#include "base.h"
39 38
40 39
41/*********\ 40/*********\
diff --git a/drivers/net/wireless/ath/ath5k/eeprom.c b/drivers/net/wireless/ath/ath5k/eeprom.c
index 9068b9165265..cd708c15b774 100644
--- a/drivers/net/wireless/ath/ath5k/eeprom.c
+++ b/drivers/net/wireless/ath/ath5k/eeprom.c
@@ -26,7 +26,6 @@
26#include "ath5k.h" 26#include "ath5k.h"
27#include "reg.h" 27#include "reg.h"
28#include "debug.h" 28#include "debug.h"
29#include "base.h"
30 29
31 30
32/******************\ 31/******************\
@@ -1780,13 +1779,12 @@ ath5k_eeprom_detach(struct ath5k_hw *ah)
1780int 1779int
1781ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel) 1780ath5k_eeprom_mode_from_channel(struct ieee80211_channel *channel)
1782{ 1781{
1783 switch (channel->hw_value & CHANNEL_MODES) { 1782 switch (channel->hw_value) {
1784 case CHANNEL_A: 1783 case AR5K_MODE_11A:
1785 case CHANNEL_XR:
1786 return AR5K_EEPROM_MODE_11A; 1784 return AR5K_EEPROM_MODE_11A;
1787 case CHANNEL_G: 1785 case AR5K_MODE_11G:
1788 return AR5K_EEPROM_MODE_11G; 1786 return AR5K_EEPROM_MODE_11G;
1789 case CHANNEL_B: 1787 case AR5K_MODE_11B:
1790 return AR5K_EEPROM_MODE_11B; 1788 return AR5K_EEPROM_MODE_11B;
1791 default: 1789 default:
1792 return -1; 1790 return -1;
diff --git a/drivers/net/wireless/ath/ath5k/gpio.c b/drivers/net/wireless/ath/ath5k/gpio.c
index bc90503f4b7a..859297811914 100644
--- a/drivers/net/wireless/ath/ath5k/gpio.c
+++ b/drivers/net/wireless/ath/ath5k/gpio.c
@@ -23,7 +23,6 @@
23#include "ath5k.h" 23#include "ath5k.h"
24#include "reg.h" 24#include "reg.h"
25#include "debug.h" 25#include "debug.h"
26#include "base.h"
27 26
28/* 27/*
29 * Set led state 28 * Set led state
diff --git a/drivers/net/wireless/ath/ath5k/initvals.c b/drivers/net/wireless/ath/ath5k/initvals.c
index 5ab607f40e0e..1ffecc0fd3ed 100644
--- a/drivers/net/wireless/ath/ath5k/initvals.c
+++ b/drivers/net/wireless/ath/ath5k/initvals.c
@@ -22,7 +22,6 @@
22#include "ath5k.h" 22#include "ath5k.h"
23#include "reg.h" 23#include "reg.h"
24#include "debug.h" 24#include "debug.h"
25#include "base.h"
26 25
27/* 26/*
28 * Mode-independent initial register writes 27 * Mode-independent initial register writes
diff --git a/drivers/net/wireless/ath/ath5k/led.c b/drivers/net/wireless/ath/ath5k/led.c
index 8c17a00f7dad..c1151c723711 100644
--- a/drivers/net/wireless/ath/ath5k/led.c
+++ b/drivers/net/wireless/ath/ath5k/led.c
@@ -41,7 +41,6 @@
41 41
42#include <linux/pci.h> 42#include <linux/pci.h>
43#include "ath5k.h" 43#include "ath5k.h"
44#include "base.h"
45 44
46#define ATH_SDEVICE(subv, subd) \ 45#define ATH_SDEVICE(subv, subd) \
47 .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \ 46 .vendor = PCI_ANY_ID, .device = PCI_ANY_ID, \
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index 2a715ca0c5e4..0560234ec3f6 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -41,8 +41,10 @@
41 * 41 *
42 */ 42 */
43 43
44#include <net/mac80211.h>
44#include <asm/unaligned.h> 45#include <asm/unaligned.h>
45 46
47#include "ath5k.h"
46#include "base.h" 48#include "base.h"
47#include "reg.h" 49#include "reg.h"
48 50
@@ -137,11 +139,8 @@ ath5k_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
137 /* Any MAC address is fine, all others are included through the 139 /* Any MAC address is fine, all others are included through the
138 * filter. 140 * filter.
139 */ 141 */
140 memcpy(&ah->lladdr, vif->addr, ETH_ALEN);
141 ath5k_hw_set_lladdr(ah, vif->addr); 142 ath5k_hw_set_lladdr(ah, vif->addr);
142 143
143 memcpy(&avf->lladdr, vif->addr, ETH_ALEN);
144
145 ath5k_update_bssid_mask_and_opmode(ah, vif); 144 ath5k_update_bssid_mask_and_opmode(ah, vif);
146 ret = 0; 145 ret = 0;
147end: 146end:
diff --git a/drivers/net/wireless/ath/ath5k/pci.c b/drivers/net/wireless/ath/ath5k/pci.c
index eaf79b49341e..c1dff2ced044 100644
--- a/drivers/net/wireless/ath/ath5k/pci.c
+++ b/drivers/net/wireless/ath/ath5k/pci.c
@@ -261,7 +261,7 @@ ath5k_pci_probe(struct pci_dev *pdev,
261 ah->iobase = mem; /* So we can unmap it on detach */ 261 ah->iobase = mem; /* So we can unmap it on detach */
262 262
263 /* Initialize */ 263 /* Initialize */
264 ret = ath5k_init_softc(ah, &ath_pci_bus_ops); 264 ret = ath5k_init_ah(ah, &ath_pci_bus_ops);
265 if (ret) 265 if (ret)
266 goto err_free; 266 goto err_free;
267 267
@@ -287,7 +287,7 @@ ath5k_pci_remove(struct pci_dev *pdev)
287 struct ieee80211_hw *hw = pci_get_drvdata(pdev); 287 struct ieee80211_hw *hw = pci_get_drvdata(pdev);
288 struct ath5k_hw *ah = hw->priv; 288 struct ath5k_hw *ah = hw->priv;
289 289
290 ath5k_deinit_softc(ah); 290 ath5k_deinit_ah(ah);
291 pci_iounmap(pdev, ah->iobase); 291 pci_iounmap(pdev, ah->iobase);
292 pci_release_region(pdev, 0); 292 pci_release_region(pdev, 0);
293 pci_disable_device(pdev); 293 pci_disable_device(pdev);
diff --git a/drivers/net/wireless/ath/ath5k/pcu.c b/drivers/net/wireless/ath/ath5k/pcu.c
index 067313845060..a7eafa3edc21 100644
--- a/drivers/net/wireless/ath/ath5k/pcu.c
+++ b/drivers/net/wireless/ath/ath5k/pcu.c
@@ -29,7 +29,6 @@
29#include "ath5k.h" 29#include "ath5k.h"
30#include "reg.h" 30#include "reg.h"
31#include "debug.h" 31#include "debug.h"
32#include "base.h"
33 32
34/* 33/*
35 * AR5212+ can use higher rates for ack transmission 34 * AR5212+ can use higher rates for ack transmission
@@ -152,7 +151,7 @@ unsigned int ath5k_hw_get_default_slottime(struct ath5k_hw *ah)
152 case AR5K_BWMODE_DEFAULT: 151 case AR5K_BWMODE_DEFAULT:
153 default: 152 default:
154 slot_time = AR5K_INIT_SLOT_TIME_DEFAULT; 153 slot_time = AR5K_INIT_SLOT_TIME_DEFAULT;
155 if ((channel->hw_value & CHANNEL_CCK) && !ah->ah_short_slot) 154 if ((channel->hw_value == AR5K_MODE_11B) && !ah->ah_short_slot)
156 slot_time = AR5K_INIT_SLOT_TIME_B; 155 slot_time = AR5K_INIT_SLOT_TIME_B;
157 break; 156 break;
158 } 157 }
@@ -183,7 +182,7 @@ unsigned int ath5k_hw_get_default_sifs(struct ath5k_hw *ah)
183 case AR5K_BWMODE_DEFAULT: 182 case AR5K_BWMODE_DEFAULT:
184 sifs = AR5K_INIT_SIFS_DEFAULT_BG; 183 sifs = AR5K_INIT_SIFS_DEFAULT_BG;
185 default: 184 default:
186 if (channel->hw_value & CHANNEL_5GHZ) 185 if (channel->band == IEEE80211_BAND_5GHZ)
187 sifs = AR5K_INIT_SIFS_DEFAULT_A; 186 sifs = AR5K_INIT_SIFS_DEFAULT_A;
188 break; 187 break;
189 } 188 }
diff --git a/drivers/net/wireless/ath/ath5k/phy.c b/drivers/net/wireless/ath/ath5k/phy.c
index 81e465e70175..01cb72de44cb 100644
--- a/drivers/net/wireless/ath/ath5k/phy.c
+++ b/drivers/net/wireless/ath/ath5k/phy.c
@@ -26,9 +26,9 @@
26 26
27#include "ath5k.h" 27#include "ath5k.h"
28#include "reg.h" 28#include "reg.h"
29#include "base.h"
30#include "rfbuffer.h" 29#include "rfbuffer.h"
31#include "rfgain.h" 30#include "rfgain.h"
31#include "../regd.h"
32 32
33 33
34/******************\ 34/******************\
@@ -38,7 +38,7 @@
38/* 38/*
39 * Get the PHY Chip revision 39 * Get the PHY Chip revision
40 */ 40 */
41u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan) 41u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, enum ieee80211_band band)
42{ 42{
43 unsigned int i; 43 unsigned int i;
44 u32 srev; 44 u32 srev;
@@ -47,11 +47,11 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
47 /* 47 /*
48 * Set the radio chip access register 48 * Set the radio chip access register
49 */ 49 */
50 switch (chan) { 50 switch (band) {
51 case CHANNEL_2GHZ: 51 case IEEE80211_BAND_2GHZ:
52 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0)); 52 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_2GHZ, AR5K_PHY(0));
53 break; 53 break;
54 case CHANNEL_5GHZ: 54 case IEEE80211_BAND_5GHZ:
55 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0)); 55 ath5k_hw_reg_write(ah, AR5K_PHY_SHIFT_5GHZ, AR5K_PHY(0));
56 break; 56 break;
57 default: 57 default:
@@ -84,14 +84,16 @@ u16 ath5k_hw_radio_revision(struct ath5k_hw *ah, unsigned int chan)
84/* 84/*
85 * Check if a channel is supported 85 * Check if a channel is supported
86 */ 86 */
87bool ath5k_channel_ok(struct ath5k_hw *ah, u16 freq, unsigned int flags) 87bool ath5k_channel_ok(struct ath5k_hw *ah, struct ieee80211_channel *channel)
88{ 88{
89 u16 freq = channel->center_freq;
90
89 /* Check if the channel is in our supported range */ 91 /* Check if the channel is in our supported range */
90 if (flags & CHANNEL_2GHZ) { 92 if (channel->band == IEEE80211_BAND_2GHZ) {
91 if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) && 93 if ((freq >= ah->ah_capabilities.cap_range.range_2ghz_min) &&
92 (freq <= ah->ah_capabilities.cap_range.range_2ghz_max)) 94 (freq <= ah->ah_capabilities.cap_range.range_2ghz_max))
93 return true; 95 return true;
94 } else if (flags & CHANNEL_5GHZ) 96 } else if (channel->band == IEEE80211_BAND_5GHZ)
95 if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) && 97 if ((freq >= ah->ah_capabilities.cap_range.range_5ghz_min) &&
96 (freq <= ah->ah_capabilities.cap_range.range_5ghz_max)) 98 (freq <= ah->ah_capabilities.cap_range.range_5ghz_max))
97 return true; 99 return true;
@@ -224,7 +226,7 @@ static inline int ath5k_hw_write_ofdm_timings(struct ath5k_hw *ah,
224 ds_coef_exp, ds_coef_man, clock; 226 ds_coef_exp, ds_coef_man, clock;
225 227
226 BUG_ON(!(ah->ah_version == AR5K_AR5212) || 228 BUG_ON(!(ah->ah_version == AR5K_AR5212) ||
227 !(channel->hw_value & CHANNEL_OFDM)); 229 (channel->hw_value == AR5K_MODE_11B));
228 230
229 /* Get coefficient 231 /* Get coefficient
230 * ALGO: coef = (5 * clock / carrier_freq) / 2 232 * ALGO: coef = (5 * clock / carrier_freq) / 2
@@ -298,7 +300,7 @@ static void ath5k_hw_wait_for_synth(struct ath5k_hw *ah,
298 u32 delay; 300 u32 delay;
299 delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) & 301 delay = ath5k_hw_reg_read(ah, AR5K_PHY_RX_DELAY) &
300 AR5K_PHY_RX_DELAY_M; 302 AR5K_PHY_RX_DELAY_M;
301 delay = (channel->hw_value & CHANNEL_CCK) ? 303 delay = (channel->hw_value == AR5K_MODE_11B) ?
302 ((delay << 2) / 22) : (delay / 10); 304 ((delay << 2) / 22) : (delay / 10);
303 if (ah->ah_bwmode == AR5K_BWMODE_10MHZ) 305 if (ah->ah_bwmode == AR5K_BWMODE_10MHZ)
304 delay = delay << 1; 306 delay = delay << 1;
@@ -798,9 +800,9 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
798 } 800 }
799 801
800 /* Set Output and Driver bias current (OB/DB) */ 802 /* Set Output and Driver bias current (OB/DB) */
801 if (channel->hw_value & CHANNEL_2GHZ) { 803 if (channel->band == IEEE80211_BAND_2GHZ) {
802 804
803 if (channel->hw_value & CHANNEL_CCK) 805 if (channel->hw_value == AR5K_MODE_11B)
804 ee_mode = AR5K_EEPROM_MODE_11B; 806 ee_mode = AR5K_EEPROM_MODE_11B;
805 else 807 else
806 ee_mode = AR5K_EEPROM_MODE_11G; 808 ee_mode = AR5K_EEPROM_MODE_11G;
@@ -825,7 +827,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
825 AR5K_RF_DB_2GHZ, true); 827 AR5K_RF_DB_2GHZ, true);
826 828
827 /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */ 829 /* RF5111 always needs OB/DB for 5GHz, even if we use 2GHz */
828 } else if ((channel->hw_value & CHANNEL_5GHZ) || 830 } else if ((channel->band == IEEE80211_BAND_5GHZ) ||
829 (ah->ah_radio == AR5K_RF5111)) { 831 (ah->ah_radio == AR5K_RF5111)) {
830 832
831 /* For 11a, Turbo and XR we need to choose 833 /* For 11a, Turbo and XR we need to choose
@@ -857,7 +859,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
857 if (ah->ah_radio == AR5K_RF5111) { 859 if (ah->ah_radio == AR5K_RF5111) {
858 860
859 /* Set gain_F settings according to current step */ 861 /* Set gain_F settings according to current step */
860 if (channel->hw_value & CHANNEL_OFDM) { 862 if (channel->hw_value != AR5K_MODE_11B) {
861 863
862 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL, 864 AR5K_REG_WRITE_BITS(ah, AR5K_PHY_FRAME_CTL,
863 AR5K_PHY_FRAME_CTL_TX_CLIP, 865 AR5K_PHY_FRAME_CTL_TX_CLIP,
@@ -914,7 +916,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
914 if (ah->ah_radio == AR5K_RF5112) { 916 if (ah->ah_radio == AR5K_RF5112) {
915 917
916 /* Set gain_F settings according to current step */ 918 /* Set gain_F settings according to current step */
917 if (channel->hw_value & CHANNEL_OFDM) { 919 if (channel->hw_value != AR5K_MODE_11B) {
918 920
919 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0], 921 ath5k_hw_rfb_op(ah, rf_regs, g_step->gos_param[0],
920 AR5K_RF_MIXGAIN_OVR, true); 922 AR5K_RF_MIXGAIN_OVR, true);
@@ -1026,7 +1028,7 @@ static int ath5k_hw_rfregs_init(struct ath5k_hw *ah,
1026 } 1028 }
1027 1029
1028 if (ah->ah_radio == AR5K_RF5413 && 1030 if (ah->ah_radio == AR5K_RF5413 &&
1029 channel->hw_value & CHANNEL_2GHZ) { 1031 channel->band == IEEE80211_BAND_2GHZ) {
1030 1032
1031 ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE, 1033 ath5k_hw_rfb_op(ah, rf_regs, 1, AR5K_RF_DERBY_CHAN_SEL_MODE,
1032 true); 1034 true);
@@ -1138,7 +1140,7 @@ static int ath5k_hw_rf5111_channel(struct ath5k_hw *ah,
1138 */ 1140 */
1139 data0 = data1 = 0; 1141 data0 = data1 = 0;
1140 1142
1141 if (channel->hw_value & CHANNEL_2GHZ) { 1143 if (channel->band == IEEE80211_BAND_2GHZ) {
1142 /* Map 2GHz channel to 5GHz Atheros channel ID */ 1144 /* Map 2GHz channel to 5GHz Atheros channel ID */
1143 ret = ath5k_hw_rf5111_chan2athchan( 1145 ret = ath5k_hw_rf5111_chan2athchan(
1144 ieee80211_frequency_to_channel(channel->center_freq), 1146 ieee80211_frequency_to_channel(channel->center_freq),
@@ -1265,10 +1267,9 @@ static int ath5k_hw_channel(struct ath5k_hw *ah,
1265 int ret; 1267 int ret;
1266 /* 1268 /*
1267 * Check bounds supported by the PHY (we don't care about regulatory 1269 * Check bounds supported by the PHY (we don't care about regulatory
1268 * restrictions at this point). Note: hw_value already has the band 1270 * restrictions at this point).
1269 * (CHANNEL_2GHZ, or CHANNEL_5GHZ) so we inform ath5k_channel_ok() 1271 */
1270 * of the band by that */ 1272 if (!ath5k_channel_ok(ah, channel)) {
1271 if (!ath5k_channel_ok(ah, channel->center_freq, channel->hw_value)) {
1272 ATH5K_ERR(ah, 1273 ATH5K_ERR(ah,
1273 "channel frequency (%u MHz) out of supported " 1274 "channel frequency (%u MHz) out of supported "
1274 "band range\n", 1275 "band range\n",
@@ -1614,7 +1615,7 @@ int ath5k_hw_phy_calibrate(struct ath5k_hw *ah,
1614 ret = ath5k_hw_rf511x_iq_calibrate(ah); 1615 ret = ath5k_hw_rf511x_iq_calibrate(ah);
1615 1616
1616 if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) && 1617 if ((ah->ah_radio == AR5K_RF5111 || ah->ah_radio == AR5K_RF5112) &&
1617 (channel->hw_value & CHANNEL_OFDM)) 1618 (channel->hw_value != AR5K_MODE_11B))
1618 ath5k_hw_request_rfgain_probe(ah); 1619 ath5k_hw_request_rfgain_probe(ah);
1619 1620
1620 return ret; 1621 return ret;
@@ -1641,7 +1642,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
1641 /* Convert current frequency to fbin value (the same way channels 1642 /* Convert current frequency to fbin value (the same way channels
1642 * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale 1643 * are stored on EEPROM, check out ath5k_eeprom_bin2freq) and scale
1643 * up by 2 so we can compare it later */ 1644 * up by 2 so we can compare it later */
1644 if (channel->hw_value & CHANNEL_2GHZ) { 1645 if (channel->band == IEEE80211_BAND_2GHZ) {
1645 chan_fbin = (channel->center_freq - 2300) * 10; 1646 chan_fbin = (channel->center_freq - 2300) * 10;
1646 freq_band = AR5K_EEPROM_BAND_2GHZ; 1647 freq_band = AR5K_EEPROM_BAND_2GHZ;
1647 } else { 1648 } else {
@@ -1703,7 +1704,7 @@ ath5k_hw_set_spur_mitigation_filter(struct ath5k_hw *ah,
1703 spur_freq_sigma_delta = (spur_delta_phase >> 10); 1704 spur_freq_sigma_delta = (spur_delta_phase >> 10);
1704 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4; 1705 symbol_width = AR5K_SPUR_SYMBOL_WIDTH_BASE_100Hz / 4;
1705 default: 1706 default:
1706 if (channel->hw_value == CHANNEL_A) { 1707 if (channel->band == IEEE80211_BAND_5GHZ) {
1707 /* Both sample_freq and chip_freq are 40MHz */ 1708 /* Both sample_freq and chip_freq are 40MHz */
1708 spur_delta_phase = (spur_offset << 17) / 25; 1709 spur_delta_phase = (spur_offset << 17) / 25;
1709 spur_freq_sigma_delta = 1710 spur_freq_sigma_delta =
@@ -2226,15 +2227,20 @@ ath5k_get_chan_pcal_surrounding_piers(struct ath5k_hw *ah,
2226 idx_l = 0; 2227 idx_l = 0;
2227 idx_r = 0; 2228 idx_r = 0;
2228 2229
2229 if (!(channel->hw_value & CHANNEL_OFDM)) { 2230 switch (channel->hw_value) {
2231 case AR5K_EEPROM_MODE_11A:
2232 pcinfo = ee->ee_pwr_cal_a;
2233 mode = AR5K_EEPROM_MODE_11A;
2234 break;
2235 case AR5K_EEPROM_MODE_11B:
2230 pcinfo = ee->ee_pwr_cal_b; 2236 pcinfo = ee->ee_pwr_cal_b;
2231 mode = AR5K_EEPROM_MODE_11B; 2237 mode = AR5K_EEPROM_MODE_11B;
2232 } else if (channel->hw_value & CHANNEL_2GHZ) { 2238 break;
2239 case AR5K_EEPROM_MODE_11G:
2240 default:
2233 pcinfo = ee->ee_pwr_cal_g; 2241 pcinfo = ee->ee_pwr_cal_g;
2234 mode = AR5K_EEPROM_MODE_11G; 2242 mode = AR5K_EEPROM_MODE_11G;
2235 } else { 2243 break;
2236 pcinfo = ee->ee_pwr_cal_a;
2237 mode = AR5K_EEPROM_MODE_11A;
2238 } 2244 }
2239 max = ee->ee_n_piers[mode] - 1; 2245 max = ee->ee_n_piers[mode] - 1;
2240 2246
@@ -2303,15 +2309,20 @@ ath5k_get_rate_pcal_data(struct ath5k_hw *ah,
2303 idx_l = 0; 2309 idx_l = 0;
2304 idx_r = 0; 2310 idx_r = 0;
2305 2311
2306 if (!(channel->hw_value & CHANNEL_OFDM)) { 2312 switch (channel->hw_value) {
2313 case AR5K_MODE_11A:
2314 rpinfo = ee->ee_rate_tpwr_a;
2315 mode = AR5K_EEPROM_MODE_11A;
2316 break;
2317 case AR5K_MODE_11B:
2307 rpinfo = ee->ee_rate_tpwr_b; 2318 rpinfo = ee->ee_rate_tpwr_b;
2308 mode = AR5K_EEPROM_MODE_11B; 2319 mode = AR5K_EEPROM_MODE_11B;
2309 } else if (channel->hw_value & CHANNEL_2GHZ) { 2320 break;
2321 case AR5K_MODE_11G:
2322 default:
2310 rpinfo = ee->ee_rate_tpwr_g; 2323 rpinfo = ee->ee_rate_tpwr_g;
2311 mode = AR5K_EEPROM_MODE_11G; 2324 mode = AR5K_EEPROM_MODE_11G;
2312 } else { 2325 break;
2313 rpinfo = ee->ee_rate_tpwr_a;
2314 mode = AR5K_EEPROM_MODE_11A;
2315 } 2326 }
2316 max = ee->ee_rate_target_pwr_num[mode] - 1; 2327 max = ee->ee_rate_target_pwr_num[mode] - 1;
2317 2328
@@ -2392,24 +2403,22 @@ ath5k_get_max_ctl_power(struct ath5k_hw *ah,
2392 2403
2393 ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band); 2404 ctl_mode = ath_regd_get_band_ctl(regulatory, channel->band);
2394 2405
2395 switch (channel->hw_value & CHANNEL_MODES) { 2406 switch (channel->hw_value) {
2396 case CHANNEL_A: 2407 case AR5K_MODE_11A:
2397 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) 2408 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
2398 ctl_mode |= AR5K_CTL_TURBO; 2409 ctl_mode |= AR5K_CTL_TURBO;
2399 else 2410 else
2400 ctl_mode |= AR5K_CTL_11A; 2411 ctl_mode |= AR5K_CTL_11A;
2401 break; 2412 break;
2402 case CHANNEL_G: 2413 case AR5K_MODE_11G:
2403 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ) 2414 if (ah->ah_bwmode == AR5K_BWMODE_40MHZ)
2404 ctl_mode |= AR5K_CTL_TURBOG; 2415 ctl_mode |= AR5K_CTL_TURBOG;
2405 else 2416 else
2406 ctl_mode |= AR5K_CTL_11G; 2417 ctl_mode |= AR5K_CTL_11G;
2407 break; 2418 break;
2408 case CHANNEL_B: 2419 case AR5K_MODE_11B:
2409 ctl_mode |= AR5K_CTL_11B; 2420 ctl_mode |= AR5K_CTL_11B;
2410 break; 2421 break;
2411 case CHANNEL_XR:
2412 /* Fall through */
2413 default: 2422 default:
2414 return; 2423 return;
2415 } 2424 }
@@ -3292,7 +3301,7 @@ int ath5k_hw_phy_init(struct ath5k_hw *ah, struct ieee80211_channel *channel,
3292 3301
3293 /* Write OFDM timings on 5212*/ 3302 /* Write OFDM timings on 5212*/
3294 if (ah->ah_version == AR5K_AR5212 && 3303 if (ah->ah_version == AR5K_AR5212 &&
3295 channel->hw_value & CHANNEL_OFDM) { 3304 channel->hw_value != AR5K_MODE_11B) {
3296 3305
3297 ret = ath5k_hw_write_ofdm_timings(ah, channel); 3306 ret = ath5k_hw_write_ofdm_timings(ah, channel);
3298 if (ret) 3307 if (ret)
diff --git a/drivers/net/wireless/ath/ath5k/qcu.c b/drivers/net/wireless/ath/ath5k/qcu.c
index 65f10398999e..776654228eaa 100644
--- a/drivers/net/wireless/ath/ath5k/qcu.c
+++ b/drivers/net/wireless/ath/ath5k/qcu.c
@@ -23,7 +23,6 @@ Queue Control Unit, DFS Control Unit Functions
23#include "ath5k.h" 23#include "ath5k.h"
24#include "reg.h" 24#include "reg.h"
25#include "debug.h" 25#include "debug.h"
26#include "base.h"
27 26
28 27
29/******************\ 28/******************\
@@ -185,13 +184,6 @@ int ath5k_hw_setup_tx_queue(struct ath5k_hw *ah, enum ath5k_tx_queue queue_type,
185 case AR5K_TX_QUEUE_CAB: 184 case AR5K_TX_QUEUE_CAB:
186 queue = AR5K_TX_QUEUE_ID_CAB; 185 queue = AR5K_TX_QUEUE_ID_CAB;
187 break; 186 break;
188 case AR5K_TX_QUEUE_XR_DATA:
189 if (ah->ah_version != AR5K_AR5212)
190 ATH5K_ERR(ah,
191 "XR data queues only supported in"
192 " 5212!\n");
193 queue = AR5K_TX_QUEUE_ID_XR_DATA;
194 break;
195 default: 187 default:
196 return -EINVAL; 188 return -EINVAL;
197 } 189 }
@@ -544,7 +536,7 @@ int ath5k_hw_set_ifs_intervals(struct ath5k_hw *ah, unsigned int slot_time)
544 * 536 *
545 * Also we have different lowest rate for 802.11a 537 * Also we have different lowest rate for 802.11a
546 */ 538 */
547 if (channel->hw_value & CHANNEL_5GHZ) 539 if (channel->band == IEEE80211_BAND_5GHZ)
548 rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0]; 540 rate = &ah->sbands[IEEE80211_BAND_5GHZ].bitrates[0];
549 else 541 else
550 rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0]; 542 rate = &ah->sbands[IEEE80211_BAND_2GHZ].bitrates[0];
diff --git a/drivers/net/wireless/ath/ath5k/reset.c b/drivers/net/wireless/ath/ath5k/reset.c
index 0686c5d8d56e..2abac257b4b4 100644
--- a/drivers/net/wireless/ath/ath5k/reset.c
+++ b/drivers/net/wireless/ath/ath5k/reset.c
@@ -30,7 +30,6 @@
30#include <linux/platform_device.h> 30#include <linux/platform_device.h>
31#include "ath5k.h" 31#include "ath5k.h"
32#include "reg.h" 32#include "reg.h"
33#include "base.h"
34#include "debug.h" 33#include "debug.h"
35 34
36 35
@@ -102,12 +101,18 @@ static void ath5k_hw_init_core_clock(struct ath5k_hw *ah)
102 /* 101 /*
103 * Set core clock frequency 102 * Set core clock frequency
104 */ 103 */
105 if (channel->hw_value & CHANNEL_5GHZ) 104 switch (channel->hw_value) {
106 clock = 40; /* 802.11a */ 105 case AR5K_MODE_11A:
107 else if (channel->hw_value & CHANNEL_CCK) 106 clock = 40;
108 clock = 22; /* 802.11b */ 107 break;
109 else 108 case AR5K_MODE_11B:
110 clock = 44; /* 802.11g */ 109 clock = 22;
110 break;
111 case AR5K_MODE_11G:
112 default:
113 clock = 44;
114 break;
115 }
111 116
112 /* Use clock multiplier for non-default 117 /* Use clock multiplier for non-default
113 * bwmode */ 118 * bwmode */
@@ -581,8 +586,9 @@ int ath5k_hw_on_hold(struct ath5k_hw *ah)
581 586
582/* 587/*
583 * Bring up MAC + PHY Chips and program PLL 588 * Bring up MAC + PHY Chips and program PLL
589 * Channel is NULL for the initial wakeup.
584 */ 590 */
585int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial) 591int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, struct ieee80211_channel *channel)
586{ 592{
587 struct pci_dev *pdev = ah->pdev; 593 struct pci_dev *pdev = ah->pdev;
588 u32 turbo, mode, clock, bus_flags; 594 u32 turbo, mode, clock, bus_flags;
@@ -592,7 +598,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
592 mode = 0; 598 mode = 0;
593 clock = 0; 599 clock = 0;
594 600
595 if ((ath5k_get_bus_type(ah) != ATH_AHB) || !initial) { 601 if ((ath5k_get_bus_type(ah) != ATH_AHB) || channel) {
596 /* Wakeup the device */ 602 /* Wakeup the device */
597 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0); 603 ret = ath5k_hw_set_power(ah, AR5K_PM_AWAKE, true, 0);
598 if (ret) { 604 if (ret) {
@@ -652,7 +658,7 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
652 658
653 /* On initialization skip PLL programming since we don't have 659 /* On initialization skip PLL programming since we don't have
654 * a channel / mode set yet */ 660 * a channel / mode set yet */
655 if (initial) 661 if (!channel)
656 return 0; 662 return 0;
657 663
658 if (ah->ah_version != AR5K_AR5210) { 664 if (ah->ah_version != AR5K_AR5210) {
@@ -668,13 +674,13 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
668 clock = AR5K_PHY_PLL_RF5111; /*Zero*/ 674 clock = AR5K_PHY_PLL_RF5111; /*Zero*/
669 } 675 }
670 676
671 if (flags & CHANNEL_2GHZ) { 677 if (channel->band == IEEE80211_BAND_2GHZ) {
672 mode |= AR5K_PHY_MODE_FREQ_2GHZ; 678 mode |= AR5K_PHY_MODE_FREQ_2GHZ;
673 clock |= AR5K_PHY_PLL_44MHZ; 679 clock |= AR5K_PHY_PLL_44MHZ;
674 680
675 if (flags & CHANNEL_CCK) { 681 if (channel->hw_value == AR5K_MODE_11B) {
676 mode |= AR5K_PHY_MODE_MOD_CCK; 682 mode |= AR5K_PHY_MODE_MOD_CCK;
677 } else if (flags & CHANNEL_OFDM) { 683 } else {
678 /* XXX Dynamic OFDM/CCK is not supported by the 684 /* XXX Dynamic OFDM/CCK is not supported by the
679 * AR5211 so we set MOD_OFDM for plain g (no 685 * AR5211 so we set MOD_OFDM for plain g (no
680 * CCK headers) operation. We need to test 686 * CCK headers) operation. We need to test
@@ -686,27 +692,16 @@ int ath5k_hw_nic_wakeup(struct ath5k_hw *ah, int flags, bool initial)
686 mode |= AR5K_PHY_MODE_MOD_OFDM; 692 mode |= AR5K_PHY_MODE_MOD_OFDM;
687 else 693 else
688 mode |= AR5K_PHY_MODE_MOD_DYN; 694 mode |= AR5K_PHY_MODE_MOD_DYN;
689 } else {
690 ATH5K_ERR(ah,
691 "invalid radio modulation mode\n");
692 return -EINVAL;
693 } 695 }
694 } else if (flags & CHANNEL_5GHZ) { 696 } else if (channel->band == IEEE80211_BAND_5GHZ) {
695 mode |= AR5K_PHY_MODE_FREQ_5GHZ; 697 mode |= (AR5K_PHY_MODE_FREQ_5GHZ |
698 AR5K_PHY_MODE_MOD_OFDM);
696 699
697 /* Different PLL setting for 5413 */ 700 /* Different PLL setting for 5413 */
698 if (ah->ah_radio == AR5K_RF5413) 701 if (ah->ah_radio == AR5K_RF5413)
699 clock = AR5K_PHY_PLL_40MHZ_5413; 702 clock = AR5K_PHY_PLL_40MHZ_5413;
700 else 703 else
701 clock |= AR5K_PHY_PLL_40MHZ; 704 clock |= AR5K_PHY_PLL_40MHZ;
702
703 if (flags & CHANNEL_OFDM)
704 mode |= AR5K_PHY_MODE_MOD_OFDM;
705 else {
706 ATH5K_ERR(ah,
707 "invalid radio modulation mode\n");
708 return -EINVAL;
709 }
710 } else { 705 } else {
711 ATH5K_ERR(ah, "invalid radio frequency mode\n"); 706 ATH5K_ERR(ah, "invalid radio frequency mode\n");
712 return -EINVAL; 707 return -EINVAL;
@@ -822,7 +817,7 @@ static void ath5k_hw_tweak_initval_settings(struct ath5k_hw *ah,
822 u32 data; 817 u32 data;
823 ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD, 818 ath5k_hw_reg_write(ah, AR5K_PHY_CCKTXCTL_WORLD,
824 AR5K_PHY_CCKTXCTL); 819 AR5K_PHY_CCKTXCTL);
825 if (channel->hw_value & CHANNEL_5GHZ) 820 if (channel->band == IEEE80211_BAND_5GHZ)
826 data = 0xffb81020; 821 data = 0xffb81020;
827 else 822 else
828 data = 0xffb80d20; 823 data = 0xffb80d20;
@@ -905,7 +900,7 @@ static void ath5k_hw_commit_eeprom_settings(struct ath5k_hw *ah,
905 /* Set CCK to OFDM power delta on tx power 900 /* Set CCK to OFDM power delta on tx power
906 * adjustment register */ 901 * adjustment register */
907 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) { 902 if (ah->ah_phy_revision >= AR5K_SREV_PHY_5212A) {
908 if (channel->hw_value == CHANNEL_G) 903 if (channel->hw_value == AR5K_MODE_11G)
909 ath5k_hw_reg_write(ah, 904 ath5k_hw_reg_write(ah,
910 AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1), 905 AR5K_REG_SM((ee->ee_cck_ofdm_gain_delta * -1),
911 AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) | 906 AR5K_PHY_TX_PWR_ADJ_CCK_GAIN_DELTA) |
@@ -1084,37 +1079,23 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1084 ret = 0; 1079 ret = 0;
1085 } 1080 }
1086 1081
1087 switch (channel->hw_value & CHANNEL_MODES) { 1082 mode = channel->hw_value;
1088 case CHANNEL_A: 1083 switch (mode) {
1089 mode = AR5K_MODE_11A; 1084 case AR5K_MODE_11A:
1090 break; 1085 break;
1091 case CHANNEL_G: 1086 case AR5K_MODE_11G:
1092
1093 if (ah->ah_version <= AR5K_AR5211) { 1087 if (ah->ah_version <= AR5K_AR5211) {
1094 ATH5K_ERR(ah, 1088 ATH5K_ERR(ah,
1095 "G mode not available on 5210/5211"); 1089 "G mode not available on 5210/5211");
1096 return -EINVAL; 1090 return -EINVAL;
1097 } 1091 }
1098
1099 mode = AR5K_MODE_11G;
1100 break; 1092 break;
1101 case CHANNEL_B: 1093 case AR5K_MODE_11B:
1102
1103 if (ah->ah_version < AR5K_AR5211) { 1094 if (ah->ah_version < AR5K_AR5211) {
1104 ATH5K_ERR(ah, 1095 ATH5K_ERR(ah,
1105 "B mode not available on 5210"); 1096 "B mode not available on 5210");
1106 return -EINVAL; 1097 return -EINVAL;
1107 } 1098 }
1108
1109 mode = AR5K_MODE_11B;
1110 break;
1111 case CHANNEL_XR:
1112 if (ah->ah_version == AR5K_AR5211) {
1113 ATH5K_ERR(ah,
1114 "XR mode not available on 5211");
1115 return -EINVAL;
1116 }
1117 mode = AR5K_MODE_XR;
1118 break; 1099 break;
1119 default: 1100 default:
1120 ATH5K_ERR(ah, 1101 ATH5K_ERR(ah,
@@ -1200,7 +1181,7 @@ int ath5k_hw_reset(struct ath5k_hw *ah, enum nl80211_iftype op_mode,
1200 } 1181 }
1201 1182
1202 /* Wakeup the device */ 1183 /* Wakeup the device */
1203 ret = ath5k_hw_nic_wakeup(ah, channel->hw_value, false); 1184 ret = ath5k_hw_nic_wakeup(ah, channel);
1204 if (ret) 1185 if (ret)
1205 return ret; 1186 return ret;
1206 1187
diff --git a/drivers/net/wireless/ath/ath5k/rfkill.c b/drivers/net/wireless/ath/ath5k/rfkill.c
index 945fc9f21e76..270a319f3aeb 100644
--- a/drivers/net/wireless/ath/ath5k/rfkill.c
+++ b/drivers/net/wireless/ath/ath5k/rfkill.c
@@ -33,7 +33,7 @@
33 * THE POSSIBILITY OF SUCH DAMAGES. 33 * THE POSSIBILITY OF SUCH DAMAGES.
34 */ 34 */
35 35
36#include "base.h" 36#include "ath5k.h"
37 37
38 38
39static inline void ath5k_rfkill_disable(struct ath5k_hw *ah) 39static inline void ath5k_rfkill_disable(struct ath5k_hw *ah)
diff --git a/drivers/net/wireless/ath/ath5k/sysfs.c b/drivers/net/wireless/ath/ath5k/sysfs.c
index 0244a36ba958..9364da7bd131 100644
--- a/drivers/net/wireless/ath/ath5k/sysfs.c
+++ b/drivers/net/wireless/ath/ath5k/sysfs.c
@@ -1,7 +1,6 @@
1#include <linux/device.h> 1#include <linux/device.h>
2#include <linux/pci.h> 2#include <linux/pci.h>
3 3
4#include "base.h"
5#include "ath5k.h" 4#include "ath5k.h"
6#include "reg.h" 5#include "reg.h"
7 6
diff --git a/drivers/net/wireless/ath/ath5k/trace.h b/drivers/net/wireless/ath/ath5k/trace.h
index c741c871f4e9..39f002ed4a88 100644
--- a/drivers/net/wireless/ath/ath5k/trace.h
+++ b/drivers/net/wireless/ath/ath5k/trace.h
@@ -2,7 +2,6 @@
2#define __TRACE_ATH5K_H 2#define __TRACE_ATH5K_H
3 3
4#include <linux/tracepoint.h> 4#include <linux/tracepoint.h>
5#include "base.h"
6 5
7#ifndef CONFIG_ATH5K_TRACER 6#ifndef CONFIG_ATH5K_TRACER
8#undef TRACE_EVENT 7#undef TRACE_EVENT
@@ -11,6 +10,8 @@ static inline void trace_ ## name(proto) {}
11#endif 10#endif
12 11
13struct sk_buff; 12struct sk_buff;
13struct ath5k_txq;
14struct ath5k_tx_status;
14 15
15#undef TRACE_SYSTEM 16#undef TRACE_SYSTEM
16#define TRACE_SYSTEM ath5k 17#define TRACE_SYSTEM ath5k
diff --git a/drivers/net/wireless/ath/ath6kl/Kconfig b/drivers/net/wireless/ath/ath6kl/Kconfig
new file mode 100644
index 000000000000..3d5f8be20eac
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/Kconfig
@@ -0,0 +1,15 @@
1config ATH6KL
2 tristate "Atheros ath6kl support"
3 depends on MMC
4 depends on CFG80211
5 ---help---
6 This module adds support for wireless adapters based on
7 Atheros AR6003 chipset running over SDIO. If you choose to
8 build it as a module, it will be called ath6kl. Pls note
9 that AR6002 and AR6001 are not supported by this driver.
10
11config ATH6KL_DEBUG
12 bool "Atheros ath6kl debugging"
13 depends on ATH6KL
14 ---help---
15 Enables debug support
diff --git a/drivers/net/wireless/ath/ath6kl/Makefile b/drivers/net/wireless/ath/ath6kl/Makefile
new file mode 100644
index 000000000000..e1bb07ea8e80
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/Makefile
@@ -0,0 +1,35 @@
1#------------------------------------------------------------------------------
2# Copyright (c) 2004-2010 Atheros Communications Inc.
3# All rights reserved.
4#
5#
6#
7# Permission to use, copy, modify, and/or distribute this software for any
8# purpose with or without fee is hereby granted, provided that the above
9# copyright notice and this permission notice appear in all copies.
10#
11# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
12# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
13# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
14# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
15# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
16# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
17# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
18#
19#
20#
21# Author(s): ="Atheros"
22#------------------------------------------------------------------------------
23
24obj-$(CONFIG_ATH6KL) := ath6kl.o
25ath6kl-y += debug.o
26ath6kl-y += htc_hif.o
27ath6kl-y += htc.o
28ath6kl-y += bmi.o
29ath6kl-y += cfg80211.o
30ath6kl-y += init.o
31ath6kl-y += main.o
32ath6kl-y += txrx.o
33ath6kl-y += wmi.o
34ath6kl-y += node.o
35ath6kl-y += sdio.o
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.c b/drivers/net/wireless/ath/ath6kl/bmi.c
new file mode 100644
index 000000000000..84676697d7eb
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/bmi.c
@@ -0,0 +1,692 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "hif-ops.h"
19#include "target.h"
20#include "debug.h"
21
22static int ath6kl_get_bmi_cmd_credits(struct ath6kl *ar)
23{
24 u32 addr;
25 unsigned long timeout;
26 int ret;
27
28 ar->bmi.cmd_credits = 0;
29
30 /* Read the counter register to get the command credits */
31 addr = COUNT_DEC_ADDRESS + (HTC_MAILBOX_NUM_MAX + ENDPOINT1) * 4;
32
33 timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
34 while (time_before(jiffies, timeout) && !ar->bmi.cmd_credits) {
35
36 /*
37 * Hit the credit counter with a 4-byte access, the first byte
38 * read will hit the counter and cause a decrement, while the
39 * remaining 3 bytes has no effect. The rationale behind this
40 * is to make all HIF accesses 4-byte aligned.
41 */
42 ret = hif_read_write_sync(ar, addr,
43 (u8 *)&ar->bmi.cmd_credits, 4,
44 HIF_RD_SYNC_BYTE_INC);
45 if (ret) {
46 ath6kl_err("Unable to decrement the command credit count register: %d\n",
47 ret);
48 return ret;
49 }
50
51 /* The counter is only 8 bits.
52 * Ignore anything in the upper 3 bytes
53 */
54 ar->bmi.cmd_credits &= 0xFF;
55 }
56
57 if (!ar->bmi.cmd_credits) {
58 ath6kl_err("bmi communication timeout\n");
59 return -ETIMEDOUT;
60 }
61
62 return 0;
63}
64
65static int ath6kl_bmi_get_rx_lkahd(struct ath6kl *ar, bool need_timeout)
66{
67 unsigned long timeout;
68 u32 rx_word = 0;
69 int ret = 0;
70
71 timeout = jiffies + msecs_to_jiffies(BMI_COMMUNICATION_TIMEOUT);
72 while ((!need_timeout || time_before(jiffies, timeout)) && !rx_word) {
73 ret = hif_read_write_sync(ar, RX_LOOKAHEAD_VALID_ADDRESS,
74 (u8 *)&rx_word, sizeof(rx_word),
75 HIF_RD_SYNC_BYTE_INC);
76 if (ret) {
77 ath6kl_err("unable to read RX_LOOKAHEAD_VALID\n");
78 return ret;
79 }
80
81 /* all we really want is one bit */
82 rx_word &= (1 << ENDPOINT1);
83 }
84
85 if (!rx_word) {
86 ath6kl_err("bmi_recv_buf FIFO empty\n");
87 return -EINVAL;
88 }
89
90 return ret;
91}
92
93static int ath6kl_bmi_send_buf(struct ath6kl *ar, u8 *buf, u32 len)
94{
95 int ret;
96 u32 addr;
97
98 ret = ath6kl_get_bmi_cmd_credits(ar);
99 if (ret)
100 return ret;
101
102 addr = ar->mbox_info.htc_addr;
103
104 ret = hif_read_write_sync(ar, addr, buf, len,
105 HIF_WR_SYNC_BYTE_INC);
106 if (ret)
107 ath6kl_err("unable to send the bmi data to the device\n");
108
109 return ret;
110}
111
112static int ath6kl_bmi_recv_buf(struct ath6kl *ar,
113 u8 *buf, u32 len, bool want_timeout)
114{
115 int ret;
116 u32 addr;
117
118 /*
119 * During normal bootup, small reads may be required.
120 * Rather than issue an HIF Read and then wait as the Target
121 * adds successive bytes to the FIFO, we wait here until
122 * we know that response data is available.
123 *
124 * This allows us to cleanly timeout on an unexpected
125 * Target failure rather than risk problems at the HIF level.
126 * In particular, this avoids SDIO timeouts and possibly garbage
127 * data on some host controllers. And on an interconnect
128 * such as Compact Flash (as well as some SDIO masters) which
129 * does not provide any indication on data timeout, it avoids
130 * a potential hang or garbage response.
131 *
132 * Synchronization is more difficult for reads larger than the
133 * size of the MBOX FIFO (128B), because the Target is unable
134 * to push the 129th byte of data until AFTER the Host posts an
135 * HIF Read and removes some FIFO data. So for large reads the
136 * Host proceeds to post an HIF Read BEFORE all the data is
137 * actually available to read. Fortunately, large BMI reads do
138 * not occur in practice -- they're supported for debug/development.
139 *
140 * So Host/Target BMI synchronization is divided into these cases:
141 * CASE 1: length < 4
142 * Should not happen
143 *
144 * CASE 2: 4 <= length <= 128
145 * Wait for first 4 bytes to be in FIFO
146 * If CONSERVATIVE_BMI_READ is enabled, also wait for
147 * a BMI command credit, which indicates that the ENTIRE
148 * response is available in the the FIFO
149 *
150 * CASE 3: length > 128
151 * Wait for the first 4 bytes to be in FIFO
152 *
153 * For most uses, a small timeout should be sufficient and we will
154 * usually see a response quickly; but there may be some unusual
155 * (debug) cases of BMI_EXECUTE where we want an larger timeout.
156 * For now, we use an unbounded busy loop while waiting for
157 * BMI_EXECUTE.
158 *
159 * If BMI_EXECUTE ever needs to support longer-latency execution,
160 * especially in production, this code needs to be enhanced to sleep
161 * and yield. Also note that BMI_COMMUNICATION_TIMEOUT is currently
162 * a function of Host processor speed.
163 */
164 if (len >= 4) { /* NB: Currently, always true */
165 ret = ath6kl_bmi_get_rx_lkahd(ar, want_timeout);
166 if (ret)
167 return ret;
168 }
169
170 addr = ar->mbox_info.htc_addr;
171 ret = hif_read_write_sync(ar, addr, buf, len,
172 HIF_RD_SYNC_BYTE_INC);
173 if (ret) {
174 ath6kl_err("Unable to read the bmi data from the device: %d\n",
175 ret);
176 return ret;
177 }
178
179 return 0;
180}
181
182int ath6kl_bmi_done(struct ath6kl *ar)
183{
184 int ret;
185 u32 cid = BMI_DONE;
186
187 if (ar->bmi.done_sent) {
188 ath6kl_dbg(ATH6KL_DBG_BMI, "bmi done skipped\n");
189 return 0;
190 }
191
192 ar->bmi.done_sent = true;
193
194 ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
195 if (ret) {
196 ath6kl_err("Unable to send bmi done: %d\n", ret);
197 return ret;
198 }
199
200 ath6kl_bmi_cleanup(ar);
201
202 return 0;
203}
204
205int ath6kl_bmi_get_target_info(struct ath6kl *ar,
206 struct ath6kl_bmi_target_info *targ_info)
207{
208 int ret;
209 u32 cid = BMI_GET_TARGET_INFO;
210
211 if (ar->bmi.done_sent) {
212 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
213 return -EACCES;
214 }
215
216 ret = ath6kl_bmi_send_buf(ar, (u8 *)&cid, sizeof(cid));
217 if (ret) {
218 ath6kl_err("Unable to send get target info: %d\n", ret);
219 return ret;
220 }
221
222 ret = ath6kl_bmi_recv_buf(ar, (u8 *)&targ_info->version,
223 sizeof(targ_info->version), true);
224 if (ret) {
225 ath6kl_err("Unable to recv target info: %d\n", ret);
226 return ret;
227 }
228
229 if (le32_to_cpu(targ_info->version) == TARGET_VERSION_SENTINAL) {
230 /* Determine how many bytes are in the Target's targ_info */
231 ret = ath6kl_bmi_recv_buf(ar,
232 (u8 *)&targ_info->byte_count,
233 sizeof(targ_info->byte_count),
234 true);
235 if (ret) {
236 ath6kl_err("unable to read target info byte count: %d\n",
237 ret);
238 return ret;
239 }
240
241 /*
242 * The target's targ_info doesn't match the host's targ_info.
243 * We need to do some backwards compatibility to make this work.
244 */
245 if (le32_to_cpu(targ_info->byte_count) != sizeof(*targ_info)) {
246 WARN_ON(1);
247 return -EINVAL;
248 }
249
250 /* Read the remainder of the targ_info */
251 ret = ath6kl_bmi_recv_buf(ar,
252 ((u8 *)targ_info) +
253 sizeof(targ_info->byte_count),
254 sizeof(*targ_info) -
255 sizeof(targ_info->byte_count),
256 true);
257
258 if (ret) {
259 ath6kl_err("Unable to read target info (%d bytes): %d\n",
260 targ_info->byte_count, ret);
261 return ret;
262 }
263 }
264
265 ath6kl_dbg(ATH6KL_DBG_BMI, "target info (ver: 0x%x type: 0x%x)\n",
266 targ_info->version, targ_info->type);
267
268 return 0;
269}
270
271int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
272{
273 u32 cid = BMI_READ_MEMORY;
274 int ret;
275 u32 offset;
276 u32 len_remain, rx_len;
277 u16 size;
278
279 if (ar->bmi.done_sent) {
280 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
281 return -EACCES;
282 }
283
284 size = BMI_DATASZ_MAX + sizeof(cid) + sizeof(addr) + sizeof(len);
285 if (size > MAX_BMI_CMDBUF_SZ) {
286 WARN_ON(1);
287 return -EINVAL;
288 }
289 memset(ar->bmi.cmd_buf, 0, size);
290
291 ath6kl_dbg(ATH6KL_DBG_BMI,
292 "bmi read memory: device: addr: 0x%x, len: %d\n",
293 addr, len);
294
295 len_remain = len;
296
297 while (len_remain) {
298 rx_len = (len_remain < BMI_DATASZ_MAX) ?
299 len_remain : BMI_DATASZ_MAX;
300 offset = 0;
301 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
302 offset += sizeof(cid);
303 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
304 offset += sizeof(addr);
305 memcpy(&(ar->bmi.cmd_buf[offset]), &rx_len, sizeof(rx_len));
306 offset += sizeof(len);
307
308 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
309 if (ret) {
310 ath6kl_err("Unable to write to the device: %d\n",
311 ret);
312 return ret;
313 }
314 ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, rx_len, true);
315 if (ret) {
316 ath6kl_err("Unable to read from the device: %d\n",
317 ret);
318 return ret;
319 }
320 memcpy(&buf[len - len_remain], ar->bmi.cmd_buf, rx_len);
321 len_remain -= rx_len; addr += rx_len;
322 }
323
324 return 0;
325}
326
327int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
328{
329 u32 cid = BMI_WRITE_MEMORY;
330 int ret;
331 u32 offset;
332 u32 len_remain, tx_len;
333 const u32 header = sizeof(cid) + sizeof(addr) + sizeof(len);
334 u8 aligned_buf[BMI_DATASZ_MAX];
335 u8 *src;
336
337 if (ar->bmi.done_sent) {
338 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
339 return -EACCES;
340 }
341
342 if ((BMI_DATASZ_MAX + header) > MAX_BMI_CMDBUF_SZ) {
343 WARN_ON(1);
344 return -EINVAL;
345 }
346
347 memset(ar->bmi.cmd_buf, 0, BMI_DATASZ_MAX + header);
348
349 ath6kl_dbg(ATH6KL_DBG_BMI,
350 "bmi write memory: addr: 0x%x, len: %d\n", addr, len);
351
352 len_remain = len;
353 while (len_remain) {
354 src = &buf[len - len_remain];
355
356 if (len_remain < (BMI_DATASZ_MAX - header)) {
357 if (len_remain & 3) {
358 /* align it with 4 bytes */
359 len_remain = len_remain +
360 (4 - (len_remain & 3));
361 memcpy(aligned_buf, src, len_remain);
362 src = aligned_buf;
363 }
364 tx_len = len_remain;
365 } else {
366 tx_len = (BMI_DATASZ_MAX - header);
367 }
368
369 offset = 0;
370 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
371 offset += sizeof(cid);
372 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
373 offset += sizeof(addr);
374 memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
375 offset += sizeof(tx_len);
376 memcpy(&(ar->bmi.cmd_buf[offset]), src, tx_len);
377 offset += tx_len;
378
379 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
380 if (ret) {
381 ath6kl_err("Unable to write to the device: %d\n",
382 ret);
383 return ret;
384 }
385 len_remain -= tx_len; addr += tx_len;
386 }
387
388 return 0;
389}
390
391int ath6kl_bmi_execute(struct ath6kl *ar, u32 addr, u32 *param)
392{
393 u32 cid = BMI_EXECUTE;
394 int ret;
395 u32 offset;
396 u16 size;
397
398 if (ar->bmi.done_sent) {
399 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
400 return -EACCES;
401 }
402
403 size = sizeof(cid) + sizeof(addr) + sizeof(param);
404 if (size > MAX_BMI_CMDBUF_SZ) {
405 WARN_ON(1);
406 return -EINVAL;
407 }
408 memset(ar->bmi.cmd_buf, 0, size);
409
410 ath6kl_dbg(ATH6KL_DBG_BMI, "bmi execute: addr: 0x%x, param: %d)\n",
411 addr, *param);
412
413 offset = 0;
414 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
415 offset += sizeof(cid);
416 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
417 offset += sizeof(addr);
418 memcpy(&(ar->bmi.cmd_buf[offset]), param, sizeof(*param));
419 offset += sizeof(*param);
420
421 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
422 if (ret) {
423 ath6kl_err("Unable to write to the device: %d\n", ret);
424 return ret;
425 }
426
427 ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), false);
428 if (ret) {
429 ath6kl_err("Unable to read from the device: %d\n", ret);
430 return ret;
431 }
432
433 memcpy(param, ar->bmi.cmd_buf, sizeof(*param));
434
435 return 0;
436}
437
438int ath6kl_bmi_set_app_start(struct ath6kl *ar, u32 addr)
439{
440 u32 cid = BMI_SET_APP_START;
441 int ret;
442 u32 offset;
443 u16 size;
444
445 if (ar->bmi.done_sent) {
446 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
447 return -EACCES;
448 }
449
450 size = sizeof(cid) + sizeof(addr);
451 if (size > MAX_BMI_CMDBUF_SZ) {
452 WARN_ON(1);
453 return -EINVAL;
454 }
455 memset(ar->bmi.cmd_buf, 0, size);
456
457 ath6kl_dbg(ATH6KL_DBG_BMI, "bmi set app start: addr: 0x%x\n", addr);
458
459 offset = 0;
460 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
461 offset += sizeof(cid);
462 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
463 offset += sizeof(addr);
464
465 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
466 if (ret) {
467 ath6kl_err("Unable to write to the device: %d\n", ret);
468 return ret;
469 }
470
471 return 0;
472}
473
474int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param)
475{
476 u32 cid = BMI_READ_SOC_REGISTER;
477 int ret;
478 u32 offset;
479 u16 size;
480
481 if (ar->bmi.done_sent) {
482 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
483 return -EACCES;
484 }
485
486 size = sizeof(cid) + sizeof(addr);
487 if (size > MAX_BMI_CMDBUF_SZ) {
488 WARN_ON(1);
489 return -EINVAL;
490 }
491 memset(ar->bmi.cmd_buf, 0, size);
492
493 ath6kl_dbg(ATH6KL_DBG_BMI, "bmi read SOC reg: addr: 0x%x\n", addr);
494
495 offset = 0;
496 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
497 offset += sizeof(cid);
498 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
499 offset += sizeof(addr);
500
501 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
502 if (ret) {
503 ath6kl_err("Unable to write to the device: %d\n", ret);
504 return ret;
505 }
506
507 ret = ath6kl_bmi_recv_buf(ar, ar->bmi.cmd_buf, sizeof(*param), true);
508 if (ret) {
509 ath6kl_err("Unable to read from the device: %d\n", ret);
510 return ret;
511 }
512 memcpy(param, ar->bmi.cmd_buf, sizeof(*param));
513
514 return 0;
515}
516
517int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param)
518{
519 u32 cid = BMI_WRITE_SOC_REGISTER;
520 int ret;
521 u32 offset;
522 u16 size;
523
524 if (ar->bmi.done_sent) {
525 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
526 return -EACCES;
527 }
528
529 size = sizeof(cid) + sizeof(addr) + sizeof(param);
530 if (size > MAX_BMI_CMDBUF_SZ) {
531 WARN_ON(1);
532 return -EINVAL;
533 }
534 memset(ar->bmi.cmd_buf, 0, size);
535
536 ath6kl_dbg(ATH6KL_DBG_BMI,
537 "bmi write SOC reg: addr: 0x%x, param: %d\n",
538 addr, param);
539
540 offset = 0;
541 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
542 offset += sizeof(cid);
543 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
544 offset += sizeof(addr);
545 memcpy(&(ar->bmi.cmd_buf[offset]), &param, sizeof(param));
546 offset += sizeof(param);
547
548 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
549 if (ret) {
550 ath6kl_err("Unable to write to the device: %d\n", ret);
551 return ret;
552 }
553
554 return 0;
555}
556
557int ath6kl_bmi_lz_data(struct ath6kl *ar, u8 *buf, u32 len)
558{
559 u32 cid = BMI_LZ_DATA;
560 int ret;
561 u32 offset;
562 u32 len_remain, tx_len;
563 const u32 header = sizeof(cid) + sizeof(len);
564 u16 size;
565
566 if (ar->bmi.done_sent) {
567 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
568 return -EACCES;
569 }
570
571 size = BMI_DATASZ_MAX + header;
572 if (size > MAX_BMI_CMDBUF_SZ) {
573 WARN_ON(1);
574 return -EINVAL;
575 }
576 memset(ar->bmi.cmd_buf, 0, size);
577
578 ath6kl_dbg(ATH6KL_DBG_BMI, "bmi send LZ data: len: %d)\n",
579 len);
580
581 len_remain = len;
582 while (len_remain) {
583 tx_len = (len_remain < (BMI_DATASZ_MAX - header)) ?
584 len_remain : (BMI_DATASZ_MAX - header);
585
586 offset = 0;
587 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
588 offset += sizeof(cid);
589 memcpy(&(ar->bmi.cmd_buf[offset]), &tx_len, sizeof(tx_len));
590 offset += sizeof(tx_len);
591 memcpy(&(ar->bmi.cmd_buf[offset]), &buf[len - len_remain],
592 tx_len);
593 offset += tx_len;
594
595 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
596 if (ret) {
597 ath6kl_err("Unable to write to the device: %d\n",
598 ret);
599 return ret;
600 }
601
602 len_remain -= tx_len;
603 }
604
605 return 0;
606}
607
608int ath6kl_bmi_lz_stream_start(struct ath6kl *ar, u32 addr)
609{
610 u32 cid = BMI_LZ_STREAM_START;
611 int ret;
612 u32 offset;
613 u16 size;
614
615 if (ar->bmi.done_sent) {
616 ath6kl_err("bmi done sent already, cmd %d disallowed\n", cid);
617 return -EACCES;
618 }
619
620 size = sizeof(cid) + sizeof(addr);
621 if (size > MAX_BMI_CMDBUF_SZ) {
622 WARN_ON(1);
623 return -EINVAL;
624 }
625 memset(ar->bmi.cmd_buf, 0, size);
626
627 ath6kl_dbg(ATH6KL_DBG_BMI,
628 "bmi LZ stream start: addr: 0x%x)\n",
629 addr);
630
631 offset = 0;
632 memcpy(&(ar->bmi.cmd_buf[offset]), &cid, sizeof(cid));
633 offset += sizeof(cid);
634 memcpy(&(ar->bmi.cmd_buf[offset]), &addr, sizeof(addr));
635 offset += sizeof(addr);
636
637 ret = ath6kl_bmi_send_buf(ar, ar->bmi.cmd_buf, offset);
638 if (ret) {
639 ath6kl_err("Unable to start LZ stream to the device: %d\n",
640 ret);
641 return ret;
642 }
643
644 return 0;
645}
646
647int ath6kl_bmi_fast_download(struct ath6kl *ar, u32 addr, u8 *buf, u32 len)
648{
649 int ret;
650 u32 last_word = 0;
651 u32 last_word_offset = len & ~0x3;
652 u32 unaligned_bytes = len & 0x3;
653
654 ret = ath6kl_bmi_lz_stream_start(ar, addr);
655 if (ret)
656 return ret;
657
658 if (unaligned_bytes) {
659 /* copy the last word into a zero padded buffer */
660 memcpy(&last_word, &buf[last_word_offset], unaligned_bytes);
661 }
662
663 ret = ath6kl_bmi_lz_data(ar, buf, last_word_offset);
664 if (ret)
665 return ret;
666
667 if (unaligned_bytes)
668 ret = ath6kl_bmi_lz_data(ar, (u8 *)&last_word, 4);
669
670 if (!ret) {
671 /* Close compressed stream and open a new (fake) one.
672 * This serves mainly to flush Target caches. */
673 ret = ath6kl_bmi_lz_stream_start(ar, 0x00);
674 }
675 return ret;
676}
677
678int ath6kl_bmi_init(struct ath6kl *ar)
679{
680 ar->bmi.cmd_buf = kzalloc(MAX_BMI_CMDBUF_SZ, GFP_ATOMIC);
681
682 if (!ar->bmi.cmd_buf)
683 return -ENOMEM;
684
685 return 0;
686}
687
688void ath6kl_bmi_cleanup(struct ath6kl *ar)
689{
690 kfree(ar->bmi.cmd_buf);
691 ar->bmi.cmd_buf = NULL;
692}
diff --git a/drivers/net/wireless/ath/ath6kl/bmi.h b/drivers/net/wireless/ath/ath6kl/bmi.h
new file mode 100644
index 000000000000..83546d76d979
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/bmi.h
@@ -0,0 +1,250 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef BMI_H
18#define BMI_H
19
20/*
21 * Bootloader Messaging Interface (BMI)
22 *
23 * BMI is a very simple messaging interface used during initialization
24 * to read memory, write memory, execute code, and to define an
25 * application entry PC.
26 *
27 * It is used to download an application to ATH6KL, to provide
28 * patches to code that is already resident on ATH6KL, and generally
29 * to examine and modify state. The Host has an opportunity to use
30 * BMI only once during bootup. Once the Host issues a BMI_DONE
31 * command, this opportunity ends.
32 *
33 * The Host writes BMI requests to mailbox0, and reads BMI responses
34 * from mailbox0. BMI requests all begin with a command
35 * (see below for specific commands), and are followed by
36 * command-specific data.
37 *
38 * Flow control:
39 * The Host can only issue a command once the Target gives it a
40 * "BMI Command Credit", using ATH6KL Counter #4. As soon as the
41 * Target has completed a command, it issues another BMI Command
42 * Credit (so the Host can issue the next command).
43 *
44 * BMI handles all required Target-side cache flushing.
45 */
46
47#define MAX_BMI_CMDBUF_SZ (BMI_DATASZ_MAX + \
48 (sizeof(u32) * 3 /* cmd + addr + len */))
49
50/* Maximum data size used for BMI transfers */
51#define BMI_DATASZ_MAX 256
52
53/* BMI Commands */
54
55#define BMI_NO_COMMAND 0
56
57#define BMI_DONE 1
58/*
59 * Semantics: Host is done using BMI
60 * Request format:
61 * u32 command (BMI_DONE)
62 * Response format: none
63 */
64
65#define BMI_READ_MEMORY 2
66/*
67 * Semantics: Host reads ATH6KL memory
68 * Request format:
69 * u32 command (BMI_READ_MEMORY)
70 * u32 address
71 * u32 length, at most BMI_DATASZ_MAX
72 * Response format:
73 * u8 data[length]
74 */
75
76#define BMI_WRITE_MEMORY 3
77/*
78 * Semantics: Host writes ATH6KL memory
79 * Request format:
80 * u32 command (BMI_WRITE_MEMORY)
81 * u32 address
82 * u32 length, at most BMI_DATASZ_MAX
83 * u8 data[length]
84 * Response format: none
85 */
86
87#define BMI_EXECUTE 4
88/*
89 * Semantics: Causes ATH6KL to execute code
90 * Request format:
91 * u32 command (BMI_EXECUTE)
92 * u32 address
93 * u32 parameter
94 * Response format:
95 * u32 return value
96 */
97
98#define BMI_SET_APP_START 5
99/*
100 * Semantics: Set Target application starting address
101 * Request format:
102 * u32 command (BMI_SET_APP_START)
103 * u32 address
104 * Response format: none
105 */
106
107#define BMI_READ_SOC_REGISTER 6
108/*
109 * Semantics: Read a 32-bit Target SOC register.
110 * Request format:
111 * u32 command (BMI_READ_REGISTER)
112 * u32 address
113 * Response format:
114 * u32 value
115 */
116
117#define BMI_WRITE_SOC_REGISTER 7
118/*
119 * Semantics: Write a 32-bit Target SOC register.
120 * Request format:
121 * u32 command (BMI_WRITE_REGISTER)
122 * u32 address
123 * u32 value
124 *
125 * Response format: none
126 */
127
128#define BMI_GET_TARGET_ID 8
129#define BMI_GET_TARGET_INFO 8
130/*
131 * Semantics: Fetch the 4-byte Target information
132 * Request format:
133 * u32 command (BMI_GET_TARGET_ID/INFO)
134 * Response format1 (old firmware):
135 * u32 TargetVersionID
136 * Response format2 (newer firmware):
137 * u32 TARGET_VERSION_SENTINAL
138 * struct bmi_target_info;
139 */
140
141#define TARGET_VERSION_SENTINAL 0xffffffff
142#define TARGET_TYPE_AR6003 3
143
144#define BMI_ROMPATCH_INSTALL 9
145/*
146 * Semantics: Install a ROM Patch.
147 * Request format:
148 * u32 command (BMI_ROMPATCH_INSTALL)
149 * u32 Target ROM Address
150 * u32 Target RAM Address or Value (depending on Target Type)
151 * u32 Size, in bytes
152 * u32 Activate? 1-->activate;
153 * 0-->install but do not activate
154 * Response format:
155 * u32 PatchID
156 */
157
158#define BMI_ROMPATCH_UNINSTALL 10
159/*
160 * Semantics: Uninstall a previously-installed ROM Patch,
161 * automatically deactivating, if necessary.
162 * Request format:
163 * u32 command (BMI_ROMPATCH_UNINSTALL)
164 * u32 PatchID
165 *
166 * Response format: none
167 */
168
169#define BMI_ROMPATCH_ACTIVATE 11
170/*
171 * Semantics: Activate a list of previously-installed ROM Patches.
172 * Request format:
173 * u32 command (BMI_ROMPATCH_ACTIVATE)
174 * u32 rompatch_count
175 * u32 PatchID[rompatch_count]
176 *
177 * Response format: none
178 */
179
180#define BMI_ROMPATCH_DEACTIVATE 12
181/*
182 * Semantics: Deactivate a list of active ROM Patches.
183 * Request format:
184 * u32 command (BMI_ROMPATCH_DEACTIVATE)
185 * u32 rompatch_count
186 * u32 PatchID[rompatch_count]
187 *
188 * Response format: none
189 */
190
191
192#define BMI_LZ_STREAM_START 13
193/*
194 * Semantics: Begin an LZ-compressed stream of input
195 * which is to be uncompressed by the Target to an
196 * output buffer at address. The output buffer must
197 * be sufficiently large to hold the uncompressed
198 * output from the compressed input stream. This BMI
199 * command should be followed by a series of 1 or more
200 * BMI_LZ_DATA commands.
201 * u32 command (BMI_LZ_STREAM_START)
202 * u32 address
203 * Note: Not supported on all versions of ROM firmware.
204 */
205
206#define BMI_LZ_DATA 14
207/*
208 * Semantics: Host writes ATH6KL memory with LZ-compressed
209 * data which is uncompressed by the Target. This command
210 * must be preceded by a BMI_LZ_STREAM_START command. A series
211 * of BMI_LZ_DATA commands are considered part of a single
212 * input stream until another BMI_LZ_STREAM_START is issued.
213 * Request format:
214 * u32 command (BMI_LZ_DATA)
215 * u32 length (of compressed data),
216 * at most BMI_DATASZ_MAX
217 * u8 CompressedData[length]
218 * Response format: none
219 * Note: Not supported on all versions of ROM firmware.
220 */
221
222#define BMI_COMMUNICATION_TIMEOUT 1000 /* in msec */
223
224struct ath6kl;
225struct ath6kl_bmi_target_info {
226 __le32 byte_count; /* size of this structure */
227 __le32 version; /* target version id */
228 __le32 type; /* target type */
229} __packed;
230
231int ath6kl_bmi_init(struct ath6kl *ar);
232void ath6kl_bmi_cleanup(struct ath6kl *ar);
233int ath6kl_bmi_done(struct ath6kl *ar);
234int ath6kl_bmi_get_target_info(struct ath6kl *ar,
235 struct ath6kl_bmi_target_info *targ_info);
236int ath6kl_bmi_read(struct ath6kl *ar, u32 addr, u8 *buf, u32 len);
237int ath6kl_bmi_write(struct ath6kl *ar, u32 addr, u8 *buf, u32 len);
238int ath6kl_bmi_execute(struct ath6kl *ar,
239 u32 addr, u32 *param);
240int ath6kl_bmi_set_app_start(struct ath6kl *ar,
241 u32 addr);
242int ath6kl_bmi_reg_read(struct ath6kl *ar, u32 addr, u32 *param);
243int ath6kl_bmi_reg_write(struct ath6kl *ar, u32 addr, u32 param);
244int ath6kl_bmi_lz_data(struct ath6kl *ar,
245 u8 *buf, u32 len);
246int ath6kl_bmi_lz_stream_start(struct ath6kl *ar,
247 u32 addr);
248int ath6kl_bmi_fast_download(struct ath6kl *ar,
249 u32 addr, u8 *buf, u32 len);
250#endif
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.c b/drivers/net/wireless/ath/ath6kl/cfg80211.c
new file mode 100644
index 000000000000..14559ffb1453
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.c
@@ -0,0 +1,1538 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "cfg80211.h"
19#include "debug.h"
20
21#define RATETAB_ENT(_rate, _rateid, _flags) { \
22 .bitrate = (_rate), \
23 .flags = (_flags), \
24 .hw_value = (_rateid), \
25}
26
27#define CHAN2G(_channel, _freq, _flags) { \
28 .band = IEEE80211_BAND_2GHZ, \
29 .hw_value = (_channel), \
30 .center_freq = (_freq), \
31 .flags = (_flags), \
32 .max_antenna_gain = 0, \
33 .max_power = 30, \
34}
35
36#define CHAN5G(_channel, _flags) { \
37 .band = IEEE80211_BAND_5GHZ, \
38 .hw_value = (_channel), \
39 .center_freq = 5000 + (5 * (_channel)), \
40 .flags = (_flags), \
41 .max_antenna_gain = 0, \
42 .max_power = 30, \
43}
44
45static struct ieee80211_rate ath6kl_rates[] = {
46 RATETAB_ENT(10, 0x1, 0),
47 RATETAB_ENT(20, 0x2, 0),
48 RATETAB_ENT(55, 0x4, 0),
49 RATETAB_ENT(110, 0x8, 0),
50 RATETAB_ENT(60, 0x10, 0),
51 RATETAB_ENT(90, 0x20, 0),
52 RATETAB_ENT(120, 0x40, 0),
53 RATETAB_ENT(180, 0x80, 0),
54 RATETAB_ENT(240, 0x100, 0),
55 RATETAB_ENT(360, 0x200, 0),
56 RATETAB_ENT(480, 0x400, 0),
57 RATETAB_ENT(540, 0x800, 0),
58};
59
60#define ath6kl_a_rates (ath6kl_rates + 4)
61#define ath6kl_a_rates_size 8
62#define ath6kl_g_rates (ath6kl_rates + 0)
63#define ath6kl_g_rates_size 12
64
65static struct ieee80211_channel ath6kl_2ghz_channels[] = {
66 CHAN2G(1, 2412, 0),
67 CHAN2G(2, 2417, 0),
68 CHAN2G(3, 2422, 0),
69 CHAN2G(4, 2427, 0),
70 CHAN2G(5, 2432, 0),
71 CHAN2G(6, 2437, 0),
72 CHAN2G(7, 2442, 0),
73 CHAN2G(8, 2447, 0),
74 CHAN2G(9, 2452, 0),
75 CHAN2G(10, 2457, 0),
76 CHAN2G(11, 2462, 0),
77 CHAN2G(12, 2467, 0),
78 CHAN2G(13, 2472, 0),
79 CHAN2G(14, 2484, 0),
80};
81
82static struct ieee80211_channel ath6kl_5ghz_a_channels[] = {
83 CHAN5G(34, 0), CHAN5G(36, 0),
84 CHAN5G(38, 0), CHAN5G(40, 0),
85 CHAN5G(42, 0), CHAN5G(44, 0),
86 CHAN5G(46, 0), CHAN5G(48, 0),
87 CHAN5G(52, 0), CHAN5G(56, 0),
88 CHAN5G(60, 0), CHAN5G(64, 0),
89 CHAN5G(100, 0), CHAN5G(104, 0),
90 CHAN5G(108, 0), CHAN5G(112, 0),
91 CHAN5G(116, 0), CHAN5G(120, 0),
92 CHAN5G(124, 0), CHAN5G(128, 0),
93 CHAN5G(132, 0), CHAN5G(136, 0),
94 CHAN5G(140, 0), CHAN5G(149, 0),
95 CHAN5G(153, 0), CHAN5G(157, 0),
96 CHAN5G(161, 0), CHAN5G(165, 0),
97 CHAN5G(184, 0), CHAN5G(188, 0),
98 CHAN5G(192, 0), CHAN5G(196, 0),
99 CHAN5G(200, 0), CHAN5G(204, 0),
100 CHAN5G(208, 0), CHAN5G(212, 0),
101 CHAN5G(216, 0),
102};
103
104static struct ieee80211_supported_band ath6kl_band_2ghz = {
105 .n_channels = ARRAY_SIZE(ath6kl_2ghz_channels),
106 .channels = ath6kl_2ghz_channels,
107 .n_bitrates = ath6kl_g_rates_size,
108 .bitrates = ath6kl_g_rates,
109};
110
111static struct ieee80211_supported_band ath6kl_band_5ghz = {
112 .n_channels = ARRAY_SIZE(ath6kl_5ghz_a_channels),
113 .channels = ath6kl_5ghz_a_channels,
114 .n_bitrates = ath6kl_a_rates_size,
115 .bitrates = ath6kl_a_rates,
116};
117
118static int ath6kl_set_wpa_version(struct ath6kl *ar,
119 enum nl80211_wpa_versions wpa_version)
120{
121 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: %u\n", __func__, wpa_version);
122
123 if (!wpa_version) {
124 ar->auth_mode = NONE_AUTH;
125 } else if (wpa_version & NL80211_WPA_VERSION_2) {
126 ar->auth_mode = WPA2_AUTH;
127 } else if (wpa_version & NL80211_WPA_VERSION_1) {
128 ar->auth_mode = WPA_AUTH;
129 } else {
130 ath6kl_err("%s: %u not supported\n", __func__, wpa_version);
131 return -ENOTSUPP;
132 }
133
134 return 0;
135}
136
137static int ath6kl_set_auth_type(struct ath6kl *ar,
138 enum nl80211_auth_type auth_type)
139{
140
141 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, auth_type);
142
143 switch (auth_type) {
144 case NL80211_AUTHTYPE_OPEN_SYSTEM:
145 ar->dot11_auth_mode = OPEN_AUTH;
146 break;
147 case NL80211_AUTHTYPE_SHARED_KEY:
148 ar->dot11_auth_mode = SHARED_AUTH;
149 break;
150 case NL80211_AUTHTYPE_NETWORK_EAP:
151 ar->dot11_auth_mode = LEAP_AUTH;
152 break;
153
154 case NL80211_AUTHTYPE_AUTOMATIC:
155 ar->dot11_auth_mode = OPEN_AUTH;
156 ar->auto_auth_stage = AUTH_OPEN_IN_PROGRESS;
157 break;
158
159 default:
160 ath6kl_err("%s: 0x%x not spported\n", __func__, auth_type);
161 return -ENOTSUPP;
162 }
163
164 return 0;
165}
166
167static int ath6kl_set_cipher(struct ath6kl *ar, u32 cipher, bool ucast)
168{
169 u8 *ar_cipher = ucast ? &ar->prwise_crypto : &ar->grp_crypto;
170 u8 *ar_cipher_len = ucast ? &ar->prwise_crypto_len : &ar->grp_crpto_len;
171
172 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: cipher 0x%x, ucast %u\n",
173 __func__, cipher, ucast);
174
175 switch (cipher) {
176 case 0:
177 /* our own hack to use value 0 as no crypto used */
178 *ar_cipher = NONE_CRYPT;
179 *ar_cipher_len = 0;
180 break;
181 case WLAN_CIPHER_SUITE_WEP40:
182 *ar_cipher = WEP_CRYPT;
183 *ar_cipher_len = 5;
184 break;
185 case WLAN_CIPHER_SUITE_WEP104:
186 *ar_cipher = WEP_CRYPT;
187 *ar_cipher_len = 13;
188 break;
189 case WLAN_CIPHER_SUITE_TKIP:
190 *ar_cipher = TKIP_CRYPT;
191 *ar_cipher_len = 0;
192 break;
193 case WLAN_CIPHER_SUITE_CCMP:
194 *ar_cipher = AES_CRYPT;
195 *ar_cipher_len = 0;
196 break;
197 default:
198 ath6kl_err("cipher 0x%x not supported\n", cipher);
199 return -ENOTSUPP;
200 }
201
202 return 0;
203}
204
205static void ath6kl_set_key_mgmt(struct ath6kl *ar, u32 key_mgmt)
206{
207 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: 0x%x\n", __func__, key_mgmt);
208
209 if (key_mgmt == WLAN_AKM_SUITE_PSK) {
210 if (ar->auth_mode == WPA_AUTH)
211 ar->auth_mode = WPA_PSK_AUTH;
212 else if (ar->auth_mode == WPA2_AUTH)
213 ar->auth_mode = WPA2_PSK_AUTH;
214 } else if (key_mgmt != WLAN_AKM_SUITE_8021X) {
215 ar->auth_mode = NONE_AUTH;
216 }
217}
218
219static bool ath6kl_cfg80211_ready(struct ath6kl *ar)
220{
221 if (!test_bit(WMI_READY, &ar->flag)) {
222 ath6kl_err("wmi is not ready\n");
223 return false;
224 }
225
226 if (!test_bit(WLAN_ENABLED, &ar->flag)) {
227 ath6kl_err("wlan disabled\n");
228 return false;
229 }
230
231 return true;
232}
233
234static int ath6kl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
235 struct cfg80211_connect_params *sme)
236{
237 struct ath6kl *ar = ath6kl_priv(dev);
238 int status;
239
240 ar->sme_state = SME_CONNECTING;
241
242 if (!ath6kl_cfg80211_ready(ar))
243 return -EIO;
244
245 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
246 ath6kl_err("destroy in progress\n");
247 return -EBUSY;
248 }
249
250 if (test_bit(SKIP_SCAN, &ar->flag) &&
251 ((sme->channel && sme->channel->center_freq == 0) ||
252 (sme->bssid && is_zero_ether_addr(sme->bssid)))) {
253 ath6kl_err("SkipScan: channel or bssid invalid\n");
254 return -EINVAL;
255 }
256
257 if (down_interruptible(&ar->sem)) {
258 ath6kl_err("busy, couldn't get access\n");
259 return -ERESTARTSYS;
260 }
261
262 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
263 ath6kl_err("busy, destroy in progress\n");
264 up(&ar->sem);
265 return -EBUSY;
266 }
267
268 if (ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)]) {
269 /*
270 * sleep until the command queue drains
271 */
272 wait_event_interruptible_timeout(ar->event_wq,
273 ar->tx_pending[ath6kl_wmi_get_control_ep(ar->wmi)] == 0,
274 WMI_TIMEOUT);
275 if (signal_pending(current)) {
276 ath6kl_err("cmd queue drain timeout\n");
277 up(&ar->sem);
278 return -EINTR;
279 }
280 }
281
282 if (test_bit(CONNECTED, &ar->flag) &&
283 ar->ssid_len == sme->ssid_len &&
284 !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
285 ar->reconnect_flag = true;
286 status = ath6kl_wmi_reconnect_cmd(ar->wmi, ar->req_bssid,
287 ar->ch_hint);
288
289 up(&ar->sem);
290 if (status) {
291 ath6kl_err("wmi_reconnect_cmd failed\n");
292 return -EIO;
293 }
294 return 0;
295 } else if (ar->ssid_len == sme->ssid_len &&
296 !memcmp(ar->ssid, sme->ssid, ar->ssid_len)) {
297 ath6kl_disconnect(ar);
298 }
299
300 memset(ar->ssid, 0, sizeof(ar->ssid));
301 ar->ssid_len = sme->ssid_len;
302 memcpy(ar->ssid, sme->ssid, sme->ssid_len);
303
304 if (sme->channel)
305 ar->ch_hint = sme->channel->center_freq;
306
307 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
308 if (sme->bssid && !is_broadcast_ether_addr(sme->bssid))
309 memcpy(ar->req_bssid, sme->bssid, sizeof(ar->req_bssid));
310
311 ath6kl_set_wpa_version(ar, sme->crypto.wpa_versions);
312
313 status = ath6kl_set_auth_type(ar, sme->auth_type);
314 if (status) {
315 up(&ar->sem);
316 return status;
317 }
318
319 if (sme->crypto.n_ciphers_pairwise)
320 ath6kl_set_cipher(ar, sme->crypto.ciphers_pairwise[0], true);
321 else
322 ath6kl_set_cipher(ar, 0, true);
323
324 ath6kl_set_cipher(ar, sme->crypto.cipher_group, false);
325
326 if (sme->crypto.n_akm_suites)
327 ath6kl_set_key_mgmt(ar, sme->crypto.akm_suites[0]);
328
329 if ((sme->key_len) &&
330 (ar->auth_mode == NONE_AUTH) && (ar->prwise_crypto == WEP_CRYPT)) {
331 struct ath6kl_key *key = NULL;
332
333 if (sme->key_idx < WMI_MIN_KEY_INDEX ||
334 sme->key_idx > WMI_MAX_KEY_INDEX) {
335 ath6kl_err("key index %d out of bounds\n",
336 sme->key_idx);
337 up(&ar->sem);
338 return -ENOENT;
339 }
340
341 key = &ar->keys[sme->key_idx];
342 key->key_len = sme->key_len;
343 memcpy(key->key, sme->key, key->key_len);
344 key->cipher = ar->prwise_crypto;
345 ar->def_txkey_index = sme->key_idx;
346
347 ath6kl_wmi_addkey_cmd(ar->wmi, sme->key_idx,
348 ar->prwise_crypto,
349 GROUP_USAGE | TX_USAGE,
350 key->key_len,
351 NULL,
352 key->key, KEY_OP_INIT_VAL, NULL,
353 NO_SYNC_WMIFLAG);
354 }
355
356 if (!ar->usr_bss_filter) {
357 if (ath6kl_wmi_bssfilter_cmd(ar->wmi, ALL_BSS_FILTER, 0) != 0) {
358 ath6kl_err("couldn't set bss filtering\n");
359 up(&ar->sem);
360 return -EIO;
361 }
362 }
363
364 ar->nw_type = ar->next_mode;
365
366 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
367 "%s: connect called with authmode %d dot11 auth %d"
368 " PW crypto %d PW crypto len %d GRP crypto %d"
369 " GRP crypto len %d channel hint %u\n",
370 __func__,
371 ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
372 ar->prwise_crypto_len, ar->grp_crypto,
373 ar->grp_crpto_len, ar->ch_hint);
374
375 ar->reconnect_flag = 0;
376 status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
377 ar->dot11_auth_mode, ar->auth_mode,
378 ar->prwise_crypto,
379 ar->prwise_crypto_len,
380 ar->grp_crypto, ar->grp_crpto_len,
381 ar->ssid_len, ar->ssid,
382 ar->req_bssid, ar->ch_hint,
383 ar->connect_ctrl_flags);
384
385 up(&ar->sem);
386
387 if (status == -EINVAL) {
388 memset(ar->ssid, 0, sizeof(ar->ssid));
389 ar->ssid_len = 0;
390 ath6kl_err("invalid request\n");
391 return -ENOENT;
392 } else if (status) {
393 ath6kl_err("ath6kl_wmi_connect_cmd failed\n");
394 return -EIO;
395 }
396
397 if ((!(ar->connect_ctrl_flags & CONNECT_DO_WPA_OFFLOAD)) &&
398 ((ar->auth_mode == WPA_PSK_AUTH)
399 || (ar->auth_mode == WPA2_PSK_AUTH))) {
400 mod_timer(&ar->disconnect_timer,
401 jiffies + msecs_to_jiffies(DISCON_TIMER_INTVAL));
402 }
403
404 ar->connect_ctrl_flags &= ~CONNECT_DO_WPA_OFFLOAD;
405 set_bit(CONNECT_PEND, &ar->flag);
406
407 return 0;
408}
409
410void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
411 u8 *bssid, u16 listen_intvl,
412 u16 beacon_intvl,
413 enum network_type nw_type,
414 u8 beacon_ie_len, u8 assoc_req_len,
415 u8 assoc_resp_len, u8 *assoc_info)
416{
417 u16 size = 0;
418 u16 capability = 0;
419 struct cfg80211_bss *bss = NULL;
420 struct ieee80211_mgmt *mgmt = NULL;
421 struct ieee80211_channel *ibss_ch = NULL;
422 s32 signal = 50 * 100;
423 u8 ie_buf_len = 0;
424 unsigned char ie_buf[256];
425 unsigned char *ptr_ie_buf = ie_buf;
426 unsigned char *ieeemgmtbuf = NULL;
427 u8 source_mac[ETH_ALEN];
428 u16 capa_mask;
429 u16 capa_val;
430
431 /* capinfo + listen interval */
432 u8 assoc_req_ie_offset = sizeof(u16) + sizeof(u16);
433
434 /* capinfo + status code + associd */
435 u8 assoc_resp_ie_offset = sizeof(u16) + sizeof(u16) + sizeof(u16);
436
437 u8 *assoc_req_ie = assoc_info + beacon_ie_len + assoc_req_ie_offset;
438 u8 *assoc_resp_ie = assoc_info + beacon_ie_len + assoc_req_len +
439 assoc_resp_ie_offset;
440
441 assoc_req_len -= assoc_req_ie_offset;
442 assoc_resp_len -= assoc_resp_ie_offset;
443
444 ar->auto_auth_stage = AUTH_IDLE;
445
446 if (nw_type & ADHOC_NETWORK) {
447 if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
448 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
449 "%s: ath6k not in ibss mode\n", __func__);
450 return;
451 }
452 }
453
454 if (nw_type & INFRA_NETWORK) {
455 if (ar->wdev->iftype != NL80211_IFTYPE_STATION) {
456 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
457 "%s: ath6k not in station mode\n", __func__);
458 return;
459 }
460 }
461
462 if (nw_type & ADHOC_NETWORK) {
463 capa_mask = WLAN_CAPABILITY_IBSS;
464 capa_val = WLAN_CAPABILITY_IBSS;
465 } else {
466 capa_mask = WLAN_CAPABILITY_ESS;
467 capa_val = WLAN_CAPABILITY_ESS;
468 }
469
470 /* Before informing the join/connect event, make sure that
471 * bss entry is present in scan list, if it not present
472 * construct and insert into scan list, otherwise that
473 * event will be dropped on the way by cfg80211, due to
474 * this keys will not be plumbed in case of WEP and
475 * application will not be aware of join/connect status. */
476 bss = cfg80211_get_bss(ar->wdev->wiphy, NULL, bssid,
477 ar->wdev->ssid, ar->wdev->ssid_len,
478 capa_mask, capa_val);
479
480 /*
481 * Earlier we were updating the cfg about bss by making a beacon frame
482 * only if the entry for bss is not there. This can have some issue if
483 * ROAM event is generated and a heavy traffic is ongoing. The ROAM
484 * event is handled through a work queue and by the time it really gets
485 * handled, BSS would have been aged out. So it is better to update the
486 * cfg about BSS irrespective of its entry being present right now or
487 * not.
488 */
489
490 if (nw_type & ADHOC_NETWORK) {
491 /* construct 802.11 mgmt beacon */
492 if (ptr_ie_buf) {
493 *ptr_ie_buf++ = WLAN_EID_SSID;
494 *ptr_ie_buf++ = ar->ssid_len;
495 memcpy(ptr_ie_buf, ar->ssid, ar->ssid_len);
496 ptr_ie_buf += ar->ssid_len;
497
498 *ptr_ie_buf++ = WLAN_EID_IBSS_PARAMS;
499 *ptr_ie_buf++ = 2; /* length */
500 *ptr_ie_buf++ = 0; /* ATIM window */
501 *ptr_ie_buf++ = 0; /* ATIM window */
502
503 /* TODO: update ibss params and include supported rates,
504 * DS param set, extened support rates, wmm. */
505
506 ie_buf_len = ptr_ie_buf - ie_buf;
507 }
508
509 capability |= WLAN_CAPABILITY_IBSS;
510
511 if (ar->prwise_crypto == WEP_CRYPT)
512 capability |= WLAN_CAPABILITY_PRIVACY;
513
514 memcpy(source_mac, ar->net_dev->dev_addr, ETH_ALEN);
515 ptr_ie_buf = ie_buf;
516 } else {
517 capability = *(u16 *) (&assoc_info[beacon_ie_len]);
518 memcpy(source_mac, bssid, ETH_ALEN);
519 ptr_ie_buf = assoc_req_ie;
520 ie_buf_len = assoc_req_len;
521 }
522
523 size = offsetof(struct ieee80211_mgmt, u)
524 + sizeof(mgmt->u.beacon)
525 + ie_buf_len;
526
527 ieeemgmtbuf = kzalloc(size, GFP_ATOMIC);
528 if (!ieeemgmtbuf) {
529 ath6kl_err("ieee mgmt buf alloc error\n");
530 cfg80211_put_bss(bss);
531 return;
532 }
533
534 mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
535 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
536 IEEE80211_STYPE_BEACON);
537 memset(mgmt->da, 0xff, ETH_ALEN); /* broadcast addr */
538 memcpy(mgmt->sa, source_mac, ETH_ALEN);
539 memcpy(mgmt->bssid, bssid, ETH_ALEN);
540 mgmt->u.beacon.beacon_int = cpu_to_le16(beacon_intvl);
541 mgmt->u.beacon.capab_info = cpu_to_le16(capability);
542 memcpy(mgmt->u.beacon.variable, ptr_ie_buf, ie_buf_len);
543
544 ibss_ch = ieee80211_get_channel(ar->wdev->wiphy, (int)channel);
545
546 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
547 "%s: inform bss with bssid %pM channel %d beacon_intvl %d capability 0x%x\n",
548 __func__, mgmt->bssid, ibss_ch->hw_value,
549 beacon_intvl, capability);
550
551 bss = cfg80211_inform_bss_frame(ar->wdev->wiphy,
552 ibss_ch, mgmt,
553 size, signal, GFP_KERNEL);
554 kfree(ieeemgmtbuf);
555 cfg80211_put_bss(bss);
556
557 if (nw_type & ADHOC_NETWORK) {
558 cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
559 return;
560 }
561
562 if (ar->sme_state == SME_CONNECTING) {
563 /* inform connect result to cfg80211 */
564 ar->sme_state = SME_CONNECTED;
565 cfg80211_connect_result(ar->net_dev, bssid,
566 assoc_req_ie, assoc_req_len,
567 assoc_resp_ie, assoc_resp_len,
568 WLAN_STATUS_SUCCESS, GFP_KERNEL);
569 } else if (ar->sme_state == SME_CONNECTED) {
570 /* inform roam event to cfg80211 */
571 cfg80211_roamed(ar->net_dev, ibss_ch, bssid,
572 assoc_req_ie, assoc_req_len,
573 assoc_resp_ie, assoc_resp_len, GFP_KERNEL);
574 }
575}
576
577static int ath6kl_cfg80211_disconnect(struct wiphy *wiphy,
578 struct net_device *dev, u16 reason_code)
579{
580 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
581
582 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: reason=%u\n", __func__,
583 reason_code);
584
585 if (!ath6kl_cfg80211_ready(ar))
586 return -EIO;
587
588 if (test_bit(DESTROY_IN_PROGRESS, &ar->flag)) {
589 ath6kl_err("busy, destroy in progress\n");
590 return -EBUSY;
591 }
592
593 if (down_interruptible(&ar->sem)) {
594 ath6kl_err("busy, couldn't get access\n");
595 return -ERESTARTSYS;
596 }
597
598 ar->reconnect_flag = 0;
599 ath6kl_disconnect(ar);
600 memset(ar->ssid, 0, sizeof(ar->ssid));
601 ar->ssid_len = 0;
602
603 if (!test_bit(SKIP_SCAN, &ar->flag))
604 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
605
606 up(&ar->sem);
607
608 return 0;
609}
610
611void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
612 u8 *bssid, u8 assoc_resp_len,
613 u8 *assoc_info, u16 proto_reason)
614{
615 struct ath6kl_key *key = NULL;
616 u16 status;
617
618 if (ar->scan_req) {
619 cfg80211_scan_done(ar->scan_req, true);
620 ar->scan_req = NULL;
621 }
622
623 if (ar->nw_type & ADHOC_NETWORK) {
624 if (ar->wdev->iftype != NL80211_IFTYPE_ADHOC) {
625 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
626 "%s: ath6k not in ibss mode\n", __func__);
627 return;
628 }
629 memset(bssid, 0, ETH_ALEN);
630 cfg80211_ibss_joined(ar->net_dev, bssid, GFP_KERNEL);
631 return;
632 }
633
634 if (ar->nw_type & INFRA_NETWORK) {
635 if (ar->wdev->iftype != NL80211_IFTYPE_STATION) {
636 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
637 "%s: ath6k not in station mode\n", __func__);
638 return;
639 }
640 }
641
642 if (!test_bit(CONNECT_PEND, &ar->flag)) {
643 if (reason != DISCONNECT_CMD)
644 ath6kl_wmi_disconnect_cmd(ar->wmi);
645
646 return;
647 }
648
649 if (reason == NO_NETWORK_AVAIL) {
650 /* connect cmd failed */
651 ath6kl_wmi_disconnect_cmd(ar->wmi);
652 return;
653 }
654
655 if (reason != DISCONNECT_CMD)
656 return;
657
658 if (!ar->auto_auth_stage) {
659 clear_bit(CONNECT_PEND, &ar->flag);
660
661 if (ar->sme_state == SME_CONNECTING) {
662 cfg80211_connect_result(ar->net_dev,
663 bssid, NULL, 0,
664 NULL, 0,
665 WLAN_STATUS_UNSPECIFIED_FAILURE,
666 GFP_KERNEL);
667 } else {
668 cfg80211_disconnected(ar->net_dev, reason,
669 NULL, 0, GFP_KERNEL);
670 }
671
672 ar->sme_state = SME_DISCONNECTED;
673 return;
674 }
675
676 if (ar->dot11_auth_mode != OPEN_AUTH)
677 return;
678
679 /*
680 * If the current auth algorithm is open, try shared and
681 * make autoAuthStage idle. We do not make it leap for now
682 * being.
683 */
684 key = &ar->keys[ar->def_txkey_index];
685 if (down_interruptible(&ar->sem)) {
686 ath6kl_err("busy, couldn't get access\n");
687 return;
688 }
689
690 ar->dot11_auth_mode = SHARED_AUTH;
691 ar->auto_auth_stage = AUTH_IDLE;
692
693 ath6kl_wmi_addkey_cmd(ar->wmi,
694 ar->def_txkey_index,
695 ar->prwise_crypto,
696 GROUP_USAGE | TX_USAGE,
697 key->key_len, NULL,
698 key->key,
699 KEY_OP_INIT_VAL, NULL,
700 NO_SYNC_WMIFLAG);
701
702 status = ath6kl_wmi_connect_cmd(ar->wmi,
703 ar->nw_type,
704 ar->dot11_auth_mode,
705 ar->auth_mode,
706 ar->prwise_crypto,
707 ar->prwise_crypto_len,
708 ar->grp_crypto,
709 ar->grp_crpto_len,
710 ar->ssid_len,
711 ar->ssid,
712 ar->req_bssid,
713 ar->ch_hint,
714 ar->connect_ctrl_flags);
715 up(&ar->sem);
716}
717
718static inline bool is_ch_11a(u16 ch)
719{
720 return (!((ch >= 2412) && (ch <= 2484)));
721}
722
723/* struct ath6kl_node_table::nt_nodelock is locked when calling this */
724void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni)
725{
726 u16 size;
727 unsigned char *ieeemgmtbuf = NULL;
728 struct ieee80211_mgmt *mgmt;
729 struct ieee80211_channel *channel;
730 struct ieee80211_supported_band *band;
731 struct ath6kl_common_ie *cie;
732 s32 signal;
733 int freq;
734
735 cie = &ni->ni_cie;
736
737 if (is_ch_11a(cie->ie_chan))
738 band = wiphy->bands[IEEE80211_BAND_5GHZ]; /* 11a */
739 else if ((cie->ie_erp) || (cie->ie_xrates))
740 band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11g */
741 else
742 band = wiphy->bands[IEEE80211_BAND_2GHZ]; /* 11b */
743
744 size = ni->ni_framelen + offsetof(struct ieee80211_mgmt, u);
745 ieeemgmtbuf = kmalloc(size, GFP_ATOMIC);
746 if (!ieeemgmtbuf) {
747 ath6kl_err("ieee mgmt buf alloc error\n");
748 return;
749 }
750
751 /*
752 * TODO: Update target to include 802.11 mac header while sending
753 * bss info. Target removes 802.11 mac header while sending the bss
754 * info to host, cfg80211 needs it, for time being just filling the
755 * da, sa and bssid fields alone.
756 */
757 mgmt = (struct ieee80211_mgmt *)ieeemgmtbuf;
758 memset(mgmt->da, 0xff, ETH_ALEN); /*broadcast addr */
759 memcpy(mgmt->sa, ni->ni_macaddr, ETH_ALEN);
760 memcpy(mgmt->bssid, ni->ni_macaddr, ETH_ALEN);
761 memcpy(ieeemgmtbuf + offsetof(struct ieee80211_mgmt, u),
762 ni->ni_buf, ni->ni_framelen);
763
764 freq = cie->ie_chan;
765 channel = ieee80211_get_channel(wiphy, freq);
766 signal = ni->ni_snr * 100;
767
768 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
769 "%s: bssid %pM ch %d freq %d size %d\n", __func__,
770 mgmt->bssid, channel->hw_value, freq, size);
771 cfg80211_inform_bss_frame(wiphy, channel, mgmt,
772 size, signal, GFP_ATOMIC);
773
774 kfree(ieeemgmtbuf);
775}
776
777static int ath6kl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
778 struct cfg80211_scan_request *request)
779{
780 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
781 int ret = 0;
782
783 if (!ath6kl_cfg80211_ready(ar))
784 return -EIO;
785
786 if (!ar->usr_bss_filter) {
787 if (ath6kl_wmi_bssfilter_cmd(ar->wmi,
788 (test_bit(CONNECTED, &ar->flag) ?
789 ALL_BUT_BSS_FILTER :
790 ALL_BSS_FILTER), 0) != 0) {
791 ath6kl_err("couldn't set bss filtering\n");
792 return -EIO;
793 }
794 }
795
796 if (request->n_ssids && request->ssids[0].ssid_len) {
797 u8 i;
798
799 if (request->n_ssids > (MAX_PROBED_SSID_INDEX - 1))
800 request->n_ssids = MAX_PROBED_SSID_INDEX - 1;
801
802 for (i = 0; i < request->n_ssids; i++)
803 ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
804 SPECIFIC_SSID_FLAG,
805 request->ssids[i].ssid_len,
806 request->ssids[i].ssid);
807 }
808
809 if (ath6kl_wmi_startscan_cmd(ar->wmi, WMI_LONG_SCAN, 0,
810 false, 0, 0, 0, NULL) != 0) {
811 ath6kl_err("wmi_startscan_cmd failed\n");
812 ret = -EIO;
813 }
814
815 ar->scan_req = request;
816
817 return ret;
818}
819
820void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status)
821{
822 int i;
823
824 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: status %d\n", __func__, status);
825
826 if (!ar->scan_req)
827 return;
828
829 if ((status == -ECANCELED) || (status == -EBUSY)) {
830 cfg80211_scan_done(ar->scan_req, true);
831 goto out;
832 }
833
834 /* Translate data to cfg80211 mgmt format */
835 wlan_iterate_nodes(&ar->scan_table, ar->wdev->wiphy);
836
837 cfg80211_scan_done(ar->scan_req, false);
838
839 if (ar->scan_req->n_ssids && ar->scan_req->ssids[0].ssid_len) {
840 for (i = 0; i < ar->scan_req->n_ssids; i++) {
841 ath6kl_wmi_probedssid_cmd(ar->wmi, i + 1,
842 DISABLE_SSID_FLAG,
843 0, NULL);
844 }
845 }
846
847out:
848 ar->scan_req = NULL;
849}
850
851static int ath6kl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *ndev,
852 u8 key_index, bool pairwise,
853 const u8 *mac_addr,
854 struct key_params *params)
855{
856 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
857 struct ath6kl_key *key = NULL;
858 u8 key_usage;
859 u8 key_type;
860 int status = 0;
861
862 if (!ath6kl_cfg80211_ready(ar))
863 return -EIO;
864
865 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
866 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
867 "%s: key index %d out of bounds\n", __func__,
868 key_index);
869 return -ENOENT;
870 }
871
872 key = &ar->keys[key_index];
873 memset(key, 0, sizeof(struct ath6kl_key));
874
875 if (pairwise)
876 key_usage = PAIRWISE_USAGE;
877 else
878 key_usage = GROUP_USAGE;
879
880 if (params) {
881 if (params->key_len > WLAN_MAX_KEY_LEN ||
882 params->seq_len > sizeof(key->seq))
883 return -EINVAL;
884
885 key->key_len = params->key_len;
886 memcpy(key->key, params->key, key->key_len);
887 key->seq_len = params->seq_len;
888 memcpy(key->seq, params->seq, key->seq_len);
889 key->cipher = params->cipher;
890 }
891
892 switch (key->cipher) {
893 case WLAN_CIPHER_SUITE_WEP40:
894 case WLAN_CIPHER_SUITE_WEP104:
895 key_type = WEP_CRYPT;
896 break;
897
898 case WLAN_CIPHER_SUITE_TKIP:
899 key_type = TKIP_CRYPT;
900 break;
901
902 case WLAN_CIPHER_SUITE_CCMP:
903 key_type = AES_CRYPT;
904 break;
905
906 default:
907 return -ENOTSUPP;
908 }
909
910 if (((ar->auth_mode == WPA_PSK_AUTH)
911 || (ar->auth_mode == WPA2_PSK_AUTH))
912 && (key_usage & GROUP_USAGE))
913 del_timer(&ar->disconnect_timer);
914
915 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
916 "%s: index %d, key_len %d, key_type 0x%x, key_usage 0x%x, seq_len %d\n",
917 __func__, key_index, key->key_len, key_type,
918 key_usage, key->seq_len);
919
920 ar->def_txkey_index = key_index;
921 status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
922 key_type, key_usage, key->key_len,
923 key->seq, key->key, KEY_OP_INIT_VAL,
924 (u8 *) mac_addr, SYNC_BOTH_WMIFLAG);
925
926 if (status)
927 return -EIO;
928
929 return 0;
930}
931
932static int ath6kl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *ndev,
933 u8 key_index, bool pairwise,
934 const u8 *mac_addr)
935{
936 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
937
938 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
939
940 if (!ath6kl_cfg80211_ready(ar))
941 return -EIO;
942
943 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
944 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
945 "%s: key index %d out of bounds\n", __func__,
946 key_index);
947 return -ENOENT;
948 }
949
950 if (!ar->keys[key_index].key_len) {
951 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
952 "%s: index %d is empty\n", __func__, key_index);
953 return 0;
954 }
955
956 ar->keys[key_index].key_len = 0;
957
958 return ath6kl_wmi_deletekey_cmd(ar->wmi, key_index);
959}
960
961static int ath6kl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *ndev,
962 u8 key_index, bool pairwise,
963 const u8 *mac_addr, void *cookie,
964 void (*callback) (void *cookie,
965 struct key_params *))
966{
967 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
968 struct ath6kl_key *key = NULL;
969 struct key_params params;
970
971 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
972
973 if (!ath6kl_cfg80211_ready(ar))
974 return -EIO;
975
976 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
977 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
978 "%s: key index %d out of bounds\n", __func__,
979 key_index);
980 return -ENOENT;
981 }
982
983 key = &ar->keys[key_index];
984 memset(&params, 0, sizeof(params));
985 params.cipher = key->cipher;
986 params.key_len = key->key_len;
987 params.seq_len = key->seq_len;
988 params.seq = key->seq;
989 params.key = key->key;
990
991 callback(cookie, &params);
992
993 return key->key_len ? 0 : -ENOENT;
994}
995
996static int ath6kl_cfg80211_set_default_key(struct wiphy *wiphy,
997 struct net_device *ndev,
998 u8 key_index, bool unicast,
999 bool multicast)
1000{
1001 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(ndev);
1002 struct ath6kl_key *key = NULL;
1003 int status = 0;
1004 u8 key_usage;
1005
1006 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: index %d\n", __func__, key_index);
1007
1008 if (!ath6kl_cfg80211_ready(ar))
1009 return -EIO;
1010
1011 if (key_index < WMI_MIN_KEY_INDEX || key_index > WMI_MAX_KEY_INDEX) {
1012 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1013 "%s: key index %d out of bounds\n",
1014 __func__, key_index);
1015 return -ENOENT;
1016 }
1017
1018 if (!ar->keys[key_index].key_len) {
1019 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: invalid key index %d\n",
1020 __func__, key_index);
1021 return -EINVAL;
1022 }
1023
1024 ar->def_txkey_index = key_index;
1025 key = &ar->keys[ar->def_txkey_index];
1026 key_usage = GROUP_USAGE;
1027 if (ar->prwise_crypto == WEP_CRYPT)
1028 key_usage |= TX_USAGE;
1029
1030 status = ath6kl_wmi_addkey_cmd(ar->wmi, ar->def_txkey_index,
1031 ar->prwise_crypto, key_usage,
1032 key->key_len, key->seq, key->key,
1033 KEY_OP_INIT_VAL, NULL,
1034 SYNC_BOTH_WMIFLAG);
1035 if (status)
1036 return -EIO;
1037
1038 return 0;
1039}
1040
1041void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
1042 bool ismcast)
1043{
1044 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1045 "%s: keyid %d, ismcast %d\n", __func__, keyid, ismcast);
1046
1047 cfg80211_michael_mic_failure(ar->net_dev, ar->bssid,
1048 (ismcast ? NL80211_KEYTYPE_GROUP :
1049 NL80211_KEYTYPE_PAIRWISE), keyid, NULL,
1050 GFP_KERNEL);
1051}
1052
1053static int ath6kl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
1054{
1055 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1056 int ret;
1057
1058 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: changed 0x%x\n", __func__,
1059 changed);
1060
1061 if (!ath6kl_cfg80211_ready(ar))
1062 return -EIO;
1063
1064 if (changed & WIPHY_PARAM_RTS_THRESHOLD) {
1065 ret = ath6kl_wmi_set_rts_cmd(ar->wmi, wiphy->rts_threshold);
1066 if (ret != 0) {
1067 ath6kl_err("ath6kl_wmi_set_rts_cmd failed\n");
1068 return -EIO;
1069 }
1070 }
1071
1072 return 0;
1073}
1074
1075/*
1076 * The type nl80211_tx_power_setting replaces the following
1077 * data type from 2.6.36 onwards
1078*/
1079static int ath6kl_cfg80211_set_txpower(struct wiphy *wiphy,
1080 enum nl80211_tx_power_setting type,
1081 int dbm)
1082{
1083 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1084 u8 ath6kl_dbm;
1085
1086 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x, dbm %d\n", __func__,
1087 type, dbm);
1088
1089 if (!ath6kl_cfg80211_ready(ar))
1090 return -EIO;
1091
1092 switch (type) {
1093 case NL80211_TX_POWER_AUTOMATIC:
1094 return 0;
1095 case NL80211_TX_POWER_LIMITED:
1096 ar->tx_pwr = ath6kl_dbm = dbm;
1097 break;
1098 default:
1099 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type 0x%x not supported\n",
1100 __func__, type);
1101 return -EOPNOTSUPP;
1102 }
1103
1104 ath6kl_wmi_set_tx_pwr_cmd(ar->wmi, ath6kl_dbm);
1105
1106 return 0;
1107}
1108
1109static int ath6kl_cfg80211_get_txpower(struct wiphy *wiphy, int *dbm)
1110{
1111 struct ath6kl *ar = (struct ath6kl *)wiphy_priv(wiphy);
1112
1113 if (!ath6kl_cfg80211_ready(ar))
1114 return -EIO;
1115
1116 if (test_bit(CONNECTED, &ar->flag)) {
1117 ar->tx_pwr = 0;
1118
1119 if (ath6kl_wmi_get_tx_pwr_cmd(ar->wmi) != 0) {
1120 ath6kl_err("ath6kl_wmi_get_tx_pwr_cmd failed\n");
1121 return -EIO;
1122 }
1123
1124 wait_event_interruptible_timeout(ar->event_wq, ar->tx_pwr != 0,
1125 5 * HZ);
1126
1127 if (signal_pending(current)) {
1128 ath6kl_err("target did not respond\n");
1129 return -EINTR;
1130 }
1131 }
1132
1133 *dbm = ar->tx_pwr;
1134 return 0;
1135}
1136
1137static int ath6kl_cfg80211_set_power_mgmt(struct wiphy *wiphy,
1138 struct net_device *dev,
1139 bool pmgmt, int timeout)
1140{
1141 struct ath6kl *ar = ath6kl_priv(dev);
1142 struct wmi_power_mode_cmd mode;
1143
1144 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: pmgmt %d, timeout %d\n",
1145 __func__, pmgmt, timeout);
1146
1147 if (!ath6kl_cfg80211_ready(ar))
1148 return -EIO;
1149
1150 if (pmgmt) {
1151 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: max perf\n", __func__);
1152 mode.pwr_mode = REC_POWER;
1153 } else {
1154 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: rec power\n", __func__);
1155 mode.pwr_mode = MAX_PERF_POWER;
1156 }
1157
1158 if (ath6kl_wmi_powermode_cmd(ar->wmi, mode.pwr_mode) != 0) {
1159 ath6kl_err("wmi_powermode_cmd failed\n");
1160 return -EIO;
1161 }
1162
1163 return 0;
1164}
1165
1166static int ath6kl_cfg80211_change_iface(struct wiphy *wiphy,
1167 struct net_device *ndev,
1168 enum nl80211_iftype type, u32 *flags,
1169 struct vif_params *params)
1170{
1171 struct ath6kl *ar = ath6kl_priv(ndev);
1172 struct wireless_dev *wdev = ar->wdev;
1173
1174 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG, "%s: type %u\n", __func__, type);
1175
1176 if (!ath6kl_cfg80211_ready(ar))
1177 return -EIO;
1178
1179 switch (type) {
1180 case NL80211_IFTYPE_STATION:
1181 ar->next_mode = INFRA_NETWORK;
1182 break;
1183 case NL80211_IFTYPE_ADHOC:
1184 ar->next_mode = ADHOC_NETWORK;
1185 break;
1186 default:
1187 ath6kl_err("invalid interface type %u\n", type);
1188 return -EOPNOTSUPP;
1189 }
1190
1191 wdev->iftype = type;
1192
1193 return 0;
1194}
1195
1196static int ath6kl_cfg80211_join_ibss(struct wiphy *wiphy,
1197 struct net_device *dev,
1198 struct cfg80211_ibss_params *ibss_param)
1199{
1200 struct ath6kl *ar = ath6kl_priv(dev);
1201 int status;
1202
1203 if (!ath6kl_cfg80211_ready(ar))
1204 return -EIO;
1205
1206 ar->ssid_len = ibss_param->ssid_len;
1207 memcpy(ar->ssid, ibss_param->ssid, ar->ssid_len);
1208
1209 if (ibss_param->channel)
1210 ar->ch_hint = ibss_param->channel->center_freq;
1211
1212 if (ibss_param->channel_fixed) {
1213 /*
1214 * TODO: channel_fixed: The channel should be fixed, do not
1215 * search for IBSSs to join on other channels. Target
1216 * firmware does not support this feature, needs to be
1217 * updated.
1218 */
1219 return -EOPNOTSUPP;
1220 }
1221
1222 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
1223 if (ibss_param->bssid && !is_broadcast_ether_addr(ibss_param->bssid))
1224 memcpy(ar->req_bssid, ibss_param->bssid, sizeof(ar->req_bssid));
1225
1226 ath6kl_set_wpa_version(ar, 0);
1227
1228 status = ath6kl_set_auth_type(ar, NL80211_AUTHTYPE_OPEN_SYSTEM);
1229 if (status)
1230 return status;
1231
1232 if (ibss_param->privacy) {
1233 ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, true);
1234 ath6kl_set_cipher(ar, WLAN_CIPHER_SUITE_WEP40, false);
1235 } else {
1236 ath6kl_set_cipher(ar, 0, true);
1237 ath6kl_set_cipher(ar, 0, false);
1238 }
1239
1240 ar->nw_type = ar->next_mode;
1241
1242 ath6kl_dbg(ATH6KL_DBG_WLAN_CFG,
1243 "%s: connect called with authmode %d dot11 auth %d"
1244 " PW crypto %d PW crypto len %d GRP crypto %d"
1245 " GRP crypto len %d channel hint %u\n",
1246 __func__,
1247 ar->auth_mode, ar->dot11_auth_mode, ar->prwise_crypto,
1248 ar->prwise_crypto_len, ar->grp_crypto,
1249 ar->grp_crpto_len, ar->ch_hint);
1250
1251 status = ath6kl_wmi_connect_cmd(ar->wmi, ar->nw_type,
1252 ar->dot11_auth_mode, ar->auth_mode,
1253 ar->prwise_crypto,
1254 ar->prwise_crypto_len,
1255 ar->grp_crypto, ar->grp_crpto_len,
1256 ar->ssid_len, ar->ssid,
1257 ar->req_bssid, ar->ch_hint,
1258 ar->connect_ctrl_flags);
1259 set_bit(CONNECT_PEND, &ar->flag);
1260
1261 return 0;
1262}
1263
1264static int ath6kl_cfg80211_leave_ibss(struct wiphy *wiphy,
1265 struct net_device *dev)
1266{
1267 struct ath6kl *ar = (struct ath6kl *)ath6kl_priv(dev);
1268
1269 if (!ath6kl_cfg80211_ready(ar))
1270 return -EIO;
1271
1272 ath6kl_disconnect(ar);
1273 memset(ar->ssid, 0, sizeof(ar->ssid));
1274 ar->ssid_len = 0;
1275
1276 return 0;
1277}
1278
1279static const u32 cipher_suites[] = {
1280 WLAN_CIPHER_SUITE_WEP40,
1281 WLAN_CIPHER_SUITE_WEP104,
1282 WLAN_CIPHER_SUITE_TKIP,
1283 WLAN_CIPHER_SUITE_CCMP,
1284};
1285
1286static bool is_rate_legacy(s32 rate)
1287{
1288 static const s32 legacy[] = { 1000, 2000, 5500, 11000,
1289 6000, 9000, 12000, 18000, 24000,
1290 36000, 48000, 54000
1291 };
1292 u8 i;
1293
1294 for (i = 0; i < ARRAY_SIZE(legacy); i++)
1295 if (rate == legacy[i])
1296 return true;
1297
1298 return false;
1299}
1300
1301static bool is_rate_ht20(s32 rate, u8 *mcs, bool *sgi)
1302{
1303 static const s32 ht20[] = { 6500, 13000, 19500, 26000, 39000,
1304 52000, 58500, 65000, 72200
1305 };
1306 u8 i;
1307
1308 for (i = 0; i < ARRAY_SIZE(ht20); i++) {
1309 if (rate == ht20[i]) {
1310 if (i == ARRAY_SIZE(ht20) - 1)
1311 /* last rate uses sgi */
1312 *sgi = true;
1313 else
1314 *sgi = false;
1315
1316 *mcs = i;
1317 return true;
1318 }
1319 }
1320 return false;
1321}
1322
1323static bool is_rate_ht40(s32 rate, u8 *mcs, bool *sgi)
1324{
1325 static const s32 ht40[] = { 13500, 27000, 40500, 54000,
1326 81000, 108000, 121500, 135000,
1327 150000
1328 };
1329 u8 i;
1330
1331 for (i = 0; i < ARRAY_SIZE(ht40); i++) {
1332 if (rate == ht40[i]) {
1333 if (i == ARRAY_SIZE(ht40) - 1)
1334 /* last rate uses sgi */
1335 *sgi = true;
1336 else
1337 *sgi = false;
1338
1339 *mcs = i;
1340 return true;
1341 }
1342 }
1343
1344 return false;
1345}
1346
1347static int ath6kl_get_station(struct wiphy *wiphy, struct net_device *dev,
1348 u8 *mac, struct station_info *sinfo)
1349{
1350 struct ath6kl *ar = ath6kl_priv(dev);
1351 long left;
1352 bool sgi;
1353 s32 rate;
1354 int ret;
1355 u8 mcs;
1356
1357 if (memcmp(mac, ar->bssid, ETH_ALEN) != 0)
1358 return -ENOENT;
1359
1360 if (down_interruptible(&ar->sem))
1361 return -EBUSY;
1362
1363 set_bit(STATS_UPDATE_PEND, &ar->flag);
1364
1365 ret = ath6kl_wmi_get_stats_cmd(ar->wmi);
1366
1367 if (ret != 0) {
1368 up(&ar->sem);
1369 return -EIO;
1370 }
1371
1372 left = wait_event_interruptible_timeout(ar->event_wq,
1373 !test_bit(STATS_UPDATE_PEND,
1374 &ar->flag),
1375 WMI_TIMEOUT);
1376
1377 up(&ar->sem);
1378
1379 if (left == 0)
1380 return -ETIMEDOUT;
1381 else if (left < 0)
1382 return left;
1383
1384 if (ar->target_stats.rx_byte) {
1385 sinfo->rx_bytes = ar->target_stats.rx_byte;
1386 sinfo->filled |= STATION_INFO_RX_BYTES;
1387 sinfo->rx_packets = ar->target_stats.rx_pkt;
1388 sinfo->filled |= STATION_INFO_RX_PACKETS;
1389 }
1390
1391 if (ar->target_stats.tx_byte) {
1392 sinfo->tx_bytes = ar->target_stats.tx_byte;
1393 sinfo->filled |= STATION_INFO_TX_BYTES;
1394 sinfo->tx_packets = ar->target_stats.tx_pkt;
1395 sinfo->filled |= STATION_INFO_TX_PACKETS;
1396 }
1397
1398 sinfo->signal = ar->target_stats.cs_rssi;
1399 sinfo->filled |= STATION_INFO_SIGNAL;
1400
1401 rate = ar->target_stats.tx_ucast_rate;
1402
1403 if (is_rate_legacy(rate)) {
1404 sinfo->txrate.legacy = rate / 100;
1405 } else if (is_rate_ht20(rate, &mcs, &sgi)) {
1406 if (sgi) {
1407 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1408 sinfo->txrate.mcs = mcs - 1;
1409 } else {
1410 sinfo->txrate.mcs = mcs;
1411 }
1412
1413 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1414 } else if (is_rate_ht40(rate, &mcs, &sgi)) {
1415 if (sgi) {
1416 sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
1417 sinfo->txrate.mcs = mcs - 1;
1418 } else {
1419 sinfo->txrate.mcs = mcs;
1420 }
1421
1422 sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
1423 sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS;
1424 } else {
1425 ath6kl_warn("invalid rate: %d\n", rate);
1426 return 0;
1427 }
1428
1429 sinfo->filled |= STATION_INFO_TX_BITRATE;
1430
1431 return 0;
1432}
1433
1434static int ath6kl_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1435 struct cfg80211_pmksa *pmksa)
1436{
1437 struct ath6kl *ar = ath6kl_priv(netdev);
1438 return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
1439 pmksa->pmkid, true);
1440}
1441
1442static int ath6kl_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
1443 struct cfg80211_pmksa *pmksa)
1444{
1445 struct ath6kl *ar = ath6kl_priv(netdev);
1446 return ath6kl_wmi_setpmkid_cmd(ar->wmi, pmksa->bssid,
1447 pmksa->pmkid, false);
1448}
1449
1450static int ath6kl_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
1451{
1452 struct ath6kl *ar = ath6kl_priv(netdev);
1453 if (test_bit(CONNECTED, &ar->flag))
1454 return ath6kl_wmi_setpmkid_cmd(ar->wmi, ar->bssid, NULL, false);
1455 return 0;
1456}
1457
1458static struct cfg80211_ops ath6kl_cfg80211_ops = {
1459 .change_virtual_intf = ath6kl_cfg80211_change_iface,
1460 .scan = ath6kl_cfg80211_scan,
1461 .connect = ath6kl_cfg80211_connect,
1462 .disconnect = ath6kl_cfg80211_disconnect,
1463 .add_key = ath6kl_cfg80211_add_key,
1464 .get_key = ath6kl_cfg80211_get_key,
1465 .del_key = ath6kl_cfg80211_del_key,
1466 .set_default_key = ath6kl_cfg80211_set_default_key,
1467 .set_wiphy_params = ath6kl_cfg80211_set_wiphy_params,
1468 .set_tx_power = ath6kl_cfg80211_set_txpower,
1469 .get_tx_power = ath6kl_cfg80211_get_txpower,
1470 .set_power_mgmt = ath6kl_cfg80211_set_power_mgmt,
1471 .join_ibss = ath6kl_cfg80211_join_ibss,
1472 .leave_ibss = ath6kl_cfg80211_leave_ibss,
1473 .get_station = ath6kl_get_station,
1474 .set_pmksa = ath6kl_set_pmksa,
1475 .del_pmksa = ath6kl_del_pmksa,
1476 .flush_pmksa = ath6kl_flush_pmksa,
1477};
1478
1479struct wireless_dev *ath6kl_cfg80211_init(struct device *dev)
1480{
1481 int ret = 0;
1482 struct wireless_dev *wdev;
1483
1484 wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
1485 if (!wdev) {
1486 ath6kl_err("couldn't allocate wireless device\n");
1487 return NULL;
1488 }
1489
1490 /* create a new wiphy for use with cfg80211 */
1491 wdev->wiphy = wiphy_new(&ath6kl_cfg80211_ops, sizeof(struct ath6kl));
1492 if (!wdev->wiphy) {
1493 ath6kl_err("couldn't allocate wiphy device\n");
1494 kfree(wdev);
1495 return NULL;
1496 }
1497
1498 /* set device pointer for wiphy */
1499 set_wiphy_dev(wdev->wiphy, dev);
1500
1501 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
1502 BIT(NL80211_IFTYPE_ADHOC);
1503 /* max num of ssids that can be probed during scanning */
1504 wdev->wiphy->max_scan_ssids = MAX_PROBED_SSID_INDEX;
1505 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &ath6kl_band_2ghz;
1506 wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &ath6kl_band_5ghz;
1507 wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
1508
1509 wdev->wiphy->cipher_suites = cipher_suites;
1510 wdev->wiphy->n_cipher_suites = ARRAY_SIZE(cipher_suites);
1511
1512 ret = wiphy_register(wdev->wiphy);
1513 if (ret < 0) {
1514 ath6kl_err("couldn't register wiphy device\n");
1515 wiphy_free(wdev->wiphy);
1516 kfree(wdev);
1517 return NULL;
1518 }
1519
1520 return wdev;
1521}
1522
1523void ath6kl_cfg80211_deinit(struct ath6kl *ar)
1524{
1525 struct wireless_dev *wdev = ar->wdev;
1526
1527 if (ar->scan_req) {
1528 cfg80211_scan_done(ar->scan_req, true);
1529 ar->scan_req = NULL;
1530 }
1531
1532 if (!wdev)
1533 return;
1534
1535 wiphy_unregister(wdev->wiphy);
1536 wiphy_free(wdev->wiphy);
1537 kfree(wdev);
1538}
diff --git a/drivers/net/wireless/ath/ath6kl/cfg80211.h b/drivers/net/wireless/ath/ath6kl/cfg80211.h
new file mode 100644
index 000000000000..a84adc249c61
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/cfg80211.h
@@ -0,0 +1,39 @@
1/*
2 * Copyright (c) 2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef ATH6KL_CFG80211_H
18#define ATH6KL_CFG80211_H
19
20struct wireless_dev *ath6kl_cfg80211_init(struct device *dev);
21void ath6kl_cfg80211_deinit(struct ath6kl *ar);
22
23void ath6kl_cfg80211_scan_complete_event(struct ath6kl *ar, int status);
24
25void ath6kl_cfg80211_connect_event(struct ath6kl *ar, u16 channel,
26 u8 *bssid, u16 listen_intvl,
27 u16 beacon_intvl,
28 enum network_type nw_type,
29 u8 beacon_ie_len, u8 assoc_req_len,
30 u8 assoc_resp_len, u8 *assoc_info);
31
32void ath6kl_cfg80211_disconnect_event(struct ath6kl *ar, u8 reason,
33 u8 *bssid, u8 assoc_resp_len,
34 u8 *assoc_info, u16 proto_reason);
35
36void ath6kl_cfg80211_tkip_micerr_event(struct ath6kl *ar, u8 keyid,
37 bool ismcast);
38
39#endif /* ATH6KL_CFG80211_H */
diff --git a/drivers/net/wireless/ath/ath6kl/common.h b/drivers/net/wireless/ath/ath6kl/common.h
new file mode 100644
index 000000000000..6b0d45642fe3
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/common.h
@@ -0,0 +1,180 @@
1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef COMMON_H
18#define COMMON_H
19
20#include <linux/netdevice.h>
21
22#define ATH6KL_MAX_IE 256
23
24extern int ath6kl_printk(const char *level, const char *fmt, ...);
25
26#define A_CACHE_LINE_PAD 128
27
28/*
29 * Reflects the version of binary interface exposed by ATH6KL target
30 * firmware. Needs to be incremented by 1 for any change in the firmware
31 * that requires upgrade of the driver on the host side for the change to
32 * work correctly
33 */
34#define ATH6KL_ABI_VERSION 1
35
36#define SIGNAL_QUALITY_METRICS_NUM_MAX 2
37
38enum {
39 SIGNAL_QUALITY_METRICS_SNR = 0,
40 SIGNAL_QUALITY_METRICS_RSSI,
41 SIGNAL_QUALITY_METRICS_ALL,
42};
43
44/*
45 * Data Path
46 */
47
48#define WMI_MAX_TX_DATA_FRAME_LENGTH \
49 (1500 + sizeof(struct wmi_data_hdr) + \
50 sizeof(struct ethhdr) + \
51 sizeof(struct ath6kl_llc_snap_hdr))
52
53/* An AMSDU frame */ /* The MAX AMSDU length of AR6003 is 3839 */
54#define WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH \
55 (3840 + sizeof(struct wmi_data_hdr) + \
56 sizeof(struct ethhdr) + \
57 sizeof(struct ath6kl_llc_snap_hdr))
58
59#define EPPING_ALIGNMENT_PAD \
60 (((sizeof(struct htc_frame_hdr) + 3) & (~0x3)) \
61 - sizeof(struct htc_frame_hdr))
62
63struct ath6kl_llc_snap_hdr {
64 u8 dsap;
65 u8 ssap;
66 u8 cntl;
67 u8 org_code[3];
68 __be16 eth_type;
69} __packed;
70
71enum crypto_type {
72 NONE_CRYPT = 0x01,
73 WEP_CRYPT = 0x02,
74 TKIP_CRYPT = 0x04,
75 AES_CRYPT = 0x08,
76};
77
78#define ATH6KL_NODE_HASHSIZE 32
79/* simple hash is enough for variation of macaddr */
80#define ATH6KL_NODE_HASH(addr) \
81 (((const u8 *)(addr))[ETH_ALEN - 1] % \
82 ATH6KL_NODE_HASHSIZE)
83
84/*
85 * Table of ath6kl_node instances. Each ieee80211com
86 * has at least one for holding the scan candidates.
87 * When operating as an access point or in ibss mode there
88 * is a second table for associated stations or neighbors.
89 */
90struct ath6kl_node_table {
91 spinlock_t nt_nodelock; /* on node table */
92 struct bss *nt_node_first; /* information of all nodes */
93 struct bss *nt_node_last; /* information of all nodes */
94 struct bss *nt_hash[ATH6KL_NODE_HASHSIZE];
95 const char *nt_name; /* for debugging */
96 u32 nt_node_age; /* node aging time */
97};
98
99#define WLAN_NODE_INACT_TIMEOUT_MSEC 120000
100#define WLAN_NODE_INACT_CNT 4
101
102struct ath6kl_common_ie {
103 u16 ie_chan;
104 u8 *ie_tstamp;
105 u8 *ie_ssid;
106 u8 *ie_rates;
107 u8 *ie_xrates;
108 u8 *ie_country;
109 u8 *ie_wpa;
110 u8 *ie_rsn;
111 u8 *ie_wmm;
112 u8 *ie_ath;
113 u16 ie_capInfo;
114 u16 ie_beaconInt;
115 u8 *ie_tim;
116 u8 *ie_chswitch;
117 u8 ie_erp;
118 u8 *ie_wsc;
119 u8 *ie_htcap;
120 u8 *ie_htop;
121};
122
123struct bss {
124 u8 ni_macaddr[ETH_ALEN];
125 u8 ni_snr;
126 s16 ni_rssi;
127 struct bss *ni_list_next;
128 struct bss *ni_list_prev;
129 struct bss *ni_hash_next;
130 struct bss *ni_hash_prev;
131 struct ath6kl_common_ie ni_cie;
132 u8 *ni_buf;
133 u16 ni_framelen;
134 struct ath6kl_node_table *ni_table;
135 u32 ni_refcnt;
136
137 u32 ni_tstamp;
138 u32 ni_actcnt;
139};
140
141struct htc_endpoint_credit_dist;
142struct ath6kl;
143enum htc_credit_dist_reason;
144struct htc_credit_state_info;
145
146struct bss *wlan_node_alloc(int wh_size);
147void wlan_node_free(struct bss *ni);
148void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni,
149 const u8 *mac_addr);
150struct bss *wlan_find_node(struct ath6kl_node_table *nt,
151 const u8 *mac_addr);
152void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni);
153void wlan_free_allnodes(struct ath6kl_node_table *nt);
154void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg);
155
156void wlan_node_table_init(struct ath6kl_node_table *nt);
157void wlan_node_table_cleanup(struct ath6kl_node_table *nt);
158
159void wlan_refresh_inactive_nodes(struct ath6kl *ar);
160
161struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 *ssid,
162 u32 ssid_len, bool is_wpa2, bool match_ssid);
163
164void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni);
165
166int ath6k_setup_credit_dist(void *htc_handle,
167 struct htc_credit_state_info *cred_info);
168void ath6k_credit_distribute(struct htc_credit_state_info *cred_inf,
169 struct list_head *epdist_list,
170 enum htc_credit_dist_reason reason);
171void ath6k_credit_init(struct htc_credit_state_info *cred_inf,
172 struct list_head *ep_list,
173 int tot_credits);
174void ath6k_seek_credits(struct htc_credit_state_info *cred_inf,
175 struct htc_endpoint_credit_dist *ep_dist);
176struct ath6kl *ath6kl_core_alloc(struct device *sdev);
177int ath6kl_core_init(struct ath6kl *ar);
178int ath6kl_unavail_ev(struct ath6kl *ar);
179struct sk_buff *ath6kl_buf_alloc(int size);
180#endif /* COMMON_H */
diff --git a/drivers/net/wireless/ath/ath6kl/core.h b/drivers/net/wireless/ath/ath6kl/core.h
new file mode 100644
index 000000000000..74170229523f
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/core.h
@@ -0,0 +1,544 @@
1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef CORE_H
18#define CORE_H
19
20#include <linux/etherdevice.h>
21#include <linux/rtnetlink.h>
22#include <linux/firmware.h>
23#include <linux/sched.h>
24#include <net/cfg80211.h>
25#include "htc.h"
26#include "wmi.h"
27#include "bmi.h"
28
29#define MAX_ATH6KL 1
30#define ATH6KL_MAX_RX_BUFFERS 16
31#define ATH6KL_BUFFER_SIZE 1664
32#define ATH6KL_MAX_AMSDU_RX_BUFFERS 4
33#define ATH6KL_AMSDU_REFILL_THRESHOLD 3
34#define ATH6KL_AMSDU_BUFFER_SIZE (WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH + 128)
35#define MAX_MSDU_SUBFRAME_PAYLOAD_LEN 1508
36#define MIN_MSDU_SUBFRAME_PAYLOAD_LEN 46
37
38#define USER_SAVEDKEYS_STAT_INIT 0
39#define USER_SAVEDKEYS_STAT_RUN 1
40
41#define ATH6KL_TX_TIMEOUT 10
42#define ATH6KL_MAX_ENDPOINTS 4
43#define MAX_NODE_NUM 15
44
45/* MAX_HI_COOKIE_NUM are reserved for high priority traffic */
46#define MAX_DEF_COOKIE_NUM 180
47#define MAX_HI_COOKIE_NUM 18 /* 10% of MAX_COOKIE_NUM */
48#define MAX_COOKIE_NUM (MAX_DEF_COOKIE_NUM + MAX_HI_COOKIE_NUM)
49
50#define MAX_DEFAULT_SEND_QUEUE_DEPTH (MAX_DEF_COOKIE_NUM / WMM_NUM_AC)
51
52#define DISCON_TIMER_INTVAL 10000 /* in msec */
53#define A_DEFAULT_LISTEN_INTERVAL 100
54#define A_MAX_WOW_LISTEN_INTERVAL 1000
55
56/* AR6003 1.0 definitions */
57#define AR6003_REV1_VERSION 0x300002ba
58
59/* AR6003 2.0 definitions */
60#define AR6003_REV2_VERSION 0x30000384
61#define AR6003_REV2_PATCH_DOWNLOAD_ADDRESS 0x57e910
62#define AR6003_REV2_OTP_FILE "ath6k/AR6003/hw2.0/otp.bin.z77"
63#define AR6003_REV2_FIRMWARE_FILE "ath6k/AR6003/hw2.0/athwlan.bin.z77"
64#define AR6003_REV2_PATCH_FILE "ath6k/AR6003/hw2.0/data.patch.bin"
65#define AR6003_REV2_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.bin"
66#define AR6003_REV2_DEFAULT_BOARD_DATA_FILE "ath6k/AR6003/hw2.0/bdata.SD31.bin"
67
68/* AR6003 3.0 definitions */
69#define AR6003_REV3_VERSION 0x30000582
70#define AR6003_REV3_OTP_FILE "ath6k/AR6003/hw2.1.1/otp.bin"
71#define AR6003_REV3_FIRMWARE_FILE "ath6k/AR6003/hw2.1.1/athwlan.bin"
72#define AR6003_REV3_PATCH_FILE "ath6k/AR6003/hw2.1.1/data.patch.bin"
73#define AR6003_REV3_BOARD_DATA_FILE "ath6k/AR6003/hw2.1.1/bdata.bin"
74#define AR6003_REV3_DEFAULT_BOARD_DATA_FILE \
75 "ath6k/AR6003/hw2.1.1/bdata.SD31.bin"
76
77/* Per STA data, used in AP mode */
78#define STA_PS_AWAKE BIT(0)
79#define STA_PS_SLEEP BIT(1)
80#define STA_PS_POLLED BIT(2)
81
82/* HTC TX packet tagging definitions */
83#define ATH6KL_CONTROL_PKT_TAG HTC_TX_PACKET_TAG_USER_DEFINED
84#define ATH6KL_DATA_PKT_TAG (ATH6KL_CONTROL_PKT_TAG + 1)
85
86#define AR6003_CUST_DATA_SIZE 16
87
88#define AGGR_WIN_IDX(x, y) ((x) % (y))
89#define AGGR_INCR_IDX(x, y) AGGR_WIN_IDX(((x) + 1), (y))
90#define AGGR_DCRM_IDX(x, y) AGGR_WIN_IDX(((x) - 1), (y))
91#define ATH6KL_MAX_SEQ_NO 0xFFF
92#define ATH6KL_NEXT_SEQ_NO(x) (((x) + 1) & ATH6KL_MAX_SEQ_NO)
93
94#define NUM_OF_TIDS 8
95#define AGGR_SZ_DEFAULT 8
96
97#define AGGR_WIN_SZ_MIN 2
98#define AGGR_WIN_SZ_MAX 8
99
100#define TID_WINDOW_SZ(_x) ((_x) << 1)
101
102#define AGGR_NUM_OF_FREE_NETBUFS 16
103
104#define AGGR_RX_TIMEOUT 400 /* in ms */
105
106#define WMI_TIMEOUT (2 * HZ)
107
108#define MBOX_YIELD_LIMIT 99
109
110/* configuration lags */
111/*
112 * ATH6KL_CONF_IGNORE_ERP_BARKER: Ignore the barker premable in
113 * ERP IE of beacon to determine the short premable support when
114 * sending (Re)Assoc req.
115 * ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN: Don't send the power
116 * module state transition failure events which happen during
117 * scan, to the host.
118 */
119#define ATH6KL_CONF_IGNORE_ERP_BARKER BIT(0)
120#define ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN BIT(1)
121#define ATH6KL_CONF_ENABLE_11N BIT(2)
122#define ATH6KL_CONF_ENABLE_TX_BURST BIT(3)
123
124enum wlan_low_pwr_state {
125 WLAN_POWER_STATE_ON,
126 WLAN_POWER_STATE_CUT_PWR,
127 WLAN_POWER_STATE_DEEP_SLEEP,
128 WLAN_POWER_STATE_WOW
129};
130
131enum sme_state {
132 SME_DISCONNECTED,
133 SME_CONNECTING,
134 SME_CONNECTED
135};
136
137struct skb_hold_q {
138 struct sk_buff *skb;
139 bool is_amsdu;
140 u16 seq_no;
141};
142
143struct rxtid {
144 bool aggr;
145 bool progress;
146 bool timer_mon;
147 u16 win_sz;
148 u16 seq_next;
149 u32 hold_q_sz;
150 struct skb_hold_q *hold_q;
151 struct sk_buff_head q;
152 spinlock_t lock;
153};
154
155struct rxtid_stats {
156 u32 num_into_aggr;
157 u32 num_dups;
158 u32 num_oow;
159 u32 num_mpdu;
160 u32 num_amsdu;
161 u32 num_delivered;
162 u32 num_timeouts;
163 u32 num_hole;
164 u32 num_bar;
165};
166
167struct aggr_info {
168 u8 aggr_sz;
169 u8 timer_scheduled;
170 struct timer_list timer;
171 struct net_device *dev;
172 struct rxtid rx_tid[NUM_OF_TIDS];
173 struct sk_buff_head free_q;
174 struct rxtid_stats stat[NUM_OF_TIDS];
175};
176
177struct ath6kl_wep_key {
178 u8 key_index;
179 u8 key_len;
180 u8 key[64];
181};
182
183#define ATH6KL_KEY_SEQ_LEN 8
184
185struct ath6kl_key {
186 u8 key[WLAN_MAX_KEY_LEN];
187 u8 key_len;
188 u8 seq[ATH6KL_KEY_SEQ_LEN];
189 u8 seq_len;
190 u32 cipher;
191};
192
193struct ath6kl_node_mapping {
194 u8 mac_addr[ETH_ALEN];
195 u8 ep_id;
196 u8 tx_pend;
197};
198
199struct ath6kl_cookie {
200 struct sk_buff *skb;
201 u32 map_no;
202 struct htc_packet htc_pkt;
203 struct ath6kl_cookie *arc_list_next;
204};
205
206struct ath6kl_sta {
207 u16 sta_flags;
208 u8 mac[ETH_ALEN];
209 u8 aid;
210 u8 keymgmt;
211 u8 ucipher;
212 u8 auth;
213 u8 wpa_ie[ATH6KL_MAX_IE];
214 struct sk_buff_head psq;
215 spinlock_t psq_lock;
216};
217
218struct ath6kl_version {
219 u32 target_ver;
220 u32 wlan_ver;
221 u32 abi_ver;
222};
223
224struct ath6kl_bmi {
225 u32 cmd_credits;
226 bool done_sent;
227 u8 *cmd_buf;
228};
229
230struct target_stats {
231 u64 tx_pkt;
232 u64 tx_byte;
233 u64 tx_ucast_pkt;
234 u64 tx_ucast_byte;
235 u64 tx_mcast_pkt;
236 u64 tx_mcast_byte;
237 u64 tx_bcast_pkt;
238 u64 tx_bcast_byte;
239 u64 tx_rts_success_cnt;
240 u64 tx_pkt_per_ac[4];
241
242 u64 tx_err;
243 u64 tx_fail_cnt;
244 u64 tx_retry_cnt;
245 u64 tx_mult_retry_cnt;
246 u64 tx_rts_fail_cnt;
247
248 u64 rx_pkt;
249 u64 rx_byte;
250 u64 rx_ucast_pkt;
251 u64 rx_ucast_byte;
252 u64 rx_mcast_pkt;
253 u64 rx_mcast_byte;
254 u64 rx_bcast_pkt;
255 u64 rx_bcast_byte;
256 u64 rx_frgment_pkt;
257
258 u64 rx_err;
259 u64 rx_crc_err;
260 u64 rx_key_cache_miss;
261 u64 rx_decrypt_err;
262 u64 rx_dupl_frame;
263
264 u64 tkip_local_mic_fail;
265 u64 tkip_cnter_measures_invoked;
266 u64 tkip_replays;
267 u64 tkip_fmt_err;
268 u64 ccmp_fmt_err;
269 u64 ccmp_replays;
270
271 u64 pwr_save_fail_cnt;
272
273 u64 cs_bmiss_cnt;
274 u64 cs_low_rssi_cnt;
275 u64 cs_connect_cnt;
276 u64 cs_discon_cnt;
277
278 s32 tx_ucast_rate;
279 s32 rx_ucast_rate;
280
281 u32 lq_val;
282
283 u32 wow_pkt_dropped;
284 u16 wow_evt_discarded;
285
286 s16 noise_floor_calib;
287 s16 cs_rssi;
288 s16 cs_ave_beacon_rssi;
289 u8 cs_ave_beacon_snr;
290 u8 cs_last_roam_msec;
291 u8 cs_snr;
292
293 u8 wow_host_pkt_wakeups;
294 u8 wow_host_evt_wakeups;
295
296 u32 arp_received;
297 u32 arp_matched;
298 u32 arp_replied;
299};
300
301struct ath6kl_mbox_info {
302 u32 htc_addr;
303 u32 htc_ext_addr;
304 u32 htc_ext_sz;
305
306 u32 block_size;
307
308 u32 gmbox_addr;
309
310 u32 gmbox_sz;
311};
312
313/*
314 * 802.11i defines an extended IV for use with non-WEP ciphers.
315 * When the EXTIV bit is set in the key id byte an additional
316 * 4 bytes immediately follow the IV for TKIP. For CCMP the
317 * EXTIV bit is likewise set but the 8 bytes represent the
318 * CCMP header rather than IV+extended-IV.
319 */
320
321#define ATH6KL_KEYBUF_SIZE 16
322#define ATH6KL_MICBUF_SIZE (8+8) /* space for both tx and rx */
323
324#define ATH6KL_KEY_XMIT 0x01
325#define ATH6KL_KEY_RECV 0x02
326#define ATH6KL_KEY_DEFAULT 0x80 /* default xmit key */
327
328/*
329 * WPA/RSN get/set key request. Specify the key/cipher
330 * type and whether the key is to be used for sending and/or
331 * receiving. The key index should be set only when working
332 * with global keys (use IEEE80211_KEYIX_NONE for ``no index'').
333 * Otherwise a unicast/pairwise key is specified by the bssid
334 * (on a station) or mac address (on an ap). They key length
335 * must include any MIC key data; otherwise it should be no
336 * more than ATH6KL_KEYBUF_SIZE.
337 */
338struct ath6kl_req_key {
339 u8 ik_type; /* key/cipher type */
340 u8 ik_pad;
341 u16 ik_keyix; /* key index */
342 u8 ik_keylen; /* key length in bytes */
343 u8 ik_flags;
344 u8 ik_macaddr[ETH_ALEN];
345 u64 ik_keyrsc; /* key receive sequence counter */
346 u64 ik_keytsc; /* key transmit sequence counter */
347 u8 ik_keydata[ATH6KL_KEYBUF_SIZE + ATH6KL_MICBUF_SIZE];
348};
349
350/* Flag info */
351#define WMI_ENABLED 0
352#define WMI_READY 1
353#define CONNECTED 2
354#define STATS_UPDATE_PEND 3
355#define CONNECT_PEND 4
356#define WMM_ENABLED 5
357#define NETQ_STOPPED 6
358#define WMI_CTRL_EP_FULL 7
359#define DTIM_EXPIRED 8
360#define DESTROY_IN_PROGRESS 9
361#define NETDEV_REGISTERED 10
362#define SKIP_SCAN 11
363#define WLAN_ENABLED 12
364
365struct ath6kl {
366 struct device *dev;
367 struct net_device *net_dev;
368 struct ath6kl_bmi bmi;
369 const struct ath6kl_hif_ops *hif_ops;
370 struct wmi *wmi;
371 int tx_pending[ENDPOINT_MAX];
372 int total_tx_data_pend;
373 struct htc_target *htc_target;
374 void *hif_priv;
375 spinlock_t lock;
376 struct semaphore sem;
377 int ssid_len;
378 u8 ssid[IEEE80211_MAX_SSID_LEN];
379 u8 next_mode;
380 u8 nw_type;
381 u8 dot11_auth_mode;
382 u8 auth_mode;
383 u8 prwise_crypto;
384 u8 prwise_crypto_len;
385 u8 grp_crypto;
386 u8 grp_crpto_len;
387 u8 def_txkey_index;
388 struct ath6kl_wep_key wep_key_list[WMI_MAX_KEY_INDEX + 1];
389 u8 bssid[ETH_ALEN];
390 u8 req_bssid[ETH_ALEN];
391 u16 ch_hint;
392 u16 bss_ch;
393 u16 listen_intvl_b;
394 u16 listen_intvl_t;
395 struct ath6kl_version version;
396 u32 target_type;
397 u8 tx_pwr;
398 struct net_device_stats net_stats;
399 struct target_stats target_stats;
400 struct ath6kl_node_mapping node_map[MAX_NODE_NUM];
401 u8 ibss_ps_enable;
402 u8 node_num;
403 u8 next_ep_id;
404 struct ath6kl_cookie *cookie_list;
405 u32 cookie_count;
406 enum htc_endpoint_id ac2ep_map[WMM_NUM_AC];
407 bool ac_stream_active[WMM_NUM_AC];
408 u8 ac_stream_pri_map[WMM_NUM_AC];
409 u8 hiac_stream_active_pri;
410 u8 ep2ac_map[ENDPOINT_MAX];
411 enum htc_endpoint_id ctrl_ep;
412 struct htc_credit_state_info credit_state_info;
413 u32 connect_ctrl_flags;
414 u32 user_key_ctrl;
415 u8 usr_bss_filter;
416 struct ath6kl_sta sta_list[AP_MAX_NUM_STA];
417 u8 sta_list_index;
418 struct ath6kl_req_key ap_mode_bkey;
419 struct sk_buff_head mcastpsq;
420 spinlock_t mcastpsq_lock;
421 u8 intra_bss;
422 struct aggr_info *aggr_cntxt;
423 struct wmi_ap_mode_stat ap_stats;
424 u8 ap_country_code[3];
425 struct list_head amsdu_rx_buffer_queue;
426 struct timer_list disconnect_timer;
427 u8 rx_meta_ver;
428 struct wireless_dev *wdev;
429 struct cfg80211_scan_request *scan_req;
430 struct ath6kl_key keys[WMI_MAX_KEY_INDEX + 1];
431 enum sme_state sme_state;
432 enum wlan_low_pwr_state wlan_pwr_state;
433 struct wmi_scan_params_cmd sc_params;
434#define AR_MCAST_FILTER_MAC_ADDR_SIZE 4
435 u8 auto_auth_stage;
436
437 u16 conf_flags;
438 wait_queue_head_t event_wq;
439 struct ath6kl_mbox_info mbox_info;
440
441 struct ath6kl_cookie cookie_mem[MAX_COOKIE_NUM];
442 int reconnect_flag;
443 unsigned long flag;
444
445 u8 *fw_board;
446 size_t fw_board_len;
447
448 u8 *fw_otp;
449 size_t fw_otp_len;
450
451 u8 *fw;
452 size_t fw_len;
453
454 u8 *fw_patch;
455 size_t fw_patch_len;
456
457 struct workqueue_struct *ath6kl_wq;
458
459 struct ath6kl_node_table scan_table;
460};
461
462static inline void *ath6kl_priv(struct net_device *dev)
463{
464 return wdev_priv(dev->ieee80211_ptr);
465}
466
467static inline void ath6kl_deposit_credit_to_ep(struct htc_credit_state_info
468 *cred_info,
469 struct htc_endpoint_credit_dist
470 *ep_dist, int credits)
471{
472 ep_dist->credits += credits;
473 ep_dist->cred_assngd += credits;
474 cred_info->cur_free_credits -= credits;
475}
476
477void ath6kl_destroy(struct net_device *dev, unsigned int unregister);
478int ath6kl_configure_target(struct ath6kl *ar);
479void ath6kl_detect_error(unsigned long ptr);
480void disconnect_timer_handler(unsigned long ptr);
481void init_netdev(struct net_device *dev);
482void ath6kl_cookie_init(struct ath6kl *ar);
483void ath6kl_cookie_cleanup(struct ath6kl *ar);
484void ath6kl_rx(struct htc_target *target, struct htc_packet *packet);
485void ath6kl_tx_complete(void *context, struct list_head *packet_queue);
486enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
487 struct htc_packet *packet);
488void ath6kl_stop_txrx(struct ath6kl *ar);
489void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar);
490int ath6kl_access_datadiag(struct ath6kl *ar, u32 address,
491 u8 *data, u32 length, bool read);
492int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data);
493void ath6kl_init_profile_info(struct ath6kl *ar);
494void ath6kl_tx_data_cleanup(struct ath6kl *ar);
495void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
496 bool get_dbglogs);
497
498struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar);
499void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie);
500int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev);
501
502struct aggr_info *aggr_init(struct net_device *dev);
503void ath6kl_rx_refill(struct htc_target *target,
504 enum htc_endpoint_id endpoint);
505void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count);
506struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
507 enum htc_endpoint_id endpoint,
508 int len);
509void aggr_module_destroy(struct aggr_info *aggr_info);
510void aggr_reset_state(struct aggr_info *aggr_info);
511
512struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 * node_addr);
513struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid);
514
515void ath6kl_ready_event(void *devt, u8 * datap, u32 sw_ver, u32 abi_ver);
516int ath6kl_control_tx(void *devt, struct sk_buff *skb,
517 enum htc_endpoint_id eid);
518void ath6kl_connect_event(struct ath6kl *ar, u16 channel,
519 u8 *bssid, u16 listen_int,
520 u16 beacon_int, enum network_type net_type,
521 u8 beacon_ie_len, u8 assoc_req_len,
522 u8 assoc_resp_len, u8 *assoc_info);
523void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason,
524 u8 *bssid, u8 assoc_resp_len,
525 u8 *assoc_info, u16 prot_reason_status);
526void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast);
527void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr);
528void ath6kl_scan_complete_evt(struct ath6kl *ar, int status);
529void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len);
530void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active);
531enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac);
532
533void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid);
534
535void ath6kl_dtimexpiry_event(struct ath6kl *ar);
536void ath6kl_disconnect(struct ath6kl *ar);
537void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid);
538void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no,
539 u8 win_sz);
540void ath6kl_wakeup_event(void *dev);
541void ath6kl_target_failure(struct ath6kl *ar);
542
543void ath6kl_cfg80211_scan_node(struct wiphy *wiphy, struct bss *ni);
544#endif /* CORE_H */
diff --git a/drivers/net/wireless/ath/ath6kl/debug.c b/drivers/net/wireless/ath/ath6kl/debug.c
new file mode 100644
index 000000000000..316136c8b903
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/debug.c
@@ -0,0 +1,150 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "debug.h"
19
20int ath6kl_printk(const char *level, const char *fmt, ...)
21{
22 struct va_format vaf;
23 va_list args;
24 int rtn;
25
26 va_start(args, fmt);
27
28 vaf.fmt = fmt;
29 vaf.va = &args;
30
31 rtn = printk("%sath6kl: %pV", level, &vaf);
32
33 va_end(args);
34
35 return rtn;
36}
37
38#ifdef CONFIG_ATH6KL_DEBUG
39void ath6kl_dump_registers(struct ath6kl_device *dev,
40 struct ath6kl_irq_proc_registers *irq_proc_reg,
41 struct ath6kl_irq_enable_reg *irq_enable_reg)
42{
43
44 ath6kl_dbg(ATH6KL_DBG_ANY, ("<------- Register Table -------->\n"));
45
46 if (irq_proc_reg != NULL) {
47 ath6kl_dbg(ATH6KL_DBG_ANY,
48 "Host Int status: 0x%x\n",
49 irq_proc_reg->host_int_status);
50 ath6kl_dbg(ATH6KL_DBG_ANY,
51 "CPU Int status: 0x%x\n",
52 irq_proc_reg->cpu_int_status);
53 ath6kl_dbg(ATH6KL_DBG_ANY,
54 "Error Int status: 0x%x\n",
55 irq_proc_reg->error_int_status);
56 ath6kl_dbg(ATH6KL_DBG_ANY,
57 "Counter Int status: 0x%x\n",
58 irq_proc_reg->counter_int_status);
59 ath6kl_dbg(ATH6KL_DBG_ANY,
60 "Mbox Frame: 0x%x\n",
61 irq_proc_reg->mbox_frame);
62 ath6kl_dbg(ATH6KL_DBG_ANY,
63 "Rx Lookahead Valid: 0x%x\n",
64 irq_proc_reg->rx_lkahd_valid);
65 ath6kl_dbg(ATH6KL_DBG_ANY,
66 "Rx Lookahead 0: 0x%x\n",
67 irq_proc_reg->rx_lkahd[0]);
68 ath6kl_dbg(ATH6KL_DBG_ANY,
69 "Rx Lookahead 1: 0x%x\n",
70 irq_proc_reg->rx_lkahd[1]);
71
72 if (dev->ar->mbox_info.gmbox_addr != 0) {
73 /*
74 * If the target supports GMBOX hardware, dump some
75 * additional state.
76 */
77 ath6kl_dbg(ATH6KL_DBG_ANY,
78 "GMBOX Host Int status 2: 0x%x\n",
79 irq_proc_reg->host_int_status2);
80 ath6kl_dbg(ATH6KL_DBG_ANY,
81 "GMBOX RX Avail: 0x%x\n",
82 irq_proc_reg->gmbox_rx_avail);
83 ath6kl_dbg(ATH6KL_DBG_ANY,
84 "GMBOX lookahead alias 0: 0x%x\n",
85 irq_proc_reg->rx_gmbox_lkahd_alias[0]);
86 ath6kl_dbg(ATH6KL_DBG_ANY,
87 "GMBOX lookahead alias 1: 0x%x\n",
88 irq_proc_reg->rx_gmbox_lkahd_alias[1]);
89 }
90
91 }
92
93 if (irq_enable_reg != NULL) {
94 ath6kl_dbg(ATH6KL_DBG_ANY,
95 "Int status Enable: 0x%x\n",
96 irq_enable_reg->int_status_en);
97 ath6kl_dbg(ATH6KL_DBG_ANY, "Counter Int status Enable: 0x%x\n",
98 irq_enable_reg->cntr_int_status_en);
99 }
100 ath6kl_dbg(ATH6KL_DBG_ANY, "<------------------------------->\n");
101}
102
103static void dump_cred_dist(struct htc_endpoint_credit_dist *ep_dist)
104{
105 ath6kl_dbg(ATH6KL_DBG_ANY,
106 "--- endpoint: %d svc_id: 0x%X ---\n",
107 ep_dist->endpoint, ep_dist->svc_id);
108 ath6kl_dbg(ATH6KL_DBG_ANY, " dist_flags : 0x%X\n",
109 ep_dist->dist_flags);
110 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_norm : %d\n",
111 ep_dist->cred_norm);
112 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_min : %d\n",
113 ep_dist->cred_min);
114 ath6kl_dbg(ATH6KL_DBG_ANY, " credits : %d\n",
115 ep_dist->credits);
116 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_assngd : %d\n",
117 ep_dist->cred_assngd);
118 ath6kl_dbg(ATH6KL_DBG_ANY, " seek_cred : %d\n",
119 ep_dist->seek_cred);
120 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_sz : %d\n",
121 ep_dist->cred_sz);
122 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_per_msg : %d\n",
123 ep_dist->cred_per_msg);
124 ath6kl_dbg(ATH6KL_DBG_ANY, " cred_to_dist : %d\n",
125 ep_dist->cred_to_dist);
126 ath6kl_dbg(ATH6KL_DBG_ANY, " txq_depth : %d\n",
127 get_queue_depth(&((struct htc_endpoint *)
128 ep_dist->htc_rsvd)->txq));
129 ath6kl_dbg(ATH6KL_DBG_ANY,
130 "----------------------------------\n");
131}
132
133void dump_cred_dist_stats(struct htc_target *target)
134{
135 struct htc_endpoint_credit_dist *ep_list;
136
137 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_TRC))
138 return;
139
140 list_for_each_entry(ep_list, &target->cred_dist_list, list)
141 dump_cred_dist(ep_list);
142
143 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:%p dist:%p\n",
144 target->cred_dist_cntxt, NULL);
145 ath6kl_dbg(ATH6KL_DBG_TRC, "credit distribution, total : %d, free : %d\n",
146 target->cred_dist_cntxt->total_avail_credits,
147 target->cred_dist_cntxt->cur_free_credits);
148}
149
150#endif
diff --git a/drivers/net/wireless/ath/ath6kl/debug.h b/drivers/net/wireless/ath/ath6kl/debug.h
new file mode 100644
index 000000000000..66b399962f01
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/debug.h
@@ -0,0 +1,105 @@
1/*
2 * Copyright (c) 2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef DEBUG_H
18#define DEBUG_H
19
20#include "htc_hif.h"
21
22enum ATH6K_DEBUG_MASK {
23 ATH6KL_DBG_WLAN_CONNECT = BIT(0), /* wlan connect */
24 ATH6KL_DBG_WLAN_SCAN = BIT(1), /* wlan scan */
25 ATH6KL_DBG_WLAN_TX = BIT(2), /* wlan tx */
26 ATH6KL_DBG_WLAN_RX = BIT(3), /* wlan rx */
27 ATH6KL_DBG_BMI = BIT(4), /* bmi tracing */
28 ATH6KL_DBG_HTC_SEND = BIT(5), /* htc send */
29 ATH6KL_DBG_HTC_RECV = BIT(6), /* htc recv */
30 ATH6KL_DBG_IRQ = BIT(7), /* interrupt processing */
31 ATH6KL_DBG_PM = BIT(8), /* power management */
32 ATH6KL_DBG_WLAN_NODE = BIT(9), /* general wlan node tracing */
33 ATH6KL_DBG_WMI = BIT(10), /* wmi tracing */
34 ATH6KL_DBG_TRC = BIT(11), /* generic func tracing */
35 ATH6KL_DBG_SCATTER = BIT(12), /* hif scatter tracing */
36 ATH6KL_DBG_WLAN_CFG = BIT(13), /* cfg80211 i/f file tracing */
37 ATH6KL_DBG_RAW_BYTES = BIT(14), /* dump tx/rx and wmi frames */
38 ATH6KL_DBG_AGGR = BIT(15), /* aggregation */
39 ATH6KL_DBG_ANY = 0xffffffff /* enable all logs */
40};
41
42extern unsigned int debug_mask;
43extern int ath6kl_printk(const char *level, const char *fmt, ...)
44 __attribute__ ((format (printf, 2, 3)));
45
46#define ath6kl_info(fmt, ...) \
47 ath6kl_printk(KERN_INFO, fmt, ##__VA_ARGS__)
48#define ath6kl_err(fmt, ...) \
49 ath6kl_printk(KERN_ERR, fmt, ##__VA_ARGS__)
50#define ath6kl_warn(fmt, ...) \
51 ath6kl_printk(KERN_WARNING, fmt, ##__VA_ARGS__)
52
53#define AR_DBG_LVL_CHECK(mask) (debug_mask & mask)
54
55#ifdef CONFIG_ATH6KL_DEBUG
56#define ath6kl_dbg(mask, fmt, ...) \
57 ({ \
58 int rtn; \
59 if (debug_mask & mask) \
60 rtn = ath6kl_printk(KERN_DEBUG, fmt, ##__VA_ARGS__); \
61 else \
62 rtn = 0; \
63 \
64 rtn; \
65 })
66
67static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
68 const char *msg, const void *buf,
69 size_t len)
70{
71 if (debug_mask & mask) {
72 ath6kl_dbg(mask, "%s\n", msg);
73 print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, buf, len);
74 }
75}
76
77void ath6kl_dump_registers(struct ath6kl_device *dev,
78 struct ath6kl_irq_proc_registers *irq_proc_reg,
79 struct ath6kl_irq_enable_reg *irq_en_reg);
80void dump_cred_dist_stats(struct htc_target *target);
81#else
82static inline int ath6kl_dbg(enum ATH6K_DEBUG_MASK dbg_mask,
83 const char *fmt, ...)
84{
85 return 0;
86}
87
88static inline void ath6kl_dbg_dump(enum ATH6K_DEBUG_MASK mask,
89 const char *msg, const void *buf,
90 size_t len)
91{
92}
93
94static inline void ath6kl_dump_registers(struct ath6kl_device *dev,
95 struct ath6kl_irq_proc_registers *irq_proc_reg,
96 struct ath6kl_irq_enable_reg *irq_en_reg)
97{
98
99}
100static inline void dump_cred_dist_stats(struct htc_target *target)
101{
102}
103#endif
104
105#endif
diff --git a/drivers/net/wireless/ath/ath6kl/hif-ops.h b/drivers/net/wireless/ath/ath6kl/hif-ops.h
new file mode 100644
index 000000000000..c923979776a0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/hif-ops.h
@@ -0,0 +1,72 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef HIF_OPS_H
18#define HIF_OPS_H
19
20#include "hif.h"
21
22static inline int hif_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
23 u32 len, u32 request)
24{
25 return ar->hif_ops->read_write_sync(ar, addr, buf, len, request);
26}
27
28static inline int hif_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
29 u32 length, u32 request,
30 struct htc_packet *packet)
31{
32 return ar->hif_ops->write_async(ar, address, buffer, length,
33 request, packet);
34}
35static inline void ath6kl_hif_irq_enable(struct ath6kl *ar)
36{
37 return ar->hif_ops->irq_enable(ar);
38}
39
40static inline void ath6kl_hif_irq_disable(struct ath6kl *ar)
41{
42 return ar->hif_ops->irq_disable(ar);
43}
44
45static inline struct hif_scatter_req *hif_scatter_req_get(struct ath6kl *ar)
46{
47 return ar->hif_ops->scatter_req_get(ar);
48}
49
50static inline void hif_scatter_req_add(struct ath6kl *ar,
51 struct hif_scatter_req *s_req)
52{
53 return ar->hif_ops->scatter_req_add(ar, s_req);
54}
55
56static inline int ath6kl_hif_enable_scatter(struct ath6kl *ar)
57{
58 return ar->hif_ops->enable_scatter(ar);
59}
60
61static inline int ath6kl_hif_scat_req_rw(struct ath6kl *ar,
62 struct hif_scatter_req *scat_req)
63{
64 return ar->hif_ops->scat_req_rw(ar, scat_req);
65}
66
67static inline void ath6kl_hif_cleanup_scatter(struct ath6kl *ar)
68{
69 return ar->hif_ops->cleanup_scatter(ar);
70}
71
72#endif
diff --git a/drivers/net/wireless/ath/ath6kl/hif.h b/drivers/net/wireless/ath/ath6kl/hif.h
new file mode 100644
index 000000000000..5ceff54775a1
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/hif.h
@@ -0,0 +1,207 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef HIF_H
18#define HIF_H
19
20#include "common.h"
21#include "core.h"
22
23#include <linux/scatterlist.h>
24
25#define BUS_REQUEST_MAX_NUM 64
26#define HIF_MBOX_BLOCK_SIZE 128
27#define HIF_MBOX0_BLOCK_SIZE 1
28
29#define HIF_DMA_BUFFER_SIZE (32 * 1024)
30#define CMD53_FIXED_ADDRESS 1
31#define CMD53_INCR_ADDRESS 2
32
33#define MAX_SCATTER_REQUESTS 4
34#define MAX_SCATTER_ENTRIES_PER_REQ 16
35#define MAX_SCATTER_REQ_TRANSFER_SIZE (32 * 1024)
36
37#define MANUFACTURER_ID_AR6003_BASE 0x300
38 /* SDIO manufacturer ID and Codes */
39#define MANUFACTURER_ID_ATH6KL_BASE_MASK 0xFF00
40#define MANUFACTURER_CODE 0x271 /* Atheros */
41
42/* Mailbox address in SDIO address space */
43#define HIF_MBOX_BASE_ADDR 0x800
44#define HIF_MBOX_WIDTH 0x800
45
46#define HIF_MBOX_END_ADDR (HTC_MAILBOX_NUM_MAX * HIF_MBOX_WIDTH - 1)
47
48/* version 1 of the chip has only a 12K extended mbox range */
49#define HIF_MBOX0_EXT_BASE_ADDR 0x4000
50#define HIF_MBOX0_EXT_WIDTH (12*1024)
51
52/* GMBOX addresses */
53#define HIF_GMBOX_BASE_ADDR 0x7000
54#define HIF_GMBOX_WIDTH 0x4000
55
56/* interrupt mode register */
57#define CCCR_SDIO_IRQ_MODE_REG 0xF0
58
59/* mode to enable special 4-bit interrupt assertion without clock */
60#define SDIO_IRQ_MODE_ASYNC_4BIT_IRQ (1 << 0)
61
62struct bus_request {
63 struct list_head list;
64
65 /* request data */
66 u32 address;
67
68 u8 *buffer;
69 u32 length;
70 u32 request;
71 struct htc_packet *packet;
72 int status;
73
74 /* this is a scatter request */
75 struct hif_scatter_req *scat_req;
76};
77
78/* direction of transfer (read/write) */
79#define HIF_READ 0x00000001
80#define HIF_WRITE 0x00000002
81#define HIF_DIR_MASK (HIF_READ | HIF_WRITE)
82
83/*
84 * emode - This indicates the whether the command is to be executed in a
85 * blocking or non-blocking fashion (HIF_SYNCHRONOUS/
86 * HIF_ASYNCHRONOUS). The read/write data paths in HTC have been
87 * implemented using the asynchronous mode allowing the the bus
88 * driver to indicate the completion of operation through the
89 * registered callback routine. The requirement primarily comes
90 * from the contexts these operations get called from (a driver's
91 * transmit context or the ISR context in case of receive).
92 * Support for both of these modes is essential.
93 */
94#define HIF_SYNCHRONOUS 0x00000010
95#define HIF_ASYNCHRONOUS 0x00000020
96#define HIF_EMODE_MASK (HIF_SYNCHRONOUS | HIF_ASYNCHRONOUS)
97
98/*
99 * dmode - An interface may support different kinds of commands based on
100 * the tradeoff between the amount of data it can carry and the
101 * setup time. Byte and Block modes are supported (HIF_BYTE_BASIS/
102 * HIF_BLOCK_BASIS). In case of latter, the data is rounded off
103 * to the nearest block size by padding. The size of the block is
104 * configurable at compile time using the HIF_BLOCK_SIZE and is
105 * negotiated with the target during initialization after the
106 * ATH6KL interrupts are enabled.
107 */
108#define HIF_BYTE_BASIS 0x00000040
109#define HIF_BLOCK_BASIS 0x00000080
110#define HIF_DMODE_MASK (HIF_BYTE_BASIS | HIF_BLOCK_BASIS)
111
112/*
113 * amode - This indicates if the address has to be incremented on ATH6KL
114 * after every read/write operation (HIF?FIXED_ADDRESS/
115 * HIF_INCREMENTAL_ADDRESS).
116 */
117#define HIF_FIXED_ADDRESS 0x00000100
118#define HIF_INCREMENTAL_ADDRESS 0x00000200
119#define HIF_AMODE_MASK (HIF_FIXED_ADDRESS | HIF_INCREMENTAL_ADDRESS)
120
121#define HIF_WR_ASYNC_BYTE_INC \
122 (HIF_WRITE | HIF_ASYNCHRONOUS | \
123 HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
124
125#define HIF_WR_ASYNC_BLOCK_INC \
126 (HIF_WRITE | HIF_ASYNCHRONOUS | \
127 HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
128
129#define HIF_WR_SYNC_BYTE_FIX \
130 (HIF_WRITE | HIF_SYNCHRONOUS | \
131 HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
132
133#define HIF_WR_SYNC_BYTE_INC \
134 (HIF_WRITE | HIF_SYNCHRONOUS | \
135 HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
136
137#define HIF_WR_SYNC_BLOCK_INC \
138 (HIF_WRITE | HIF_SYNCHRONOUS | \
139 HIF_BLOCK_BASIS | HIF_INCREMENTAL_ADDRESS)
140
141#define HIF_RD_SYNC_BYTE_INC \
142 (HIF_READ | HIF_SYNCHRONOUS | \
143 HIF_BYTE_BASIS | HIF_INCREMENTAL_ADDRESS)
144
145#define HIF_RD_SYNC_BYTE_FIX \
146 (HIF_READ | HIF_SYNCHRONOUS | \
147 HIF_BYTE_BASIS | HIF_FIXED_ADDRESS)
148
149#define HIF_RD_ASYNC_BLOCK_FIX \
150 (HIF_READ | HIF_ASYNCHRONOUS | \
151 HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
152
153#define HIF_RD_SYNC_BLOCK_FIX \
154 (HIF_READ | HIF_SYNCHRONOUS | \
155 HIF_BLOCK_BASIS | HIF_FIXED_ADDRESS)
156
157struct hif_scatter_item {
158 u8 *buf;
159 int len;
160 struct htc_packet *packet;
161};
162
163struct hif_scatter_req {
164 struct list_head list;
165 /* address for the read/write operation */
166 u32 addr;
167
168 /* request flags */
169 u32 req;
170
171 /* total length of entire transfer */
172 u32 len;
173
174 bool virt_scat;
175
176 void (*complete) (struct htc_target *, struct hif_scatter_req *);
177 int status;
178 int scat_entries;
179
180 struct bus_request *busrequest;
181 struct scatterlist *sgentries;
182
183 /* bounce buffer for upper layers to copy to/from */
184 u8 *virt_dma_buf;
185
186 struct hif_scatter_item scat_list[1];
187};
188
189struct ath6kl_hif_ops {
190 int (*read_write_sync)(struct ath6kl *ar, u32 addr, u8 *buf,
191 u32 len, u32 request);
192 int (*write_async)(struct ath6kl *ar, u32 address, u8 *buffer,
193 u32 length, u32 request, struct htc_packet *packet);
194
195 void (*irq_enable)(struct ath6kl *ar);
196 void (*irq_disable)(struct ath6kl *ar);
197
198 struct hif_scatter_req *(*scatter_req_get)(struct ath6kl *ar);
199 void (*scatter_req_add)(struct ath6kl *ar,
200 struct hif_scatter_req *s_req);
201 int (*enable_scatter)(struct ath6kl *ar);
202 int (*scat_req_rw) (struct ath6kl *ar,
203 struct hif_scatter_req *scat_req);
204 void (*cleanup_scatter)(struct ath6kl *ar);
205};
206
207#endif
diff --git a/drivers/net/wireless/ath/ath6kl/htc.c b/drivers/net/wireless/ath/ath6kl/htc.c
new file mode 100644
index 000000000000..a8dc5c3ea567
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc.c
@@ -0,0 +1,2457 @@
1/*
2 * Copyright (c) 2007-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "htc_hif.h"
19#include "debug.h"
20#include "hif-ops.h"
21#include <asm/unaligned.h>
22
23#define CALC_TXRX_PADDED_LEN(dev, len) (__ALIGN_MASK((len), (dev)->block_mask))
24
25static void htc_prep_send_pkt(struct htc_packet *packet, u8 flags, int ctrl0,
26 int ctrl1)
27{
28 struct htc_frame_hdr *hdr;
29
30 packet->buf -= HTC_HDR_LENGTH;
31 hdr = (struct htc_frame_hdr *)packet->buf;
32
33 /* Endianess? */
34 put_unaligned((u16)packet->act_len, &hdr->payld_len);
35 hdr->flags = flags;
36 hdr->eid = packet->endpoint;
37 hdr->ctrl[0] = ctrl0;
38 hdr->ctrl[1] = ctrl1;
39}
40
41static void htc_reclaim_txctrl_buf(struct htc_target *target,
42 struct htc_packet *pkt)
43{
44 spin_lock_bh(&target->htc_lock);
45 list_add_tail(&pkt->list, &target->free_ctrl_txbuf);
46 spin_unlock_bh(&target->htc_lock);
47}
48
49static struct htc_packet *htc_get_control_buf(struct htc_target *target,
50 bool tx)
51{
52 struct htc_packet *packet = NULL;
53 struct list_head *buf_list;
54
55 buf_list = tx ? &target->free_ctrl_txbuf : &target->free_ctrl_rxbuf;
56
57 spin_lock_bh(&target->htc_lock);
58
59 if (list_empty(buf_list)) {
60 spin_unlock_bh(&target->htc_lock);
61 return NULL;
62 }
63
64 packet = list_first_entry(buf_list, struct htc_packet, list);
65 list_del(&packet->list);
66 spin_unlock_bh(&target->htc_lock);
67
68 if (tx)
69 packet->buf = packet->buf_start + HTC_HDR_LENGTH;
70
71 return packet;
72}
73
74static void htc_tx_comp_update(struct htc_target *target,
75 struct htc_endpoint *endpoint,
76 struct htc_packet *packet)
77{
78 packet->completion = NULL;
79 packet->buf += HTC_HDR_LENGTH;
80
81 if (!packet->status)
82 return;
83
84 ath6kl_err("req failed (status:%d, ep:%d, len:%d creds:%d)\n",
85 packet->status, packet->endpoint, packet->act_len,
86 packet->info.tx.cred_used);
87
88 /* on failure to submit, reclaim credits for this packet */
89 spin_lock_bh(&target->tx_lock);
90 endpoint->cred_dist.cred_to_dist +=
91 packet->info.tx.cred_used;
92 endpoint->cred_dist.txq_depth = get_queue_depth(&endpoint->txq);
93
94 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
95 target->cred_dist_cntxt, &target->cred_dist_list);
96
97 ath6k_credit_distribute(target->cred_dist_cntxt,
98 &target->cred_dist_list,
99 HTC_CREDIT_DIST_SEND_COMPLETE);
100
101 spin_unlock_bh(&target->tx_lock);
102}
103
104static void htc_tx_complete(struct htc_endpoint *endpoint,
105 struct list_head *txq)
106{
107 if (list_empty(txq))
108 return;
109
110 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
111 "send complete ep %d, (%d pkts)\n",
112 endpoint->eid, get_queue_depth(txq));
113
114 ath6kl_tx_complete(endpoint->target->dev->ar, txq);
115}
116
117static void htc_tx_comp_handler(struct htc_target *target,
118 struct htc_packet *packet)
119{
120 struct htc_endpoint *endpoint = &target->endpoint[packet->endpoint];
121 struct list_head container;
122
123 htc_tx_comp_update(target, endpoint, packet);
124 INIT_LIST_HEAD(&container);
125 list_add_tail(&packet->list, &container);
126 /* do completion */
127 htc_tx_complete(endpoint, &container);
128}
129
130static void htc_async_tx_scat_complete(struct htc_target *target,
131 struct hif_scatter_req *scat_req)
132{
133 struct htc_endpoint *endpoint;
134 struct htc_packet *packet;
135 struct list_head tx_compq;
136 int i;
137
138 INIT_LIST_HEAD(&tx_compq);
139
140 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
141 "htc_async_tx_scat_complete total len: %d entries: %d\n",
142 scat_req->len, scat_req->scat_entries);
143
144 if (scat_req->status)
145 ath6kl_err("send scatter req failed: %d\n", scat_req->status);
146
147 packet = scat_req->scat_list[0].packet;
148 endpoint = &target->endpoint[packet->endpoint];
149
150 /* walk through the scatter list and process */
151 for (i = 0; i < scat_req->scat_entries; i++) {
152 packet = scat_req->scat_list[i].packet;
153 if (!packet) {
154 WARN_ON(1);
155 return;
156 }
157
158 packet->status = scat_req->status;
159 htc_tx_comp_update(target, endpoint, packet);
160 list_add_tail(&packet->list, &tx_compq);
161 }
162
163 /* free scatter request */
164 hif_scatter_req_add(target->dev->ar, scat_req);
165
166 /* complete all packets */
167 htc_tx_complete(endpoint, &tx_compq);
168}
169
170static int htc_issue_send(struct htc_target *target, struct htc_packet *packet)
171{
172 int status;
173 bool sync = false;
174 u32 padded_len, send_len;
175
176 if (!packet->completion)
177 sync = true;
178
179 send_len = packet->act_len + HTC_HDR_LENGTH;
180
181 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "%s: transmit len : %d (%s)\n",
182 __func__, send_len, sync ? "sync" : "async");
183
184 padded_len = CALC_TXRX_PADDED_LEN(target, send_len);
185
186 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
187 "DevSendPacket, padded len: %d mbox:0x%X (mode:%s)\n",
188 padded_len,
189 target->dev->ar->mbox_info.htc_addr,
190 sync ? "sync" : "async");
191
192 if (sync) {
193 status = hif_read_write_sync(target->dev->ar,
194 target->dev->ar->mbox_info.htc_addr,
195 packet->buf, padded_len,
196 HIF_WR_SYNC_BLOCK_INC);
197
198 packet->status = status;
199 packet->buf += HTC_HDR_LENGTH;
200 } else
201 status = hif_write_async(target->dev->ar,
202 target->dev->ar->mbox_info.htc_addr,
203 packet->buf, padded_len,
204 HIF_WR_ASYNC_BLOCK_INC, packet);
205
206 return status;
207}
208
209static int htc_check_credits(struct htc_target *target,
210 struct htc_endpoint *ep, u8 *flags,
211 enum htc_endpoint_id eid, unsigned int len,
212 int *req_cred)
213{
214
215 *req_cred = (len > target->tgt_cred_sz) ?
216 DIV_ROUND_UP(len, target->tgt_cred_sz) : 1;
217
218 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "creds required:%d got:%d\n",
219 *req_cred, ep->cred_dist.credits);
220
221 if (ep->cred_dist.credits < *req_cred) {
222 if (eid == ENDPOINT_0)
223 return -EINVAL;
224
225 /* Seek more credits */
226 ep->cred_dist.seek_cred = *req_cred - ep->cred_dist.credits;
227
228 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
229 target->cred_dist_cntxt, &ep->cred_dist);
230
231 ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist);
232
233 ep->cred_dist.seek_cred = 0;
234
235 if (ep->cred_dist.credits < *req_cred) {
236 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
237 "not enough credits for ep %d - leaving packet in queue\n",
238 eid);
239 return -EINVAL;
240 }
241 }
242
243 ep->cred_dist.credits -= *req_cred;
244 ep->ep_st.cred_cosumd += *req_cred;
245
246 /* When we are getting low on credits, ask for more */
247 if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) {
248 ep->cred_dist.seek_cred =
249 ep->cred_dist.cred_per_msg - ep->cred_dist.credits;
250
251 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
252 target->cred_dist_cntxt, &ep->cred_dist);
253
254 ath6k_seek_credits(target->cred_dist_cntxt, &ep->cred_dist);
255
256 /* see if we were successful in getting more */
257 if (ep->cred_dist.credits < ep->cred_dist.cred_per_msg) {
258 /* tell the target we need credits ASAP! */
259 *flags |= HTC_FLAGS_NEED_CREDIT_UPDATE;
260 ep->ep_st.cred_low_indicate += 1;
261 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "host needs credits\n");
262 }
263 }
264
265 return 0;
266}
267
268static void htc_tx_pkts_get(struct htc_target *target,
269 struct htc_endpoint *endpoint,
270 struct list_head *queue)
271{
272 int req_cred;
273 u8 flags;
274 struct htc_packet *packet;
275 unsigned int len;
276
277 while (true) {
278
279 flags = 0;
280
281 if (list_empty(&endpoint->txq))
282 break;
283 packet = list_first_entry(&endpoint->txq, struct htc_packet,
284 list);
285
286 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
287 "got head pkt:0x%p , queue depth: %d\n",
288 packet, get_queue_depth(&endpoint->txq));
289
290 len = CALC_TXRX_PADDED_LEN(target,
291 packet->act_len + HTC_HDR_LENGTH);
292
293 if (htc_check_credits(target, endpoint, &flags,
294 packet->endpoint, len, &req_cred))
295 break;
296
297 /* now we can fully move onto caller's queue */
298 packet = list_first_entry(&endpoint->txq, struct htc_packet,
299 list);
300 list_move_tail(&packet->list, queue);
301
302 /* save the number of credits this packet consumed */
303 packet->info.tx.cred_used = req_cred;
304
305 /* all TX packets are handled asynchronously */
306 packet->completion = htc_tx_comp_handler;
307 packet->context = target;
308 endpoint->ep_st.tx_issued += 1;
309
310 /* save send flags */
311 packet->info.tx.flags = flags;
312 packet->info.tx.seqno = endpoint->seqno;
313 endpoint->seqno++;
314 }
315}
316
317/* See if the padded tx length falls on a credit boundary */
318static int htc_get_credit_padding(unsigned int cred_sz, int *len,
319 struct htc_endpoint *ep)
320{
321 int rem_cred, cred_pad;
322
323 rem_cred = *len % cred_sz;
324
325 /* No padding needed */
326 if (!rem_cred)
327 return 0;
328
329 if (!(ep->conn_flags & HTC_FLGS_TX_BNDL_PAD_EN))
330 return -1;
331
332 /*
333 * The transfer consumes a "partial" credit, this
334 * packet cannot be bundled unless we add
335 * additional "dummy" padding (max 255 bytes) to
336 * consume the entire credit.
337 */
338 cred_pad = *len < cred_sz ? (cred_sz - *len) : rem_cred;
339
340 if ((cred_pad > 0) && (cred_pad <= 255))
341 *len += cred_pad;
342 else
343 /* The amount of padding is too large, send as non-bundled */
344 return -1;
345
346 return cred_pad;
347}
348
349static int htc_setup_send_scat_list(struct htc_target *target,
350 struct htc_endpoint *endpoint,
351 struct hif_scatter_req *scat_req,
352 int n_scat,
353 struct list_head *queue)
354{
355 struct htc_packet *packet;
356 int i, len, rem_scat, cred_pad;
357 int status = 0;
358
359 rem_scat = target->max_tx_bndl_sz;
360
361 for (i = 0; i < n_scat; i++) {
362 scat_req->scat_list[i].packet = NULL;
363
364 if (list_empty(queue))
365 break;
366
367 packet = list_first_entry(queue, struct htc_packet, list);
368 len = CALC_TXRX_PADDED_LEN(target,
369 packet->act_len + HTC_HDR_LENGTH);
370
371 cred_pad = htc_get_credit_padding(target->tgt_cred_sz,
372 &len, endpoint);
373 if (cred_pad < 0) {
374 status = -EINVAL;
375 break;
376 }
377
378 if (rem_scat < len) {
379 /* exceeds what we can transfer */
380 status = -ENOSPC;
381 break;
382 }
383
384 rem_scat -= len;
385 /* now remove it from the queue */
386 packet = list_first_entry(queue, struct htc_packet, list);
387 list_del(&packet->list);
388
389 scat_req->scat_list[i].packet = packet;
390 /* prepare packet and flag message as part of a send bundle */
391 htc_prep_send_pkt(packet,
392 packet->info.tx.flags | HTC_FLAGS_SEND_BUNDLE,
393 cred_pad, packet->info.tx.seqno);
394 scat_req->scat_list[i].buf = packet->buf;
395 scat_req->scat_list[i].len = len;
396
397 scat_req->len += len;
398 scat_req->scat_entries++;
399 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
400 "%d, adding pkt : 0x%p len:%d (remaining space:%d)\n",
401 i, packet, len, rem_scat);
402 }
403
404 /* Roll back scatter setup in case of any failure */
405 if (status || (scat_req->scat_entries < HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
406 for (i = scat_req->scat_entries - 1; i >= 0; i--) {
407 packet = scat_req->scat_list[i].packet;
408 if (packet) {
409 packet->buf += HTC_HDR_LENGTH;
410 list_add(&packet->list, queue);
411 }
412 }
413 return -EINVAL;
414 }
415
416 return 0;
417}
418
419/*
420 * htc_issue_send_bundle: drain a queue and send as bundles
421 * this function may return without fully draining the queue
422 * when
423 *
424 * 1. scatter resources are exhausted
425 * 2. a message that will consume a partial credit will stop the
426 * bundling process early
427 * 3. we drop below the minimum number of messages for a bundle
428 */
429static void htc_issue_send_bundle(struct htc_endpoint *endpoint,
430 struct list_head *queue,
431 int *sent_bundle, int *n_bundle_pkts)
432{
433 struct htc_target *target = endpoint->target;
434 struct hif_scatter_req *scat_req = NULL;
435 int n_scat, n_sent_bundle = 0, tot_pkts_bundle = 0;
436
437 while (true) {
438 n_scat = get_queue_depth(queue);
439 n_scat = min(n_scat, target->msg_per_bndl_max);
440
441 if (n_scat < HTC_MIN_HTC_MSGS_TO_BUNDLE)
442 /* not enough to bundle */
443 break;
444
445 scat_req = hif_scatter_req_get(target->dev->ar);
446
447 if (!scat_req) {
448 /* no scatter resources */
449 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
450 "no more scatter resources\n");
451 break;
452 }
453
454 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "pkts to scatter: %d\n",
455 n_scat);
456
457 scat_req->len = 0;
458 scat_req->scat_entries = 0;
459
460 if (htc_setup_send_scat_list(target, endpoint, scat_req,
461 n_scat, queue)) {
462 hif_scatter_req_add(target->dev->ar, scat_req);
463 break;
464 }
465
466 /* send path is always asynchronous */
467 scat_req->complete = htc_async_tx_scat_complete;
468 n_sent_bundle++;
469 tot_pkts_bundle += scat_req->scat_entries;
470
471 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
472 "send scatter total bytes: %d , entries: %d\n",
473 scat_req->len, scat_req->scat_entries);
474 ath6kldev_submit_scat_req(target->dev, scat_req, false);
475 }
476
477 *sent_bundle = n_sent_bundle;
478 *n_bundle_pkts = tot_pkts_bundle;
479 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_issue_send_bundle (sent:%d)\n",
480 n_sent_bundle);
481
482 return;
483}
484
485static void htc_tx_from_ep_txq(struct htc_target *target,
486 struct htc_endpoint *endpoint)
487{
488 struct list_head txq;
489 struct htc_packet *packet;
490 int bundle_sent;
491 int n_pkts_bundle;
492
493 spin_lock_bh(&target->tx_lock);
494
495 endpoint->tx_proc_cnt++;
496 if (endpoint->tx_proc_cnt > 1) {
497 endpoint->tx_proc_cnt--;
498 spin_unlock_bh(&target->tx_lock);
499 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "htc_try_send (busy)\n");
500 return;
501 }
502
503 /*
504 * drain the endpoint TX queue for transmission as long
505 * as we have enough credits.
506 */
507 INIT_LIST_HEAD(&txq);
508
509 while (true) {
510
511 if (list_empty(&endpoint->txq))
512 break;
513
514 htc_tx_pkts_get(target, endpoint, &txq);
515
516 if (list_empty(&txq))
517 break;
518
519 spin_unlock_bh(&target->tx_lock);
520
521 bundle_sent = 0;
522 n_pkts_bundle = 0;
523
524 while (true) {
525 /* try to send a bundle on each pass */
526 if ((target->tx_bndl_enable) &&
527 (get_queue_depth(&txq) >=
528 HTC_MIN_HTC_MSGS_TO_BUNDLE)) {
529 int temp1 = 0, temp2 = 0;
530
531 htc_issue_send_bundle(endpoint, &txq,
532 &temp1, &temp2);
533 bundle_sent += temp1;
534 n_pkts_bundle += temp2;
535 }
536
537 if (list_empty(&txq))
538 break;
539
540 packet = list_first_entry(&txq, struct htc_packet,
541 list);
542 list_del(&packet->list);
543
544 htc_prep_send_pkt(packet, packet->info.tx.flags,
545 0, packet->info.tx.seqno);
546 htc_issue_send(target, packet);
547 }
548
549 spin_lock_bh(&target->tx_lock);
550
551 endpoint->ep_st.tx_bundles += bundle_sent;
552 endpoint->ep_st.tx_pkt_bundled += n_pkts_bundle;
553 }
554
555 endpoint->tx_proc_cnt = 0;
556 spin_unlock_bh(&target->tx_lock);
557}
558
559static bool htc_try_send(struct htc_target *target,
560 struct htc_endpoint *endpoint,
561 struct htc_packet *tx_pkt)
562{
563 struct htc_ep_callbacks ep_cb;
564 int txq_depth;
565 bool overflow = false;
566
567 ep_cb = endpoint->ep_cb;
568
569 spin_lock_bh(&target->tx_lock);
570 txq_depth = get_queue_depth(&endpoint->txq);
571 spin_unlock_bh(&target->tx_lock);
572
573 if (txq_depth >= endpoint->max_txq_depth)
574 overflow = true;
575
576 if (overflow)
577 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
578 "ep %d, tx queue will overflow :%d , tx depth:%d, max:%d\n",
579 endpoint->eid, overflow, txq_depth,
580 endpoint->max_txq_depth);
581
582 if (overflow && ep_cb.tx_full) {
583 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
584 "indicating overflowed tx packet: 0x%p\n", tx_pkt);
585
586 if (ep_cb.tx_full(endpoint->target, tx_pkt) ==
587 HTC_SEND_FULL_DROP) {
588 endpoint->ep_st.tx_dropped += 1;
589 return false;
590 }
591 }
592
593 spin_lock_bh(&target->tx_lock);
594 list_add_tail(&tx_pkt->list, &endpoint->txq);
595 spin_unlock_bh(&target->tx_lock);
596
597 htc_tx_from_ep_txq(target, endpoint);
598
599 return true;
600}
601
602static void htc_chk_ep_txq(struct htc_target *target)
603{
604 struct htc_endpoint *endpoint;
605 struct htc_endpoint_credit_dist *cred_dist;
606
607 /*
608 * Run through the credit distribution list to see if there are
609 * packets queued. NOTE: no locks need to be taken since the
610 * distribution list is not dynamic (cannot be re-ordered) and we
611 * are not modifying any state.
612 */
613 list_for_each_entry(cred_dist, &target->cred_dist_list, list) {
614 endpoint = (struct htc_endpoint *)cred_dist->htc_rsvd;
615
616 spin_lock_bh(&target->tx_lock);
617 if (!list_empty(&endpoint->txq)) {
618 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
619 "ep %d has %d credits and %d packets in tx queue\n",
620 cred_dist->endpoint,
621 endpoint->cred_dist.credits,
622 get_queue_depth(&endpoint->txq));
623 spin_unlock_bh(&target->tx_lock);
624 /*
625 * Try to start the stalled queue, this list is
626 * ordered by priority. If there are credits
627 * available the highest priority queue will get a
628 * chance to reclaim credits from lower priority
629 * ones.
630 */
631 htc_tx_from_ep_txq(target, endpoint);
632 spin_lock_bh(&target->tx_lock);
633 }
634 spin_unlock_bh(&target->tx_lock);
635 }
636}
637
638static int htc_setup_tx_complete(struct htc_target *target)
639{
640 struct htc_packet *send_pkt = NULL;
641 int status;
642
643 send_pkt = htc_get_control_buf(target, true);
644
645 if (!send_pkt)
646 return -ENOMEM;
647
648 if (target->htc_tgt_ver >= HTC_VERSION_2P1) {
649 struct htc_setup_comp_ext_msg *setup_comp_ext;
650 u32 flags = 0;
651
652 setup_comp_ext =
653 (struct htc_setup_comp_ext_msg *)send_pkt->buf;
654 memset(setup_comp_ext, 0, sizeof(*setup_comp_ext));
655 setup_comp_ext->msg_id =
656 cpu_to_le16(HTC_MSG_SETUP_COMPLETE_EX_ID);
657
658 if (target->msg_per_bndl_max > 0) {
659 /* Indicate HTC bundling to the target */
660 flags |= HTC_SETUP_COMP_FLG_RX_BNDL_EN;
661 setup_comp_ext->msg_per_rxbndl =
662 target->msg_per_bndl_max;
663 }
664
665 memcpy(&setup_comp_ext->flags, &flags,
666 sizeof(setup_comp_ext->flags));
667 set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp_ext,
668 sizeof(struct htc_setup_comp_ext_msg),
669 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
670
671 } else {
672 struct htc_setup_comp_msg *setup_comp;
673 setup_comp = (struct htc_setup_comp_msg *)send_pkt->buf;
674 memset(setup_comp, 0, sizeof(struct htc_setup_comp_msg));
675 setup_comp->msg_id = cpu_to_le16(HTC_MSG_SETUP_COMPLETE_ID);
676 set_htc_pkt_info(send_pkt, NULL, (u8 *) setup_comp,
677 sizeof(struct htc_setup_comp_msg),
678 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
679 }
680
681 /* we want synchronous operation */
682 send_pkt->completion = NULL;
683 htc_prep_send_pkt(send_pkt, 0, 0, 0);
684 status = htc_issue_send(target, send_pkt);
685
686 if (send_pkt != NULL)
687 htc_reclaim_txctrl_buf(target, send_pkt);
688
689 return status;
690}
691
692void ath6kl_htc_set_credit_dist(struct htc_target *target,
693 struct htc_credit_state_info *cred_dist_cntxt,
694 u16 srvc_pri_order[], int list_len)
695{
696 struct htc_endpoint *endpoint;
697 int i, ep;
698
699 target->cred_dist_cntxt = cred_dist_cntxt;
700
701 list_add_tail(&target->endpoint[ENDPOINT_0].cred_dist.list,
702 &target->cred_dist_list);
703
704 for (i = 0; i < list_len; i++) {
705 for (ep = ENDPOINT_1; ep < ENDPOINT_MAX; ep++) {
706 endpoint = &target->endpoint[ep];
707 if (endpoint->svc_id == srvc_pri_order[i]) {
708 list_add_tail(&endpoint->cred_dist.list,
709 &target->cred_dist_list);
710 break;
711 }
712 }
713 if (ep >= ENDPOINT_MAX) {
714 WARN_ON(1);
715 return;
716 }
717 }
718}
719
720int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet)
721{
722 struct htc_endpoint *endpoint;
723 struct list_head queue;
724
725 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
726 "htc_tx: ep id: %d, buf: 0x%p, len: %d\n",
727 packet->endpoint, packet->buf, packet->act_len);
728
729 if (packet->endpoint >= ENDPOINT_MAX) {
730 WARN_ON(1);
731 return -EINVAL;
732 }
733
734 endpoint = &target->endpoint[packet->endpoint];
735
736 if (!htc_try_send(target, endpoint, packet)) {
737 packet->status = (target->htc_flags & HTC_OP_STATE_STOPPING) ?
738 -ECANCELED : -ENOSPC;
739 INIT_LIST_HEAD(&queue);
740 list_add(&packet->list, &queue);
741 htc_tx_complete(endpoint, &queue);
742 }
743
744 return 0;
745}
746
747/* flush endpoint TX queue */
748void ath6kl_htc_flush_txep(struct htc_target *target,
749 enum htc_endpoint_id eid, u16 tag)
750{
751 struct htc_packet *packet, *tmp_pkt;
752 struct list_head discard_q, container;
753 struct htc_endpoint *endpoint = &target->endpoint[eid];
754
755 if (!endpoint->svc_id) {
756 WARN_ON(1);
757 return;
758 }
759
760 /* initialize the discard queue */
761 INIT_LIST_HEAD(&discard_q);
762
763 spin_lock_bh(&target->tx_lock);
764
765 list_for_each_entry_safe(packet, tmp_pkt, &endpoint->txq, list) {
766 if ((tag == HTC_TX_PACKET_TAG_ALL) ||
767 (tag == packet->info.tx.tag))
768 list_move_tail(&packet->list, &discard_q);
769 }
770
771 spin_unlock_bh(&target->tx_lock);
772
773 list_for_each_entry_safe(packet, tmp_pkt, &discard_q, list) {
774 packet->status = -ECANCELED;
775 list_del(&packet->list);
776 ath6kl_dbg(ATH6KL_DBG_TRC,
777 "flushing tx pkt:0x%p, len:%d, ep:%d tag:0x%X\n",
778 packet, packet->act_len,
779 packet->endpoint, packet->info.tx.tag);
780
781 INIT_LIST_HEAD(&container);
782 list_add_tail(&packet->list, &container);
783 htc_tx_complete(endpoint, &container);
784 }
785
786}
787
788static void ath6kl_htc_flush_txep_all(struct htc_target *target)
789{
790 struct htc_endpoint *endpoint;
791 int i;
792
793 dump_cred_dist_stats(target);
794
795 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
796 endpoint = &target->endpoint[i];
797 if (endpoint->svc_id == 0)
798 /* not in use.. */
799 continue;
800 ath6kl_htc_flush_txep(target, i, HTC_TX_PACKET_TAG_ALL);
801 }
802}
803
804void ath6kl_htc_indicate_activity_change(struct htc_target *target,
805 enum htc_endpoint_id eid, bool active)
806{
807 struct htc_endpoint *endpoint = &target->endpoint[eid];
808 bool dist = false;
809
810 if (endpoint->svc_id == 0) {
811 WARN_ON(1);
812 return;
813 }
814
815 spin_lock_bh(&target->tx_lock);
816
817 if (active) {
818 if (!(endpoint->cred_dist.dist_flags & HTC_EP_ACTIVE)) {
819 endpoint->cred_dist.dist_flags |= HTC_EP_ACTIVE;
820 dist = true;
821 }
822 } else {
823 if (endpoint->cred_dist.dist_flags & HTC_EP_ACTIVE) {
824 endpoint->cred_dist.dist_flags &= ~HTC_EP_ACTIVE;
825 dist = true;
826 }
827 }
828
829 if (dist) {
830 endpoint->cred_dist.txq_depth =
831 get_queue_depth(&endpoint->txq);
832
833 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
834 target->cred_dist_cntxt, &target->cred_dist_list);
835
836 ath6k_credit_distribute(target->cred_dist_cntxt,
837 &target->cred_dist_list,
838 HTC_CREDIT_DIST_ACTIVITY_CHANGE);
839 }
840
841 spin_unlock_bh(&target->tx_lock);
842
843 if (dist && !active)
844 htc_chk_ep_txq(target);
845}
846
847/* HTC Rx */
848
849static inline void htc_update_rx_stats(struct htc_endpoint *endpoint,
850 int n_look_ahds)
851{
852 endpoint->ep_st.rx_pkts++;
853 if (n_look_ahds == 1)
854 endpoint->ep_st.rx_lkahds++;
855 else if (n_look_ahds > 1)
856 endpoint->ep_st.rx_bundle_lkahd++;
857}
858
859static inline bool htc_valid_rx_frame_len(struct htc_target *target,
860 enum htc_endpoint_id eid, int len)
861{
862 return (eid == target->dev->ar->ctrl_ep) ?
863 len <= ATH6KL_BUFFER_SIZE : len <= ATH6KL_AMSDU_BUFFER_SIZE;
864}
865
866static int htc_add_rxbuf(struct htc_target *target, struct htc_packet *packet)
867{
868 struct list_head queue;
869
870 INIT_LIST_HEAD(&queue);
871 list_add_tail(&packet->list, &queue);
872 return ath6kl_htc_add_rxbuf_multiple(target, &queue);
873}
874
875static void htc_reclaim_rxbuf(struct htc_target *target,
876 struct htc_packet *packet,
877 struct htc_endpoint *ep)
878{
879 if (packet->info.rx.rx_flags & HTC_RX_PKT_NO_RECYCLE) {
880 htc_rxpkt_reset(packet);
881 packet->status = -ECANCELED;
882 ep->ep_cb.rx(ep->target, packet);
883 } else {
884 htc_rxpkt_reset(packet);
885 htc_add_rxbuf((void *)(target), packet);
886 }
887}
888
889static void reclaim_rx_ctrl_buf(struct htc_target *target,
890 struct htc_packet *packet)
891{
892 spin_lock_bh(&target->htc_lock);
893 list_add_tail(&packet->list, &target->free_ctrl_rxbuf);
894 spin_unlock_bh(&target->htc_lock);
895}
896
897static int dev_rx_pkt(struct htc_target *target, struct htc_packet *packet,
898 u32 rx_len)
899{
900 struct ath6kl_device *dev = target->dev;
901 u32 padded_len;
902 int status;
903
904 padded_len = CALC_TXRX_PADDED_LEN(target, rx_len);
905
906 if (padded_len > packet->buf_len) {
907 ath6kl_err("not enough receive space for packet - padlen:%d recvlen:%d bufferlen:%d\n",
908 padded_len, rx_len, packet->buf_len);
909 return -ENOMEM;
910 }
911
912 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
913 "dev_rx_pkt (0x%p : hdr:0x%X) padded len: %d mbox:0x%X (mode:%s)\n",
914 packet, packet->info.rx.exp_hdr,
915 padded_len, dev->ar->mbox_info.htc_addr, "sync");
916
917 status = hif_read_write_sync(dev->ar,
918 dev->ar->mbox_info.htc_addr,
919 packet->buf, padded_len,
920 HIF_RD_SYNC_BLOCK_FIX);
921
922 packet->status = status;
923
924 return status;
925}
926
927/*
928 * optimization for recv packets, we can indicate a
929 * "hint" that there are more single-packets to fetch
930 * on this endpoint.
931 */
932static void set_rxpkt_indication_flag(u32 lk_ahd,
933 struct htc_endpoint *endpoint,
934 struct htc_packet *packet)
935{
936 struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)&lk_ahd;
937
938 if (htc_hdr->eid == packet->endpoint) {
939 if (!list_empty(&endpoint->rx_bufq))
940 packet->info.rx.indicat_flags |=
941 HTC_RX_FLAGS_INDICATE_MORE_PKTS;
942 }
943}
944
945static void chk_rx_water_mark(struct htc_endpoint *endpoint)
946{
947 struct htc_ep_callbacks ep_cb = endpoint->ep_cb;
948
949 if (ep_cb.rx_refill_thresh > 0) {
950 spin_lock_bh(&endpoint->target->rx_lock);
951 if (get_queue_depth(&endpoint->rx_bufq)
952 < ep_cb.rx_refill_thresh) {
953 spin_unlock_bh(&endpoint->target->rx_lock);
954 ep_cb.rx_refill(endpoint->target, endpoint->eid);
955 return;
956 }
957 spin_unlock_bh(&endpoint->target->rx_lock);
958 }
959}
960
961/* This function is called with rx_lock held */
962static int htc_setup_rxpkts(struct htc_target *target, struct htc_endpoint *ep,
963 u32 *lk_ahds, struct list_head *queue, int n_msg)
964{
965 struct htc_packet *packet;
966 /* FIXME: type of lk_ahds can't be right */
967 struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)lk_ahds;
968 struct htc_ep_callbacks ep_cb;
969 int status = 0, j, full_len;
970 bool no_recycle;
971
972 full_len = CALC_TXRX_PADDED_LEN(target,
973 le16_to_cpu(htc_hdr->payld_len) +
974 sizeof(*htc_hdr));
975
976 if (!htc_valid_rx_frame_len(target, ep->eid, full_len)) {
977 ath6kl_warn("Rx buffer requested with invalid length\n");
978 return -EINVAL;
979 }
980
981 ep_cb = ep->ep_cb;
982 for (j = 0; j < n_msg; j++) {
983
984 /*
985 * Reset flag, any packets allocated using the
986 * rx_alloc() API cannot be recycled on
987 * cleanup,they must be explicitly returned.
988 */
989 no_recycle = false;
990
991 if (ep_cb.rx_allocthresh &&
992 (full_len > ep_cb.rx_alloc_thresh)) {
993 ep->ep_st.rx_alloc_thresh_hit += 1;
994 ep->ep_st.rxalloc_thresh_byte +=
995 le16_to_cpu(htc_hdr->payld_len);
996
997 spin_unlock_bh(&target->rx_lock);
998 no_recycle = true;
999
1000 packet = ep_cb.rx_allocthresh(ep->target, ep->eid,
1001 full_len);
1002 spin_lock_bh(&target->rx_lock);
1003 } else {
1004 /* refill handler is being used */
1005 if (list_empty(&ep->rx_bufq)) {
1006 if (ep_cb.rx_refill) {
1007 spin_unlock_bh(&target->rx_lock);
1008 ep_cb.rx_refill(ep->target, ep->eid);
1009 spin_lock_bh(&target->rx_lock);
1010 }
1011 }
1012
1013 if (list_empty(&ep->rx_bufq))
1014 packet = NULL;
1015 else {
1016 packet = list_first_entry(&ep->rx_bufq,
1017 struct htc_packet, list);
1018 list_del(&packet->list);
1019 }
1020 }
1021
1022 if (!packet) {
1023 target->rx_st_flags |= HTC_RECV_WAIT_BUFFERS;
1024 target->ep_waiting = ep->eid;
1025 return -ENOSPC;
1026 }
1027
1028 /* clear flags */
1029 packet->info.rx.rx_flags = 0;
1030 packet->info.rx.indicat_flags = 0;
1031 packet->status = 0;
1032
1033 if (no_recycle)
1034 /*
1035 * flag that these packets cannot be
1036 * recycled, they have to be returned to
1037 * the user
1038 */
1039 packet->info.rx.rx_flags |= HTC_RX_PKT_NO_RECYCLE;
1040
1041 /* Caller needs to free this upon any failure */
1042 list_add_tail(&packet->list, queue);
1043
1044 if (target->htc_flags & HTC_OP_STATE_STOPPING) {
1045 status = -ECANCELED;
1046 break;
1047 }
1048
1049 if (j) {
1050 packet->info.rx.rx_flags |= HTC_RX_PKT_REFRESH_HDR;
1051 packet->info.rx.exp_hdr = 0xFFFFFFFF;
1052 } else
1053 /* set expected look ahead */
1054 packet->info.rx.exp_hdr = *lk_ahds;
1055
1056 packet->act_len = le16_to_cpu(htc_hdr->payld_len) +
1057 HTC_HDR_LENGTH;
1058 }
1059
1060 return status;
1061}
1062
1063static int alloc_and_prep_rxpkts(struct htc_target *target,
1064 u32 lk_ahds[], int msg,
1065 struct htc_endpoint *endpoint,
1066 struct list_head *queue)
1067{
1068 int status = 0;
1069 struct htc_packet *packet, *tmp_pkt;
1070 struct htc_frame_hdr *htc_hdr;
1071 int i, n_msg;
1072
1073 spin_lock_bh(&target->rx_lock);
1074
1075 for (i = 0; i < msg; i++) {
1076
1077 htc_hdr = (struct htc_frame_hdr *)&lk_ahds[i];
1078
1079 if (htc_hdr->eid >= ENDPOINT_MAX) {
1080 ath6kl_err("invalid ep in look-ahead: %d\n",
1081 htc_hdr->eid);
1082 status = -ENOMEM;
1083 break;
1084 }
1085
1086 if (htc_hdr->eid != endpoint->eid) {
1087 ath6kl_err("invalid ep in look-ahead: %d should be : %d (index:%d)\n",
1088 htc_hdr->eid, endpoint->eid, i);
1089 status = -ENOMEM;
1090 break;
1091 }
1092
1093 if (le16_to_cpu(htc_hdr->payld_len) > HTC_MAX_PAYLOAD_LENGTH) {
1094 ath6kl_err("payload len %d exceeds max htc : %d !\n",
1095 htc_hdr->payld_len,
1096 (u32) HTC_MAX_PAYLOAD_LENGTH);
1097 status = -ENOMEM;
1098 break;
1099 }
1100
1101 if (endpoint->svc_id == 0) {
1102 ath6kl_err("ep %d is not connected !\n", htc_hdr->eid);
1103 status = -ENOMEM;
1104 break;
1105 }
1106
1107 if (htc_hdr->flags & HTC_FLG_RX_BNDL_CNT) {
1108 /*
1109 * HTC header indicates that every packet to follow
1110 * has the same padded length so that it can be
1111 * optimally fetched as a full bundle.
1112 */
1113 n_msg = (htc_hdr->flags & HTC_FLG_RX_BNDL_CNT) >>
1114 HTC_FLG_RX_BNDL_CNT_S;
1115
1116 /* the count doesn't include the starter frame */
1117 n_msg++;
1118 if (n_msg > target->msg_per_bndl_max) {
1119 status = -ENOMEM;
1120 break;
1121 }
1122
1123 endpoint->ep_st.rx_bundle_from_hdr += 1;
1124 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1125 "htc hdr indicates :%d msg can be fetched as a bundle\n",
1126 n_msg);
1127 } else
1128 /* HTC header only indicates 1 message to fetch */
1129 n_msg = 1;
1130
1131 /* Setup packet buffers for each message */
1132 status = htc_setup_rxpkts(target, endpoint, &lk_ahds[i], queue,
1133 n_msg);
1134
1135 /*
1136 * This is due to unavailabilty of buffers to rx entire data.
1137 * Return no error so that free buffers from queue can be used
1138 * to receive partial data.
1139 */
1140 if (status == -ENOSPC) {
1141 spin_unlock_bh(&target->rx_lock);
1142 return 0;
1143 }
1144
1145 if (status)
1146 break;
1147 }
1148
1149 spin_unlock_bh(&target->rx_lock);
1150
1151 if (status) {
1152 list_for_each_entry_safe(packet, tmp_pkt, queue, list) {
1153 list_del(&packet->list);
1154 htc_reclaim_rxbuf(target, packet,
1155 &target->endpoint[packet->endpoint]);
1156 }
1157 }
1158
1159 return status;
1160}
1161
1162static void htc_ctrl_rx(struct htc_target *context, struct htc_packet *packets)
1163{
1164 if (packets->endpoint != ENDPOINT_0) {
1165 WARN_ON(1);
1166 return;
1167 }
1168
1169 if (packets->status == -ECANCELED) {
1170 reclaim_rx_ctrl_buf(context, packets);
1171 return;
1172 }
1173
1174 if (packets->act_len > 0) {
1175 ath6kl_err("htc_ctrl_rx, got message with len:%zu\n",
1176 packets->act_len + HTC_HDR_LENGTH);
1177
1178 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
1179 "Unexpected ENDPOINT 0 Message",
1180 packets->buf - HTC_HDR_LENGTH,
1181 packets->act_len + HTC_HDR_LENGTH);
1182 }
1183
1184 htc_reclaim_rxbuf(context, packets, &context->endpoint[0]);
1185}
1186
1187static void htc_proc_cred_rpt(struct htc_target *target,
1188 struct htc_credit_report *rpt,
1189 int n_entries,
1190 enum htc_endpoint_id from_ep)
1191{
1192 struct htc_endpoint *endpoint;
1193 int tot_credits = 0, i;
1194 bool dist = false;
1195
1196 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
1197 "htc_proc_cred_rpt, credit report entries:%d\n", n_entries);
1198
1199 spin_lock_bh(&target->tx_lock);
1200
1201 for (i = 0; i < n_entries; i++, rpt++) {
1202 if (rpt->eid >= ENDPOINT_MAX) {
1203 WARN_ON(1);
1204 spin_unlock_bh(&target->tx_lock);
1205 return;
1206 }
1207
1208 endpoint = &target->endpoint[rpt->eid];
1209
1210 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, " ep %d got %d credits\n",
1211 rpt->eid, rpt->credits);
1212
1213 endpoint->ep_st.tx_cred_rpt += 1;
1214 endpoint->ep_st.cred_retnd += rpt->credits;
1215
1216 if (from_ep == rpt->eid) {
1217 /*
1218 * This credit report arrived on the same endpoint
1219 * indicating it arrived in an RX packet.
1220 */
1221 endpoint->ep_st.cred_from_rx += rpt->credits;
1222 endpoint->ep_st.cred_rpt_from_rx += 1;
1223 } else if (from_ep == ENDPOINT_0) {
1224 /* credit arrived on endpoint 0 as a NULL message */
1225 endpoint->ep_st.cred_from_ep0 += rpt->credits;
1226 endpoint->ep_st.cred_rpt_ep0 += 1;
1227 } else {
1228 endpoint->ep_st.cred_from_other += rpt->credits;
1229 endpoint->ep_st.cred_rpt_from_other += 1;
1230 }
1231
1232 if (rpt->eid == ENDPOINT_0)
1233 /* always give endpoint 0 credits back */
1234 endpoint->cred_dist.credits += rpt->credits;
1235 else {
1236 endpoint->cred_dist.cred_to_dist += rpt->credits;
1237 dist = true;
1238 }
1239
1240 /*
1241 * Refresh tx depth for distribution function that will
1242 * recover these credits NOTE: this is only valid when
1243 * there are credits to recover!
1244 */
1245 endpoint->cred_dist.txq_depth =
1246 get_queue_depth(&endpoint->txq);
1247
1248 tot_credits += rpt->credits;
1249 }
1250
1251 ath6kl_dbg(ATH6KL_DBG_HTC_SEND,
1252 "report indicated %d credits to distribute\n",
1253 tot_credits);
1254
1255 if (dist) {
1256 /*
1257 * This was a credit return based on a completed send
1258 * operations note, this is done with the lock held
1259 */
1260 ath6kl_dbg(ATH6KL_DBG_HTC_SEND, "ctxt:0x%p dist:0x%p\n",
1261 target->cred_dist_cntxt, &target->cred_dist_list);
1262
1263 ath6k_credit_distribute(target->cred_dist_cntxt,
1264 &target->cred_dist_list,
1265 HTC_CREDIT_DIST_SEND_COMPLETE);
1266 }
1267
1268 spin_unlock_bh(&target->tx_lock);
1269
1270 if (tot_credits)
1271 htc_chk_ep_txq(target);
1272}
1273
1274static int htc_parse_trailer(struct htc_target *target,
1275 struct htc_record_hdr *record,
1276 u8 *record_buf, u32 *next_lk_ahds,
1277 enum htc_endpoint_id endpoint,
1278 int *n_lk_ahds)
1279{
1280 struct htc_bundle_lkahd_rpt *bundle_lkahd_rpt;
1281 struct htc_lookahead_report *lk_ahd;
1282 int len;
1283
1284 switch (record->rec_id) {
1285 case HTC_RECORD_CREDITS:
1286 len = record->len / sizeof(struct htc_credit_report);
1287 if (!len) {
1288 WARN_ON(1);
1289 return -EINVAL;
1290 }
1291
1292 htc_proc_cred_rpt(target,
1293 (struct htc_credit_report *) record_buf,
1294 len, endpoint);
1295 break;
1296 case HTC_RECORD_LOOKAHEAD:
1297 len = record->len / sizeof(*lk_ahd);
1298 if (!len) {
1299 WARN_ON(1);
1300 return -EINVAL;
1301 }
1302
1303 lk_ahd = (struct htc_lookahead_report *) record_buf;
1304 if ((lk_ahd->pre_valid == ((~lk_ahd->post_valid) & 0xFF))
1305 && next_lk_ahds) {
1306
1307 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1308 "lk_ahd report found (pre valid:0x%X, post valid:0x%X)\n",
1309 lk_ahd->pre_valid, lk_ahd->post_valid);
1310
1311 /* look ahead bytes are valid, copy them over */
1312 memcpy((u8 *)&next_lk_ahds[0], lk_ahd->lk_ahd, 4);
1313
1314 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Next Look Ahead",
1315 next_lk_ahds, 4);
1316
1317 *n_lk_ahds = 1;
1318 }
1319 break;
1320 case HTC_RECORD_LOOKAHEAD_BUNDLE:
1321 len = record->len / sizeof(*bundle_lkahd_rpt);
1322 if (!len || (len > HTC_HOST_MAX_MSG_PER_BUNDLE)) {
1323 WARN_ON(1);
1324 return -EINVAL;
1325 }
1326
1327 if (next_lk_ahds) {
1328 int i;
1329
1330 bundle_lkahd_rpt =
1331 (struct htc_bundle_lkahd_rpt *) record_buf;
1332
1333 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Bundle lk_ahd",
1334 record_buf, record->len);
1335
1336 for (i = 0; i < len; i++) {
1337 memcpy((u8 *)&next_lk_ahds[i],
1338 bundle_lkahd_rpt->lk_ahd, 4);
1339 bundle_lkahd_rpt++;
1340 }
1341
1342 *n_lk_ahds = i;
1343 }
1344 break;
1345 default:
1346 ath6kl_err("unhandled record: id:%d len:%d\n",
1347 record->rec_id, record->len);
1348 break;
1349 }
1350
1351 return 0;
1352
1353}
1354
1355static int htc_proc_trailer(struct htc_target *target,
1356 u8 *buf, int len, u32 *next_lk_ahds,
1357 int *n_lk_ahds, enum htc_endpoint_id endpoint)
1358{
1359 struct htc_record_hdr *record;
1360 int orig_len;
1361 int status;
1362 u8 *record_buf;
1363 u8 *orig_buf;
1364
1365 ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "+htc_proc_trailer (len:%d)\n", len);
1366
1367 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Recv Trailer", buf, len);
1368
1369 orig_buf = buf;
1370 orig_len = len;
1371 status = 0;
1372
1373 while (len > 0) {
1374
1375 if (len < sizeof(struct htc_record_hdr)) {
1376 status = -ENOMEM;
1377 break;
1378 }
1379 /* these are byte aligned structs */
1380 record = (struct htc_record_hdr *) buf;
1381 len -= sizeof(struct htc_record_hdr);
1382 buf += sizeof(struct htc_record_hdr);
1383
1384 if (record->len > len) {
1385 ath6kl_err("invalid record len: %d (id:%d) buf has: %d bytes left\n",
1386 record->len, record->rec_id, len);
1387 status = -ENOMEM;
1388 break;
1389 }
1390 record_buf = buf;
1391
1392 status = htc_parse_trailer(target, record, record_buf,
1393 next_lk_ahds, endpoint, n_lk_ahds);
1394
1395 if (status)
1396 break;
1397
1398 /* advance buffer past this record for next time around */
1399 buf += record->len;
1400 len -= record->len;
1401 }
1402
1403 if (status)
1404 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD Recv Trailer",
1405 orig_buf, orig_len);
1406
1407 return status;
1408}
1409
1410static int htc_proc_rxhdr(struct htc_target *target,
1411 struct htc_packet *packet,
1412 u32 *next_lkahds, int *n_lkahds)
1413{
1414 int status = 0;
1415 u16 payload_len;
1416 u32 lk_ahd;
1417 struct htc_frame_hdr *htc_hdr = (struct htc_frame_hdr *)packet->buf;
1418
1419 if (n_lkahds != NULL)
1420 *n_lkahds = 0;
1421
1422 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "HTC Recv PKT", packet->buf,
1423 packet->act_len);
1424
1425 /*
1426 * NOTE: we cannot assume the alignment of buf, so we use the safe
1427 * macros to retrieve 16 bit fields.
1428 */
1429 payload_len = le16_to_cpu(get_unaligned(&htc_hdr->payld_len));
1430
1431 memcpy((u8 *)&lk_ahd, packet->buf, sizeof(lk_ahd));
1432
1433 if (packet->info.rx.rx_flags & HTC_RX_PKT_REFRESH_HDR) {
1434 /*
1435 * Refresh the expected header and the actual length as it
1436 * was unknown when this packet was grabbed as part of the
1437 * bundle.
1438 */
1439 packet->info.rx.exp_hdr = lk_ahd;
1440 packet->act_len = payload_len + HTC_HDR_LENGTH;
1441
1442 /* validate the actual header that was refreshed */
1443 if (packet->act_len > packet->buf_len) {
1444 ath6kl_err("refreshed hdr payload len (%d) in bundled recv is invalid (hdr: 0x%X)\n",
1445 payload_len, lk_ahd);
1446 /*
1447 * Limit this to max buffer just to print out some
1448 * of the buffer.
1449 */
1450 packet->act_len = min(packet->act_len, packet->buf_len);
1451 status = -ENOMEM;
1452 goto fail_rx;
1453 }
1454
1455 if (packet->endpoint != htc_hdr->eid) {
1456 ath6kl_err("refreshed hdr ep (%d) does not match expected ep (%d)\n",
1457 htc_hdr->eid, packet->endpoint);
1458 status = -ENOMEM;
1459 goto fail_rx;
1460 }
1461 }
1462
1463 if (lk_ahd != packet->info.rx.exp_hdr) {
1464 ath6kl_err("htc_proc_rxhdr, lk_ahd mismatch! (pPkt:0x%p flags:0x%X)\n",
1465 packet, packet->info.rx.rx_flags);
1466 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Expected Message lk_ahd",
1467 &packet->info.rx.exp_hdr, 4);
1468 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "Current Frame Header",
1469 (u8 *)&lk_ahd, sizeof(lk_ahd));
1470 status = -ENOMEM;
1471 goto fail_rx;
1472 }
1473
1474 if (htc_hdr->flags & HTC_FLG_RX_TRAILER) {
1475 if (htc_hdr->ctrl[0] < sizeof(struct htc_record_hdr) ||
1476 htc_hdr->ctrl[0] > payload_len) {
1477 ath6kl_err("htc_proc_rxhdr, invalid hdr (payload len should be :%d, CB[0] is:%d)\n",
1478 payload_len, htc_hdr->ctrl[0]);
1479 status = -ENOMEM;
1480 goto fail_rx;
1481 }
1482
1483 if (packet->info.rx.rx_flags & HTC_RX_PKT_IGNORE_LOOKAHEAD) {
1484 next_lkahds = NULL;
1485 n_lkahds = NULL;
1486 }
1487
1488 status = htc_proc_trailer(target, packet->buf + HTC_HDR_LENGTH
1489 + payload_len - htc_hdr->ctrl[0],
1490 htc_hdr->ctrl[0], next_lkahds,
1491 n_lkahds, packet->endpoint);
1492
1493 if (status)
1494 goto fail_rx;
1495
1496 packet->act_len -= htc_hdr->ctrl[0];
1497 }
1498
1499 packet->buf += HTC_HDR_LENGTH;
1500 packet->act_len -= HTC_HDR_LENGTH;
1501
1502fail_rx:
1503 if (status)
1504 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "BAD HTC Recv PKT",
1505 packet->buf,
1506 packet->act_len < 256 ? packet->act_len : 256);
1507 else {
1508 if (packet->act_len > 0)
1509 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES,
1510 "HTC - Application Msg",
1511 packet->buf, packet->act_len);
1512 }
1513
1514 return status;
1515}
1516
1517static void do_rx_completion(struct htc_endpoint *endpoint,
1518 struct htc_packet *packet)
1519{
1520 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1521 "htc calling ep %d recv callback on packet 0x%p\n",
1522 endpoint->eid, packet);
1523 endpoint->ep_cb.rx(endpoint->target, packet);
1524}
1525
1526static int htc_issue_rxpkt_bundle(struct htc_target *target,
1527 struct list_head *rxq,
1528 struct list_head *sync_compq,
1529 int *n_pkt_fetched, bool part_bundle)
1530{
1531 struct hif_scatter_req *scat_req;
1532 struct htc_packet *packet;
1533 int rem_space = target->max_rx_bndl_sz;
1534 int n_scat_pkt, status = 0, i, len;
1535
1536 n_scat_pkt = get_queue_depth(rxq);
1537 n_scat_pkt = min(n_scat_pkt, target->msg_per_bndl_max);
1538
1539 if ((get_queue_depth(rxq) - n_scat_pkt) > 0) {
1540 /*
1541 * We were forced to split this bundle receive operation
1542 * all packets in this partial bundle must have their
1543 * lookaheads ignored.
1544 */
1545 part_bundle = true;
1546
1547 /*
1548 * This would only happen if the target ignored our max
1549 * bundle limit.
1550 */
1551 ath6kl_warn("htc_issue_rxpkt_bundle : partial bundle detected num:%d , %d\n",
1552 get_queue_depth(rxq), n_scat_pkt);
1553 }
1554
1555 len = 0;
1556
1557 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1558 "htc_issue_rxpkt_bundle (numpackets: %d , actual : %d)\n",
1559 get_queue_depth(rxq), n_scat_pkt);
1560
1561 scat_req = hif_scatter_req_get(target->dev->ar);
1562
1563 if (scat_req == NULL)
1564 goto fail_rx_pkt;
1565
1566 for (i = 0; i < n_scat_pkt; i++) {
1567 int pad_len;
1568
1569 packet = list_first_entry(rxq, struct htc_packet, list);
1570 list_del(&packet->list);
1571
1572 pad_len = CALC_TXRX_PADDED_LEN(target,
1573 packet->act_len);
1574
1575 if ((rem_space - pad_len) < 0) {
1576 list_add(&packet->list, rxq);
1577 break;
1578 }
1579
1580 rem_space -= pad_len;
1581
1582 if (part_bundle || (i < (n_scat_pkt - 1)))
1583 /*
1584 * Packet 0..n-1 cannot be checked for look-aheads
1585 * since we are fetching a bundle the last packet
1586 * however can have it's lookahead used
1587 */
1588 packet->info.rx.rx_flags |=
1589 HTC_RX_PKT_IGNORE_LOOKAHEAD;
1590
1591 /* NOTE: 1 HTC packet per scatter entry */
1592 scat_req->scat_list[i].buf = packet->buf;
1593 scat_req->scat_list[i].len = pad_len;
1594
1595 packet->info.rx.rx_flags |= HTC_RX_PKT_PART_OF_BUNDLE;
1596
1597 list_add_tail(&packet->list, sync_compq);
1598
1599 WARN_ON(!scat_req->scat_list[i].len);
1600 len += scat_req->scat_list[i].len;
1601 }
1602
1603 scat_req->len = len;
1604 scat_req->scat_entries = i;
1605
1606 status = ath6kldev_submit_scat_req(target->dev, scat_req, true);
1607
1608 if (!status)
1609 *n_pkt_fetched = i;
1610
1611 /* free scatter request */
1612 hif_scatter_req_add(target->dev->ar, scat_req);
1613
1614fail_rx_pkt:
1615
1616 return status;
1617}
1618
1619static int htc_proc_fetched_rxpkts(struct htc_target *target,
1620 struct list_head *comp_pktq, u32 lk_ahds[],
1621 int *n_lk_ahd)
1622{
1623 struct htc_packet *packet, *tmp_pkt;
1624 struct htc_endpoint *ep;
1625 int status = 0;
1626
1627 list_for_each_entry_safe(packet, tmp_pkt, comp_pktq, list) {
1628 list_del(&packet->list);
1629 ep = &target->endpoint[packet->endpoint];
1630
1631 /* process header for each of the recv packet */
1632 status = htc_proc_rxhdr(target, packet, lk_ahds, n_lk_ahd);
1633 if (status)
1634 return status;
1635
1636 if (list_empty(comp_pktq)) {
1637 /*
1638 * Last packet's more packet flag is set
1639 * based on the lookahead.
1640 */
1641 if (*n_lk_ahd > 0)
1642 set_rxpkt_indication_flag(lk_ahds[0],
1643 ep, packet);
1644 } else
1645 /*
1646 * Packets in a bundle automatically have
1647 * this flag set.
1648 */
1649 packet->info.rx.indicat_flags |=
1650 HTC_RX_FLAGS_INDICATE_MORE_PKTS;
1651
1652 htc_update_rx_stats(ep, *n_lk_ahd);
1653
1654 if (packet->info.rx.rx_flags & HTC_RX_PKT_PART_OF_BUNDLE)
1655 ep->ep_st.rx_bundl += 1;
1656
1657 do_rx_completion(ep, packet);
1658 }
1659
1660 return status;
1661}
1662
1663static int htc_fetch_rxpkts(struct htc_target *target,
1664 struct list_head *rx_pktq,
1665 struct list_head *comp_pktq)
1666{
1667 int fetched_pkts;
1668 bool part_bundle = false;
1669 int status = 0;
1670
1671 /* now go fetch the list of HTC packets */
1672 while (!list_empty(rx_pktq)) {
1673 fetched_pkts = 0;
1674
1675 if (target->rx_bndl_enable && (get_queue_depth(rx_pktq) > 1)) {
1676 /*
1677 * There are enough packets to attempt a
1678 * bundle transfer and recv bundling is
1679 * allowed.
1680 */
1681 status = htc_issue_rxpkt_bundle(target, rx_pktq,
1682 comp_pktq,
1683 &fetched_pkts,
1684 part_bundle);
1685 if (status)
1686 return status;
1687
1688 if (!list_empty(rx_pktq))
1689 part_bundle = true;
1690 }
1691
1692 if (!fetched_pkts) {
1693 struct htc_packet *packet;
1694
1695 packet = list_first_entry(rx_pktq, struct htc_packet,
1696 list);
1697
1698 list_del(&packet->list);
1699
1700 /* fully synchronous */
1701 packet->completion = NULL;
1702
1703 if (!list_empty(rx_pktq))
1704 /*
1705 * look_aheads in all packet
1706 * except the last one in the
1707 * bundle must be ignored
1708 */
1709 packet->info.rx.rx_flags |=
1710 HTC_RX_PKT_IGNORE_LOOKAHEAD;
1711
1712 /* go fetch the packet */
1713 status = dev_rx_pkt(target, packet, packet->act_len);
1714 if (status)
1715 return status;
1716
1717 list_add_tail(&packet->list, comp_pktq);
1718 }
1719 }
1720
1721 return status;
1722}
1723
1724int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
1725 u32 msg_look_ahead[], int *num_pkts)
1726{
1727 struct htc_packet *packets, *tmp_pkt;
1728 struct htc_endpoint *endpoint;
1729 struct list_head rx_pktq, comp_pktq;
1730 int status = 0;
1731 u32 look_aheads[HTC_HOST_MAX_MSG_PER_BUNDLE];
1732 int num_look_ahead = 1;
1733 enum htc_endpoint_id id;
1734 int n_fetched = 0;
1735
1736 *num_pkts = 0;
1737
1738 /*
1739 * On first entry copy the look_aheads into our temp array for
1740 * processing
1741 */
1742 memcpy(look_aheads, msg_look_ahead, sizeof(look_aheads));
1743
1744 while (true) {
1745
1746 /*
1747 * First lookahead sets the expected endpoint IDs for all
1748 * packets in a bundle.
1749 */
1750 id = ((struct htc_frame_hdr *)&look_aheads[0])->eid;
1751 endpoint = &target->endpoint[id];
1752
1753 if (id >= ENDPOINT_MAX) {
1754 ath6kl_err("MsgPend, invalid endpoint in look-ahead: %d\n",
1755 id);
1756 status = -ENOMEM;
1757 break;
1758 }
1759
1760 INIT_LIST_HEAD(&rx_pktq);
1761 INIT_LIST_HEAD(&comp_pktq);
1762
1763 /*
1764 * Try to allocate as many HTC RX packets indicated by the
1765 * look_aheads.
1766 */
1767 status = alloc_and_prep_rxpkts(target, look_aheads,
1768 num_look_ahead, endpoint,
1769 &rx_pktq);
1770 if (status)
1771 break;
1772
1773 if (get_queue_depth(&rx_pktq) >= 2)
1774 /*
1775 * A recv bundle was detected, force IRQ status
1776 * re-check again
1777 */
1778 target->chk_irq_status_cnt = 1;
1779
1780 n_fetched += get_queue_depth(&rx_pktq);
1781
1782 num_look_ahead = 0;
1783
1784 status = htc_fetch_rxpkts(target, &rx_pktq, &comp_pktq);
1785
1786 if (!status)
1787 chk_rx_water_mark(endpoint);
1788
1789 /* Process fetched packets */
1790 status = htc_proc_fetched_rxpkts(target, &comp_pktq,
1791 look_aheads, &num_look_ahead);
1792
1793 if (!num_look_ahead || status)
1794 break;
1795
1796 /*
1797 * For SYNCH processing, if we get here, we are running
1798 * through the loop again due to a detected lookahead. Set
1799 * flag that we should re-check IRQ status registers again
1800 * before leaving IRQ processing, this can net better
1801 * performance in high throughput situations.
1802 */
1803 target->chk_irq_status_cnt = 1;
1804 }
1805
1806 if (status) {
1807 ath6kl_err("failed to get pending recv messages: %d\n",
1808 status);
1809 /*
1810 * Cleanup any packets we allocated but didn't use to
1811 * actually fetch any packets.
1812 */
1813 list_for_each_entry_safe(packets, tmp_pkt, &rx_pktq, list) {
1814 list_del(&packets->list);
1815 htc_reclaim_rxbuf(target, packets,
1816 &target->endpoint[packets->endpoint]);
1817 }
1818
1819 /* cleanup any packets in sync completion queue */
1820 list_for_each_entry_safe(packets, tmp_pkt, &comp_pktq, list) {
1821 list_del(&packets->list);
1822 htc_reclaim_rxbuf(target, packets,
1823 &target->endpoint[packets->endpoint]);
1824 }
1825
1826 if (target->htc_flags & HTC_OP_STATE_STOPPING) {
1827 ath6kl_warn("host is going to stop blocking receiver for htc_stop\n");
1828 ath6kldev_rx_control(target->dev, false);
1829 }
1830 }
1831
1832 /*
1833 * Before leaving, check to see if host ran out of buffers and
1834 * needs to stop the receiver.
1835 */
1836 if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
1837 ath6kl_warn("host has no rx buffers blocking receiver to prevent overrun\n");
1838 ath6kldev_rx_control(target->dev, false);
1839 }
1840 *num_pkts = n_fetched;
1841
1842 return status;
1843}
1844
1845/*
1846 * Synchronously wait for a control message from the target,
1847 * This function is used at initialization time ONLY. At init messages
1848 * on ENDPOINT 0 are expected.
1849 */
1850static struct htc_packet *htc_wait_for_ctrl_msg(struct htc_target *target)
1851{
1852 struct htc_packet *packet = NULL;
1853 struct htc_frame_hdr *htc_hdr;
1854 u32 look_ahead;
1855
1856 if (ath6kldev_poll_mboxmsg_rx(target->dev, &look_ahead,
1857 HTC_TARGET_RESPONSE_TIMEOUT))
1858 return NULL;
1859
1860 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1861 "htc_wait_for_ctrl_msg: look_ahead : 0x%X\n", look_ahead);
1862
1863 htc_hdr = (struct htc_frame_hdr *)&look_ahead;
1864
1865 if (htc_hdr->eid != ENDPOINT_0)
1866 return NULL;
1867
1868 packet = htc_get_control_buf(target, false);
1869
1870 if (!packet)
1871 return NULL;
1872
1873 packet->info.rx.rx_flags = 0;
1874 packet->info.rx.exp_hdr = look_ahead;
1875 packet->act_len = le16_to_cpu(htc_hdr->payld_len) + HTC_HDR_LENGTH;
1876
1877 if (packet->act_len > packet->buf_len)
1878 goto fail_ctrl_rx;
1879
1880 /* we want synchronous operation */
1881 packet->completion = NULL;
1882
1883 /* get the message from the device, this will block */
1884 if (dev_rx_pkt(target, packet, packet->act_len))
1885 goto fail_ctrl_rx;
1886
1887 /* process receive header */
1888 packet->status = htc_proc_rxhdr(target, packet, NULL, NULL);
1889
1890 if (packet->status) {
1891 ath6kl_err("htc_wait_for_ctrl_msg, htc_proc_rxhdr failed (status = %d)\n",
1892 packet->status);
1893 goto fail_ctrl_rx;
1894 }
1895
1896 return packet;
1897
1898fail_ctrl_rx:
1899 if (packet != NULL) {
1900 htc_rxpkt_reset(packet);
1901 reclaim_rx_ctrl_buf(target, packet);
1902 }
1903
1904 return NULL;
1905}
1906
1907int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
1908 struct list_head *pkt_queue)
1909{
1910 struct htc_endpoint *endpoint;
1911 struct htc_packet *first_pkt;
1912 bool rx_unblock = false;
1913 int status = 0, depth;
1914
1915 if (list_empty(pkt_queue))
1916 return -ENOMEM;
1917
1918 first_pkt = list_first_entry(pkt_queue, struct htc_packet, list);
1919
1920 if (first_pkt->endpoint >= ENDPOINT_MAX)
1921 return status;
1922
1923 depth = get_queue_depth(pkt_queue);
1924
1925 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1926 "htc_add_rxbuf_multiple: ep id: %d, cnt:%d, len: %d\n",
1927 first_pkt->endpoint, depth, first_pkt->buf_len);
1928
1929 endpoint = &target->endpoint[first_pkt->endpoint];
1930
1931 if (target->htc_flags & HTC_OP_STATE_STOPPING) {
1932 struct htc_packet *packet, *tmp_pkt;
1933
1934 /* walk through queue and mark each one canceled */
1935 list_for_each_entry_safe(packet, tmp_pkt, pkt_queue, list) {
1936 packet->status = -ECANCELED;
1937 list_del(&packet->list);
1938 do_rx_completion(endpoint, packet);
1939 }
1940
1941 return status;
1942 }
1943
1944 spin_lock_bh(&target->rx_lock);
1945
1946 list_splice_tail_init(pkt_queue, &endpoint->rx_bufq);
1947
1948 /* check if we are blocked waiting for a new buffer */
1949 if (target->rx_st_flags & HTC_RECV_WAIT_BUFFERS) {
1950 if (target->ep_waiting == first_pkt->endpoint) {
1951 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1952 "receiver was blocked on ep:%d, unblocking.\n",
1953 target->ep_waiting);
1954 target->rx_st_flags &= ~HTC_RECV_WAIT_BUFFERS;
1955 target->ep_waiting = ENDPOINT_MAX;
1956 rx_unblock = true;
1957 }
1958 }
1959
1960 spin_unlock_bh(&target->rx_lock);
1961
1962 if (rx_unblock && !(target->htc_flags & HTC_OP_STATE_STOPPING))
1963 /* TODO : implement a buffer threshold count? */
1964 ath6kldev_rx_control(target->dev, true);
1965
1966 return status;
1967}
1968
1969void ath6kl_htc_flush_rx_buf(struct htc_target *target)
1970{
1971 struct htc_endpoint *endpoint;
1972 struct htc_packet *packet, *tmp_pkt;
1973 int i;
1974
1975 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
1976 endpoint = &target->endpoint[i];
1977 if (!endpoint->svc_id)
1978 /* not in use.. */
1979 continue;
1980
1981 spin_lock_bh(&target->rx_lock);
1982 list_for_each_entry_safe(packet, tmp_pkt,
1983 &endpoint->rx_bufq, list) {
1984 list_del(&packet->list);
1985 spin_unlock_bh(&target->rx_lock);
1986 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
1987 "flushing rx pkt:0x%p, len:%d, ep:%d\n",
1988 packet, packet->buf_len,
1989 packet->endpoint);
1990 dev_kfree_skb(packet->pkt_cntxt);
1991 spin_lock_bh(&target->rx_lock);
1992 }
1993 spin_unlock_bh(&target->rx_lock);
1994 }
1995}
1996
1997int ath6kl_htc_conn_service(struct htc_target *target,
1998 struct htc_service_connect_req *conn_req,
1999 struct htc_service_connect_resp *conn_resp)
2000{
2001 struct htc_packet *rx_pkt = NULL;
2002 struct htc_packet *tx_pkt = NULL;
2003 struct htc_conn_service_resp *resp_msg;
2004 struct htc_conn_service_msg *conn_msg;
2005 struct htc_endpoint *endpoint;
2006 enum htc_endpoint_id assigned_ep = ENDPOINT_MAX;
2007 unsigned int max_msg_sz = 0;
2008 int status = 0;
2009
2010 ath6kl_dbg(ATH6KL_DBG_TRC,
2011 "htc_conn_service, target:0x%p service id:0x%X\n",
2012 target, conn_req->svc_id);
2013
2014 if (conn_req->svc_id == HTC_CTRL_RSVD_SVC) {
2015 /* special case for pseudo control service */
2016 assigned_ep = ENDPOINT_0;
2017 max_msg_sz = HTC_MAX_CTRL_MSG_LEN;
2018 } else {
2019 /* allocate a packet to send to the target */
2020 tx_pkt = htc_get_control_buf(target, true);
2021
2022 if (!tx_pkt)
2023 return -ENOMEM;
2024
2025 conn_msg = (struct htc_conn_service_msg *)tx_pkt->buf;
2026 memset(conn_msg, 0, sizeof(*conn_msg));
2027 conn_msg->msg_id = cpu_to_le16(HTC_MSG_CONN_SVC_ID);
2028 conn_msg->svc_id = cpu_to_le16(conn_req->svc_id);
2029 conn_msg->conn_flags = cpu_to_le16(conn_req->conn_flags);
2030
2031 set_htc_pkt_info(tx_pkt, NULL, (u8 *) conn_msg,
2032 sizeof(*conn_msg) + conn_msg->svc_meta_len,
2033 ENDPOINT_0, HTC_SERVICE_TX_PACKET_TAG);
2034
2035 /* we want synchronous operation */
2036 tx_pkt->completion = NULL;
2037 htc_prep_send_pkt(tx_pkt, 0, 0, 0);
2038 status = htc_issue_send(target, tx_pkt);
2039
2040 if (status)
2041 goto fail_tx;
2042
2043 /* wait for response */
2044 rx_pkt = htc_wait_for_ctrl_msg(target);
2045
2046 if (!rx_pkt) {
2047 status = -ENOMEM;
2048 goto fail_tx;
2049 }
2050
2051 resp_msg = (struct htc_conn_service_resp *)rx_pkt->buf;
2052
2053 if ((le16_to_cpu(resp_msg->msg_id) != HTC_MSG_CONN_SVC_RESP_ID)
2054 || (rx_pkt->act_len < sizeof(*resp_msg))) {
2055 status = -ENOMEM;
2056 goto fail_tx;
2057 }
2058
2059 conn_resp->resp_code = resp_msg->status;
2060 /* check response status */
2061 if (resp_msg->status != HTC_SERVICE_SUCCESS) {
2062 ath6kl_err("target failed service 0x%X connect request (status:%d)\n",
2063 resp_msg->svc_id, resp_msg->status);
2064 status = -ENOMEM;
2065 goto fail_tx;
2066 }
2067
2068 assigned_ep = (enum htc_endpoint_id)resp_msg->eid;
2069 max_msg_sz = le16_to_cpu(resp_msg->max_msg_sz);
2070 }
2071
2072 if (assigned_ep >= ENDPOINT_MAX || !max_msg_sz) {
2073 status = -ENOMEM;
2074 goto fail_tx;
2075 }
2076
2077 endpoint = &target->endpoint[assigned_ep];
2078 endpoint->eid = assigned_ep;
2079 if (endpoint->svc_id) {
2080 status = -ENOMEM;
2081 goto fail_tx;
2082 }
2083
2084 /* return assigned endpoint to caller */
2085 conn_resp->endpoint = assigned_ep;
2086 conn_resp->len_max = max_msg_sz;
2087
2088 /* setup the endpoint */
2089
2090 /* this marks the endpoint in use */
2091 endpoint->svc_id = conn_req->svc_id;
2092
2093 endpoint->max_txq_depth = conn_req->max_txq_depth;
2094 endpoint->len_max = max_msg_sz;
2095 endpoint->ep_cb = conn_req->ep_cb;
2096 endpoint->cred_dist.svc_id = conn_req->svc_id;
2097 endpoint->cred_dist.htc_rsvd = endpoint;
2098 endpoint->cred_dist.endpoint = assigned_ep;
2099 endpoint->cred_dist.cred_sz = target->tgt_cred_sz;
2100
2101 if (conn_req->max_rxmsg_sz) {
2102 /*
2103 * Override cred_per_msg calculation, this optimizes
2104 * the credit-low indications since the host will actually
2105 * issue smaller messages in the Send path.
2106 */
2107 if (conn_req->max_rxmsg_sz > max_msg_sz) {
2108 status = -ENOMEM;
2109 goto fail_tx;
2110 }
2111 endpoint->cred_dist.cred_per_msg =
2112 conn_req->max_rxmsg_sz / target->tgt_cred_sz;
2113 } else
2114 endpoint->cred_dist.cred_per_msg =
2115 max_msg_sz / target->tgt_cred_sz;
2116
2117 if (!endpoint->cred_dist.cred_per_msg)
2118 endpoint->cred_dist.cred_per_msg = 1;
2119
2120 /* save local connection flags */
2121 endpoint->conn_flags = conn_req->flags;
2122
2123fail_tx:
2124 if (tx_pkt)
2125 htc_reclaim_txctrl_buf(target, tx_pkt);
2126
2127 if (rx_pkt) {
2128 htc_rxpkt_reset(rx_pkt);
2129 reclaim_rx_ctrl_buf(target, rx_pkt);
2130 }
2131
2132 return status;
2133}
2134
2135static void reset_ep_state(struct htc_target *target)
2136{
2137 struct htc_endpoint *endpoint;
2138 int i;
2139
2140 for (i = ENDPOINT_0; i < ENDPOINT_MAX; i++) {
2141 endpoint = &target->endpoint[i];
2142 memset(&endpoint->cred_dist, 0, sizeof(endpoint->cred_dist));
2143 endpoint->svc_id = 0;
2144 endpoint->len_max = 0;
2145 endpoint->max_txq_depth = 0;
2146 memset(&endpoint->ep_st, 0,
2147 sizeof(endpoint->ep_st));
2148 INIT_LIST_HEAD(&endpoint->rx_bufq);
2149 INIT_LIST_HEAD(&endpoint->txq);
2150 endpoint->target = target;
2151 }
2152
2153 /* reset distribution list */
2154 INIT_LIST_HEAD(&target->cred_dist_list);
2155}
2156
2157int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
2158 enum htc_endpoint_id endpoint)
2159{
2160 int num;
2161
2162 spin_lock_bh(&target->rx_lock);
2163 num = get_queue_depth(&(target->endpoint[endpoint].rx_bufq));
2164 spin_unlock_bh(&target->rx_lock);
2165 return num;
2166}
2167
2168static void htc_setup_msg_bndl(struct htc_target *target)
2169{
2170 /* limit what HTC can handle */
2171 target->msg_per_bndl_max = min(HTC_HOST_MAX_MSG_PER_BUNDLE,
2172 target->msg_per_bndl_max);
2173
2174 if (ath6kl_hif_enable_scatter(target->dev->ar)) {
2175 target->msg_per_bndl_max = 0;
2176 return;
2177 }
2178
2179 /* limit bundle what the device layer can handle */
2180 target->msg_per_bndl_max = min(target->max_scat_entries,
2181 target->msg_per_bndl_max);
2182
2183 ath6kl_dbg(ATH6KL_DBG_TRC,
2184 "htc bundling allowed. max msg per htc bundle: %d\n",
2185 target->msg_per_bndl_max);
2186
2187 /* Max rx bundle size is limited by the max tx bundle size */
2188 target->max_rx_bndl_sz = target->max_xfer_szper_scatreq;
2189 /* Max tx bundle size if limited by the extended mbox address range */
2190 target->max_tx_bndl_sz = min(HIF_MBOX0_EXT_WIDTH,
2191 target->max_xfer_szper_scatreq);
2192
2193 ath6kl_dbg(ATH6KL_DBG_ANY, "max recv: %d max send: %d\n",
2194 target->max_rx_bndl_sz, target->max_tx_bndl_sz);
2195
2196 if (target->max_tx_bndl_sz)
2197 target->tx_bndl_enable = true;
2198
2199 if (target->max_rx_bndl_sz)
2200 target->rx_bndl_enable = true;
2201
2202 if ((target->tgt_cred_sz % target->block_sz) != 0) {
2203 ath6kl_warn("credit size: %d is not block aligned! Disabling send bundling\n",
2204 target->tgt_cred_sz);
2205
2206 /*
2207 * Disallow send bundling since the credit size is
2208 * not aligned to a block size the I/O block
2209 * padding will spill into the next credit buffer
2210 * which is fatal.
2211 */
2212 target->tx_bndl_enable = false;
2213 }
2214}
2215
2216int ath6kl_htc_wait_target(struct htc_target *target)
2217{
2218 struct htc_packet *packet = NULL;
2219 struct htc_ready_ext_msg *rdy_msg;
2220 struct htc_service_connect_req connect;
2221 struct htc_service_connect_resp resp;
2222 int status;
2223
2224 /* we should be getting 1 control message that the target is ready */
2225 packet = htc_wait_for_ctrl_msg(target);
2226
2227 if (!packet)
2228 return -ENOMEM;
2229
2230 /* we controlled the buffer creation so it's properly aligned */
2231 rdy_msg = (struct htc_ready_ext_msg *)packet->buf;
2232
2233 if ((le16_to_cpu(rdy_msg->ver2_0_info.msg_id) != HTC_MSG_READY_ID) ||
2234 (packet->act_len < sizeof(struct htc_ready_msg))) {
2235 status = -ENOMEM;
2236 goto fail_wait_target;
2237 }
2238
2239 if (!rdy_msg->ver2_0_info.cred_cnt || !rdy_msg->ver2_0_info.cred_sz) {
2240 status = -ENOMEM;
2241 goto fail_wait_target;
2242 }
2243
2244 target->tgt_creds = le16_to_cpu(rdy_msg->ver2_0_info.cred_cnt);
2245 target->tgt_cred_sz = le16_to_cpu(rdy_msg->ver2_0_info.cred_sz);
2246
2247 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
2248 "target ready: credits: %d credit size: %d\n",
2249 target->tgt_creds, target->tgt_cred_sz);
2250
2251 /* check if this is an extended ready message */
2252 if (packet->act_len >= sizeof(struct htc_ready_ext_msg)) {
2253 /* this is an extended message */
2254 target->htc_tgt_ver = rdy_msg->htc_ver;
2255 target->msg_per_bndl_max = rdy_msg->msg_per_htc_bndl;
2256 } else {
2257 /* legacy */
2258 target->htc_tgt_ver = HTC_VERSION_2P0;
2259 target->msg_per_bndl_max = 0;
2260 }
2261
2262 ath6kl_dbg(ATH6KL_DBG_TRC, "using htc protocol version : %s (%d)\n",
2263 (target->htc_tgt_ver == HTC_VERSION_2P0) ? "2.0" : ">= 2.1",
2264 target->htc_tgt_ver);
2265
2266 if (target->msg_per_bndl_max > 0)
2267 htc_setup_msg_bndl(target);
2268
2269 /* setup our pseudo HTC control endpoint connection */
2270 memset(&connect, 0, sizeof(connect));
2271 memset(&resp, 0, sizeof(resp));
2272 connect.ep_cb.rx = htc_ctrl_rx;
2273 connect.ep_cb.rx_refill = NULL;
2274 connect.ep_cb.tx_full = NULL;
2275 connect.max_txq_depth = NUM_CONTROL_BUFFERS;
2276 connect.svc_id = HTC_CTRL_RSVD_SVC;
2277
2278 /* connect fake service */
2279 status = ath6kl_htc_conn_service((void *)target, &connect, &resp);
2280
2281 if (status)
2282 ath6kl_hif_cleanup_scatter(target->dev->ar);
2283
2284fail_wait_target:
2285 if (packet) {
2286 htc_rxpkt_reset(packet);
2287 reclaim_rx_ctrl_buf(target, packet);
2288 }
2289
2290 return status;
2291}
2292
2293/*
2294 * Start HTC, enable interrupts and let the target know
2295 * host has finished setup.
2296 */
2297int ath6kl_htc_start(struct htc_target *target)
2298{
2299 struct htc_packet *packet;
2300 int status;
2301
2302 /* Disable interrupts at the chip level */
2303 ath6kldev_disable_intrs(target->dev);
2304
2305 target->htc_flags = 0;
2306 target->rx_st_flags = 0;
2307
2308 /* Push control receive buffers into htc control endpoint */
2309 while ((packet = htc_get_control_buf(target, false)) != NULL) {
2310 status = htc_add_rxbuf(target, packet);
2311 if (status)
2312 return status;
2313 }
2314
2315 /* NOTE: the first entry in the distribution list is ENDPOINT_0 */
2316 ath6k_credit_init(target->cred_dist_cntxt, &target->cred_dist_list,
2317 target->tgt_creds);
2318
2319 dump_cred_dist_stats(target);
2320
2321 /* Indicate to the target of the setup completion */
2322 status = htc_setup_tx_complete(target);
2323
2324 if (status)
2325 return status;
2326
2327 /* unmask interrupts */
2328 status = ath6kldev_unmask_intrs(target->dev);
2329
2330 if (status)
2331 ath6kl_htc_stop(target);
2332
2333 return status;
2334}
2335
2336/* htc_stop: stop interrupt reception, and flush all queued buffers */
2337void ath6kl_htc_stop(struct htc_target *target)
2338{
2339 spin_lock_bh(&target->htc_lock);
2340 target->htc_flags |= HTC_OP_STATE_STOPPING;
2341 spin_unlock_bh(&target->htc_lock);
2342
2343 /*
2344 * Masking interrupts is a synchronous operation, when this
2345 * function returns all pending HIF I/O has completed, we can
2346 * safely flush the queues.
2347 */
2348 ath6kldev_mask_intrs(target->dev);
2349
2350 ath6kl_htc_flush_txep_all(target);
2351
2352 ath6kl_htc_flush_rx_buf(target);
2353
2354 reset_ep_state(target);
2355}
2356
2357void *ath6kl_htc_create(struct ath6kl *ar)
2358{
2359 struct htc_target *target = NULL;
2360 struct htc_packet *packet;
2361 int status = 0, i = 0;
2362 u32 block_size, ctrl_bufsz;
2363
2364 target = kzalloc(sizeof(*target), GFP_KERNEL);
2365 if (!target) {
2366 ath6kl_err("unable to allocate memory\n");
2367 return NULL;
2368 }
2369
2370 target->dev = kzalloc(sizeof(*target->dev), GFP_KERNEL);
2371 if (!target->dev) {
2372 ath6kl_err("unable to allocate memory\n");
2373 status = -ENOMEM;
2374 goto fail_create_htc;
2375 }
2376
2377 spin_lock_init(&target->htc_lock);
2378 spin_lock_init(&target->rx_lock);
2379 spin_lock_init(&target->tx_lock);
2380
2381 INIT_LIST_HEAD(&target->free_ctrl_txbuf);
2382 INIT_LIST_HEAD(&target->free_ctrl_rxbuf);
2383 INIT_LIST_HEAD(&target->cred_dist_list);
2384
2385 target->dev->ar = ar;
2386 target->dev->htc_cnxt = target;
2387 target->ep_waiting = ENDPOINT_MAX;
2388
2389 reset_ep_state(target);
2390
2391 status = ath6kldev_setup(target->dev);
2392
2393 if (status)
2394 goto fail_create_htc;
2395
2396 block_size = ar->mbox_info.block_size;
2397
2398 ctrl_bufsz = (block_size > HTC_MAX_CTRL_MSG_LEN) ?
2399 (block_size + HTC_HDR_LENGTH) :
2400 (HTC_MAX_CTRL_MSG_LEN + HTC_HDR_LENGTH);
2401
2402 for (i = 0; i < NUM_CONTROL_BUFFERS; i++) {
2403 packet = kzalloc(sizeof(*packet), GFP_KERNEL);
2404 if (!packet)
2405 break;
2406
2407 packet->buf_start = kzalloc(ctrl_bufsz, GFP_KERNEL);
2408 if (!packet->buf_start) {
2409 kfree(packet);
2410 break;
2411 }
2412
2413 packet->buf_len = ctrl_bufsz;
2414 if (i < NUM_CONTROL_RX_BUFFERS) {
2415 packet->act_len = 0;
2416 packet->buf = packet->buf_start;
2417 packet->endpoint = ENDPOINT_0;
2418 list_add_tail(&packet->list, &target->free_ctrl_rxbuf);
2419 } else
2420 list_add_tail(&packet->list, &target->free_ctrl_txbuf);
2421 }
2422
2423fail_create_htc:
2424 if (i != NUM_CONTROL_BUFFERS || status) {
2425 if (target) {
2426 ath6kl_htc_cleanup(target);
2427 target = NULL;
2428 }
2429 }
2430
2431 return target;
2432}
2433
2434/* cleanup the HTC instance */
2435void ath6kl_htc_cleanup(struct htc_target *target)
2436{
2437 struct htc_packet *packet, *tmp_packet;
2438
2439 ath6kl_hif_cleanup_scatter(target->dev->ar);
2440
2441 list_for_each_entry_safe(packet, tmp_packet,
2442 &target->free_ctrl_txbuf, list) {
2443 list_del(&packet->list);
2444 kfree(packet->buf_start);
2445 kfree(packet);
2446 }
2447
2448 list_for_each_entry_safe(packet, tmp_packet,
2449 &target->free_ctrl_rxbuf, list) {
2450 list_del(&packet->list);
2451 kfree(packet->buf_start);
2452 kfree(packet);
2453 }
2454
2455 kfree(target->dev);
2456 kfree(target);
2457}
diff --git a/drivers/net/wireless/ath/ath6kl/htc.h b/drivers/net/wireless/ath/ath6kl/htc.h
new file mode 100644
index 000000000000..8ce0c2c07ded
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc.h
@@ -0,0 +1,607 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef HTC_H
18#define HTC_H
19
20#include "common.h"
21
22/* frame header flags */
23
24/* send direction */
25#define HTC_FLAGS_NEED_CREDIT_UPDATE (1 << 0)
26#define HTC_FLAGS_SEND_BUNDLE (1 << 1)
27
28/* receive direction */
29#define HTC_FLG_RX_UNUSED (1 << 0)
30#define HTC_FLG_RX_TRAILER (1 << 1)
31/* Bundle count maske and shift */
32#define HTC_FLG_RX_BNDL_CNT (0xF0)
33#define HTC_FLG_RX_BNDL_CNT_S 4
34
35#define HTC_HDR_LENGTH (sizeof(struct htc_frame_hdr))
36#define HTC_MAX_PAYLOAD_LENGTH (4096 - sizeof(struct htc_frame_hdr))
37
38/* HTC control message IDs */
39
40#define HTC_MSG_READY_ID 1
41#define HTC_MSG_CONN_SVC_ID 2
42#define HTC_MSG_CONN_SVC_RESP_ID 3
43#define HTC_MSG_SETUP_COMPLETE_ID 4
44#define HTC_MSG_SETUP_COMPLETE_EX_ID 5
45
46#define HTC_MAX_CTRL_MSG_LEN 256
47
48#define HTC_VERSION_2P0 0x00
49#define HTC_VERSION_2P1 0x01
50
51#define HTC_SERVICE_META_DATA_MAX_LENGTH 128
52
53#define HTC_CONN_FLGS_THRESH_LVL_QUAT 0x0
54#define HTC_CONN_FLGS_THRESH_LVL_HALF 0x1
55#define HTC_CONN_FLGS_THRESH_LVL_THREE_QUAT 0x2
56#define HTC_CONN_FLGS_REDUCE_CRED_DRIB 0x4
57#define HTC_CONN_FLGS_THRESH_MASK 0x3
58
59/* connect response status codes */
60#define HTC_SERVICE_SUCCESS 0
61#define HTC_SERVICE_NOT_FOUND 1
62#define HTC_SERVICE_FAILED 2
63
64/* no resources (i.e. no more endpoints) */
65#define HTC_SERVICE_NO_RESOURCES 3
66
67/* specific service is not allowing any more endpoints */
68#define HTC_SERVICE_NO_MORE_EP 4
69
70/* report record IDs */
71#define HTC_RECORD_NULL 0
72#define HTC_RECORD_CREDITS 1
73#define HTC_RECORD_LOOKAHEAD 2
74#define HTC_RECORD_LOOKAHEAD_BUNDLE 3
75
76#define HTC_SETUP_COMP_FLG_RX_BNDL_EN (1 << 0)
77
78#define MAKE_SERVICE_ID(group, index) \
79 (int)(((int)group << 8) | (int)(index))
80
81/* NOTE: service ID of 0x0000 is reserved and should never be used */
82#define HTC_CTRL_RSVD_SVC MAKE_SERVICE_ID(RSVD_SERVICE_GROUP, 1)
83#define WMI_CONTROL_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 0)
84#define WMI_DATA_BE_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 1)
85#define WMI_DATA_BK_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 2)
86#define WMI_DATA_VI_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 3)
87#define WMI_DATA_VO_SVC MAKE_SERVICE_ID(WMI_SERVICE_GROUP, 4)
88#define WMI_MAX_SERVICES 5
89
90/* reserved and used to flush ALL packets */
91#define HTC_TX_PACKET_TAG_ALL 0
92#define HTC_SERVICE_TX_PACKET_TAG 1
93#define HTC_TX_PACKET_TAG_USER_DEFINED (HTC_SERVICE_TX_PACKET_TAG + 9)
94
95/* more packets on this endpoint are being fetched */
96#define HTC_RX_FLAGS_INDICATE_MORE_PKTS (1 << 0)
97
98/* TODO.. for BMI */
99#define ENDPOINT1 0
100/* TODO -remove me, but we have to fix BMI first */
101#define HTC_MAILBOX_NUM_MAX 4
102
103/* enable send bundle padding for this endpoint */
104#define HTC_FLGS_TX_BNDL_PAD_EN (1 << 0)
105#define HTC_EP_ACTIVE ((u32) (1u << 31))
106
107/* HTC operational parameters */
108#define HTC_TARGET_RESPONSE_TIMEOUT 2000 /* in ms */
109#define HTC_TARGET_DEBUG_INTR_MASK 0x01
110#define HTC_TARGET_CREDIT_INTR_MASK 0xF0
111
112#define HTC_HOST_MAX_MSG_PER_BUNDLE 8
113#define HTC_MIN_HTC_MSGS_TO_BUNDLE 2
114
115/* packet flags */
116
117#define HTC_RX_PKT_IGNORE_LOOKAHEAD (1 << 0)
118#define HTC_RX_PKT_REFRESH_HDR (1 << 1)
119#define HTC_RX_PKT_PART_OF_BUNDLE (1 << 2)
120#define HTC_RX_PKT_NO_RECYCLE (1 << 3)
121
122#define NUM_CONTROL_BUFFERS 8
123#define NUM_CONTROL_TX_BUFFERS 2
124#define NUM_CONTROL_RX_BUFFERS (NUM_CONTROL_BUFFERS - NUM_CONTROL_TX_BUFFERS)
125
126#define HTC_RECV_WAIT_BUFFERS (1 << 0)
127#define HTC_OP_STATE_STOPPING (1 << 0)
128
129/*
130 * The frame header length and message formats defined herein were selected
131 * to accommodate optimal alignment for target processing. This reduces
132 * code size and improves performance. Any changes to the header length may
133 * alter the alignment and cause exceptions on the target. When adding to
134 * the messagestructures insure that fields are properly aligned.
135 */
136
137/* HTC frame header
138 *
139 * NOTE: do not remove or re-arrange the fields, these are minimally
140 * required to take advantage of 4-byte lookaheads in some hardware
141 * implementations.
142 */
143struct htc_frame_hdr {
144 u8 eid;
145 u8 flags;
146
147 /* length of data (including trailer) that follows the header */
148 __le16 payld_len;
149
150 /* end of 4-byte lookahead */
151
152 u8 ctrl[2];
153} __packed;
154
155/* HTC ready message */
156struct htc_ready_msg {
157 __le16 msg_id;
158 __le16 cred_cnt;
159 __le16 cred_sz;
160 u8 max_ep;
161 u8 pad;
162} __packed;
163
164/* extended HTC ready message */
165struct htc_ready_ext_msg {
166 struct htc_ready_msg ver2_0_info;
167 u8 htc_ver;
168 u8 msg_per_htc_bndl;
169} __packed;
170
171/* connect service */
172struct htc_conn_service_msg {
173 __le16 msg_id;
174 __le16 svc_id;
175 __le16 conn_flags;
176 u8 svc_meta_len;
177 u8 pad;
178} __packed;
179
180/* connect response */
181struct htc_conn_service_resp {
182 __le16 msg_id;
183 __le16 svc_id;
184 u8 status;
185 u8 eid;
186 __le16 max_msg_sz;
187 u8 svc_meta_len;
188 u8 pad;
189} __packed;
190
191struct htc_setup_comp_msg {
192 __le16 msg_id;
193} __packed;
194
195/* extended setup completion message */
196struct htc_setup_comp_ext_msg {
197 __le16 msg_id;
198 __le32 flags;
199 u8 msg_per_rxbndl;
200 u8 Rsvd[3];
201} __packed;
202
203struct htc_record_hdr {
204 u8 rec_id;
205 u8 len;
206} __packed;
207
208struct htc_credit_report {
209 u8 eid;
210 u8 credits;
211} __packed;
212
213/*
214 * NOTE: The lk_ahd array is guarded by a pre_valid
215 * and Post Valid guard bytes. The pre_valid bytes must
216 * equal the inverse of the post_valid byte.
217 */
218struct htc_lookahead_report {
219 u8 pre_valid;
220 u8 lk_ahd[4];
221 u8 post_valid;
222} __packed;
223
224struct htc_bundle_lkahd_rpt {
225 u8 lk_ahd[4];
226} __packed;
227
228/* Current service IDs */
229
230enum htc_service_grp_ids {
231 RSVD_SERVICE_GROUP = 0,
232 WMI_SERVICE_GROUP = 1,
233
234 HTC_TEST_GROUP = 254,
235 HTC_SERVICE_GROUP_LAST = 255
236};
237
238/* ------ endpoint IDS ------ */
239
240enum htc_endpoint_id {
241 ENDPOINT_UNUSED = -1,
242 ENDPOINT_0 = 0,
243 ENDPOINT_1 = 1,
244 ENDPOINT_2 = 2,
245 ENDPOINT_3,
246 ENDPOINT_4,
247 ENDPOINT_5,
248 ENDPOINT_6,
249 ENDPOINT_7,
250 ENDPOINT_8,
251 ENDPOINT_MAX,
252};
253
254struct htc_tx_packet_info {
255 u16 tag;
256 int cred_used;
257 u8 flags;
258 int seqno;
259};
260
261struct htc_rx_packet_info {
262 u32 exp_hdr;
263 u32 rx_flags;
264 u32 indicat_flags;
265};
266
267struct htc_target;
268
269/* wrapper around endpoint-specific packets */
270struct htc_packet {
271 struct list_head list;
272
273 /* caller's per packet specific context */
274 void *pkt_cntxt;
275
276 /*
277 * the true buffer start , the caller can store the real
278 * buffer start here. In receive callbacks, the HTC layer
279 * sets buf to the start of the payload past the header.
280 * This field allows the caller to reset buf when it recycles
281 * receive packets back to HTC.
282 */
283 u8 *buf_start;
284
285 /*
286 * Pointer to the start of the buffer. In the transmit
287 * direction this points to the start of the payload. In the
288 * receive direction, however, the buffer when queued up
289 * points to the start of the HTC header but when returned
290 * to the caller points to the start of the payload
291 */
292 u8 *buf;
293 u32 buf_len;
294
295 /* actual length of payload */
296 u32 act_len;
297
298 /* endpoint that this packet was sent/recv'd from */
299 enum htc_endpoint_id endpoint;
300
301 /* completion status */
302
303 int status;
304 union {
305 struct htc_tx_packet_info tx;
306 struct htc_rx_packet_info rx;
307 } info;
308
309 void (*completion) (struct htc_target *, struct htc_packet *);
310 struct htc_target *context;
311};
312
313enum htc_send_full_action {
314 HTC_SEND_FULL_KEEP = 0,
315 HTC_SEND_FULL_DROP = 1,
316};
317
318struct htc_ep_callbacks {
319 void (*rx) (struct htc_target *, struct htc_packet *);
320 void (*rx_refill) (struct htc_target *, enum htc_endpoint_id endpoint);
321 enum htc_send_full_action (*tx_full) (struct htc_target *,
322 struct htc_packet *);
323 struct htc_packet *(*rx_allocthresh) (struct htc_target *,
324 enum htc_endpoint_id, int);
325 int rx_alloc_thresh;
326 int rx_refill_thresh;
327};
328
329/* service connection information */
330struct htc_service_connect_req {
331 u16 svc_id;
332 u16 conn_flags;
333 struct htc_ep_callbacks ep_cb;
334 int max_txq_depth;
335 u32 flags;
336 unsigned int max_rxmsg_sz;
337};
338
339/* service connection response information */
340struct htc_service_connect_resp {
341 u8 buf_len;
342 u8 act_len;
343 enum htc_endpoint_id endpoint;
344 unsigned int len_max;
345 u8 resp_code;
346};
347
348/* endpoint distributionstructure */
349struct htc_endpoint_credit_dist {
350 struct list_head list;
351
352 /* Service ID (set by HTC) */
353 u16 svc_id;
354
355 /* endpoint for this distributionstruct (set by HTC) */
356 enum htc_endpoint_id endpoint;
357
358 u32 dist_flags;
359
360 /*
361 * credits for normal operation, anything above this
362 * indicates the endpoint is over-subscribed.
363 */
364 int cred_norm;
365
366 /* floor for credit distribution */
367 int cred_min;
368
369 int cred_assngd;
370
371 /* current credits available */
372 int credits;
373
374 /*
375 * pending credits to distribute on this endpoint, this
376 * is set by HTC when credit reports arrive. The credit
377 * distribution functions sets this to zero when it distributes
378 * the credits.
379 */
380 int cred_to_dist;
381
382 /*
383 * the number of credits that the current pending TX packet needs
384 * to transmit. This is set by HTC when endpoint needs credits in
385 * order to transmit.
386 */
387 int seek_cred;
388
389 /* size in bytes of each credit */
390 int cred_sz;
391
392 /* credits required for a maximum sized messages */
393 int cred_per_msg;
394
395 /* reserved for HTC use */
396 void *htc_rsvd;
397
398 /*
399 * current depth of TX queue , i.e. messages waiting for credits
400 * This field is valid only when HTC_CREDIT_DIST_ACTIVITY_CHANGE
401 * or HTC_CREDIT_DIST_SEND_COMPLETE is indicated on an endpoint
402 * that has non-zero credits to recover.
403 */
404 int txq_depth;
405};
406
407/*
408 * credit distibution code that is passed into the distrbution function,
409 * there are mandatory and optional codes that must be handled
410 */
411enum htc_credit_dist_reason {
412 HTC_CREDIT_DIST_SEND_COMPLETE = 0,
413 HTC_CREDIT_DIST_ACTIVITY_CHANGE = 1,
414 HTC_CREDIT_DIST_SEEK_CREDITS,
415};
416
417struct htc_credit_state_info {
418 int total_avail_credits;
419 int cur_free_credits;
420 struct list_head lowestpri_ep_dist;
421};
422
423/* endpoint statistics */
424struct htc_endpoint_stats {
425 /*
426 * number of times the host set the credit-low flag in a send
427 * message on this endpoint
428 */
429 u32 cred_low_indicate;
430
431 u32 tx_issued;
432 u32 tx_pkt_bundled;
433 u32 tx_bundles;
434 u32 tx_dropped;
435
436 /* running count of total credit reports received for this endpoint */
437 u32 tx_cred_rpt;
438
439 /* credit reports received from this endpoint's RX packets */
440 u32 cred_rpt_from_rx;
441
442 /* credit reports received from RX packets of other endpoints */
443 u32 cred_rpt_from_other;
444
445 /* credit reports received from endpoint 0 RX packets */
446 u32 cred_rpt_ep0;
447
448 /* count of credits received via Rx packets on this endpoint */
449 u32 cred_from_rx;
450
451 /* count of credits received via another endpoint */
452 u32 cred_from_other;
453
454 /* count of credits received via another endpoint */
455 u32 cred_from_ep0;
456
457 /* count of consummed credits */
458 u32 cred_cosumd;
459
460 /* count of credits returned */
461 u32 cred_retnd;
462
463 u32 rx_pkts;
464
465 /* count of lookahead records found in Rx msg */
466 u32 rx_lkahds;
467
468 /* count of recv packets received in a bundle */
469 u32 rx_bundl;
470
471 /* count of number of bundled lookaheads */
472 u32 rx_bundle_lkahd;
473
474 /* count of the number of bundle indications from the HTC header */
475 u32 rx_bundle_from_hdr;
476
477 /* the number of times the recv allocation threshold was hit */
478 u32 rx_alloc_thresh_hit;
479
480 /* total number of bytes */
481 u32 rxalloc_thresh_byte;
482};
483
484struct htc_endpoint {
485 enum htc_endpoint_id eid;
486 u16 svc_id;
487 struct list_head txq;
488 struct list_head rx_bufq;
489 struct htc_endpoint_credit_dist cred_dist;
490 struct htc_ep_callbacks ep_cb;
491 int max_txq_depth;
492 int len_max;
493 int tx_proc_cnt;
494 int rx_proc_cnt;
495 struct htc_target *target;
496 u8 seqno;
497 u32 conn_flags;
498 struct htc_endpoint_stats ep_st;
499};
500
501struct htc_control_buffer {
502 struct htc_packet packet;
503 u8 *buf;
504};
505
506struct ath6kl_device;
507
508/* our HTC target state */
509struct htc_target {
510 struct htc_endpoint endpoint[ENDPOINT_MAX];
511 struct list_head cred_dist_list;
512 struct list_head free_ctrl_txbuf;
513 struct list_head free_ctrl_rxbuf;
514 struct htc_credit_state_info *cred_dist_cntxt;
515 int tgt_creds;
516 unsigned int tgt_cred_sz;
517 spinlock_t htc_lock;
518 spinlock_t rx_lock;
519 spinlock_t tx_lock;
520 struct ath6kl_device *dev;
521 u32 htc_flags;
522 u32 rx_st_flags;
523 enum htc_endpoint_id ep_waiting;
524 u8 htc_tgt_ver;
525
526 /* max messages per bundle for HTC */
527 int msg_per_bndl_max;
528
529 bool tx_bndl_enable;
530 int rx_bndl_enable;
531 int max_rx_bndl_sz;
532 int max_tx_bndl_sz;
533
534 u32 block_sz;
535 u32 block_mask;
536
537 int max_scat_entries;
538 int max_xfer_szper_scatreq;
539
540 int chk_irq_status_cnt;
541};
542
543void *ath6kl_htc_create(struct ath6kl *ar);
544void ath6kl_htc_set_credit_dist(struct htc_target *target,
545 struct htc_credit_state_info *cred_info,
546 u16 svc_pri_order[], int len);
547int ath6kl_htc_wait_target(struct htc_target *target);
548int ath6kl_htc_start(struct htc_target *target);
549int ath6kl_htc_conn_service(struct htc_target *target,
550 struct htc_service_connect_req *req,
551 struct htc_service_connect_resp *resp);
552int ath6kl_htc_tx(struct htc_target *target, struct htc_packet *packet);
553void ath6kl_htc_stop(struct htc_target *target);
554void ath6kl_htc_cleanup(struct htc_target *target);
555void ath6kl_htc_flush_txep(struct htc_target *target,
556 enum htc_endpoint_id endpoint, u16 tag);
557void ath6kl_htc_flush_rx_buf(struct htc_target *target);
558void ath6kl_htc_indicate_activity_change(struct htc_target *target,
559 enum htc_endpoint_id endpoint,
560 bool active);
561int ath6kl_htc_get_rxbuf_num(struct htc_target *target,
562 enum htc_endpoint_id endpoint);
563int ath6kl_htc_add_rxbuf_multiple(struct htc_target *target,
564 struct list_head *pktq);
565int ath6kl_htc_rxmsg_pending_handler(struct htc_target *target,
566 u32 msg_look_ahead[], int *n_pkts);
567
568static inline void set_htc_pkt_info(struct htc_packet *packet, void *context,
569 u8 *buf, unsigned int len,
570 enum htc_endpoint_id eid, u16 tag)
571{
572 packet->pkt_cntxt = context;
573 packet->buf = buf;
574 packet->act_len = len;
575 packet->endpoint = eid;
576 packet->info.tx.tag = tag;
577}
578
579static inline void htc_rxpkt_reset(struct htc_packet *packet)
580{
581 packet->buf = packet->buf_start;
582 packet->act_len = 0;
583}
584
585static inline void set_htc_rxpkt_info(struct htc_packet *packet, void *context,
586 u8 *buf, unsigned long len,
587 enum htc_endpoint_id eid)
588{
589 packet->pkt_cntxt = context;
590 packet->buf = buf;
591 packet->buf_start = buf;
592 packet->buf_len = len;
593 packet->endpoint = eid;
594}
595
596static inline int get_queue_depth(struct list_head *queue)
597{
598 struct list_head *tmp_list;
599 int depth = 0;
600
601 list_for_each(tmp_list, queue)
602 depth++;
603
604 return depth;
605}
606
607#endif
diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.c b/drivers/net/wireless/ath/ath6kl/htc_hif.c
new file mode 100644
index 000000000000..86b1cc7409c2
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc_hif.c
@@ -0,0 +1,641 @@
1/*
2 * Copyright (c) 2007-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "target.h"
19#include "hif-ops.h"
20#include "htc_hif.h"
21#include "debug.h"
22
23#define MAILBOX_FOR_BLOCK_SIZE 1
24
25#define ATH6KL_TIME_QUANTUM 10 /* in ms */
26
27static int ath6kldev_cp_scat_dma_buf(struct hif_scatter_req *req, bool from_dma)
28{
29 u8 *buf;
30 int i;
31
32 buf = req->virt_dma_buf;
33
34 for (i = 0; i < req->scat_entries; i++) {
35
36 if (from_dma)
37 memcpy(req->scat_list[i].buf, buf,
38 req->scat_list[i].len);
39 else
40 memcpy(buf, req->scat_list[i].buf,
41 req->scat_list[i].len);
42
43 buf += req->scat_list[i].len;
44 }
45
46 return 0;
47}
48
49int ath6kldev_rw_comp_handler(void *context, int status)
50{
51 struct htc_packet *packet = context;
52
53 ath6kl_dbg(ATH6KL_DBG_HTC_RECV,
54 "ath6kldev_rw_comp_handler (pkt:0x%p , status: %d\n",
55 packet, status);
56
57 packet->status = status;
58 packet->completion(packet->context, packet);
59
60 return 0;
61}
62
63static int ath6kldev_proc_dbg_intr(struct ath6kl_device *dev)
64{
65 u32 dummy;
66 int status;
67
68 ath6kl_err("target debug interrupt\n");
69
70 ath6kl_target_failure(dev->ar);
71
72 /*
73 * read counter to clear the interrupt, the debug error interrupt is
74 * counter 0.
75 */
76 status = hif_read_write_sync(dev->ar, COUNT_DEC_ADDRESS,
77 (u8 *)&dummy, 4, HIF_RD_SYNC_BYTE_INC);
78 if (status)
79 WARN_ON(1);
80
81 return status;
82}
83
84/* mailbox recv message polling */
85int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev, u32 *lk_ahd,
86 int timeout)
87{
88 struct ath6kl_irq_proc_registers *rg;
89 int status = 0, i;
90 u8 htc_mbox = 1 << HTC_MAILBOX;
91
92 for (i = timeout / ATH6KL_TIME_QUANTUM; i > 0; i--) {
93 /* this is the standard HIF way, load the reg table */
94 status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS,
95 (u8 *) &dev->irq_proc_reg,
96 sizeof(dev->irq_proc_reg),
97 HIF_RD_SYNC_BYTE_INC);
98
99 if (status) {
100 ath6kl_err("failed to read reg table\n");
101 return status;
102 }
103
104 /* check for MBOX data and valid lookahead */
105 if (dev->irq_proc_reg.host_int_status & htc_mbox) {
106 if (dev->irq_proc_reg.rx_lkahd_valid &
107 htc_mbox) {
108 /*
109 * Mailbox has a message and the look ahead
110 * is valid.
111 */
112 rg = &dev->irq_proc_reg;
113 *lk_ahd =
114 le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]);
115 break;
116 }
117 }
118
119 /* delay a little */
120 mdelay(ATH6KL_TIME_QUANTUM);
121 ath6kl_dbg(ATH6KL_DBG_HTC_RECV, "retry mbox poll : %d\n", i);
122 }
123
124 if (i == 0) {
125 ath6kl_err("timeout waiting for recv message\n");
126 status = -ETIME;
127 /* check if the target asserted */
128 if (dev->irq_proc_reg.counter_int_status &
129 ATH6KL_TARGET_DEBUG_INTR_MASK)
130 /*
131 * Target failure handler will be called in case of
132 * an assert.
133 */
134 ath6kldev_proc_dbg_intr(dev);
135 }
136
137 return status;
138}
139
140/*
141 * Disable packet reception (used in case the host runs out of buffers)
142 * using the interrupt enable registers through the host I/F
143 */
144int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx)
145{
146 struct ath6kl_irq_enable_reg regs;
147 int status = 0;
148
149 /* take the lock to protect interrupt enable shadows */
150 spin_lock_bh(&dev->lock);
151
152 if (enable_rx)
153 dev->irq_en_reg.int_status_en |=
154 SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01);
155 else
156 dev->irq_en_reg.int_status_en &=
157 ~SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01);
158
159 memcpy(&regs, &dev->irq_en_reg, sizeof(regs));
160
161 spin_unlock_bh(&dev->lock);
162
163 status = hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS,
164 &regs.int_status_en,
165 sizeof(struct ath6kl_irq_enable_reg),
166 HIF_WR_SYNC_BYTE_INC);
167
168 return status;
169}
170
171int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
172 struct hif_scatter_req *scat_req, bool read)
173{
174 int status = 0;
175
176 if (read) {
177 scat_req->req = HIF_RD_SYNC_BLOCK_FIX;
178 scat_req->addr = dev->ar->mbox_info.htc_addr;
179 } else {
180 scat_req->req = HIF_WR_ASYNC_BLOCK_INC;
181
182 scat_req->addr =
183 (scat_req->len > HIF_MBOX_WIDTH) ?
184 dev->ar->mbox_info.htc_ext_addr :
185 dev->ar->mbox_info.htc_addr;
186 }
187
188 ath6kl_dbg((ATH6KL_DBG_HTC_RECV | ATH6KL_DBG_HTC_SEND),
189 "ath6kldev_submit_scat_req, entries: %d, total len: %d mbox:0x%X (mode: %s : %s)\n",
190 scat_req->scat_entries, scat_req->len,
191 scat_req->addr, !read ? "async" : "sync",
192 (read) ? "rd" : "wr");
193
194 if (!read && scat_req->virt_scat) {
195 status = ath6kldev_cp_scat_dma_buf(scat_req, false);
196 if (status) {
197 scat_req->status = status;
198 scat_req->complete(dev->ar->htc_target, scat_req);
199 return 0;
200 }
201 }
202
203 status = ath6kl_hif_scat_req_rw(dev->ar, scat_req);
204
205 if (read) {
206 /* in sync mode, we can touch the scatter request */
207 scat_req->status = status;
208 if (!status && scat_req->virt_scat)
209 scat_req->status =
210 ath6kldev_cp_scat_dma_buf(scat_req, true);
211 }
212
213 return status;
214}
215
216static int ath6kldev_proc_counter_intr(struct ath6kl_device *dev)
217{
218 u8 counter_int_status;
219
220 ath6kl_dbg(ATH6KL_DBG_IRQ, "counter interrupt\n");
221
222 counter_int_status = dev->irq_proc_reg.counter_int_status &
223 dev->irq_en_reg.cntr_int_status_en;
224
225 ath6kl_dbg(ATH6KL_DBG_IRQ,
226 "valid interrupt source(s) in COUNTER_INT_STATUS: 0x%x\n",
227 counter_int_status);
228
229 /*
230 * NOTE: other modules like GMBOX may use the counter interrupt for
231 * credit flow control on other counters, we only need to check for
232 * the debug assertion counter interrupt.
233 */
234 if (counter_int_status & ATH6KL_TARGET_DEBUG_INTR_MASK)
235 return ath6kldev_proc_dbg_intr(dev);
236
237 return 0;
238}
239
240static int ath6kldev_proc_err_intr(struct ath6kl_device *dev)
241{
242 int status;
243 u8 error_int_status;
244 u8 reg_buf[4];
245
246 ath6kl_dbg(ATH6KL_DBG_IRQ, "error interrupt\n");
247
248 error_int_status = dev->irq_proc_reg.error_int_status & 0x0F;
249 if (!error_int_status) {
250 WARN_ON(1);
251 return -EIO;
252 }
253
254 ath6kl_dbg(ATH6KL_DBG_IRQ,
255 "valid interrupt source(s) in ERROR_INT_STATUS: 0x%x\n",
256 error_int_status);
257
258 if (MS(ERROR_INT_STATUS_WAKEUP, error_int_status))
259 ath6kl_dbg(ATH6KL_DBG_IRQ, "error : wakeup\n");
260
261 if (MS(ERROR_INT_STATUS_RX_UNDERFLOW, error_int_status))
262 ath6kl_err("rx underflow\n");
263
264 if (MS(ERROR_INT_STATUS_TX_OVERFLOW, error_int_status))
265 ath6kl_err("tx overflow\n");
266
267 /* Clear the interrupt */
268 dev->irq_proc_reg.error_int_status &= ~error_int_status;
269
270 /* set W1C value to clear the interrupt, this hits the register first */
271 reg_buf[0] = error_int_status;
272 reg_buf[1] = 0;
273 reg_buf[2] = 0;
274 reg_buf[3] = 0;
275
276 status = hif_read_write_sync(dev->ar, ERROR_INT_STATUS_ADDRESS,
277 reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
278
279 if (status)
280 WARN_ON(1);
281
282 return status;
283}
284
285static int ath6kldev_proc_cpu_intr(struct ath6kl_device *dev)
286{
287 int status;
288 u8 cpu_int_status;
289 u8 reg_buf[4];
290
291 ath6kl_dbg(ATH6KL_DBG_IRQ, "cpu interrupt\n");
292
293 cpu_int_status = dev->irq_proc_reg.cpu_int_status &
294 dev->irq_en_reg.cpu_int_status_en;
295 if (!cpu_int_status) {
296 WARN_ON(1);
297 return -EIO;
298 }
299
300 ath6kl_dbg(ATH6KL_DBG_IRQ,
301 "valid interrupt source(s) in CPU_INT_STATUS: 0x%x\n",
302 cpu_int_status);
303
304 /* Clear the interrupt */
305 dev->irq_proc_reg.cpu_int_status &= ~cpu_int_status;
306
307 /*
308 * Set up the register transfer buffer to hit the register 4 times ,
309 * this is done to make the access 4-byte aligned to mitigate issues
310 * with host bus interconnects that restrict bus transfer lengths to
311 * be a multiple of 4-bytes.
312 */
313
314 /* set W1C value to clear the interrupt, this hits the register first */
315 reg_buf[0] = cpu_int_status;
316 /* the remaining are set to zero which have no-effect */
317 reg_buf[1] = 0;
318 reg_buf[2] = 0;
319 reg_buf[3] = 0;
320
321 status = hif_read_write_sync(dev->ar, CPU_INT_STATUS_ADDRESS,
322 reg_buf, 4, HIF_WR_SYNC_BYTE_FIX);
323
324 if (status)
325 WARN_ON(1);
326
327 return status;
328}
329
330/* process pending interrupts synchronously */
331static int proc_pending_irqs(struct ath6kl_device *dev, bool *done)
332{
333 struct ath6kl_irq_proc_registers *rg;
334 int status = 0;
335 u8 host_int_status = 0;
336 u32 lk_ahd = 0;
337 u8 htc_mbox = 1 << HTC_MAILBOX;
338
339 ath6kl_dbg(ATH6KL_DBG_IRQ, "proc_pending_irqs: (dev: 0x%p)\n", dev);
340
341 /*
342 * NOTE: HIF implementation guarantees that the context of this
343 * call allows us to perform SYNCHRONOUS I/O, that is we can block,
344 * sleep or call any API that can block or switch thread/task
345 * contexts. This is a fully schedulable context.
346 */
347
348 /*
349 * Process pending intr only when int_status_en is clear, it may
350 * result in unnecessary bus transaction otherwise. Target may be
351 * unresponsive at the time.
352 */
353 if (dev->irq_en_reg.int_status_en) {
354 /*
355 * Read the first 28 bytes of the HTC register table. This
356 * will yield us the value of different int status
357 * registers and the lookahead registers.
358 *
359 * length = sizeof(int_status) + sizeof(cpu_int_status)
360 * + sizeof(error_int_status) +
361 * sizeof(counter_int_status) +
362 * sizeof(mbox_frame) + sizeof(rx_lkahd_valid)
363 * + sizeof(hole) + sizeof(rx_lkahd) +
364 * sizeof(int_status_en) +
365 * sizeof(cpu_int_status_en) +
366 * sizeof(err_int_status_en) +
367 * sizeof(cntr_int_status_en);
368 */
369 status = hif_read_write_sync(dev->ar, HOST_INT_STATUS_ADDRESS,
370 (u8 *) &dev->irq_proc_reg,
371 sizeof(dev->irq_proc_reg),
372 HIF_RD_SYNC_BYTE_INC);
373 if (status)
374 goto out;
375
376 if (AR_DBG_LVL_CHECK(ATH6KL_DBG_IRQ))
377 ath6kl_dump_registers(dev, &dev->irq_proc_reg,
378 &dev->irq_en_reg);
379
380 /* Update only those registers that are enabled */
381 host_int_status = dev->irq_proc_reg.host_int_status &
382 dev->irq_en_reg.int_status_en;
383
384 /* Look at mbox status */
385 if (host_int_status & htc_mbox) {
386 /*
387 * Mask out pending mbox value, we use "lookAhead as
388 * the real flag for mbox processing.
389 */
390 host_int_status &= ~htc_mbox;
391 if (dev->irq_proc_reg.rx_lkahd_valid &
392 htc_mbox) {
393 rg = &dev->irq_proc_reg;
394 lk_ahd = le32_to_cpu(rg->rx_lkahd[HTC_MAILBOX]);
395 if (!lk_ahd)
396 ath6kl_err("lookAhead is zero!\n");
397 }
398 }
399 }
400
401 if (!host_int_status && !lk_ahd) {
402 *done = true;
403 goto out;
404 }
405
406 if (lk_ahd) {
407 int fetched = 0;
408
409 ath6kl_dbg(ATH6KL_DBG_IRQ,
410 "pending mailbox msg, lk_ahd: 0x%X\n", lk_ahd);
411 /*
412 * Mailbox Interrupt, the HTC layer may issue async
413 * requests to empty the mailbox. When emptying the recv
414 * mailbox we use the async handler above called from the
415 * completion routine of the callers read request. This can
416 * improve performance by reducing context switching when
417 * we rapidly pull packets.
418 */
419 status = ath6kl_htc_rxmsg_pending_handler(dev->htc_cnxt,
420 &lk_ahd, &fetched);
421 if (status)
422 goto out;
423
424 if (!fetched)
425 /*
426 * HTC could not pull any messages out due to lack
427 * of resources.
428 */
429 dev->htc_cnxt->chk_irq_status_cnt = 0;
430 }
431
432 /* now handle the rest of them */
433 ath6kl_dbg(ATH6KL_DBG_IRQ,
434 "valid interrupt source(s) for other interrupts: 0x%x\n",
435 host_int_status);
436
437 if (MS(HOST_INT_STATUS_CPU, host_int_status)) {
438 /* CPU Interrupt */
439 status = ath6kldev_proc_cpu_intr(dev);
440 if (status)
441 goto out;
442 }
443
444 if (MS(HOST_INT_STATUS_ERROR, host_int_status)) {
445 /* Error Interrupt */
446 status = ath6kldev_proc_err_intr(dev);
447 if (status)
448 goto out;
449 }
450
451 if (MS(HOST_INT_STATUS_COUNTER, host_int_status))
452 /* Counter Interrupt */
453 status = ath6kldev_proc_counter_intr(dev);
454
455out:
456 /*
457 * An optimization to bypass reading the IRQ status registers
458 * unecessarily which can re-wake the target, if upper layers
459 * determine that we are in a low-throughput mode, we can rely on
460 * taking another interrupt rather than re-checking the status
461 * registers which can re-wake the target.
462 *
463 * NOTE : for host interfaces that makes use of detecting pending
464 * mbox messages at hif can not use this optimization due to
465 * possible side effects, SPI requires the host to drain all
466 * messages from the mailbox before exiting the ISR routine.
467 */
468
469 ath6kl_dbg(ATH6KL_DBG_IRQ,
470 "bypassing irq status re-check, forcing done\n");
471
472 if (!dev->htc_cnxt->chk_irq_status_cnt)
473 *done = true;
474
475 ath6kl_dbg(ATH6KL_DBG_IRQ,
476 "proc_pending_irqs: (done:%d, status=%d\n", *done, status);
477
478 return status;
479}
480
481/* interrupt handler, kicks off all interrupt processing */
482int ath6kldev_intr_bh_handler(struct ath6kl *ar)
483{
484 struct ath6kl_device *dev = ar->htc_target->dev;
485 int status = 0;
486 bool done = false;
487
488 /*
489 * Reset counter used to flag a re-scan of IRQ status registers on
490 * the target.
491 */
492 dev->htc_cnxt->chk_irq_status_cnt = 0;
493
494 /*
495 * IRQ processing is synchronous, interrupt status registers can be
496 * re-read.
497 */
498 while (!done) {
499 status = proc_pending_irqs(dev, &done);
500 if (status)
501 break;
502 }
503
504 return status;
505}
506
507static int ath6kldev_enable_intrs(struct ath6kl_device *dev)
508{
509 struct ath6kl_irq_enable_reg regs;
510 int status;
511
512 spin_lock_bh(&dev->lock);
513
514 /* Enable all but ATH6KL CPU interrupts */
515 dev->irq_en_reg.int_status_en =
516 SM(INT_STATUS_ENABLE_ERROR, 0x01) |
517 SM(INT_STATUS_ENABLE_CPU, 0x01) |
518 SM(INT_STATUS_ENABLE_COUNTER, 0x01);
519
520 /*
521 * NOTE: There are some cases where HIF can do detection of
522 * pending mbox messages which is disabled now.
523 */
524 dev->irq_en_reg.int_status_en |= SM(INT_STATUS_ENABLE_MBOX_DATA, 0x01);
525
526 /* Set up the CPU Interrupt status Register */
527 dev->irq_en_reg.cpu_int_status_en = 0;
528
529 /* Set up the Error Interrupt status Register */
530 dev->irq_en_reg.err_int_status_en =
531 SM(ERROR_STATUS_ENABLE_RX_UNDERFLOW, 0x01) |
532 SM(ERROR_STATUS_ENABLE_TX_OVERFLOW, 0x1);
533
534 /*
535 * Enable Counter interrupt status register to get fatal errors for
536 * debugging.
537 */
538 dev->irq_en_reg.cntr_int_status_en = SM(COUNTER_INT_STATUS_ENABLE_BIT,
539 ATH6KL_TARGET_DEBUG_INTR_MASK);
540 memcpy(&regs, &dev->irq_en_reg, sizeof(regs));
541
542 spin_unlock_bh(&dev->lock);
543
544 status = hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS,
545 &regs.int_status_en, sizeof(regs),
546 HIF_WR_SYNC_BYTE_INC);
547
548 if (status)
549 ath6kl_err("failed to update interrupt ctl reg err: %d\n",
550 status);
551
552 return status;
553}
554
555int ath6kldev_disable_intrs(struct ath6kl_device *dev)
556{
557 struct ath6kl_irq_enable_reg regs;
558
559 spin_lock_bh(&dev->lock);
560 /* Disable all interrupts */
561 dev->irq_en_reg.int_status_en = 0;
562 dev->irq_en_reg.cpu_int_status_en = 0;
563 dev->irq_en_reg.err_int_status_en = 0;
564 dev->irq_en_reg.cntr_int_status_en = 0;
565 memcpy(&regs, &dev->irq_en_reg, sizeof(regs));
566 spin_unlock_bh(&dev->lock);
567
568 return hif_read_write_sync(dev->ar, INT_STATUS_ENABLE_ADDRESS,
569 &regs.int_status_en, sizeof(regs),
570 HIF_WR_SYNC_BYTE_INC);
571}
572
573/* enable device interrupts */
574int ath6kldev_unmask_intrs(struct ath6kl_device *dev)
575{
576 int status = 0;
577
578 /*
579 * Make sure interrupt are disabled before unmasking at the HIF
580 * layer. The rationale here is that between device insertion
581 * (where we clear the interrupts the first time) and when HTC
582 * is finally ready to handle interrupts, other software can perform
583 * target "soft" resets. The ATH6KL interrupt enables reset back to an
584 * "enabled" state when this happens.
585 */
586 ath6kldev_disable_intrs(dev);
587
588 /* unmask the host controller interrupts */
589 ath6kl_hif_irq_enable(dev->ar);
590 status = ath6kldev_enable_intrs(dev);
591
592 return status;
593}
594
595/* disable all device interrupts */
596int ath6kldev_mask_intrs(struct ath6kl_device *dev)
597{
598 /*
599 * Mask the interrupt at the HIF layer to avoid any stray interrupt
600 * taken while we zero out our shadow registers in
601 * ath6kldev_disable_intrs().
602 */
603 ath6kl_hif_irq_disable(dev->ar);
604
605 return ath6kldev_disable_intrs(dev);
606}
607
608int ath6kldev_setup(struct ath6kl_device *dev)
609{
610 int status = 0;
611
612 spin_lock_init(&dev->lock);
613
614 /*
615 * NOTE: we actually get the block size of a mailbox other than 0,
616 * for SDIO the block size on mailbox 0 is artificially set to 1.
617 * So we use the block size that is set for the other 3 mailboxes.
618 */
619 dev->htc_cnxt->block_sz = dev->ar->mbox_info.block_size;
620
621 /* must be a power of 2 */
622 if ((dev->htc_cnxt->block_sz & (dev->htc_cnxt->block_sz - 1)) != 0) {
623 WARN_ON(1);
624 goto fail_setup;
625 }
626
627 /* assemble mask, used for padding to a block */
628 dev->htc_cnxt->block_mask = dev->htc_cnxt->block_sz - 1;
629
630 ath6kl_dbg(ATH6KL_DBG_TRC, "block size: %d, mbox addr:0x%X\n",
631 dev->htc_cnxt->block_sz, dev->ar->mbox_info.htc_addr);
632
633 ath6kl_dbg(ATH6KL_DBG_TRC,
634 "hif interrupt processing is sync only\n");
635
636 status = ath6kldev_disable_intrs(dev);
637
638fail_setup:
639 return status;
640
641}
diff --git a/drivers/net/wireless/ath/ath6kl/htc_hif.h b/drivers/net/wireless/ath/ath6kl/htc_hif.h
new file mode 100644
index 000000000000..171ad63d89b0
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/htc_hif.h
@@ -0,0 +1,92 @@
1/*
2 * Copyright (c) 2007-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef HTC_HIF_H
18#define HTC_HIF_H
19
20#include "htc.h"
21#include "hif.h"
22
23#define ATH6KL_MAILBOXES 4
24
25/* HTC runs over mailbox 0 */
26#define HTC_MAILBOX 0
27
28#define ATH6KL_TARGET_DEBUG_INTR_MASK 0x01
29
30#define OTHER_INTS_ENABLED (INT_STATUS_ENABLE_ERROR_MASK | \
31 INT_STATUS_ENABLE_CPU_MASK | \
32 INT_STATUS_ENABLE_COUNTER_MASK)
33
34#define ATH6KL_REG_IO_BUFFER_SIZE 32
35#define ATH6KL_MAX_REG_IO_BUFFERS 8
36#define ATH6KL_SCATTER_ENTRIES_PER_REQ 16
37#define ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER (16 * 1024)
38#define ATH6KL_SCATTER_REQS 4
39
40#ifndef A_CACHE_LINE_PAD
41#define A_CACHE_LINE_PAD 128
42#endif
43#define ATH6KL_MIN_SCATTER_ENTRIES_PER_REQ 2
44#define ATH6KL_MIN_TRANSFER_SIZE_PER_SCATTER (4 * 1024)
45
46struct ath6kl_irq_proc_registers {
47 u8 host_int_status;
48 u8 cpu_int_status;
49 u8 error_int_status;
50 u8 counter_int_status;
51 u8 mbox_frame;
52 u8 rx_lkahd_valid;
53 u8 host_int_status2;
54 u8 gmbox_rx_avail;
55 __le32 rx_lkahd[2];
56 __le32 rx_gmbox_lkahd_alias[2];
57} __packed;
58
59struct ath6kl_irq_enable_reg {
60 u8 int_status_en;
61 u8 cpu_int_status_en;
62 u8 err_int_status_en;
63 u8 cntr_int_status_en;
64} __packed;
65
66struct ath6kl_device {
67 spinlock_t lock;
68 u8 pad1[A_CACHE_LINE_PAD];
69 struct ath6kl_irq_proc_registers irq_proc_reg;
70 u8 pad2[A_CACHE_LINE_PAD];
71 struct ath6kl_irq_enable_reg irq_en_reg;
72 u8 pad3[A_CACHE_LINE_PAD];
73 struct htc_target *htc_cnxt;
74 struct ath6kl *ar;
75};
76
77int ath6kldev_setup(struct ath6kl_device *dev);
78int ath6kldev_unmask_intrs(struct ath6kl_device *dev);
79int ath6kldev_mask_intrs(struct ath6kl_device *dev);
80int ath6kldev_poll_mboxmsg_rx(struct ath6kl_device *dev,
81 u32 *lk_ahd, int timeout);
82int ath6kldev_rx_control(struct ath6kl_device *dev, bool enable_rx);
83int ath6kldev_disable_intrs(struct ath6kl_device *dev);
84
85int ath6kldev_rw_comp_handler(void *context, int status);
86int ath6kldev_intr_bh_handler(struct ath6kl *ar);
87
88/* Scatter Function and Definitions */
89int ath6kldev_submit_scat_req(struct ath6kl_device *dev,
90 struct hif_scatter_req *scat_req, bool read);
91
92#endif /*ATH6KL_H_ */
diff --git a/drivers/net/wireless/ath/ath6kl/init.c b/drivers/net/wireless/ath/ath6kl/init.c
new file mode 100644
index 000000000000..9d10322eac41
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/init.c
@@ -0,0 +1,1303 @@
1
2/*
3 * Copyright (c) 2011 Atheros Communications Inc.
4 *
5 * Permission to use, copy, modify, and/or distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <linux/mmc/sdio_func.h>
19#include "core.h"
20#include "cfg80211.h"
21#include "target.h"
22#include "debug.h"
23#include "hif-ops.h"
24
25unsigned int debug_mask;
26
27module_param(debug_mask, uint, 0644);
28
29/*
30 * Include definitions here that can be used to tune the WLAN module
31 * behavior. Different customers can tune the behavior as per their needs,
32 * here.
33 */
34
35/*
36 * This configuration item enable/disable keepalive support.
37 * Keepalive support: In the absence of any data traffic to AP, null
38 * frames will be sent to the AP at periodic interval, to keep the association
39 * active. This configuration item defines the periodic interval.
40 * Use value of zero to disable keepalive support
41 * Default: 60 seconds
42 */
43#define WLAN_CONFIG_KEEP_ALIVE_INTERVAL 60
44
45/*
46 * This configuration item sets the value of disconnect timeout
47 * Firmware delays sending the disconnec event to the host for this
48 * timeout after is gets disconnected from the current AP.
49 * If the firmware successly roams within the disconnect timeout
50 * it sends a new connect event
51 */
52#define WLAN_CONFIG_DISCONNECT_TIMEOUT 10
53
54#define CONFIG_AR600x_DEBUG_UART_TX_PIN 8
55
56enum addr_type {
57 DATASET_PATCH_ADDR,
58 APP_LOAD_ADDR,
59 APP_START_OVERRIDE_ADDR,
60};
61
62#define ATH6KL_DATA_OFFSET 64
63struct sk_buff *ath6kl_buf_alloc(int size)
64{
65 struct sk_buff *skb;
66 u16 reserved;
67
68 /* Add chacheline space at front and back of buffer */
69 reserved = (2 * L1_CACHE_BYTES) + ATH6KL_DATA_OFFSET +
70 sizeof(struct htc_packet);
71 skb = dev_alloc_skb(size + reserved);
72
73 if (skb)
74 skb_reserve(skb, reserved - L1_CACHE_BYTES);
75 return skb;
76}
77
78void ath6kl_init_profile_info(struct ath6kl *ar)
79{
80 ar->ssid_len = 0;
81 memset(ar->ssid, 0, sizeof(ar->ssid));
82
83 ar->dot11_auth_mode = OPEN_AUTH;
84 ar->auth_mode = NONE_AUTH;
85 ar->prwise_crypto = NONE_CRYPT;
86 ar->prwise_crypto_len = 0;
87 ar->grp_crypto = NONE_CRYPT;
88 ar->grp_crpto_len = 0;
89 memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
90 memset(ar->req_bssid, 0, sizeof(ar->req_bssid));
91 memset(ar->bssid, 0, sizeof(ar->bssid));
92 ar->bss_ch = 0;
93 ar->nw_type = ar->next_mode = INFRA_NETWORK;
94}
95
96static u8 ath6kl_get_fw_iftype(struct ath6kl *ar)
97{
98 switch (ar->nw_type) {
99 case INFRA_NETWORK:
100 return HI_OPTION_FW_MODE_BSS_STA;
101 case ADHOC_NETWORK:
102 return HI_OPTION_FW_MODE_IBSS;
103 case AP_NETWORK:
104 return HI_OPTION_FW_MODE_AP;
105 default:
106 ath6kl_err("Unsupported interface type :%d\n", ar->nw_type);
107 return 0xff;
108 }
109}
110
111static inline u32 ath6kl_get_hi_item_addr(struct ath6kl *ar,
112 u32 item_offset)
113{
114 u32 addr = 0;
115
116 if (ar->target_type == TARGET_TYPE_AR6003)
117 addr = ATH6KL_HI_START_ADDR + item_offset;
118
119 return addr;
120}
121
122static int ath6kl_set_host_app_area(struct ath6kl *ar)
123{
124 u32 address, data;
125 struct host_app_area host_app_area;
126
127 /* Fetch the address of the host_app_area_s
128 * instance in the host interest area */
129 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_app_host_interest));
130 address = TARG_VTOP(address);
131
132 if (ath6kl_read_reg_diag(ar, &address, &data))
133 return -EIO;
134
135 address = TARG_VTOP(data);
136 host_app_area.wmi_protocol_ver = WMI_PROTOCOL_VERSION;
137 if (ath6kl_access_datadiag(ar, address,
138 (u8 *)&host_app_area,
139 sizeof(struct host_app_area), false))
140 return -EIO;
141
142 return 0;
143}
144
145static inline void set_ac2_ep_map(struct ath6kl *ar,
146 u8 ac,
147 enum htc_endpoint_id ep)
148{
149 ar->ac2ep_map[ac] = ep;
150 ar->ep2ac_map[ep] = ac;
151}
152
153/* connect to a service */
154static int ath6kl_connectservice(struct ath6kl *ar,
155 struct htc_service_connect_req *con_req,
156 char *desc)
157{
158 int status;
159 struct htc_service_connect_resp response;
160
161 memset(&response, 0, sizeof(response));
162
163 status = ath6kl_htc_conn_service(ar->htc_target, con_req, &response);
164 if (status) {
165 ath6kl_err("failed to connect to %s service status:%d\n",
166 desc, status);
167 return status;
168 }
169
170 switch (con_req->svc_id) {
171 case WMI_CONTROL_SVC:
172 if (test_bit(WMI_ENABLED, &ar->flag))
173 ath6kl_wmi_set_control_ep(ar->wmi, response.endpoint);
174 ar->ctrl_ep = response.endpoint;
175 break;
176 case WMI_DATA_BE_SVC:
177 set_ac2_ep_map(ar, WMM_AC_BE, response.endpoint);
178 break;
179 case WMI_DATA_BK_SVC:
180 set_ac2_ep_map(ar, WMM_AC_BK, response.endpoint);
181 break;
182 case WMI_DATA_VI_SVC:
183 set_ac2_ep_map(ar, WMM_AC_VI, response.endpoint);
184 break;
185 case WMI_DATA_VO_SVC:
186 set_ac2_ep_map(ar, WMM_AC_VO, response.endpoint);
187 break;
188 default:
189 ath6kl_err("service id is not mapped %d\n", con_req->svc_id);
190 return -EINVAL;
191 }
192
193 return 0;
194}
195
196static int ath6kl_init_service_ep(struct ath6kl *ar)
197{
198 struct htc_service_connect_req connect;
199
200 memset(&connect, 0, sizeof(connect));
201
202 /* these fields are the same for all service endpoints */
203 connect.ep_cb.rx = ath6kl_rx;
204 connect.ep_cb.rx_refill = ath6kl_rx_refill;
205 connect.ep_cb.tx_full = ath6kl_tx_queue_full;
206
207 /*
208 * Set the max queue depth so that our ath6kl_tx_queue_full handler
209 * gets called.
210 */
211 connect.max_txq_depth = MAX_DEFAULT_SEND_QUEUE_DEPTH;
212 connect.ep_cb.rx_refill_thresh = ATH6KL_MAX_RX_BUFFERS / 4;
213 if (!connect.ep_cb.rx_refill_thresh)
214 connect.ep_cb.rx_refill_thresh++;
215
216 /* connect to control service */
217 connect.svc_id = WMI_CONTROL_SVC;
218 if (ath6kl_connectservice(ar, &connect, "WMI CONTROL"))
219 return -EIO;
220
221 connect.flags |= HTC_FLGS_TX_BNDL_PAD_EN;
222
223 /*
224 * Limit the HTC message size on the send path, although e can
225 * receive A-MSDU frames of 4K, we will only send ethernet-sized
226 * (802.3) frames on the send path.
227 */
228 connect.max_rxmsg_sz = WMI_MAX_TX_DATA_FRAME_LENGTH;
229
230 /*
231 * To reduce the amount of committed memory for larger A_MSDU
232 * frames, use the recv-alloc threshold mechanism for larger
233 * packets.
234 */
235 connect.ep_cb.rx_alloc_thresh = ATH6KL_BUFFER_SIZE;
236 connect.ep_cb.rx_allocthresh = ath6kl_alloc_amsdu_rxbuf;
237
238 /*
239 * For the remaining data services set the connection flag to
240 * reduce dribbling, if configured to do so.
241 */
242 connect.conn_flags |= HTC_CONN_FLGS_REDUCE_CRED_DRIB;
243 connect.conn_flags &= ~HTC_CONN_FLGS_THRESH_MASK;
244 connect.conn_flags |= HTC_CONN_FLGS_THRESH_LVL_HALF;
245
246 connect.svc_id = WMI_DATA_BE_SVC;
247
248 if (ath6kl_connectservice(ar, &connect, "WMI DATA BE"))
249 return -EIO;
250
251 /* connect to back-ground map this to WMI LOW_PRI */
252 connect.svc_id = WMI_DATA_BK_SVC;
253 if (ath6kl_connectservice(ar, &connect, "WMI DATA BK"))
254 return -EIO;
255
256 /* connect to Video service, map this to to HI PRI */
257 connect.svc_id = WMI_DATA_VI_SVC;
258 if (ath6kl_connectservice(ar, &connect, "WMI DATA VI"))
259 return -EIO;
260
261 /*
262 * Connect to VO service, this is currently not mapped to a WMI
263 * priority stream due to historical reasons. WMI originally
264 * defined 3 priorities over 3 mailboxes We can change this when
265 * WMI is reworked so that priorities are not dependent on
266 * mailboxes.
267 */
268 connect.svc_id = WMI_DATA_VO_SVC;
269 if (ath6kl_connectservice(ar, &connect, "WMI DATA VO"))
270 return -EIO;
271
272 return 0;
273}
274
275static void ath6kl_init_control_info(struct ath6kl *ar)
276{
277 u8 ctr;
278
279 clear_bit(WMI_ENABLED, &ar->flag);
280 ath6kl_init_profile_info(ar);
281 ar->def_txkey_index = 0;
282 memset(ar->wep_key_list, 0, sizeof(ar->wep_key_list));
283 ar->ch_hint = 0;
284 ar->listen_intvl_t = A_DEFAULT_LISTEN_INTERVAL;
285 ar->listen_intvl_b = 0;
286 ar->tx_pwr = 0;
287 clear_bit(SKIP_SCAN, &ar->flag);
288 set_bit(WMM_ENABLED, &ar->flag);
289 ar->intra_bss = 1;
290 memset(&ar->sc_params, 0, sizeof(ar->sc_params));
291 ar->sc_params.short_scan_ratio = WMI_SHORTSCANRATIO_DEFAULT;
292 ar->sc_params.scan_ctrl_flags = DEFAULT_SCAN_CTRL_FLAGS;
293
294 memset((u8 *)ar->sta_list, 0,
295 AP_MAX_NUM_STA * sizeof(struct ath6kl_sta));
296
297 spin_lock_init(&ar->mcastpsq_lock);
298
299 /* Init the PS queues */
300 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
301 spin_lock_init(&ar->sta_list[ctr].psq_lock);
302 skb_queue_head_init(&ar->sta_list[ctr].psq);
303 }
304
305 skb_queue_head_init(&ar->mcastpsq);
306
307 memcpy(ar->ap_country_code, DEF_AP_COUNTRY_CODE, 3);
308}
309
310/*
311 * Set HTC/Mbox operational parameters, this can only be called when the
312 * target is in the BMI phase.
313 */
314static int ath6kl_set_htc_params(struct ath6kl *ar, u32 mbox_isr_yield_val,
315 u8 htc_ctrl_buf)
316{
317 int status;
318 u32 blk_size;
319
320 blk_size = ar->mbox_info.block_size;
321
322 if (htc_ctrl_buf)
323 blk_size |= ((u32)htc_ctrl_buf) << 16;
324
325 /* set the host interest area for the block size */
326 status = ath6kl_bmi_write(ar,
327 ath6kl_get_hi_item_addr(ar,
328 HI_ITEM(hi_mbox_io_block_sz)),
329 (u8 *)&blk_size,
330 4);
331 if (status) {
332 ath6kl_err("bmi_write_memory for IO block size failed\n");
333 goto out;
334 }
335
336 ath6kl_dbg(ATH6KL_DBG_TRC, "block size set: %d (target addr:0x%X)\n",
337 blk_size,
338 ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_mbox_io_block_sz)));
339
340 if (mbox_isr_yield_val) {
341 /* set the host interest area for the mbox ISR yield limit */
342 status = ath6kl_bmi_write(ar,
343 ath6kl_get_hi_item_addr(ar,
344 HI_ITEM(hi_mbox_isr_yield_limit)),
345 (u8 *)&mbox_isr_yield_val,
346 4);
347 if (status) {
348 ath6kl_err("bmi_write_memory for yield limit failed\n");
349 goto out;
350 }
351 }
352
353out:
354 return status;
355}
356
357#define REG_DUMP_COUNT_AR6003 60
358#define REGISTER_DUMP_LEN_MAX 60
359
360static void ath6kl_dump_target_assert_info(struct ath6kl *ar)
361{
362 u32 address;
363 u32 regdump_loc = 0;
364 int status;
365 u32 regdump_val[REGISTER_DUMP_LEN_MAX];
366 u32 i;
367
368 if (ar->target_type != TARGET_TYPE_AR6003)
369 return;
370
371 /* the reg dump pointer is copied to the host interest area */
372 address = ath6kl_get_hi_item_addr(ar, HI_ITEM(hi_failure_state));
373 address = TARG_VTOP(address);
374
375 /* read RAM location through diagnostic window */
376 status = ath6kl_read_reg_diag(ar, &address, &regdump_loc);
377
378 if (status || !regdump_loc) {
379 ath6kl_err("failed to get ptr to register dump area\n");
380 return;
381 }
382
383 ath6kl_dbg(ATH6KL_DBG_TRC, "location of register dump data: 0x%X\n",
384 regdump_loc);
385
386 regdump_loc = TARG_VTOP(regdump_loc);
387
388 /* fetch register dump data */
389 status = ath6kl_access_datadiag(ar,
390 regdump_loc,
391 (u8 *)&regdump_val[0],
392 REG_DUMP_COUNT_AR6003 * (sizeof(u32)),
393 true);
394
395 if (status) {
396 ath6kl_err("failed to get register dump\n");
397 return;
398 }
399 ath6kl_dbg(ATH6KL_DBG_TRC, "Register Dump:\n");
400
401 for (i = 0; i < REG_DUMP_COUNT_AR6003; i++)
402 ath6kl_dbg(ATH6KL_DBG_TRC, " %d : 0x%8.8X\n",
403 i, regdump_val[i]);
404
405}
406
407void ath6kl_target_failure(struct ath6kl *ar)
408{
409 ath6kl_err("target asserted\n");
410
411 /* try dumping target assertion information (if any) */
412 ath6kl_dump_target_assert_info(ar);
413
414}
415
416static int ath6kl_target_config_wlan_params(struct ath6kl *ar)
417{
418 int status = 0;
419
420 /*
421 * Configure the device for rx dot11 header rules. "0,0" are the
422 * default values. Required if checksum offload is needed. Set
423 * RxMetaVersion to 2.
424 */
425 if (ath6kl_wmi_set_rx_frame_format_cmd(ar->wmi,
426 ar->rx_meta_ver, 0, 0)) {
427 ath6kl_err("unable to set the rx frame format\n");
428 status = -EIO;
429 }
430
431 if (ar->conf_flags & ATH6KL_CONF_IGNORE_PS_FAIL_EVT_IN_SCAN)
432 if ((ath6kl_wmi_pmparams_cmd(ar->wmi, 0, 1, 0, 0, 1,
433 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN)) != 0) {
434 ath6kl_err("unable to set power save fail event policy\n");
435 status = -EIO;
436 }
437
438 if (!(ar->conf_flags & ATH6KL_CONF_IGNORE_ERP_BARKER))
439 if ((ath6kl_wmi_set_lpreamble_cmd(ar->wmi, 0,
440 WMI_DONOT_IGNORE_BARKER_IN_ERP)) != 0) {
441 ath6kl_err("unable to set barker preamble policy\n");
442 status = -EIO;
443 }
444
445 if (ath6kl_wmi_set_keepalive_cmd(ar->wmi,
446 WLAN_CONFIG_KEEP_ALIVE_INTERVAL)) {
447 ath6kl_err("unable to set keep alive interval\n");
448 status = -EIO;
449 }
450
451 if (ath6kl_wmi_disctimeout_cmd(ar->wmi,
452 WLAN_CONFIG_DISCONNECT_TIMEOUT)) {
453 ath6kl_err("unable to set disconnect timeout\n");
454 status = -EIO;
455 }
456
457 if (!(ar->conf_flags & ATH6KL_CONF_ENABLE_TX_BURST))
458 if (ath6kl_wmi_set_wmm_txop(ar->wmi, WMI_TXOP_DISABLED)) {
459 ath6kl_err("unable to set txop bursting\n");
460 status = -EIO;
461 }
462
463 return status;
464}
465
466int ath6kl_configure_target(struct ath6kl *ar)
467{
468 u32 param, ram_reserved_size;
469 u8 fw_iftype;
470
471 fw_iftype = ath6kl_get_fw_iftype(ar);
472 if (fw_iftype == 0xff)
473 return -EINVAL;
474
475 /* Tell target which HTC version it is used*/
476 param = HTC_PROTOCOL_VERSION;
477 if (ath6kl_bmi_write(ar,
478 ath6kl_get_hi_item_addr(ar,
479 HI_ITEM(hi_app_host_interest)),
480 (u8 *)&param, 4) != 0) {
481 ath6kl_err("bmi_write_memory for htc version failed\n");
482 return -EIO;
483 }
484
485 /* set the firmware mode to STA/IBSS/AP */
486 param = 0;
487
488 if (ath6kl_bmi_read(ar,
489 ath6kl_get_hi_item_addr(ar,
490 HI_ITEM(hi_option_flag)),
491 (u8 *)&param, 4) != 0) {
492 ath6kl_err("bmi_read_memory for setting fwmode failed\n");
493 return -EIO;
494 }
495
496 param |= (1 << HI_OPTION_NUM_DEV_SHIFT);
497 param |= (fw_iftype << HI_OPTION_FW_MODE_SHIFT);
498 param |= (0 << HI_OPTION_MAC_ADDR_METHOD_SHIFT);
499 param |= (0 << HI_OPTION_FW_BRIDGE_SHIFT);
500
501 if (ath6kl_bmi_write(ar,
502 ath6kl_get_hi_item_addr(ar,
503 HI_ITEM(hi_option_flag)),
504 (u8 *)&param,
505 4) != 0) {
506 ath6kl_err("bmi_write_memory for setting fwmode failed\n");
507 return -EIO;
508 }
509
510 ath6kl_dbg(ATH6KL_DBG_TRC, "firmware mode set\n");
511
512 /*
513 * Hardcode the address use for the extended board data
514 * Ideally this should be pre-allocate by the OS at boot time
515 * But since it is a new feature and board data is loaded
516 * at init time, we have to workaround this from host.
517 * It is difficult to patch the firmware boot code,
518 * but possible in theory.
519 */
520
521 if (ar->target_type == TARGET_TYPE_AR6003) {
522 if (ar->version.target_ver == AR6003_REV2_VERSION) {
523 param = AR6003_REV2_BOARD_EXT_DATA_ADDRESS;
524 ram_reserved_size = AR6003_REV2_RAM_RESERVE_SIZE;
525 } else {
526 param = AR6003_REV3_BOARD_EXT_DATA_ADDRESS;
527 ram_reserved_size = AR6003_REV3_RAM_RESERVE_SIZE;
528 }
529
530 if (ath6kl_bmi_write(ar,
531 ath6kl_get_hi_item_addr(ar,
532 HI_ITEM(hi_board_ext_data)),
533 (u8 *)&param, 4) != 0) {
534 ath6kl_err("bmi_write_memory for hi_board_ext_data failed\n");
535 return -EIO;
536 }
537 if (ath6kl_bmi_write(ar,
538 ath6kl_get_hi_item_addr(ar,
539 HI_ITEM(hi_end_ram_reserve_sz)),
540 (u8 *)&ram_reserved_size, 4) != 0) {
541 ath6kl_err("bmi_write_memory for hi_end_ram_reserve_sz failed\n");
542 return -EIO;
543 }
544 }
545
546 /* set the block size for the target */
547 if (ath6kl_set_htc_params(ar, MBOX_YIELD_LIMIT, 0))
548 /* use default number of control buffers */
549 return -EIO;
550
551 return 0;
552}
553
554struct ath6kl *ath6kl_core_alloc(struct device *sdev)
555{
556 struct net_device *dev;
557 struct ath6kl *ar;
558 struct wireless_dev *wdev;
559
560 wdev = ath6kl_cfg80211_init(sdev);
561 if (!wdev) {
562 ath6kl_err("ath6kl_cfg80211_init failed\n");
563 return NULL;
564 }
565
566 ar = wdev_priv(wdev);
567 ar->dev = sdev;
568 ar->wdev = wdev;
569 wdev->iftype = NL80211_IFTYPE_STATION;
570
571 dev = alloc_netdev(0, "wlan%d", ether_setup);
572 if (!dev) {
573 ath6kl_err("no memory for network device instance\n");
574 ath6kl_cfg80211_deinit(ar);
575 return NULL;
576 }
577
578 dev->ieee80211_ptr = wdev;
579 SET_NETDEV_DEV(dev, wiphy_dev(wdev->wiphy));
580 wdev->netdev = dev;
581 ar->sme_state = SME_DISCONNECTED;
582 ar->auto_auth_stage = AUTH_IDLE;
583
584 init_netdev(dev);
585
586 ar->net_dev = dev;
587 set_bit(WLAN_ENABLED, &ar->flag);
588
589 ar->wlan_pwr_state = WLAN_POWER_STATE_ON;
590
591 spin_lock_init(&ar->lock);
592
593 ath6kl_init_control_info(ar);
594 init_waitqueue_head(&ar->event_wq);
595 sema_init(&ar->sem, 1);
596 clear_bit(DESTROY_IN_PROGRESS, &ar->flag);
597
598 INIT_LIST_HEAD(&ar->amsdu_rx_buffer_queue);
599
600 setup_timer(&ar->disconnect_timer, disconnect_timer_handler,
601 (unsigned long) dev);
602
603 return ar;
604}
605
606int ath6kl_unavail_ev(struct ath6kl *ar)
607{
608 ath6kl_destroy(ar->net_dev, 1);
609
610 return 0;
611}
612
613/* firmware upload */
614static u32 ath6kl_get_load_address(u32 target_ver, enum addr_type type)
615{
616 WARN_ON(target_ver != AR6003_REV2_VERSION &&
617 target_ver != AR6003_REV3_VERSION);
618
619 switch (type) {
620 case DATASET_PATCH_ADDR:
621 return (target_ver == AR6003_REV2_VERSION) ?
622 AR6003_REV2_DATASET_PATCH_ADDRESS :
623 AR6003_REV3_DATASET_PATCH_ADDRESS;
624 case APP_LOAD_ADDR:
625 return (target_ver == AR6003_REV2_VERSION) ?
626 AR6003_REV2_APP_LOAD_ADDRESS :
627 0x1234;
628 case APP_START_OVERRIDE_ADDR:
629 return (target_ver == AR6003_REV2_VERSION) ?
630 AR6003_REV2_APP_START_OVERRIDE :
631 AR6003_REV3_APP_START_OVERRIDE;
632 default:
633 return 0;
634 }
635}
636
637static int ath6kl_get_fw(struct ath6kl *ar, const char *filename,
638 u8 **fw, size_t *fw_len)
639{
640 const struct firmware *fw_entry;
641 int ret;
642
643 ret = request_firmware(&fw_entry, filename, ar->dev);
644 if (ret)
645 return ret;
646
647 *fw_len = fw_entry->size;
648 *fw = kmemdup(fw_entry->data, fw_entry->size, GFP_KERNEL);
649
650 if (*fw == NULL)
651 ret = -ENOMEM;
652
653 release_firmware(fw_entry);
654
655 return ret;
656}
657
658static int ath6kl_fetch_board_file(struct ath6kl *ar)
659{
660 const char *filename;
661 int ret;
662
663 switch (ar->version.target_ver) {
664 case AR6003_REV2_VERSION:
665 filename = AR6003_REV2_BOARD_DATA_FILE;
666 break;
667 default:
668 filename = AR6003_REV3_BOARD_DATA_FILE;
669 break;
670 }
671
672 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
673 &ar->fw_board_len);
674 if (ret == 0) {
675 /* managed to get proper board file */
676 return 0;
677 }
678
679 /* there was no proper board file, try to use default instead */
680 ath6kl_warn("Failed to get board file %s (%d), trying to find default board file.\n",
681 filename, ret);
682
683 switch (ar->version.target_ver) {
684 case AR6003_REV2_VERSION:
685 filename = AR6003_REV2_DEFAULT_BOARD_DATA_FILE;
686 break;
687 default:
688 filename = AR6003_REV3_DEFAULT_BOARD_DATA_FILE;
689 break;
690 }
691
692 ret = ath6kl_get_fw(ar, filename, &ar->fw_board,
693 &ar->fw_board_len);
694 if (ret) {
695 ath6kl_err("Failed to get default board file %s: %d\n",
696 filename, ret);
697 return ret;
698 }
699
700 ath6kl_warn("WARNING! No proper board file was not found, instead using a default board file.\n");
701 ath6kl_warn("Most likely your hardware won't work as specified. Install correct board file!\n");
702
703 return 0;
704}
705
706
707static int ath6kl_upload_board_file(struct ath6kl *ar)
708{
709 u32 board_address, board_ext_address, param;
710 int ret;
711
712 if (ar->fw_board == NULL) {
713 ret = ath6kl_fetch_board_file(ar);
714 if (ret)
715 return ret;
716 }
717
718 /* Determine where in Target RAM to write Board Data */
719 ath6kl_bmi_read(ar,
720 ath6kl_get_hi_item_addr(ar,
721 HI_ITEM(hi_board_data)),
722 (u8 *) &board_address, 4);
723 ath6kl_dbg(ATH6KL_DBG_TRC, "board data download addr: 0x%x\n",
724 board_address);
725
726 /* determine where in target ram to write extended board data */
727 ath6kl_bmi_read(ar,
728 ath6kl_get_hi_item_addr(ar,
729 HI_ITEM(hi_board_ext_data)),
730 (u8 *) &board_ext_address, 4);
731
732 ath6kl_dbg(ATH6KL_DBG_TRC, "board file download addr: 0x%x\n",
733 board_ext_address);
734
735 if (board_ext_address == 0) {
736 ath6kl_err("Failed to get board file target address.\n");
737 return -EINVAL;
738 }
739
740 if (ar->fw_board_len == (AR6003_BOARD_DATA_SZ +
741 AR6003_BOARD_EXT_DATA_SZ)) {
742 /* write extended board data */
743 ret = ath6kl_bmi_write(ar, board_ext_address,
744 ar->fw_board + AR6003_BOARD_DATA_SZ,
745 AR6003_BOARD_EXT_DATA_SZ);
746
747 if (ret) {
748 ath6kl_err("Failed to write extended board data: %d\n",
749 ret);
750 return ret;
751 }
752
753 /* record that extended board data is initialized */
754 param = (AR6003_BOARD_EXT_DATA_SZ << 16) | 1;
755 ath6kl_bmi_write(ar,
756 ath6kl_get_hi_item_addr(ar,
757 HI_ITEM(hi_board_ext_data_config)),
758 (unsigned char *) &param, 4);
759 }
760
761 if (ar->fw_board_len < AR6003_BOARD_DATA_SZ) {
762 ath6kl_err("Too small board file: %zu\n", ar->fw_board_len);
763 ret = -EINVAL;
764 return ret;
765 }
766
767 ret = ath6kl_bmi_write(ar, board_address, ar->fw_board,
768 AR6003_BOARD_DATA_SZ);
769
770 if (ret) {
771 ath6kl_err("Board file bmi write failed: %d\n", ret);
772 return ret;
773 }
774
775 /* record the fact that Board Data IS initialized */
776 param = 1;
777 ath6kl_bmi_write(ar,
778 ath6kl_get_hi_item_addr(ar,
779 HI_ITEM(hi_board_data_initialized)),
780 (u8 *)&param, 4);
781
782 return ret;
783}
784
785static int ath6kl_upload_otp(struct ath6kl *ar)
786{
787 const char *filename;
788 u32 address, param;
789 int ret;
790
791 switch (ar->version.target_ver) {
792 case AR6003_REV2_VERSION:
793 filename = AR6003_REV2_OTP_FILE;
794 break;
795 default:
796 filename = AR6003_REV3_OTP_FILE;
797 break;
798 }
799
800 if (ar->fw_otp == NULL) {
801 ret = ath6kl_get_fw(ar, filename, &ar->fw_otp,
802 &ar->fw_otp_len);
803 if (ret) {
804 ath6kl_err("Failed to get OTP file %s: %d\n",
805 filename, ret);
806 return ret;
807 }
808 }
809
810 address = ath6kl_get_load_address(ar->version.target_ver,
811 APP_LOAD_ADDR);
812
813 ret = ath6kl_bmi_fast_download(ar, address, ar->fw_otp,
814 ar->fw_otp_len);
815 if (ret) {
816 ath6kl_err("Failed to upload OTP file: %d\n", ret);
817 return ret;
818 }
819
820 /* execute the OTP code */
821 param = 0;
822 address = ath6kl_get_load_address(ar->version.target_ver,
823 APP_START_OVERRIDE_ADDR);
824 ath6kl_bmi_execute(ar, address, &param);
825
826 return ret;
827}
828
829static int ath6kl_upload_firmware(struct ath6kl *ar)
830{
831 const char *filename;
832 u32 address;
833 int ret;
834
835 switch (ar->version.target_ver) {
836 case AR6003_REV2_VERSION:
837 filename = AR6003_REV2_FIRMWARE_FILE;
838 break;
839 default:
840 filename = AR6003_REV3_FIRMWARE_FILE;
841 break;
842 }
843
844 if (ar->fw == NULL) {
845 ret = ath6kl_get_fw(ar, filename, &ar->fw, &ar->fw_len);
846 if (ret) {
847 ath6kl_err("Failed to get firmware file %s: %d\n",
848 filename, ret);
849 return ret;
850 }
851 }
852
853 address = ath6kl_get_load_address(ar->version.target_ver,
854 APP_LOAD_ADDR);
855
856 ret = ath6kl_bmi_fast_download(ar, address, ar->fw, ar->fw_len);
857
858 if (ret) {
859 ath6kl_err("Failed to write firmware: %d\n", ret);
860 return ret;
861 }
862
863 /* Set starting address for firmware */
864 address = ath6kl_get_load_address(ar->version.target_ver,
865 APP_START_OVERRIDE_ADDR);
866 ath6kl_bmi_set_app_start(ar, address);
867
868 return ret;
869}
870
871static int ath6kl_upload_patch(struct ath6kl *ar)
872{
873 const char *filename;
874 u32 address, param;
875 int ret;
876
877 switch (ar->version.target_ver) {
878 case AR6003_REV2_VERSION:
879 filename = AR6003_REV2_PATCH_FILE;
880 break;
881 default:
882 filename = AR6003_REV3_PATCH_FILE;
883 break;
884 }
885
886 if (ar->fw_patch == NULL) {
887 ret = ath6kl_get_fw(ar, filename, &ar->fw_patch,
888 &ar->fw_patch_len);
889 if (ret) {
890 ath6kl_err("Failed to get patch file %s: %d\n",
891 filename, ret);
892 return ret;
893 }
894 }
895
896 address = ath6kl_get_load_address(ar->version.target_ver,
897 DATASET_PATCH_ADDR);
898
899 ret = ath6kl_bmi_write(ar, address, ar->fw_patch, ar->fw_patch_len);
900 if (ret) {
901 ath6kl_err("Failed to write patch file: %d\n", ret);
902 return ret;
903 }
904
905 param = address;
906 ath6kl_bmi_write(ar,
907 ath6kl_get_hi_item_addr(ar,
908 HI_ITEM(hi_dset_list_head)),
909 (unsigned char *) &param, 4);
910
911 return 0;
912}
913
914static int ath6kl_init_upload(struct ath6kl *ar)
915{
916 u32 param, options, sleep, address;
917 int status = 0;
918
919 if (ar->target_type != TARGET_TYPE_AR6003)
920 return -EINVAL;
921
922 /* temporarily disable system sleep */
923 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
924 status = ath6kl_bmi_reg_read(ar, address, &param);
925 if (status)
926 return status;
927
928 options = param;
929
930 param |= ATH6KL_OPTION_SLEEP_DISABLE;
931 status = ath6kl_bmi_reg_write(ar, address, param);
932 if (status)
933 return status;
934
935 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
936 status = ath6kl_bmi_reg_read(ar, address, &param);
937 if (status)
938 return status;
939
940 sleep = param;
941
942 param |= SM(SYSTEM_SLEEP_DISABLE, 1);
943 status = ath6kl_bmi_reg_write(ar, address, param);
944 if (status)
945 return status;
946
947 ath6kl_dbg(ATH6KL_DBG_TRC, "old options: %d, old sleep: %d\n",
948 options, sleep);
949
950 /* program analog PLL register */
951 status = ath6kl_bmi_reg_write(ar, ATH6KL_ANALOG_PLL_REGISTER,
952 0xF9104001);
953 if (status)
954 return status;
955
956 /* Run at 80/88MHz by default */
957 param = SM(CPU_CLOCK_STANDARD, 1);
958
959 address = RTC_BASE_ADDRESS + CPU_CLOCK_ADDRESS;
960 status = ath6kl_bmi_reg_write(ar, address, param);
961 if (status)
962 return status;
963
964 param = 0;
965 address = RTC_BASE_ADDRESS + LPO_CAL_ADDRESS;
966 param = SM(LPO_CAL_ENABLE, 1);
967 status = ath6kl_bmi_reg_write(ar, address, param);
968 if (status)
969 return status;
970
971 /* WAR to avoid SDIO CRC err */
972 if (ar->version.target_ver == AR6003_REV2_VERSION) {
973 ath6kl_err("temporary war to avoid sdio crc error\n");
974
975 param = 0x20;
976
977 address = GPIO_BASE_ADDRESS + GPIO_PIN10_ADDRESS;
978 status = ath6kl_bmi_reg_write(ar, address, param);
979 if (status)
980 return status;
981
982 address = GPIO_BASE_ADDRESS + GPIO_PIN11_ADDRESS;
983 status = ath6kl_bmi_reg_write(ar, address, param);
984 if (status)
985 return status;
986
987 address = GPIO_BASE_ADDRESS + GPIO_PIN12_ADDRESS;
988 status = ath6kl_bmi_reg_write(ar, address, param);
989 if (status)
990 return status;
991
992 address = GPIO_BASE_ADDRESS + GPIO_PIN13_ADDRESS;
993 status = ath6kl_bmi_reg_write(ar, address, param);
994 if (status)
995 return status;
996 }
997
998 /* write EEPROM data to Target RAM */
999 status = ath6kl_upload_board_file(ar);
1000 if (status)
1001 return status;
1002
1003 /* transfer One time Programmable data */
1004 status = ath6kl_upload_otp(ar);
1005 if (status)
1006 return status;
1007
1008 /* Download Target firmware */
1009 status = ath6kl_upload_firmware(ar);
1010 if (status)
1011 return status;
1012
1013 status = ath6kl_upload_patch(ar);
1014 if (status)
1015 return status;
1016
1017 /* Restore system sleep */
1018 address = RTC_BASE_ADDRESS + SYSTEM_SLEEP_ADDRESS;
1019 status = ath6kl_bmi_reg_write(ar, address, sleep);
1020 if (status)
1021 return status;
1022
1023 address = MBOX_BASE_ADDRESS + LOCAL_SCRATCH_ADDRESS;
1024 param = options | 0x20;
1025 status = ath6kl_bmi_reg_write(ar, address, param);
1026 if (status)
1027 return status;
1028
1029 /* Configure GPIO AR6003 UART */
1030 param = CONFIG_AR600x_DEBUG_UART_TX_PIN;
1031 status = ath6kl_bmi_write(ar,
1032 ath6kl_get_hi_item_addr(ar,
1033 HI_ITEM(hi_dbg_uart_txpin)),
1034 (u8 *)&param, 4);
1035
1036 return status;
1037}
1038
1039static int ath6kl_init(struct net_device *dev)
1040{
1041 struct ath6kl *ar = ath6kl_priv(dev);
1042 int status = 0;
1043 s32 timeleft;
1044
1045 if (!ar)
1046 return -EIO;
1047
1048 /* Do we need to finish the BMI phase */
1049 if (ath6kl_bmi_done(ar)) {
1050 status = -EIO;
1051 goto ath6kl_init_done;
1052 }
1053
1054 /* Indicate that WMI is enabled (although not ready yet) */
1055 set_bit(WMI_ENABLED, &ar->flag);
1056 ar->wmi = ath6kl_wmi_init(ar);
1057 if (!ar->wmi) {
1058 ath6kl_err("failed to initialize wmi\n");
1059 status = -EIO;
1060 goto ath6kl_init_done;
1061 }
1062
1063 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: got wmi @ 0x%p.\n", __func__, ar->wmi);
1064
1065 wlan_node_table_init(&ar->scan_table);
1066
1067 /*
1068 * The reason we have to wait for the target here is that the
1069 * driver layer has to init BMI in order to set the host block
1070 * size.
1071 */
1072 if (ath6kl_htc_wait_target(ar->htc_target)) {
1073 status = -EIO;
1074 goto err_node_cleanup;
1075 }
1076
1077 if (ath6kl_init_service_ep(ar)) {
1078 status = -EIO;
1079 goto err_cleanup_scatter;
1080 }
1081
1082 /* setup access class priority mappings */
1083 ar->ac_stream_pri_map[WMM_AC_BK] = 0; /* lowest */
1084 ar->ac_stream_pri_map[WMM_AC_BE] = 1;
1085 ar->ac_stream_pri_map[WMM_AC_VI] = 2;
1086 ar->ac_stream_pri_map[WMM_AC_VO] = 3; /* highest */
1087
1088 /* give our connected endpoints some buffers */
1089 ath6kl_rx_refill(ar->htc_target, ar->ctrl_ep);
1090 ath6kl_rx_refill(ar->htc_target, ar->ac2ep_map[WMM_AC_BE]);
1091
1092 /* allocate some buffers that handle larger AMSDU frames */
1093 ath6kl_refill_amsdu_rxbufs(ar, ATH6KL_MAX_AMSDU_RX_BUFFERS);
1094
1095 /* setup credit distribution */
1096 ath6k_setup_credit_dist(ar->htc_target, &ar->credit_state_info);
1097
1098 ath6kl_cookie_init(ar);
1099
1100 /* start HTC */
1101 status = ath6kl_htc_start(ar->htc_target);
1102
1103 if (status) {
1104 ath6kl_cookie_cleanup(ar);
1105 goto err_rxbuf_cleanup;
1106 }
1107
1108 /* Wait for Wmi event to be ready */
1109 timeleft = wait_event_interruptible_timeout(ar->event_wq,
1110 test_bit(WMI_READY,
1111 &ar->flag),
1112 WMI_TIMEOUT);
1113
1114 if (ar->version.abi_ver != ATH6KL_ABI_VERSION) {
1115 ath6kl_err("abi version mismatch: host(0x%x), target(0x%x)\n",
1116 ATH6KL_ABI_VERSION, ar->version.abi_ver);
1117 status = -EIO;
1118 goto err_htc_stop;
1119 }
1120
1121 if (!timeleft || signal_pending(current)) {
1122 ath6kl_err("wmi is not ready or wait was interrupted\n");
1123 status = -EIO;
1124 goto err_htc_stop;
1125 }
1126
1127 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: wmi is ready\n", __func__);
1128
1129 /* communicate the wmi protocol verision to the target */
1130 if ((ath6kl_set_host_app_area(ar)) != 0)
1131 ath6kl_err("unable to set the host app area\n");
1132
1133 ar->conf_flags = ATH6KL_CONF_IGNORE_ERP_BARKER |
1134 ATH6KL_CONF_ENABLE_11N | ATH6KL_CONF_ENABLE_TX_BURST;
1135
1136 status = ath6kl_target_config_wlan_params(ar);
1137 if (!status)
1138 goto ath6kl_init_done;
1139
1140err_htc_stop:
1141 ath6kl_htc_stop(ar->htc_target);
1142err_rxbuf_cleanup:
1143 ath6kl_htc_flush_rx_buf(ar->htc_target);
1144 ath6kl_cleanup_amsdu_rxbufs(ar);
1145err_cleanup_scatter:
1146 ath6kl_hif_cleanup_scatter(ar);
1147err_node_cleanup:
1148 wlan_node_table_cleanup(&ar->scan_table);
1149 ath6kl_wmi_shutdown(ar->wmi);
1150 clear_bit(WMI_ENABLED, &ar->flag);
1151 ar->wmi = NULL;
1152
1153ath6kl_init_done:
1154 return status;
1155}
1156
1157int ath6kl_core_init(struct ath6kl *ar)
1158{
1159 int ret = 0;
1160 struct ath6kl_bmi_target_info targ_info;
1161
1162 ar->ath6kl_wq = create_singlethread_workqueue("ath6kl");
1163 if (!ar->ath6kl_wq)
1164 return -ENOMEM;
1165
1166 ret = ath6kl_bmi_init(ar);
1167 if (ret)
1168 goto err_wq;
1169
1170 ret = ath6kl_bmi_get_target_info(ar, &targ_info);
1171 if (ret)
1172 goto err_bmi_cleanup;
1173
1174 ar->version.target_ver = le32_to_cpu(targ_info.version);
1175 ar->target_type = le32_to_cpu(targ_info.type);
1176 ar->wdev->wiphy->hw_version = le32_to_cpu(targ_info.version);
1177
1178 ret = ath6kl_configure_target(ar);
1179 if (ret)
1180 goto err_bmi_cleanup;
1181
1182 ar->htc_target = ath6kl_htc_create(ar);
1183
1184 if (!ar->htc_target) {
1185 ret = -ENOMEM;
1186 goto err_bmi_cleanup;
1187 }
1188
1189 ar->aggr_cntxt = aggr_init(ar->net_dev);
1190 if (!ar->aggr_cntxt) {
1191 ath6kl_err("failed to initialize aggr\n");
1192 ret = -ENOMEM;
1193 goto err_htc_cleanup;
1194 }
1195
1196 ret = ath6kl_init_upload(ar);
1197 if (ret)
1198 goto err_htc_cleanup;
1199
1200 ret = ath6kl_init(ar->net_dev);
1201 if (ret)
1202 goto err_htc_cleanup;
1203
1204 /* This runs the init function if registered */
1205 ret = register_netdev(ar->net_dev);
1206 if (ret) {
1207 ath6kl_err("register_netdev failed\n");
1208 ath6kl_destroy(ar->net_dev, 0);
1209 return ret;
1210 }
1211
1212 set_bit(NETDEV_REGISTERED, &ar->flag);
1213
1214 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: name=%s dev=0x%p, ar=0x%p\n",
1215 __func__, ar->net_dev->name, ar->net_dev, ar);
1216
1217 return ret;
1218
1219err_htc_cleanup:
1220 ath6kl_htc_cleanup(ar->htc_target);
1221err_bmi_cleanup:
1222 ath6kl_bmi_cleanup(ar);
1223err_wq:
1224 destroy_workqueue(ar->ath6kl_wq);
1225 return ret;
1226}
1227
1228void ath6kl_stop_txrx(struct ath6kl *ar)
1229{
1230 struct net_device *ndev = ar->net_dev;
1231
1232 if (!ndev)
1233 return;
1234
1235 set_bit(DESTROY_IN_PROGRESS, &ar->flag);
1236
1237 if (down_interruptible(&ar->sem)) {
1238 ath6kl_err("down_interruptible failed\n");
1239 return;
1240 }
1241
1242 if (ar->wlan_pwr_state != WLAN_POWER_STATE_CUT_PWR)
1243 ath6kl_stop_endpoint(ndev, false, true);
1244
1245 clear_bit(WLAN_ENABLED, &ar->flag);
1246}
1247
1248/*
1249 * We need to differentiate between the surprise and planned removal of the
1250 * device because of the following consideration:
1251 *
1252 * - In case of surprise removal, the hcd already frees up the pending
1253 * for the device and hence there is no need to unregister the function
1254 * driver inorder to get these requests. For planned removal, the function
1255 * driver has to explicitly unregister itself to have the hcd return all the
1256 * pending requests before the data structures for the devices are freed up.
1257 * Note that as per the current implementation, the function driver will
1258 * end up releasing all the devices since there is no API to selectively
1259 * release a particular device.
1260 *
1261 * - Certain commands issued to the target can be skipped for surprise
1262 * removal since they will anyway not go through.
1263 */
1264void ath6kl_destroy(struct net_device *dev, unsigned int unregister)
1265{
1266 struct ath6kl *ar;
1267
1268 if (!dev || !ath6kl_priv(dev)) {
1269 ath6kl_err("failed to get device structure\n");
1270 return;
1271 }
1272
1273 ar = ath6kl_priv(dev);
1274
1275 destroy_workqueue(ar->ath6kl_wq);
1276
1277 if (ar->htc_target)
1278 ath6kl_htc_cleanup(ar->htc_target);
1279
1280 aggr_module_destroy(ar->aggr_cntxt);
1281
1282 ath6kl_cookie_cleanup(ar);
1283
1284 ath6kl_cleanup_amsdu_rxbufs(ar);
1285
1286 ath6kl_bmi_cleanup(ar);
1287
1288 if (unregister && test_bit(NETDEV_REGISTERED, &ar->flag)) {
1289 unregister_netdev(dev);
1290 clear_bit(NETDEV_REGISTERED, &ar->flag);
1291 }
1292
1293 free_netdev(dev);
1294
1295 wlan_node_table_cleanup(&ar->scan_table);
1296
1297 kfree(ar->fw_board);
1298 kfree(ar->fw_otp);
1299 kfree(ar->fw);
1300 kfree(ar->fw_patch);
1301
1302 ath6kl_cfg80211_deinit(ar);
1303}
diff --git a/drivers/net/wireless/ath/ath6kl/main.c b/drivers/net/wireless/ath/ath6kl/main.c
new file mode 100644
index 000000000000..c336eae0cf48
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/main.c
@@ -0,0 +1,1337 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "hif-ops.h"
19#include "cfg80211.h"
20#include "target.h"
21#include "debug.h"
22
23struct ath6kl_sta *ath6kl_find_sta(struct ath6kl *ar, u8 *node_addr)
24{
25 struct ath6kl_sta *conn = NULL;
26 u8 i, max_conn;
27
28 max_conn = (ar->nw_type == AP_NETWORK) ? AP_MAX_NUM_STA : 0;
29
30 for (i = 0; i < max_conn; i++) {
31 if (memcmp(node_addr, ar->sta_list[i].mac, ETH_ALEN) == 0) {
32 conn = &ar->sta_list[i];
33 break;
34 }
35 }
36
37 return conn;
38}
39
40struct ath6kl_sta *ath6kl_find_sta_by_aid(struct ath6kl *ar, u8 aid)
41{
42 struct ath6kl_sta *conn = NULL;
43 u8 ctr;
44
45 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
46 if (ar->sta_list[ctr].aid == aid) {
47 conn = &ar->sta_list[ctr];
48 break;
49 }
50 }
51 return conn;
52}
53
54static void ath6kl_add_new_sta(struct ath6kl *ar, u8 *mac, u16 aid, u8 *wpaie,
55 u8 ielen, u8 keymgmt, u8 ucipher, u8 auth)
56{
57 struct ath6kl_sta *sta;
58 u8 free_slot;
59
60 free_slot = aid - 1;
61
62 sta = &ar->sta_list[free_slot];
63 memcpy(sta->mac, mac, ETH_ALEN);
64 memcpy(sta->wpa_ie, wpaie, ielen);
65 sta->aid = aid;
66 sta->keymgmt = keymgmt;
67 sta->ucipher = ucipher;
68 sta->auth = auth;
69
70 ar->sta_list_index = ar->sta_list_index | (1 << free_slot);
71 ar->ap_stats.sta[free_slot].aid = cpu_to_le32(aid);
72}
73
74static void ath6kl_sta_cleanup(struct ath6kl *ar, u8 i)
75{
76 struct ath6kl_sta *sta = &ar->sta_list[i];
77
78 /* empty the queued pkts in the PS queue if any */
79 spin_lock_bh(&sta->psq_lock);
80 skb_queue_purge(&sta->psq);
81 spin_unlock_bh(&sta->psq_lock);
82
83 memset(&ar->ap_stats.sta[sta->aid - 1], 0,
84 sizeof(struct wmi_per_sta_stat));
85 memset(sta->mac, 0, ETH_ALEN);
86 memset(sta->wpa_ie, 0, ATH6KL_MAX_IE);
87 sta->aid = 0;
88 sta->sta_flags = 0;
89
90 ar->sta_list_index = ar->sta_list_index & ~(1 << i);
91
92}
93
94static u8 ath6kl_remove_sta(struct ath6kl *ar, u8 *mac, u16 reason)
95{
96 u8 i, removed = 0;
97
98 if (is_zero_ether_addr(mac))
99 return removed;
100
101 if (is_broadcast_ether_addr(mac)) {
102 ath6kl_dbg(ATH6KL_DBG_TRC, "deleting all station\n");
103
104 for (i = 0; i < AP_MAX_NUM_STA; i++) {
105 if (!is_zero_ether_addr(ar->sta_list[i].mac)) {
106 ath6kl_sta_cleanup(ar, i);
107 removed = 1;
108 }
109 }
110 } else {
111 for (i = 0; i < AP_MAX_NUM_STA; i++) {
112 if (memcmp(ar->sta_list[i].mac, mac, ETH_ALEN) == 0) {
113 ath6kl_dbg(ATH6KL_DBG_TRC,
114 "deleting station %pM aid=%d reason=%d\n",
115 mac, ar->sta_list[i].aid, reason);
116 ath6kl_sta_cleanup(ar, i);
117 removed = 1;
118 break;
119 }
120 }
121 }
122
123 return removed;
124}
125
126enum htc_endpoint_id ath6kl_ac2_endpoint_id(void *devt, u8 ac)
127{
128 struct ath6kl *ar = devt;
129 return ar->ac2ep_map[ac];
130}
131
132struct ath6kl_cookie *ath6kl_alloc_cookie(struct ath6kl *ar)
133{
134 struct ath6kl_cookie *cookie;
135
136 cookie = ar->cookie_list;
137 if (cookie != NULL) {
138 ar->cookie_list = cookie->arc_list_next;
139 ar->cookie_count--;
140 }
141
142 return cookie;
143}
144
145void ath6kl_cookie_init(struct ath6kl *ar)
146{
147 u32 i;
148
149 ar->cookie_list = NULL;
150 ar->cookie_count = 0;
151
152 memset(ar->cookie_mem, 0, sizeof(ar->cookie_mem));
153
154 for (i = 0; i < MAX_COOKIE_NUM; i++)
155 ath6kl_free_cookie(ar, &ar->cookie_mem[i]);
156}
157
158void ath6kl_cookie_cleanup(struct ath6kl *ar)
159{
160 ar->cookie_list = NULL;
161 ar->cookie_count = 0;
162}
163
164void ath6kl_free_cookie(struct ath6kl *ar, struct ath6kl_cookie *cookie)
165{
166 /* Insert first */
167
168 if (!ar || !cookie)
169 return;
170
171 cookie->arc_list_next = ar->cookie_list;
172 ar->cookie_list = cookie;
173 ar->cookie_count++;
174}
175
176/* set the window address register (using 4-byte register access ). */
177static int ath6kl_set_addrwin_reg(struct ath6kl *ar, u32 reg_addr, u32 addr)
178{
179 int status;
180 u8 addr_val[4];
181 s32 i;
182
183 /*
184 * Write bytes 1,2,3 of the register to set the upper address bytes,
185 * the LSB is written last to initiate the access cycle
186 */
187
188 for (i = 1; i <= 3; i++) {
189 /*
190 * Fill the buffer with the address byte value we want to
191 * hit 4 times.
192 */
193 memset(addr_val, ((u8 *)&addr)[i], 4);
194
195 /*
196 * Hit each byte of the register address with a 4-byte
197 * write operation to the same address, this is a harmless
198 * operation.
199 */
200 status = hif_read_write_sync(ar, reg_addr + i, addr_val,
201 4, HIF_WR_SYNC_BYTE_FIX);
202 if (status)
203 break;
204 }
205
206 if (status) {
207 ath6kl_err("failed to write initial bytes of 0x%x to window reg: 0x%X\n",
208 addr, reg_addr);
209 return status;
210 }
211
212 /*
213 * Write the address register again, this time write the whole
214 * 4-byte value. The effect here is that the LSB write causes the
215 * cycle to start, the extra 3 byte write to bytes 1,2,3 has no
216 * effect since we are writing the same values again
217 */
218 status = hif_read_write_sync(ar, reg_addr, (u8 *)(&addr),
219 4, HIF_WR_SYNC_BYTE_INC);
220
221 if (status) {
222 ath6kl_err("failed to write 0x%x to window reg: 0x%X\n",
223 addr, reg_addr);
224 return status;
225 }
226
227 return 0;
228}
229
230/*
231 * Read from the ATH6KL through its diagnostic window. No cooperation from
232 * the Target is required for this.
233 */
234int ath6kl_read_reg_diag(struct ath6kl *ar, u32 *address, u32 *data)
235{
236 int status;
237
238 /* set window register to start read cycle */
239 status = ath6kl_set_addrwin_reg(ar, WINDOW_READ_ADDR_ADDRESS,
240 *address);
241
242 if (status)
243 return status;
244
245 /* read the data */
246 status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data,
247 sizeof(u32), HIF_RD_SYNC_BYTE_INC);
248 if (status) {
249 ath6kl_err("failed to read from window data addr\n");
250 return status;
251 }
252
253 return status;
254}
255
256
257/*
258 * Write to the ATH6KL through its diagnostic window. No cooperation from
259 * the Target is required for this.
260 */
261static int ath6kl_write_reg_diag(struct ath6kl *ar, u32 *address, u32 *data)
262{
263 int status;
264
265 /* set write data */
266 status = hif_read_write_sync(ar, WINDOW_DATA_ADDRESS, (u8 *)data,
267 sizeof(u32), HIF_WR_SYNC_BYTE_INC);
268 if (status) {
269 ath6kl_err("failed to write 0x%x to window data addr\n", *data);
270 return status;
271 }
272
273 /* set window register, which starts the write cycle */
274 return ath6kl_set_addrwin_reg(ar, WINDOW_WRITE_ADDR_ADDRESS,
275 *address);
276}
277
278int ath6kl_access_datadiag(struct ath6kl *ar, u32 address,
279 u8 *data, u32 length, bool read)
280{
281 u32 count;
282 int status = 0;
283
284 for (count = 0; count < length; count += 4, address += 4) {
285 if (read) {
286 status = ath6kl_read_reg_diag(ar, &address,
287 (u32 *) &data[count]);
288 if (status)
289 break;
290 } else {
291 status = ath6kl_write_reg_diag(ar, &address,
292 (u32 *) &data[count]);
293 if (status)
294 break;
295 }
296 }
297
298 return status;
299}
300
301static void ath6kl_reset_device(struct ath6kl *ar, u32 target_type,
302 bool wait_fot_compltn, bool cold_reset)
303{
304 int status = 0;
305 u32 address;
306 u32 data;
307
308 if (target_type != TARGET_TYPE_AR6003)
309 return;
310
311 data = cold_reset ? RESET_CONTROL_COLD_RST : RESET_CONTROL_MBOX_RST;
312
313 address = RTC_BASE_ADDRESS;
314 status = ath6kl_write_reg_diag(ar, &address, &data);
315
316 if (status)
317 ath6kl_err("failed to reset target\n");
318}
319
320void ath6kl_stop_endpoint(struct net_device *dev, bool keep_profile,
321 bool get_dbglogs)
322{
323 struct ath6kl *ar = ath6kl_priv(dev);
324 static u8 bcast_mac[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
325 bool discon_issued;
326
327 netif_stop_queue(dev);
328
329 /* disable the target and the interrupts associated with it */
330 if (test_bit(WMI_READY, &ar->flag)) {
331 discon_issued = (test_bit(CONNECTED, &ar->flag) ||
332 test_bit(CONNECT_PEND, &ar->flag));
333 ath6kl_disconnect(ar);
334 if (!keep_profile)
335 ath6kl_init_profile_info(ar);
336
337 del_timer(&ar->disconnect_timer);
338
339 clear_bit(WMI_READY, &ar->flag);
340 ath6kl_wmi_shutdown(ar->wmi);
341 clear_bit(WMI_ENABLED, &ar->flag);
342 ar->wmi = NULL;
343
344 /*
345 * After wmi_shudown all WMI events will be dropped. We
346 * need to cleanup the buffers allocated in AP mode and
347 * give disconnect notification to stack, which usually
348 * happens in the disconnect_event. Simulate the disconnect
349 * event by calling the function directly. Sometimes
350 * disconnect_event will be received when the debug logs
351 * are collected.
352 */
353 if (discon_issued)
354 ath6kl_disconnect_event(ar, DISCONNECT_CMD,
355 (ar->nw_type & AP_NETWORK) ?
356 bcast_mac : ar->bssid,
357 0, NULL, 0);
358
359 ar->user_key_ctrl = 0;
360
361 } else {
362 ath6kl_dbg(ATH6KL_DBG_TRC,
363 "%s: wmi is not ready 0x%p 0x%p\n",
364 __func__, ar, ar->wmi);
365
366 /* Shut down WMI if we have started it */
367 if (test_bit(WMI_ENABLED, &ar->flag)) {
368 ath6kl_dbg(ATH6KL_DBG_TRC,
369 "%s: shut down wmi\n", __func__);
370 ath6kl_wmi_shutdown(ar->wmi);
371 clear_bit(WMI_ENABLED, &ar->flag);
372 ar->wmi = NULL;
373 }
374 }
375
376 if (ar->htc_target) {
377 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: shut down htc\n", __func__);
378 ath6kl_htc_stop(ar->htc_target);
379 }
380
381 /*
382 * Try to reset the device if we can. The driver may have been
383 * configure NOT to reset the target during a debug session.
384 */
385 ath6kl_dbg(ATH6KL_DBG_TRC,
386 "attempting to reset target on instance destroy\n");
387 ath6kl_reset_device(ar, ar->target_type, true, true);
388}
389
390static void ath6kl_install_static_wep_keys(struct ath6kl *ar)
391{
392 u8 index;
393 u8 keyusage;
394
395 for (index = WMI_MIN_KEY_INDEX; index <= WMI_MAX_KEY_INDEX; index++) {
396 if (ar->wep_key_list[index].key_len) {
397 keyusage = GROUP_USAGE;
398 if (index == ar->def_txkey_index)
399 keyusage |= TX_USAGE;
400
401 ath6kl_wmi_addkey_cmd(ar->wmi,
402 index,
403 WEP_CRYPT,
404 keyusage,
405 ar->wep_key_list[index].key_len,
406 NULL,
407 ar->wep_key_list[index].key,
408 KEY_OP_INIT_VAL, NULL,
409 NO_SYNC_WMIFLAG);
410 }
411 }
412}
413
414static void ath6kl_connect_ap_mode(struct ath6kl *ar, u16 channel, u8 *bssid,
415 u16 listen_int, u16 beacon_int,
416 u8 assoc_resp_len, u8 *assoc_info)
417{
418 struct net_device *dev = ar->net_dev;
419 struct station_info sinfo;
420 struct ath6kl_req_key *ik;
421 enum crypto_type keyType = NONE_CRYPT;
422
423 if (memcmp(dev->dev_addr, bssid, ETH_ALEN) == 0) {
424 ik = &ar->ap_mode_bkey;
425
426 switch (ar->auth_mode) {
427 case NONE_AUTH:
428 if (ar->prwise_crypto == WEP_CRYPT)
429 ath6kl_install_static_wep_keys(ar);
430 break;
431 case WPA_PSK_AUTH:
432 case WPA2_PSK_AUTH:
433 case (WPA_PSK_AUTH|WPA2_PSK_AUTH):
434 switch (ik->ik_type) {
435 case ATH6KL_CIPHER_TKIP:
436 keyType = TKIP_CRYPT;
437 break;
438 case ATH6KL_CIPHER_AES_CCM:
439 keyType = AES_CRYPT;
440 break;
441 default:
442 goto skip_key;
443 }
444 ath6kl_wmi_addkey_cmd(ar->wmi, ik->ik_keyix, keyType,
445 GROUP_USAGE, ik->ik_keylen,
446 (u8 *)&ik->ik_keyrsc,
447 ik->ik_keydata,
448 KEY_OP_INIT_VAL, ik->ik_macaddr,
449 SYNC_BOTH_WMIFLAG);
450 break;
451 }
452skip_key:
453 set_bit(CONNECTED, &ar->flag);
454 return;
455 }
456
457 ath6kl_dbg(ATH6KL_DBG_TRC, "new station %pM aid=%d\n",
458 bssid, channel);
459
460 ath6kl_add_new_sta(ar, bssid, channel, assoc_info, assoc_resp_len,
461 listen_int & 0xFF, beacon_int,
462 (listen_int >> 8) & 0xFF);
463
464 /* send event to application */
465 memset(&sinfo, 0, sizeof(sinfo));
466
467 /* TODO: sinfo.generation */
468 /* TODO: need to deliver (Re)AssocReq IEs somehow.. change in
469 * cfg80211 needed, e.g., by adding those into sinfo
470 */
471 cfg80211_new_sta(ar->net_dev, bssid, &sinfo, GFP_KERNEL);
472
473 netif_wake_queue(ar->net_dev);
474
475 return;
476}
477
478/* Functions for Tx credit handling */
479void ath6k_credit_init(struct htc_credit_state_info *cred_info,
480 struct list_head *ep_list,
481 int tot_credits)
482{
483 struct htc_endpoint_credit_dist *cur_ep_dist;
484 int count;
485
486 cred_info->cur_free_credits = tot_credits;
487 cred_info->total_avail_credits = tot_credits;
488
489 list_for_each_entry(cur_ep_dist, ep_list, list) {
490 if (cur_ep_dist->endpoint == ENDPOINT_0)
491 continue;
492
493 cur_ep_dist->cred_min = cur_ep_dist->cred_per_msg;
494
495 if (tot_credits > 4)
496 if ((cur_ep_dist->svc_id == WMI_DATA_BK_SVC) ||
497 (cur_ep_dist->svc_id == WMI_DATA_BE_SVC)) {
498 ath6kl_deposit_credit_to_ep(cred_info,
499 cur_ep_dist,
500 cur_ep_dist->cred_min);
501 cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
502 }
503
504 if (cur_ep_dist->svc_id == WMI_CONTROL_SVC) {
505 ath6kl_deposit_credit_to_ep(cred_info, cur_ep_dist,
506 cur_ep_dist->cred_min);
507 /*
508 * Control service is always marked active, it
509 * never goes inactive EVER.
510 */
511 cur_ep_dist->dist_flags |= HTC_EP_ACTIVE;
512 } else if (cur_ep_dist->svc_id == WMI_DATA_BK_SVC)
513 /* this is the lowest priority data endpoint */
514 cred_info->lowestpri_ep_dist = cur_ep_dist->list;
515
516 /*
517 * Streams have to be created (explicit | implicit) for all
518 * kinds of traffic. BE endpoints are also inactive in the
519 * beginning. When BE traffic starts it creates implicit
520 * streams that redistributes credits.
521 *
522 * Note: all other endpoints have minimums set but are
523 * initially given NO credits. credits will be distributed
524 * as traffic activity demands
525 */
526 }
527
528 WARN_ON(cred_info->cur_free_credits <= 0);
529
530 list_for_each_entry(cur_ep_dist, ep_list, list) {
531 if (cur_ep_dist->endpoint == ENDPOINT_0)
532 continue;
533
534 if (cur_ep_dist->svc_id == WMI_CONTROL_SVC)
535 cur_ep_dist->cred_norm = cur_ep_dist->cred_per_msg;
536 else {
537 /*
538 * For the remaining data endpoints, we assume that
539 * each cred_per_msg are the same. We use a simple
540 * calculation here, we take the remaining credits
541 * and determine how many max messages this can
542 * cover and then set each endpoint's normal value
543 * equal to 3/4 this amount.
544 */
545 count = (cred_info->cur_free_credits /
546 cur_ep_dist->cred_per_msg)
547 * cur_ep_dist->cred_per_msg;
548 count = (count * 3) >> 2;
549 count = max(count, cur_ep_dist->cred_per_msg);
550 cur_ep_dist->cred_norm = count;
551
552 }
553 }
554}
555
556/* initialize and setup credit distribution */
557int ath6k_setup_credit_dist(void *htc_handle,
558 struct htc_credit_state_info *cred_info)
559{
560 u16 servicepriority[5];
561
562 memset(cred_info, 0, sizeof(struct htc_credit_state_info));
563
564 servicepriority[0] = WMI_CONTROL_SVC; /* highest */
565 servicepriority[1] = WMI_DATA_VO_SVC;
566 servicepriority[2] = WMI_DATA_VI_SVC;
567 servicepriority[3] = WMI_DATA_BE_SVC;
568 servicepriority[4] = WMI_DATA_BK_SVC; /* lowest */
569
570 /* set priority list */
571 ath6kl_htc_set_credit_dist(htc_handle, cred_info, servicepriority, 5);
572
573 return 0;
574}
575
576/* reduce an ep's credits back to a set limit */
577static void ath6k_reduce_credits(struct htc_credit_state_info *cred_info,
578 struct htc_endpoint_credit_dist *ep_dist,
579 int limit)
580{
581 int credits;
582
583 ep_dist->cred_assngd = limit;
584
585 if (ep_dist->credits <= limit)
586 return;
587
588 credits = ep_dist->credits - limit;
589 ep_dist->credits -= credits;
590 cred_info->cur_free_credits += credits;
591}
592
593static void ath6k_credit_update(struct htc_credit_state_info *cred_info,
594 struct list_head *epdist_list)
595{
596 struct htc_endpoint_credit_dist *cur_dist_list;
597
598 list_for_each_entry(cur_dist_list, epdist_list, list) {
599 if (cur_dist_list->endpoint == ENDPOINT_0)
600 continue;
601
602 if (cur_dist_list->cred_to_dist > 0) {
603 cur_dist_list->credits +=
604 cur_dist_list->cred_to_dist;
605 cur_dist_list->cred_to_dist = 0;
606 if (cur_dist_list->credits >
607 cur_dist_list->cred_assngd)
608 ath6k_reduce_credits(cred_info,
609 cur_dist_list,
610 cur_dist_list->cred_assngd);
611
612 if (cur_dist_list->credits >
613 cur_dist_list->cred_norm)
614 ath6k_reduce_credits(cred_info, cur_dist_list,
615 cur_dist_list->cred_norm);
616
617 if (!(cur_dist_list->dist_flags & HTC_EP_ACTIVE)) {
618 if (cur_dist_list->txq_depth == 0)
619 ath6k_reduce_credits(cred_info,
620 cur_dist_list, 0);
621 }
622 }
623 }
624}
625
626/*
627 * HTC has an endpoint that needs credits, ep_dist is the endpoint in
628 * question.
629 */
630void ath6k_seek_credits(struct htc_credit_state_info *cred_info,
631 struct htc_endpoint_credit_dist *ep_dist)
632{
633 struct htc_endpoint_credit_dist *curdist_list;
634 int credits = 0;
635 int need;
636
637 if (ep_dist->svc_id == WMI_CONTROL_SVC)
638 goto out;
639
640 if ((ep_dist->svc_id == WMI_DATA_VI_SVC) ||
641 (ep_dist->svc_id == WMI_DATA_VO_SVC))
642 if ((ep_dist->cred_assngd >= ep_dist->cred_norm))
643 goto out;
644
645 /*
646 * For all other services, we follow a simple algorithm of:
647 *
648 * 1. checking the free pool for credits
649 * 2. checking lower priority endpoints for credits to take
650 */
651
652 credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
653
654 if (credits >= ep_dist->seek_cred)
655 goto out;
656
657 /*
658 * We don't have enough in the free pool, try taking away from
659 * lower priority services The rule for taking away credits:
660 *
661 * 1. Only take from lower priority endpoints
662 * 2. Only take what is allocated above the minimum (never
663 * starve an endpoint completely)
664 * 3. Only take what you need.
665 */
666
667 list_for_each_entry_reverse(curdist_list,
668 &cred_info->lowestpri_ep_dist,
669 list) {
670 if (curdist_list == ep_dist)
671 break;
672
673 need = ep_dist->seek_cred - cred_info->cur_free_credits;
674
675 if ((curdist_list->cred_assngd - need) >=
676 curdist_list->cred_min) {
677 /*
678 * The current one has been allocated more than
679 * it's minimum and it has enough credits assigned
680 * above it's minimum to fulfill our need try to
681 * take away just enough to fulfill our need.
682 */
683 ath6k_reduce_credits(cred_info, curdist_list,
684 curdist_list->cred_assngd - need);
685
686 if (cred_info->cur_free_credits >=
687 ep_dist->seek_cred)
688 break;
689 }
690
691 if (curdist_list->endpoint == ENDPOINT_0)
692 break;
693 }
694
695 credits = min(cred_info->cur_free_credits, ep_dist->seek_cred);
696
697out:
698 /* did we find some credits? */
699 if (credits)
700 ath6kl_deposit_credit_to_ep(cred_info, ep_dist, credits);
701
702 ep_dist->seek_cred = 0;
703}
704
705/* redistribute credits based on activity change */
706static void ath6k_redistribute_credits(struct htc_credit_state_info *info,
707 struct list_head *ep_dist_list)
708{
709 struct htc_endpoint_credit_dist *curdist_list;
710
711 list_for_each_entry(curdist_list, ep_dist_list, list) {
712 if (curdist_list->endpoint == ENDPOINT_0)
713 continue;
714
715 if ((curdist_list->svc_id == WMI_DATA_BK_SVC) ||
716 (curdist_list->svc_id == WMI_DATA_BE_SVC))
717 curdist_list->dist_flags |= HTC_EP_ACTIVE;
718
719 if ((curdist_list->svc_id != WMI_CONTROL_SVC) &&
720 !(curdist_list->dist_flags & HTC_EP_ACTIVE)) {
721 if (curdist_list->txq_depth == 0)
722 ath6k_reduce_credits(info,
723 curdist_list, 0);
724 else
725 ath6k_reduce_credits(info,
726 curdist_list,
727 curdist_list->cred_min);
728 }
729 }
730}
731
732/*
733 *
734 * This function is invoked whenever endpoints require credit
735 * distributions. A lock is held while this function is invoked, this
736 * function shall NOT block. The ep_dist_list is a list of distribution
737 * structures in prioritized order as defined by the call to the
738 * htc_set_credit_dist() api.
739 */
740void ath6k_credit_distribute(struct htc_credit_state_info *cred_info,
741 struct list_head *ep_dist_list,
742 enum htc_credit_dist_reason reason)
743{
744 switch (reason) {
745 case HTC_CREDIT_DIST_SEND_COMPLETE:
746 ath6k_credit_update(cred_info, ep_dist_list);
747 break;
748 case HTC_CREDIT_DIST_ACTIVITY_CHANGE:
749 ath6k_redistribute_credits(cred_info, ep_dist_list);
750 break;
751 default:
752 break;
753 }
754
755 WARN_ON(cred_info->cur_free_credits > cred_info->total_avail_credits);
756 WARN_ON(cred_info->cur_free_credits < 0);
757}
758
759void disconnect_timer_handler(unsigned long ptr)
760{
761 struct net_device *dev = (struct net_device *)ptr;
762 struct ath6kl *ar = ath6kl_priv(dev);
763
764 ath6kl_init_profile_info(ar);
765 ath6kl_disconnect(ar);
766}
767
768void ath6kl_disconnect(struct ath6kl *ar)
769{
770 if (test_bit(CONNECTED, &ar->flag) ||
771 test_bit(CONNECT_PEND, &ar->flag)) {
772 ath6kl_wmi_disconnect_cmd(ar->wmi);
773 /*
774 * Disconnect command is issued, clear the connect pending
775 * flag. The connected flag will be cleared in
776 * disconnect event notification.
777 */
778 clear_bit(CONNECT_PEND, &ar->flag);
779 }
780}
781
782/* WMI Event handlers */
783
784static const char *get_hw_id_string(u32 id)
785{
786 switch (id) {
787 case AR6003_REV1_VERSION:
788 return "1.0";
789 case AR6003_REV2_VERSION:
790 return "2.0";
791 case AR6003_REV3_VERSION:
792 return "2.1.1";
793 default:
794 return "unknown";
795 }
796}
797
798void ath6kl_ready_event(void *devt, u8 *datap, u32 sw_ver, u32 abi_ver)
799{
800 struct ath6kl *ar = devt;
801 struct net_device *dev = ar->net_dev;
802
803 memcpy(dev->dev_addr, datap, ETH_ALEN);
804 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: mac addr = %pM\n",
805 __func__, dev->dev_addr);
806
807 ar->version.wlan_ver = sw_ver;
808 ar->version.abi_ver = abi_ver;
809
810 snprintf(ar->wdev->wiphy->fw_version,
811 sizeof(ar->wdev->wiphy->fw_version),
812 "%u.%u.%u.%u",
813 (ar->version.wlan_ver & 0xf0000000) >> 28,
814 (ar->version.wlan_ver & 0x0f000000) >> 24,
815 (ar->version.wlan_ver & 0x00ff0000) >> 16,
816 (ar->version.wlan_ver & 0x0000ffff));
817
818 /* indicate to the waiting thread that the ready event was received */
819 set_bit(WMI_READY, &ar->flag);
820 wake_up(&ar->event_wq);
821
822 ath6kl_info("hw %s fw %s\n",
823 get_hw_id_string(ar->wdev->wiphy->hw_version),
824 ar->wdev->wiphy->fw_version);
825}
826
827void ath6kl_scan_complete_evt(struct ath6kl *ar, int status)
828{
829 ath6kl_cfg80211_scan_complete_event(ar, status);
830
831 if (!ar->usr_bss_filter)
832 ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
833
834 ath6kl_dbg(ATH6KL_DBG_WLAN_SCAN, "scan complete: %d\n", status);
835}
836
837void ath6kl_connect_event(struct ath6kl *ar, u16 channel, u8 *bssid,
838 u16 listen_int, u16 beacon_int,
839 enum network_type net_type, u8 beacon_ie_len,
840 u8 assoc_req_len, u8 assoc_resp_len,
841 u8 *assoc_info)
842{
843 unsigned long flags;
844
845 if (ar->nw_type == AP_NETWORK) {
846 ath6kl_connect_ap_mode(ar, channel, bssid, listen_int,
847 beacon_int, assoc_resp_len,
848 assoc_info);
849 return;
850 }
851
852 ath6kl_cfg80211_connect_event(ar, channel, bssid,
853 listen_int, beacon_int,
854 net_type, beacon_ie_len,
855 assoc_req_len, assoc_resp_len,
856 assoc_info);
857
858 memcpy(ar->bssid, bssid, sizeof(ar->bssid));
859 ar->bss_ch = channel;
860
861 if ((ar->nw_type == INFRA_NETWORK))
862 ath6kl_wmi_listeninterval_cmd(ar->wmi, ar->listen_intvl_t,
863 ar->listen_intvl_b);
864
865 netif_wake_queue(ar->net_dev);
866
867 /* Update connect & link status atomically */
868 spin_lock_irqsave(&ar->lock, flags);
869 set_bit(CONNECTED, &ar->flag);
870 clear_bit(CONNECT_PEND, &ar->flag);
871 netif_carrier_on(ar->net_dev);
872 spin_unlock_irqrestore(&ar->lock, flags);
873
874 aggr_reset_state(ar->aggr_cntxt);
875 ar->reconnect_flag = 0;
876
877 if ((ar->nw_type == ADHOC_NETWORK) && ar->ibss_ps_enable) {
878 memset(ar->node_map, 0, sizeof(ar->node_map));
879 ar->node_num = 0;
880 ar->next_ep_id = ENDPOINT_2;
881 }
882
883 if (!ar->usr_bss_filter)
884 ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
885}
886
887void ath6kl_tkip_micerr_event(struct ath6kl *ar, u8 keyid, bool ismcast)
888{
889 struct ath6kl_sta *sta;
890 u8 tsc[6];
891 /*
892 * For AP case, keyid will have aid of STA which sent pkt with
893 * MIC error. Use this aid to get MAC & send it to hostapd.
894 */
895 if (ar->nw_type == AP_NETWORK) {
896 sta = ath6kl_find_sta_by_aid(ar, (keyid >> 2));
897 if (!sta)
898 return;
899
900 ath6kl_dbg(ATH6KL_DBG_TRC,
901 "ap tkip mic error received from aid=%d\n", keyid);
902
903 memset(tsc, 0, sizeof(tsc)); /* FIX: get correct TSC */
904 cfg80211_michael_mic_failure(ar->net_dev, sta->mac,
905 NL80211_KEYTYPE_PAIRWISE, keyid,
906 tsc, GFP_KERNEL);
907 } else
908 ath6kl_cfg80211_tkip_micerr_event(ar, keyid, ismcast);
909
910}
911
912static void ath6kl_update_target_stats(struct ath6kl *ar, u8 *ptr, u32 len)
913{
914 struct wmi_target_stats *tgt_stats =
915 (struct wmi_target_stats *) ptr;
916 struct target_stats *stats = &ar->target_stats;
917 struct tkip_ccmp_stats *ccmp_stats;
918 struct bss *conn_bss = NULL;
919 struct cserv_stats *c_stats;
920 u8 ac;
921
922 if (len < sizeof(*tgt_stats))
923 return;
924
925 /* update the RSSI of the connected bss */
926 if (test_bit(CONNECTED, &ar->flag)) {
927 conn_bss = ath6kl_wmi_find_node(ar->wmi, ar->bssid);
928 if (conn_bss) {
929 c_stats = &tgt_stats->cserv_stats;
930 conn_bss->ni_rssi =
931 a_sle16_to_cpu(c_stats->cs_ave_beacon_rssi);
932 conn_bss->ni_snr =
933 tgt_stats->cserv_stats.cs_ave_beacon_snr;
934 ath6kl_wmi_node_return(ar->wmi, conn_bss);
935 }
936 }
937
938 ath6kl_dbg(ATH6KL_DBG_TRC, "updating target stats\n");
939
940 stats->tx_pkt += le32_to_cpu(tgt_stats->stats.tx.pkt);
941 stats->tx_byte += le32_to_cpu(tgt_stats->stats.tx.byte);
942 stats->tx_ucast_pkt += le32_to_cpu(tgt_stats->stats.tx.ucast_pkt);
943 stats->tx_ucast_byte += le32_to_cpu(tgt_stats->stats.tx.ucast_byte);
944 stats->tx_mcast_pkt += le32_to_cpu(tgt_stats->stats.tx.mcast_pkt);
945 stats->tx_mcast_byte += le32_to_cpu(tgt_stats->stats.tx.mcast_byte);
946 stats->tx_bcast_pkt += le32_to_cpu(tgt_stats->stats.tx.bcast_pkt);
947 stats->tx_bcast_byte += le32_to_cpu(tgt_stats->stats.tx.bcast_byte);
948 stats->tx_rts_success_cnt +=
949 le32_to_cpu(tgt_stats->stats.tx.rts_success_cnt);
950
951 for (ac = 0; ac < WMM_NUM_AC; ac++)
952 stats->tx_pkt_per_ac[ac] +=
953 le32_to_cpu(tgt_stats->stats.tx.pkt_per_ac[ac]);
954
955 stats->tx_err += le32_to_cpu(tgt_stats->stats.tx.err);
956 stats->tx_fail_cnt += le32_to_cpu(tgt_stats->stats.tx.fail_cnt);
957 stats->tx_retry_cnt += le32_to_cpu(tgt_stats->stats.tx.retry_cnt);
958 stats->tx_mult_retry_cnt +=
959 le32_to_cpu(tgt_stats->stats.tx.mult_retry_cnt);
960 stats->tx_rts_fail_cnt +=
961 le32_to_cpu(tgt_stats->stats.tx.rts_fail_cnt);
962 stats->tx_ucast_rate =
963 ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.tx.ucast_rate));
964
965 stats->rx_pkt += le32_to_cpu(tgt_stats->stats.rx.pkt);
966 stats->rx_byte += le32_to_cpu(tgt_stats->stats.rx.byte);
967 stats->rx_ucast_pkt += le32_to_cpu(tgt_stats->stats.rx.ucast_pkt);
968 stats->rx_ucast_byte += le32_to_cpu(tgt_stats->stats.rx.ucast_byte);
969 stats->rx_mcast_pkt += le32_to_cpu(tgt_stats->stats.rx.mcast_pkt);
970 stats->rx_mcast_byte += le32_to_cpu(tgt_stats->stats.rx.mcast_byte);
971 stats->rx_bcast_pkt += le32_to_cpu(tgt_stats->stats.rx.bcast_pkt);
972 stats->rx_bcast_byte += le32_to_cpu(tgt_stats->stats.rx.bcast_byte);
973 stats->rx_frgment_pkt += le32_to_cpu(tgt_stats->stats.rx.frgment_pkt);
974 stats->rx_err += le32_to_cpu(tgt_stats->stats.rx.err);
975 stats->rx_crc_err += le32_to_cpu(tgt_stats->stats.rx.crc_err);
976 stats->rx_key_cache_miss +=
977 le32_to_cpu(tgt_stats->stats.rx.key_cache_miss);
978 stats->rx_decrypt_err += le32_to_cpu(tgt_stats->stats.rx.decrypt_err);
979 stats->rx_dupl_frame += le32_to_cpu(tgt_stats->stats.rx.dupl_frame);
980 stats->rx_ucast_rate =
981 ath6kl_wmi_get_rate(a_sle32_to_cpu(tgt_stats->stats.rx.ucast_rate));
982
983 ccmp_stats = &tgt_stats->stats.tkip_ccmp_stats;
984
985 stats->tkip_local_mic_fail +=
986 le32_to_cpu(ccmp_stats->tkip_local_mic_fail);
987 stats->tkip_cnter_measures_invoked +=
988 le32_to_cpu(ccmp_stats->tkip_cnter_measures_invoked);
989 stats->tkip_fmt_err += le32_to_cpu(ccmp_stats->tkip_fmt_err);
990
991 stats->ccmp_fmt_err += le32_to_cpu(ccmp_stats->ccmp_fmt_err);
992 stats->ccmp_replays += le32_to_cpu(ccmp_stats->ccmp_replays);
993
994 stats->pwr_save_fail_cnt +=
995 le32_to_cpu(tgt_stats->pm_stats.pwr_save_failure_cnt);
996 stats->noise_floor_calib =
997 a_sle32_to_cpu(tgt_stats->noise_floor_calib);
998
999 stats->cs_bmiss_cnt +=
1000 le32_to_cpu(tgt_stats->cserv_stats.cs_bmiss_cnt);
1001 stats->cs_low_rssi_cnt +=
1002 le32_to_cpu(tgt_stats->cserv_stats.cs_low_rssi_cnt);
1003 stats->cs_connect_cnt +=
1004 le16_to_cpu(tgt_stats->cserv_stats.cs_connect_cnt);
1005 stats->cs_discon_cnt +=
1006 le16_to_cpu(tgt_stats->cserv_stats.cs_discon_cnt);
1007
1008 stats->cs_ave_beacon_rssi =
1009 a_sle16_to_cpu(tgt_stats->cserv_stats.cs_ave_beacon_rssi);
1010
1011 stats->cs_last_roam_msec =
1012 tgt_stats->cserv_stats.cs_last_roam_msec;
1013 stats->cs_snr = tgt_stats->cserv_stats.cs_snr;
1014 stats->cs_rssi = a_sle16_to_cpu(tgt_stats->cserv_stats.cs_rssi);
1015
1016 stats->lq_val = le32_to_cpu(tgt_stats->lq_val);
1017
1018 stats->wow_pkt_dropped +=
1019 le32_to_cpu(tgt_stats->wow_stats.wow_pkt_dropped);
1020 stats->wow_host_pkt_wakeups +=
1021 tgt_stats->wow_stats.wow_host_pkt_wakeups;
1022 stats->wow_host_evt_wakeups +=
1023 tgt_stats->wow_stats.wow_host_evt_wakeups;
1024 stats->wow_evt_discarded +=
1025 le16_to_cpu(tgt_stats->wow_stats.wow_evt_discarded);
1026
1027 if (test_bit(STATS_UPDATE_PEND, &ar->flag)) {
1028 clear_bit(STATS_UPDATE_PEND, &ar->flag);
1029 wake_up(&ar->event_wq);
1030 }
1031}
1032
1033static void ath6kl_add_le32(__le32 *var, __le32 val)
1034{
1035 *var = cpu_to_le32(le32_to_cpu(*var) + le32_to_cpu(val));
1036}
1037
1038void ath6kl_tgt_stats_event(struct ath6kl *ar, u8 *ptr, u32 len)
1039{
1040 struct wmi_ap_mode_stat *p = (struct wmi_ap_mode_stat *) ptr;
1041 struct wmi_ap_mode_stat *ap = &ar->ap_stats;
1042 struct wmi_per_sta_stat *st_ap, *st_p;
1043 u8 ac;
1044
1045 if (ar->nw_type == AP_NETWORK) {
1046 if (len < sizeof(*p))
1047 return;
1048
1049 for (ac = 0; ac < AP_MAX_NUM_STA; ac++) {
1050 st_ap = &ap->sta[ac];
1051 st_p = &p->sta[ac];
1052
1053 ath6kl_add_le32(&st_ap->tx_bytes, st_p->tx_bytes);
1054 ath6kl_add_le32(&st_ap->tx_pkts, st_p->tx_pkts);
1055 ath6kl_add_le32(&st_ap->tx_error, st_p->tx_error);
1056 ath6kl_add_le32(&st_ap->tx_discard, st_p->tx_discard);
1057 ath6kl_add_le32(&st_ap->rx_bytes, st_p->rx_bytes);
1058 ath6kl_add_le32(&st_ap->rx_pkts, st_p->rx_pkts);
1059 ath6kl_add_le32(&st_ap->rx_error, st_p->rx_error);
1060 ath6kl_add_le32(&st_ap->rx_discard, st_p->rx_discard);
1061 }
1062
1063 } else {
1064 ath6kl_update_target_stats(ar, ptr, len);
1065 }
1066}
1067
1068void ath6kl_wakeup_event(void *dev)
1069{
1070 struct ath6kl *ar = (struct ath6kl *) dev;
1071
1072 wake_up(&ar->event_wq);
1073}
1074
1075void ath6kl_txpwr_rx_evt(void *devt, u8 tx_pwr)
1076{
1077 struct ath6kl *ar = (struct ath6kl *) devt;
1078
1079 ar->tx_pwr = tx_pwr;
1080 wake_up(&ar->event_wq);
1081}
1082
1083void ath6kl_pspoll_event(struct ath6kl *ar, u8 aid)
1084{
1085 struct ath6kl_sta *conn;
1086 struct sk_buff *skb;
1087 bool psq_empty = false;
1088
1089 conn = ath6kl_find_sta_by_aid(ar, aid);
1090
1091 if (!conn)
1092 return;
1093 /*
1094 * Send out a packet queued on ps queue. When the ps queue
1095 * becomes empty update the PVB for this station.
1096 */
1097 spin_lock_bh(&conn->psq_lock);
1098 psq_empty = skb_queue_empty(&conn->psq);
1099 spin_unlock_bh(&conn->psq_lock);
1100
1101 if (psq_empty)
1102 /* TODO: Send out a NULL data frame */
1103 return;
1104
1105 spin_lock_bh(&conn->psq_lock);
1106 skb = skb_dequeue(&conn->psq);
1107 spin_unlock_bh(&conn->psq_lock);
1108
1109 conn->sta_flags |= STA_PS_POLLED;
1110 ath6kl_data_tx(skb, ar->net_dev);
1111 conn->sta_flags &= ~STA_PS_POLLED;
1112
1113 spin_lock_bh(&conn->psq_lock);
1114 psq_empty = skb_queue_empty(&conn->psq);
1115 spin_unlock_bh(&conn->psq_lock);
1116
1117 if (psq_empty)
1118 ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0);
1119}
1120
1121void ath6kl_dtimexpiry_event(struct ath6kl *ar)
1122{
1123 bool mcastq_empty = false;
1124 struct sk_buff *skb;
1125
1126 /*
1127 * If there are no associated STAs, ignore the DTIM expiry event.
1128 * There can be potential race conditions where the last associated
1129 * STA may disconnect & before the host could clear the 'Indicate
1130 * DTIM' request to the firmware, the firmware would have just
1131 * indicated a DTIM expiry event. The race is between 'clear DTIM
1132 * expiry cmd' going from the host to the firmware & the DTIM
1133 * expiry event happening from the firmware to the host.
1134 */
1135 if (!ar->sta_list_index)
1136 return;
1137
1138 spin_lock_bh(&ar->mcastpsq_lock);
1139 mcastq_empty = skb_queue_empty(&ar->mcastpsq);
1140 spin_unlock_bh(&ar->mcastpsq_lock);
1141
1142 if (mcastq_empty)
1143 return;
1144
1145 /* set the STA flag to dtim_expired for the frame to go out */
1146 set_bit(DTIM_EXPIRED, &ar->flag);
1147
1148 spin_lock_bh(&ar->mcastpsq_lock);
1149 while ((skb = skb_dequeue(&ar->mcastpsq)) != NULL) {
1150 spin_unlock_bh(&ar->mcastpsq_lock);
1151
1152 ath6kl_data_tx(skb, ar->net_dev);
1153
1154 spin_lock_bh(&ar->mcastpsq_lock);
1155 }
1156 spin_unlock_bh(&ar->mcastpsq_lock);
1157
1158 clear_bit(DTIM_EXPIRED, &ar->flag);
1159
1160 /* clear the LSB of the BitMapCtl field of the TIM IE */
1161 ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0);
1162}
1163
1164void ath6kl_disconnect_event(struct ath6kl *ar, u8 reason, u8 *bssid,
1165 u8 assoc_resp_len, u8 *assoc_info,
1166 u16 prot_reason_status)
1167{
1168 struct bss *wmi_ssid_node = NULL;
1169 unsigned long flags;
1170
1171 if (ar->nw_type == AP_NETWORK) {
1172 if (!ath6kl_remove_sta(ar, bssid, prot_reason_status))
1173 return;
1174
1175 /* if no more associated STAs, empty the mcast PS q */
1176 if (ar->sta_list_index == 0) {
1177 spin_lock_bh(&ar->mcastpsq_lock);
1178 skb_queue_purge(&ar->mcastpsq);
1179 spin_unlock_bh(&ar->mcastpsq_lock);
1180
1181 /* clear the LSB of the TIM IE's BitMapCtl field */
1182 if (test_bit(WMI_READY, &ar->flag))
1183 ath6kl_wmi_set_pvb_cmd(ar->wmi, MCAST_AID, 0);
1184 }
1185
1186 if (!is_broadcast_ether_addr(bssid)) {
1187 /* send event to application */
1188 cfg80211_del_sta(ar->net_dev, bssid, GFP_KERNEL);
1189 }
1190
1191 clear_bit(CONNECTED, &ar->flag);
1192 return;
1193 }
1194
1195 ath6kl_cfg80211_disconnect_event(ar, reason, bssid,
1196 assoc_resp_len, assoc_info,
1197 prot_reason_status);
1198
1199 aggr_reset_state(ar->aggr_cntxt);
1200
1201 del_timer(&ar->disconnect_timer);
1202
1203 ath6kl_dbg(ATH6KL_DBG_WLAN_CONNECT,
1204 "disconnect reason is %d\n", reason);
1205
1206 /*
1207 * If the event is due to disconnect cmd from the host, only they
1208 * the target would stop trying to connect. Under any other
1209 * condition, target would keep trying to connect.
1210 */
1211 if (reason == DISCONNECT_CMD) {
1212 if (!ar->usr_bss_filter && test_bit(WMI_READY, &ar->flag))
1213 ath6kl_wmi_bssfilter_cmd(ar->wmi, NONE_BSS_FILTER, 0);
1214 } else {
1215 set_bit(CONNECT_PEND, &ar->flag);
1216 if (((reason == ASSOC_FAILED) &&
1217 (prot_reason_status == 0x11)) ||
1218 ((reason == ASSOC_FAILED) && (prot_reason_status == 0x0)
1219 && (ar->reconnect_flag == 1))) {
1220 set_bit(CONNECTED, &ar->flag);
1221 return;
1222 }
1223 }
1224
1225 if ((reason == NO_NETWORK_AVAIL) && test_bit(WMI_READY, &ar->flag)) {
1226 ath6kl_wmi_node_free(ar->wmi, bssid);
1227
1228 /*
1229 * In case any other same SSID nodes are present remove it,
1230 * since those nodes also not available now.
1231 */
1232 do {
1233 /*
1234 * Find the nodes based on SSID and remove it
1235 *
1236 * Note: This case will not work out for
1237 * Hidden-SSID
1238 */
1239 wmi_ssid_node = ath6kl_wmi_find_ssid_node(ar->wmi,
1240 ar->ssid,
1241 ar->ssid_len,
1242 false,
1243 true);
1244
1245 if (wmi_ssid_node)
1246 ath6kl_wmi_node_free(ar->wmi,
1247 wmi_ssid_node->ni_macaddr);
1248
1249 } while (wmi_ssid_node);
1250 }
1251
1252 /* update connect & link status atomically */
1253 spin_lock_irqsave(&ar->lock, flags);
1254 clear_bit(CONNECTED, &ar->flag);
1255 netif_carrier_off(ar->net_dev);
1256 spin_unlock_irqrestore(&ar->lock, flags);
1257
1258 if ((reason != CSERV_DISCONNECT) || (ar->reconnect_flag != 1))
1259 ar->reconnect_flag = 0;
1260
1261 if (reason != CSERV_DISCONNECT)
1262 ar->user_key_ctrl = 0;
1263
1264 netif_stop_queue(ar->net_dev);
1265 memset(ar->bssid, 0, sizeof(ar->bssid));
1266 ar->bss_ch = 0;
1267
1268 ath6kl_tx_data_cleanup(ar);
1269}
1270
1271static int ath6kl_open(struct net_device *dev)
1272{
1273 struct ath6kl *ar = ath6kl_priv(dev);
1274 unsigned long flags;
1275
1276 spin_lock_irqsave(&ar->lock, flags);
1277
1278 set_bit(WLAN_ENABLED, &ar->flag);
1279
1280 if (test_bit(CONNECTED, &ar->flag)) {
1281 netif_carrier_on(dev);
1282 netif_wake_queue(dev);
1283 } else
1284 netif_carrier_off(dev);
1285
1286 spin_unlock_irqrestore(&ar->lock, flags);
1287
1288 return 0;
1289}
1290
1291static int ath6kl_close(struct net_device *dev)
1292{
1293 struct ath6kl *ar = ath6kl_priv(dev);
1294
1295 netif_stop_queue(dev);
1296
1297 ath6kl_disconnect(ar);
1298
1299 if (test_bit(WMI_READY, &ar->flag)) {
1300 if (ath6kl_wmi_scanparams_cmd(ar->wmi, 0xFFFF, 0, 0, 0, 0, 0, 0,
1301 0, 0, 0))
1302 return -EIO;
1303
1304 clear_bit(WLAN_ENABLED, &ar->flag);
1305 }
1306
1307 ath6kl_cfg80211_scan_complete_event(ar, -ECANCELED);
1308
1309 return 0;
1310}
1311
1312static struct net_device_stats *ath6kl_get_stats(struct net_device *dev)
1313{
1314 struct ath6kl *ar = ath6kl_priv(dev);
1315
1316 return &ar->net_stats;
1317}
1318
1319static struct net_device_ops ath6kl_netdev_ops = {
1320 .ndo_open = ath6kl_open,
1321 .ndo_stop = ath6kl_close,
1322 .ndo_start_xmit = ath6kl_data_tx,
1323 .ndo_get_stats = ath6kl_get_stats,
1324};
1325
1326void init_netdev(struct net_device *dev)
1327{
1328 dev->netdev_ops = &ath6kl_netdev_ops;
1329 dev->watchdog_timeo = ATH6KL_TX_TIMEOUT;
1330
1331 dev->needed_headroom = ETH_HLEN;
1332 dev->needed_headroom += sizeof(struct ath6kl_llc_snap_hdr) +
1333 sizeof(struct wmi_data_hdr) + HTC_HDR_LENGTH
1334 + WMI_MAX_TX_META_SZ;
1335
1336 return;
1337}
diff --git a/drivers/net/wireless/ath/ath6kl/node.c b/drivers/net/wireless/ath/ath6kl/node.c
new file mode 100644
index 000000000000..131205c610b9
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/node.c
@@ -0,0 +1,234 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "htc.h"
18#include "wmi.h"
19#include "debug.h"
20
21struct bss *wlan_node_alloc(int wh_size)
22{
23 struct bss *ni;
24
25 ni = kzalloc(sizeof(struct bss), GFP_ATOMIC);
26
27 if ((ni != NULL) && wh_size) {
28 ni->ni_buf = kmalloc(wh_size, GFP_ATOMIC);
29 if (ni->ni_buf == NULL) {
30 kfree(ni);
31 return NULL;
32 }
33 }
34
35 return ni;
36}
37
38void wlan_node_free(struct bss *ni)
39{
40 kfree(ni->ni_buf);
41 kfree(ni);
42}
43
44void wlan_setup_node(struct ath6kl_node_table *nt, struct bss *ni,
45 const u8 *mac_addr)
46{
47 int hash;
48
49 memcpy(ni->ni_macaddr, mac_addr, ETH_ALEN);
50 hash = ATH6KL_NODE_HASH(mac_addr);
51 ni->ni_refcnt = 1;
52
53 ni->ni_tstamp = jiffies_to_msecs(jiffies);
54 ni->ni_actcnt = WLAN_NODE_INACT_CNT;
55
56 spin_lock_bh(&nt->nt_nodelock);
57
58 /* insert at the end of the node list */
59 ni->ni_list_next = NULL;
60 ni->ni_list_prev = nt->nt_node_last;
61 if (nt->nt_node_last != NULL)
62 nt->nt_node_last->ni_list_next = ni;
63
64 nt->nt_node_last = ni;
65 if (nt->nt_node_first == NULL)
66 nt->nt_node_first = ni;
67
68 /* insert into the hash list */
69 ni->ni_hash_next = nt->nt_hash[hash];
70 if (ni->ni_hash_next != NULL)
71 nt->nt_hash[hash]->ni_hash_prev = ni;
72
73 ni->ni_hash_prev = NULL;
74 nt->nt_hash[hash] = ni;
75
76 spin_unlock_bh(&nt->nt_nodelock);
77}
78
79struct bss *wlan_find_node(struct ath6kl_node_table *nt,
80 const u8 *mac_addr)
81{
82 struct bss *ni, *found_ni = NULL;
83 int hash;
84
85 spin_lock_bh(&nt->nt_nodelock);
86
87 hash = ATH6KL_NODE_HASH(mac_addr);
88 for (ni = nt->nt_hash[hash]; ni; ni = ni->ni_hash_next) {
89 if (memcmp(ni->ni_macaddr, mac_addr, ETH_ALEN) == 0) {
90 ni->ni_refcnt++;
91 found_ni = ni;
92 break;
93 }
94 }
95
96 spin_unlock_bh(&nt->nt_nodelock);
97
98 return found_ni;
99}
100
101void wlan_node_reclaim(struct ath6kl_node_table *nt, struct bss *ni)
102{
103 int hash;
104
105 spin_lock_bh(&nt->nt_nodelock);
106
107 if (ni->ni_list_prev == NULL)
108 /* fix list head */
109 nt->nt_node_first = ni->ni_list_next;
110 else
111 ni->ni_list_prev->ni_list_next = ni->ni_list_next;
112
113 if (ni->ni_list_next == NULL)
114 /* fix list tail */
115 nt->nt_node_last = ni->ni_list_prev;
116 else
117 ni->ni_list_next->ni_list_prev = ni->ni_list_prev;
118
119 if (ni->ni_hash_prev == NULL) {
120 /* first in list so fix the list head */
121 hash = ATH6KL_NODE_HASH(ni->ni_macaddr);
122 nt->nt_hash[hash] = ni->ni_hash_next;
123 } else {
124 ni->ni_hash_prev->ni_hash_next = ni->ni_hash_next;
125 }
126
127 if (ni->ni_hash_next != NULL)
128 ni->ni_hash_next->ni_hash_prev = ni->ni_hash_prev;
129
130 wlan_node_free(ni);
131
132 spin_unlock_bh(&nt->nt_nodelock);
133}
134
135static void wlan_node_dec_free(struct bss *ni)
136{
137 if ((ni->ni_refcnt--) == 1)
138 wlan_node_free(ni);
139}
140
141void wlan_free_allnodes(struct ath6kl_node_table *nt)
142{
143 struct bss *ni;
144
145 while ((ni = nt->nt_node_first) != NULL)
146 wlan_node_reclaim(nt, ni);
147}
148
149void wlan_iterate_nodes(struct ath6kl_node_table *nt, void *arg)
150{
151 struct bss *ni;
152
153 spin_lock_bh(&nt->nt_nodelock);
154 for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
155 ni->ni_refcnt++;
156 ath6kl_cfg80211_scan_node(arg, ni);
157 wlan_node_dec_free(ni);
158 }
159 spin_unlock_bh(&nt->nt_nodelock);
160}
161
162void wlan_node_table_init(struct ath6kl_node_table *nt)
163{
164 ath6kl_dbg(ATH6KL_DBG_WLAN_NODE, "node table = 0x%lx\n",
165 (unsigned long)nt);
166
167 memset(nt, 0, sizeof(struct ath6kl_node_table));
168
169 spin_lock_init(&nt->nt_nodelock);
170
171 nt->nt_node_age = WLAN_NODE_INACT_TIMEOUT_MSEC;
172}
173
174void wlan_refresh_inactive_nodes(struct ath6kl *ar)
175{
176 struct ath6kl_node_table *nt = &ar->scan_table;
177 struct bss *bss;
178 u32 now;
179
180 now = jiffies_to_msecs(jiffies);
181 bss = nt->nt_node_first;
182 while (bss != NULL) {
183 /* refresh all nodes except the current bss */
184 if (memcmp(ar->bssid, bss->ni_macaddr, ETH_ALEN) != 0) {
185 if (((now - bss->ni_tstamp) > nt->nt_node_age)
186 || --bss->ni_actcnt == 0) {
187 wlan_node_reclaim(nt, bss);
188 }
189 }
190 bss = bss->ni_list_next;
191 }
192}
193
194void wlan_node_table_cleanup(struct ath6kl_node_table *nt)
195{
196 wlan_free_allnodes(nt);
197}
198
199struct bss *wlan_find_ssid_node(struct ath6kl_node_table *nt, u8 * ssid,
200 u32 ssid_len, bool is_wpa2, bool match_ssid)
201{
202 struct bss *ni, *found_ni = NULL;
203 u8 *ie_ssid;
204
205 spin_lock_bh(&nt->nt_nodelock);
206
207 for (ni = nt->nt_node_first; ni; ni = ni->ni_list_next) {
208
209 ie_ssid = ni->ni_cie.ie_ssid;
210
211 if ((ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) &&
212 (memcmp(ssid, &ie_ssid[2], ssid_len) == 0)) {
213
214 if (match_ssid ||
215 (is_wpa2 && ni->ni_cie.ie_rsn != NULL) ||
216 (!is_wpa2 && ni->ni_cie.ie_wpa != NULL)) {
217 ni->ni_refcnt++;
218 found_ni = ni;
219 break;
220 }
221 }
222 }
223
224 spin_unlock_bh(&nt->nt_nodelock);
225
226 return found_ni;
227}
228
229void wlan_node_return(struct ath6kl_node_table *nt, struct bss *ni)
230{
231 spin_lock_bh(&nt->nt_nodelock);
232 wlan_node_dec_free(ni);
233 spin_unlock_bh(&nt->nt_nodelock);
234}
diff --git a/drivers/net/wireless/ath/ath6kl/sdio.c b/drivers/net/wireless/ath/ath6kl/sdio.c
new file mode 100644
index 000000000000..34171604cbe4
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/sdio.c
@@ -0,0 +1,912 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/mmc/card.h>
18#include <linux/mmc/mmc.h>
19#include <linux/mmc/host.h>
20#include <linux/mmc/sdio_func.h>
21#include <linux/mmc/sdio_ids.h>
22#include <linux/mmc/sdio.h>
23#include <linux/mmc/sd.h>
24#include "htc_hif.h"
25#include "hif-ops.h"
26#include "target.h"
27#include "debug.h"
28
29struct ath6kl_sdio {
30 struct sdio_func *func;
31
32 spinlock_t lock;
33
34 /* free list */
35 struct list_head bus_req_freeq;
36
37 /* available bus requests */
38 struct bus_request bus_req[BUS_REQUEST_MAX_NUM];
39
40 struct ath6kl *ar;
41 u8 *dma_buffer;
42
43 /* scatter request list head */
44 struct list_head scat_req;
45
46 spinlock_t scat_lock;
47 bool is_disabled;
48 atomic_t irq_handling;
49 const struct sdio_device_id *id;
50 struct work_struct wr_async_work;
51 struct list_head wr_asyncq;
52 spinlock_t wr_async_lock;
53};
54
55#define CMD53_ARG_READ 0
56#define CMD53_ARG_WRITE 1
57#define CMD53_ARG_BLOCK_BASIS 1
58#define CMD53_ARG_FIXED_ADDRESS 0
59#define CMD53_ARG_INCR_ADDRESS 1
60
61static inline struct ath6kl_sdio *ath6kl_sdio_priv(struct ath6kl *ar)
62{
63 return ar->hif_priv;
64}
65
66/*
67 * Macro to check if DMA buffer is WORD-aligned and DMA-able.
68 * Most host controllers assume the buffer is DMA'able and will
69 * bug-check otherwise (i.e. buffers on the stack). virt_addr_valid
70 * check fails on stack memory.
71 */
72static inline bool buf_needs_bounce(u8 *buf)
73{
74 return ((unsigned long) buf & 0x3) || !virt_addr_valid(buf);
75}
76
77static void ath6kl_sdio_set_mbox_info(struct ath6kl *ar)
78{
79 struct ath6kl_mbox_info *mbox_info = &ar->mbox_info;
80
81 /* EP1 has an extended range */
82 mbox_info->htc_addr = HIF_MBOX_BASE_ADDR;
83 mbox_info->htc_ext_addr = HIF_MBOX0_EXT_BASE_ADDR;
84 mbox_info->htc_ext_sz = HIF_MBOX0_EXT_WIDTH;
85 mbox_info->block_size = HIF_MBOX_BLOCK_SIZE;
86 mbox_info->gmbox_addr = HIF_GMBOX_BASE_ADDR;
87 mbox_info->gmbox_sz = HIF_GMBOX_WIDTH;
88}
89
90static inline void ath6kl_sdio_set_cmd53_arg(u32 *arg, u8 rw, u8 func,
91 u8 mode, u8 opcode, u32 addr,
92 u16 blksz)
93{
94 *arg = (((rw & 1) << 31) |
95 ((func & 0x7) << 28) |
96 ((mode & 1) << 27) |
97 ((opcode & 1) << 26) |
98 ((addr & 0x1FFFF) << 9) |
99 (blksz & 0x1FF));
100}
101
102static inline void ath6kl_sdio_set_cmd52_arg(u32 *arg, u8 write, u8 raw,
103 unsigned int address,
104 unsigned char val)
105{
106 const u8 func = 0;
107
108 *arg = ((write & 1) << 31) |
109 ((func & 0x7) << 28) |
110 ((raw & 1) << 27) |
111 (1 << 26) |
112 ((address & 0x1FFFF) << 9) |
113 (1 << 8) |
114 (val & 0xFF);
115}
116
117static int ath6kl_sdio_func0_cmd52_wr_byte(struct mmc_card *card,
118 unsigned int address,
119 unsigned char byte)
120{
121 struct mmc_command io_cmd;
122
123 memset(&io_cmd, 0, sizeof(io_cmd));
124 ath6kl_sdio_set_cmd52_arg(&io_cmd.arg, 1, 0, address, byte);
125 io_cmd.opcode = SD_IO_RW_DIRECT;
126 io_cmd.flags = MMC_RSP_R5 | MMC_CMD_AC;
127
128 return mmc_wait_for_cmd(card->host, &io_cmd, 0);
129}
130
131static int ath6kl_sdio_io(struct sdio_func *func, u32 request, u32 addr,
132 u8 *buf, u32 len)
133{
134 int ret = 0;
135
136 if (request & HIF_WRITE) {
137 if (addr >= HIF_MBOX_BASE_ADDR &&
138 addr <= HIF_MBOX_END_ADDR)
139 addr += (HIF_MBOX_WIDTH - len);
140
141 if (addr == HIF_MBOX0_EXT_BASE_ADDR)
142 addr += HIF_MBOX0_EXT_WIDTH - len;
143
144 if (request & HIF_FIXED_ADDRESS)
145 ret = sdio_writesb(func, addr, buf, len);
146 else
147 ret = sdio_memcpy_toio(func, addr, buf, len);
148 } else {
149 if (request & HIF_FIXED_ADDRESS)
150 ret = sdio_readsb(func, buf, addr, len);
151 else
152 ret = sdio_memcpy_fromio(func, buf, addr, len);
153 }
154
155 return ret;
156}
157
158static struct bus_request *ath6kl_sdio_alloc_busreq(struct ath6kl_sdio *ar_sdio)
159{
160 struct bus_request *bus_req;
161 unsigned long flag;
162
163 spin_lock_irqsave(&ar_sdio->lock, flag);
164
165 if (list_empty(&ar_sdio->bus_req_freeq)) {
166 spin_unlock_irqrestore(&ar_sdio->lock, flag);
167 return NULL;
168 }
169
170 bus_req = list_first_entry(&ar_sdio->bus_req_freeq,
171 struct bus_request, list);
172 list_del(&bus_req->list);
173
174 spin_unlock_irqrestore(&ar_sdio->lock, flag);
175 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req);
176
177 return bus_req;
178}
179
180static void ath6kl_sdio_free_bus_req(struct ath6kl_sdio *ar_sdio,
181 struct bus_request *bus_req)
182{
183 unsigned long flag;
184
185 ath6kl_dbg(ATH6KL_DBG_TRC, "%s: bus request 0x%p\n", __func__, bus_req);
186
187 spin_lock_irqsave(&ar_sdio->lock, flag);
188 list_add_tail(&bus_req->list, &ar_sdio->bus_req_freeq);
189 spin_unlock_irqrestore(&ar_sdio->lock, flag);
190}
191
192static void ath6kl_sdio_setup_scat_data(struct hif_scatter_req *scat_req,
193 struct mmc_data *data)
194{
195 struct scatterlist *sg;
196 int i;
197
198 data->blksz = HIF_MBOX_BLOCK_SIZE;
199 data->blocks = scat_req->len / HIF_MBOX_BLOCK_SIZE;
200
201 ath6kl_dbg(ATH6KL_DBG_SCATTER,
202 "hif-scatter: (%s) addr: 0x%X, (block len: %d, block count: %d) , (tot:%d,sg:%d)\n",
203 (scat_req->req & HIF_WRITE) ? "WR" : "RD", scat_req->addr,
204 data->blksz, data->blocks, scat_req->len,
205 scat_req->scat_entries);
206
207 data->flags = (scat_req->req & HIF_WRITE) ? MMC_DATA_WRITE :
208 MMC_DATA_READ;
209
210 /* fill SG entries */
211 sg = scat_req->sgentries;
212 sg_init_table(sg, scat_req->scat_entries);
213
214 /* assemble SG list */
215 for (i = 0; i < scat_req->scat_entries; i++, sg++) {
216 if ((unsigned long)scat_req->scat_list[i].buf & 0x3)
217 /*
218 * Some scatter engines can handle unaligned
219 * buffers, print this as informational only.
220 */
221 ath6kl_dbg(ATH6KL_DBG_SCATTER,
222 "(%s) scatter buffer is unaligned 0x%p\n",
223 scat_req->req & HIF_WRITE ? "WR" : "RD",
224 scat_req->scat_list[i].buf);
225
226 ath6kl_dbg(ATH6KL_DBG_SCATTER, "%d: addr:0x%p, len:%d\n",
227 i, scat_req->scat_list[i].buf,
228 scat_req->scat_list[i].len);
229
230 sg_set_buf(sg, scat_req->scat_list[i].buf,
231 scat_req->scat_list[i].len);
232 }
233
234 /* set scatter-gather table for request */
235 data->sg = scat_req->sgentries;
236 data->sg_len = scat_req->scat_entries;
237}
238
239static int ath6kl_sdio_scat_rw(struct ath6kl_sdio *ar_sdio,
240 struct bus_request *req)
241{
242 struct mmc_request mmc_req;
243 struct mmc_command cmd;
244 struct mmc_data data;
245 struct hif_scatter_req *scat_req;
246 u8 opcode, rw;
247 int status, len;
248
249 scat_req = req->scat_req;
250
251 if (scat_req->virt_scat) {
252 len = scat_req->len;
253 if (scat_req->req & HIF_BLOCK_BASIS)
254 len = round_down(len, HIF_MBOX_BLOCK_SIZE);
255
256 status = ath6kl_sdio_io(ar_sdio->func, scat_req->req,
257 scat_req->addr, scat_req->virt_dma_buf,
258 len);
259 goto scat_complete;
260 }
261
262 memset(&mmc_req, 0, sizeof(struct mmc_request));
263 memset(&cmd, 0, sizeof(struct mmc_command));
264 memset(&data, 0, sizeof(struct mmc_data));
265
266 ath6kl_sdio_setup_scat_data(scat_req, &data);
267
268 opcode = (scat_req->req & HIF_FIXED_ADDRESS) ?
269 CMD53_ARG_FIXED_ADDRESS : CMD53_ARG_INCR_ADDRESS;
270
271 rw = (scat_req->req & HIF_WRITE) ? CMD53_ARG_WRITE : CMD53_ARG_READ;
272
273 /* Fixup the address so that the last byte will fall on MBOX EOM */
274 if (scat_req->req & HIF_WRITE) {
275 if (scat_req->addr == HIF_MBOX_BASE_ADDR)
276 scat_req->addr += HIF_MBOX_WIDTH - scat_req->len;
277 else
278 /* Uses extended address range */
279 scat_req->addr += HIF_MBOX0_EXT_WIDTH - scat_req->len;
280 }
281
282 /* set command argument */
283 ath6kl_sdio_set_cmd53_arg(&cmd.arg, rw, ar_sdio->func->num,
284 CMD53_ARG_BLOCK_BASIS, opcode, scat_req->addr,
285 data.blocks);
286
287 cmd.opcode = SD_IO_RW_EXTENDED;
288 cmd.flags = MMC_RSP_SPI_R5 | MMC_RSP_R5 | MMC_CMD_ADTC;
289
290 mmc_req.cmd = &cmd;
291 mmc_req.data = &data;
292
293 mmc_set_data_timeout(&data, ar_sdio->func->card);
294 /* synchronous call to process request */
295 mmc_wait_for_req(ar_sdio->func->card->host, &mmc_req);
296
297 status = cmd.error ? cmd.error : data.error;
298
299scat_complete:
300 scat_req->status = status;
301
302 if (scat_req->status)
303 ath6kl_err("Scatter write request failed:%d\n",
304 scat_req->status);
305
306 if (scat_req->req & HIF_ASYNCHRONOUS)
307 scat_req->complete(ar_sdio->ar->htc_target, scat_req);
308
309 return status;
310}
311
312static int ath6kl_sdio_alloc_prep_scat_req(struct ath6kl_sdio *ar_sdio,
313 int n_scat_entry, int n_scat_req,
314 bool virt_scat)
315{
316 struct hif_scatter_req *s_req;
317 struct bus_request *bus_req;
318 int i, scat_req_sz, scat_list_sz, sg_sz, buf_sz;
319 u8 *virt_buf;
320
321 scat_list_sz = (n_scat_entry - 1) * sizeof(struct hif_scatter_item);
322 scat_req_sz = sizeof(*s_req) + scat_list_sz;
323
324 if (!virt_scat)
325 sg_sz = sizeof(struct scatterlist) * n_scat_entry;
326 else
327 buf_sz = 2 * L1_CACHE_BYTES +
328 ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER;
329
330 for (i = 0; i < n_scat_req; i++) {
331 /* allocate the scatter request */
332 s_req = kzalloc(scat_req_sz, GFP_KERNEL);
333 if (!s_req)
334 return -ENOMEM;
335
336 if (virt_scat) {
337 virt_buf = kzalloc(buf_sz, GFP_KERNEL);
338 if (!virt_buf) {
339 kfree(s_req);
340 return -ENOMEM;
341 }
342
343 s_req->virt_dma_buf =
344 (u8 *)L1_CACHE_ALIGN((unsigned long)virt_buf);
345 } else {
346 /* allocate sglist */
347 s_req->sgentries = kzalloc(sg_sz, GFP_KERNEL);
348
349 if (!s_req->sgentries) {
350 kfree(s_req);
351 return -ENOMEM;
352 }
353 }
354
355 /* allocate a bus request for this scatter request */
356 bus_req = ath6kl_sdio_alloc_busreq(ar_sdio);
357 if (!bus_req) {
358 kfree(s_req->sgentries);
359 kfree(s_req->virt_dma_buf);
360 kfree(s_req);
361 return -ENOMEM;
362 }
363
364 /* assign the scatter request to this bus request */
365 bus_req->scat_req = s_req;
366 s_req->busrequest = bus_req;
367
368 s_req->virt_scat = virt_scat;
369
370 /* add it to the scatter pool */
371 hif_scatter_req_add(ar_sdio->ar, s_req);
372 }
373
374 return 0;
375}
376
377static int ath6kl_sdio_read_write_sync(struct ath6kl *ar, u32 addr, u8 *buf,
378 u32 len, u32 request)
379{
380 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
381 u8 *tbuf = NULL;
382 int ret;
383 bool bounced = false;
384
385 if (request & HIF_BLOCK_BASIS)
386 len = round_down(len, HIF_MBOX_BLOCK_SIZE);
387
388 if (buf_needs_bounce(buf)) {
389 if (!ar_sdio->dma_buffer)
390 return -ENOMEM;
391 tbuf = ar_sdio->dma_buffer;
392 memcpy(tbuf, buf, len);
393 bounced = true;
394 } else
395 tbuf = buf;
396
397 sdio_claim_host(ar_sdio->func);
398 ret = ath6kl_sdio_io(ar_sdio->func, request, addr, tbuf, len);
399 if ((request & HIF_READ) && bounced)
400 memcpy(buf, tbuf, len);
401 sdio_release_host(ar_sdio->func);
402
403 return ret;
404}
405
406static void __ath6kl_sdio_write_async(struct ath6kl_sdio *ar_sdio,
407 struct bus_request *req)
408{
409 if (req->scat_req)
410 ath6kl_sdio_scat_rw(ar_sdio, req);
411 else {
412 void *context;
413 int status;
414
415 status = ath6kl_sdio_read_write_sync(ar_sdio->ar, req->address,
416 req->buffer, req->length,
417 req->request);
418 context = req->packet;
419 ath6kl_sdio_free_bus_req(ar_sdio, req);
420 ath6kldev_rw_comp_handler(context, status);
421 }
422}
423
424static void ath6kl_sdio_write_async_work(struct work_struct *work)
425{
426 struct ath6kl_sdio *ar_sdio;
427 unsigned long flags;
428 struct bus_request *req, *tmp_req;
429
430 ar_sdio = container_of(work, struct ath6kl_sdio, wr_async_work);
431 sdio_claim_host(ar_sdio->func);
432
433 spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
434 list_for_each_entry_safe(req, tmp_req, &ar_sdio->wr_asyncq, list) {
435 list_del(&req->list);
436 spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
437 __ath6kl_sdio_write_async(ar_sdio, req);
438 spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
439 }
440 spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
441
442 sdio_release_host(ar_sdio->func);
443}
444
445static void ath6kl_sdio_irq_handler(struct sdio_func *func)
446{
447 int status;
448 struct ath6kl_sdio *ar_sdio;
449
450 ar_sdio = sdio_get_drvdata(func);
451 atomic_set(&ar_sdio->irq_handling, 1);
452
453 /*
454 * Release the host during interrups so we can pick it back up when
455 * we process commands.
456 */
457 sdio_release_host(ar_sdio->func);
458
459 status = ath6kldev_intr_bh_handler(ar_sdio->ar);
460 sdio_claim_host(ar_sdio->func);
461 atomic_set(&ar_sdio->irq_handling, 0);
462 WARN_ON(status && status != -ECANCELED);
463}
464
465static int ath6kl_sdio_power_on(struct ath6kl_sdio *ar_sdio)
466{
467 struct sdio_func *func = ar_sdio->func;
468 int ret = 0;
469
470 if (!ar_sdio->is_disabled)
471 return 0;
472
473 sdio_claim_host(func);
474
475 ret = sdio_enable_func(func);
476 if (ret) {
477 ath6kl_err("Unable to enable sdio func: %d)\n", ret);
478 sdio_release_host(func);
479 return ret;
480 }
481
482 sdio_release_host(func);
483
484 /*
485 * Wait for hardware to initialise. It should take a lot less than
486 * 10 ms but let's be conservative here.
487 */
488 msleep(10);
489
490 ar_sdio->is_disabled = false;
491
492 return ret;
493}
494
495static int ath6kl_sdio_power_off(struct ath6kl_sdio *ar_sdio)
496{
497 int ret;
498
499 if (ar_sdio->is_disabled)
500 return 0;
501
502 /* Disable the card */
503 sdio_claim_host(ar_sdio->func);
504 ret = sdio_disable_func(ar_sdio->func);
505 sdio_release_host(ar_sdio->func);
506
507 if (ret)
508 return ret;
509
510 ar_sdio->is_disabled = true;
511
512 return ret;
513}
514
515static int ath6kl_sdio_write_async(struct ath6kl *ar, u32 address, u8 *buffer,
516 u32 length, u32 request,
517 struct htc_packet *packet)
518{
519 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
520 struct bus_request *bus_req;
521 unsigned long flags;
522
523 bus_req = ath6kl_sdio_alloc_busreq(ar_sdio);
524
525 if (!bus_req)
526 return -ENOMEM;
527
528 bus_req->address = address;
529 bus_req->buffer = buffer;
530 bus_req->length = length;
531 bus_req->request = request;
532 bus_req->packet = packet;
533
534 spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
535 list_add_tail(&bus_req->list, &ar_sdio->wr_asyncq);
536 spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
537 queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work);
538
539 return 0;
540}
541
542static void ath6kl_sdio_irq_enable(struct ath6kl *ar)
543{
544 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
545 int ret;
546
547 sdio_claim_host(ar_sdio->func);
548
549 /* Register the isr */
550 ret = sdio_claim_irq(ar_sdio->func, ath6kl_sdio_irq_handler);
551 if (ret)
552 ath6kl_err("Failed to claim sdio irq: %d\n", ret);
553
554 sdio_release_host(ar_sdio->func);
555}
556
557static void ath6kl_sdio_irq_disable(struct ath6kl *ar)
558{
559 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
560 int ret;
561
562 sdio_claim_host(ar_sdio->func);
563
564 /* Mask our function IRQ */
565 while (atomic_read(&ar_sdio->irq_handling)) {
566 sdio_release_host(ar_sdio->func);
567 schedule_timeout(HZ / 10);
568 sdio_claim_host(ar_sdio->func);
569 }
570
571 ret = sdio_release_irq(ar_sdio->func);
572 if (ret)
573 ath6kl_err("Failed to release sdio irq: %d\n", ret);
574
575 sdio_release_host(ar_sdio->func);
576}
577
578static struct hif_scatter_req *ath6kl_sdio_scatter_req_get(struct ath6kl *ar)
579{
580 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
581 struct hif_scatter_req *node = NULL;
582 unsigned long flag;
583
584 spin_lock_irqsave(&ar_sdio->scat_lock, flag);
585
586 if (!list_empty(&ar_sdio->scat_req)) {
587 node = list_first_entry(&ar_sdio->scat_req,
588 struct hif_scatter_req, list);
589 list_del(&node->list);
590 }
591
592 spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
593
594 return node;
595}
596
597static void ath6kl_sdio_scatter_req_add(struct ath6kl *ar,
598 struct hif_scatter_req *s_req)
599{
600 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
601 unsigned long flag;
602
603 spin_lock_irqsave(&ar_sdio->scat_lock, flag);
604
605 list_add_tail(&s_req->list, &ar_sdio->scat_req);
606
607 spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
608
609}
610
611/* scatter gather read write request */
612static int ath6kl_sdio_async_rw_scatter(struct ath6kl *ar,
613 struct hif_scatter_req *scat_req)
614{
615 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
616 u32 request = scat_req->req;
617 int status = 0;
618 unsigned long flags;
619
620 if (!scat_req->len)
621 return -EINVAL;
622
623 ath6kl_dbg(ATH6KL_DBG_SCATTER,
624 "hif-scatter: total len: %d scatter entries: %d\n",
625 scat_req->len, scat_req->scat_entries);
626
627 if (request & HIF_SYNCHRONOUS) {
628 sdio_claim_host(ar_sdio->func);
629 status = ath6kl_sdio_scat_rw(ar_sdio, scat_req->busrequest);
630 sdio_release_host(ar_sdio->func);
631 } else {
632 spin_lock_irqsave(&ar_sdio->wr_async_lock, flags);
633 list_add_tail(&scat_req->busrequest->list, &ar_sdio->wr_asyncq);
634 spin_unlock_irqrestore(&ar_sdio->wr_async_lock, flags);
635 queue_work(ar->ath6kl_wq, &ar_sdio->wr_async_work);
636 }
637
638 return status;
639}
640
641/* clean up scatter support */
642static void ath6kl_sdio_cleanup_scatter(struct ath6kl *ar)
643{
644 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
645 struct hif_scatter_req *s_req, *tmp_req;
646 unsigned long flag;
647
648 /* empty the free list */
649 spin_lock_irqsave(&ar_sdio->scat_lock, flag);
650 list_for_each_entry_safe(s_req, tmp_req, &ar_sdio->scat_req, list) {
651 list_del(&s_req->list);
652 spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
653
654 if (s_req->busrequest)
655 ath6kl_sdio_free_bus_req(ar_sdio, s_req->busrequest);
656 kfree(s_req->virt_dma_buf);
657 kfree(s_req->sgentries);
658 kfree(s_req);
659
660 spin_lock_irqsave(&ar_sdio->scat_lock, flag);
661 }
662 spin_unlock_irqrestore(&ar_sdio->scat_lock, flag);
663}
664
665/* setup of HIF scatter resources */
666static int ath6kl_sdio_enable_scatter(struct ath6kl *ar)
667{
668 struct ath6kl_sdio *ar_sdio = ath6kl_sdio_priv(ar);
669 struct htc_target *target = ar->htc_target;
670 int ret;
671 bool virt_scat = false;
672
673 /* check if host supports scatter and it meets our requirements */
674 if (ar_sdio->func->card->host->max_segs < MAX_SCATTER_ENTRIES_PER_REQ) {
675 ath6kl_err("host only supports scatter of :%d entries, need: %d\n",
676 ar_sdio->func->card->host->max_segs,
677 MAX_SCATTER_ENTRIES_PER_REQ);
678 virt_scat = true;
679 }
680
681 if (!virt_scat) {
682 ret = ath6kl_sdio_alloc_prep_scat_req(ar_sdio,
683 MAX_SCATTER_ENTRIES_PER_REQ,
684 MAX_SCATTER_REQUESTS, virt_scat);
685
686 if (!ret) {
687 ath6kl_dbg(ATH6KL_DBG_ANY,
688 "hif-scatter enabled: max scatter req : %d entries: %d\n",
689 MAX_SCATTER_REQUESTS,
690 MAX_SCATTER_ENTRIES_PER_REQ);
691
692 target->max_scat_entries = MAX_SCATTER_ENTRIES_PER_REQ;
693 target->max_xfer_szper_scatreq =
694 MAX_SCATTER_REQ_TRANSFER_SIZE;
695 } else {
696 ath6kl_sdio_cleanup_scatter(ar);
697 ath6kl_warn("hif scatter resource setup failed, trying virtual scatter method\n");
698 }
699 }
700
701 if (virt_scat || ret) {
702 ret = ath6kl_sdio_alloc_prep_scat_req(ar_sdio,
703 ATH6KL_SCATTER_ENTRIES_PER_REQ,
704 ATH6KL_SCATTER_REQS, virt_scat);
705
706 if (ret) {
707 ath6kl_err("failed to alloc virtual scatter resources !\n");
708 ath6kl_sdio_cleanup_scatter(ar);
709 return ret;
710 }
711
712 ath6kl_dbg(ATH6KL_DBG_ANY,
713 "Vitual scatter enabled, max_scat_req:%d, entries:%d\n",
714 ATH6KL_SCATTER_REQS, ATH6KL_SCATTER_ENTRIES_PER_REQ);
715
716 target->max_scat_entries = ATH6KL_SCATTER_ENTRIES_PER_REQ;
717 target->max_xfer_szper_scatreq =
718 ATH6KL_MAX_TRANSFER_SIZE_PER_SCATTER;
719 }
720
721 return 0;
722}
723
724static const struct ath6kl_hif_ops ath6kl_sdio_ops = {
725 .read_write_sync = ath6kl_sdio_read_write_sync,
726 .write_async = ath6kl_sdio_write_async,
727 .irq_enable = ath6kl_sdio_irq_enable,
728 .irq_disable = ath6kl_sdio_irq_disable,
729 .scatter_req_get = ath6kl_sdio_scatter_req_get,
730 .scatter_req_add = ath6kl_sdio_scatter_req_add,
731 .enable_scatter = ath6kl_sdio_enable_scatter,
732 .scat_req_rw = ath6kl_sdio_async_rw_scatter,
733 .cleanup_scatter = ath6kl_sdio_cleanup_scatter,
734};
735
736static int ath6kl_sdio_probe(struct sdio_func *func,
737 const struct sdio_device_id *id)
738{
739 int ret;
740 struct ath6kl_sdio *ar_sdio;
741 struct ath6kl *ar;
742 int count;
743
744 ath6kl_dbg(ATH6KL_DBG_TRC,
745 "%s: func: 0x%X, vendor id: 0x%X, dev id: 0x%X, block size: 0x%X/0x%X\n",
746 __func__, func->num, func->vendor,
747 func->device, func->max_blksize, func->cur_blksize);
748
749 ar_sdio = kzalloc(sizeof(struct ath6kl_sdio), GFP_KERNEL);
750 if (!ar_sdio)
751 return -ENOMEM;
752
753 ar_sdio->dma_buffer = kzalloc(HIF_DMA_BUFFER_SIZE, GFP_KERNEL);
754 if (!ar_sdio->dma_buffer) {
755 ret = -ENOMEM;
756 goto err_hif;
757 }
758
759 ar_sdio->func = func;
760 sdio_set_drvdata(func, ar_sdio);
761
762 ar_sdio->id = id;
763 ar_sdio->is_disabled = true;
764
765 spin_lock_init(&ar_sdio->lock);
766 spin_lock_init(&ar_sdio->scat_lock);
767 spin_lock_init(&ar_sdio->wr_async_lock);
768
769 INIT_LIST_HEAD(&ar_sdio->scat_req);
770 INIT_LIST_HEAD(&ar_sdio->bus_req_freeq);
771 INIT_LIST_HEAD(&ar_sdio->wr_asyncq);
772
773 INIT_WORK(&ar_sdio->wr_async_work, ath6kl_sdio_write_async_work);
774
775 for (count = 0; count < BUS_REQUEST_MAX_NUM; count++)
776 ath6kl_sdio_free_bus_req(ar_sdio, &ar_sdio->bus_req[count]);
777
778 ar = ath6kl_core_alloc(&ar_sdio->func->dev);
779 if (!ar) {
780 ath6kl_err("Failed to alloc ath6kl core\n");
781 ret = -ENOMEM;
782 goto err_dma;
783 }
784
785 ar_sdio->ar = ar;
786 ar->hif_priv = ar_sdio;
787 ar->hif_ops = &ath6kl_sdio_ops;
788
789 ath6kl_sdio_set_mbox_info(ar);
790
791 sdio_claim_host(func);
792
793 if ((ar_sdio->id->device & MANUFACTURER_ID_ATH6KL_BASE_MASK) >=
794 MANUFACTURER_ID_AR6003_BASE) {
795 /* enable 4-bit ASYNC interrupt on AR6003 or later */
796 ret = ath6kl_sdio_func0_cmd52_wr_byte(func->card,
797 CCCR_SDIO_IRQ_MODE_REG,
798 SDIO_IRQ_MODE_ASYNC_4BIT_IRQ);
799 if (ret) {
800 ath6kl_err("Failed to enable 4-bit async irq mode %d\n",
801 ret);
802 sdio_release_host(func);
803 goto err_dma;
804 }
805
806 ath6kl_dbg(ATH6KL_DBG_TRC, "4-bit async irq mode enabled\n");
807 }
808
809 /* give us some time to enable, in ms */
810 func->enable_timeout = 100;
811
812 sdio_release_host(func);
813
814 ret = ath6kl_sdio_power_on(ar_sdio);
815 if (ret)
816 goto err_dma;
817
818 sdio_claim_host(func);
819
820 ret = sdio_set_block_size(func, HIF_MBOX_BLOCK_SIZE);
821 if (ret) {
822 ath6kl_err("Set sdio block size %d failed: %d)\n",
823 HIF_MBOX_BLOCK_SIZE, ret);
824 sdio_release_host(func);
825 goto err_off;
826 }
827
828 sdio_release_host(func);
829
830 ret = ath6kl_core_init(ar);
831 if (ret) {
832 ath6kl_err("Failed to init ath6kl core\n");
833 goto err_off;
834 }
835
836 return ret;
837
838err_off:
839 ath6kl_sdio_power_off(ar_sdio);
840err_dma:
841 kfree(ar_sdio->dma_buffer);
842err_hif:
843 kfree(ar_sdio);
844
845 return ret;
846}
847
848static void ath6kl_sdio_remove(struct sdio_func *func)
849{
850 struct ath6kl_sdio *ar_sdio;
851
852 ar_sdio = sdio_get_drvdata(func);
853
854 ath6kl_stop_txrx(ar_sdio->ar);
855 cancel_work_sync(&ar_sdio->wr_async_work);
856
857 ath6kl_unavail_ev(ar_sdio->ar);
858
859 ath6kl_sdio_power_off(ar_sdio);
860
861 kfree(ar_sdio->dma_buffer);
862 kfree(ar_sdio);
863}
864
865static const struct sdio_device_id ath6kl_sdio_devices[] = {
866 {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x0))},
867 {SDIO_DEVICE(MANUFACTURER_CODE, (MANUFACTURER_ID_AR6003_BASE | 0x1))},
868 {},
869};
870
871MODULE_DEVICE_TABLE(sdio, ath6kl_sdio_devices);
872
873static struct sdio_driver ath6kl_sdio_driver = {
874 .name = "ath6kl_sdio",
875 .id_table = ath6kl_sdio_devices,
876 .probe = ath6kl_sdio_probe,
877 .remove = ath6kl_sdio_remove,
878};
879
880static int __init ath6kl_sdio_init(void)
881{
882 int ret;
883
884 ret = sdio_register_driver(&ath6kl_sdio_driver);
885 if (ret)
886 ath6kl_err("sdio driver registration failed: %d\n", ret);
887
888 return ret;
889}
890
891static void __exit ath6kl_sdio_exit(void)
892{
893 sdio_unregister_driver(&ath6kl_sdio_driver);
894}
895
896module_init(ath6kl_sdio_init);
897module_exit(ath6kl_sdio_exit);
898
899MODULE_AUTHOR("Atheros Communications, Inc.");
900MODULE_DESCRIPTION("Driver support for Atheros AR600x SDIO devices");
901MODULE_LICENSE("Dual BSD/GPL");
902
903MODULE_FIRMWARE(AR6003_REV2_OTP_FILE);
904MODULE_FIRMWARE(AR6003_REV2_FIRMWARE_FILE);
905MODULE_FIRMWARE(AR6003_REV2_PATCH_FILE);
906MODULE_FIRMWARE(AR6003_REV2_BOARD_DATA_FILE);
907MODULE_FIRMWARE(AR6003_REV2_DEFAULT_BOARD_DATA_FILE);
908MODULE_FIRMWARE(AR6003_REV3_OTP_FILE);
909MODULE_FIRMWARE(AR6003_REV3_FIRMWARE_FILE);
910MODULE_FIRMWARE(AR6003_REV3_PATCH_FILE);
911MODULE_FIRMWARE(AR6003_REV3_BOARD_DATA_FILE);
912MODULE_FIRMWARE(AR6003_REV3_DEFAULT_BOARD_DATA_FILE);
diff --git a/drivers/net/wireless/ath/ath6kl/target.h b/drivers/net/wireless/ath/ath6kl/target.h
new file mode 100644
index 000000000000..519a013c9991
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/target.h
@@ -0,0 +1,331 @@
1/*
2 * Copyright (c) 2004-2010 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef TARGET_H
18#define TARGET_H
19
20#define AR6003_BOARD_DATA_SZ 1024
21#define AR6003_BOARD_EXT_DATA_SZ 768
22
23#define RESET_CONTROL_ADDRESS 0x00000000
24#define RESET_CONTROL_COLD_RST 0x00000100
25#define RESET_CONTROL_MBOX_RST 0x00000004
26
27#define CPU_CLOCK_STANDARD_S 0
28#define CPU_CLOCK_STANDARD 0x00000003
29#define CPU_CLOCK_ADDRESS 0x00000020
30
31#define CLOCK_CONTROL_ADDRESS 0x00000028
32#define CLOCK_CONTROL_LF_CLK32_S 2
33#define CLOCK_CONTROL_LF_CLK32 0x00000004
34
35#define SYSTEM_SLEEP_ADDRESS 0x000000c4
36#define SYSTEM_SLEEP_DISABLE_S 0
37#define SYSTEM_SLEEP_DISABLE 0x00000001
38
39#define LPO_CAL_ADDRESS 0x000000e0
40#define LPO_CAL_ENABLE_S 20
41#define LPO_CAL_ENABLE 0x00100000
42
43#define GPIO_PIN10_ADDRESS 0x00000050
44#define GPIO_PIN11_ADDRESS 0x00000054
45#define GPIO_PIN12_ADDRESS 0x00000058
46#define GPIO_PIN13_ADDRESS 0x0000005c
47
48#define HOST_INT_STATUS_ADDRESS 0x00000400
49#define HOST_INT_STATUS_ERROR_S 7
50#define HOST_INT_STATUS_ERROR 0x00000080
51
52#define HOST_INT_STATUS_CPU_S 6
53#define HOST_INT_STATUS_CPU 0x00000040
54
55#define HOST_INT_STATUS_COUNTER_S 4
56#define HOST_INT_STATUS_COUNTER 0x00000010
57
58#define CPU_INT_STATUS_ADDRESS 0x00000401
59
60#define ERROR_INT_STATUS_ADDRESS 0x00000402
61#define ERROR_INT_STATUS_WAKEUP_S 2
62#define ERROR_INT_STATUS_WAKEUP 0x00000004
63
64#define ERROR_INT_STATUS_RX_UNDERFLOW_S 1
65#define ERROR_INT_STATUS_RX_UNDERFLOW 0x00000002
66
67#define ERROR_INT_STATUS_TX_OVERFLOW_S 0
68#define ERROR_INT_STATUS_TX_OVERFLOW 0x00000001
69
70#define COUNTER_INT_STATUS_ADDRESS 0x00000403
71#define COUNTER_INT_STATUS_COUNTER_S 0
72#define COUNTER_INT_STATUS_COUNTER 0x000000ff
73
74#define RX_LOOKAHEAD_VALID_ADDRESS 0x00000405
75
76#define INT_STATUS_ENABLE_ADDRESS 0x00000418
77#define INT_STATUS_ENABLE_ERROR_S 7
78#define INT_STATUS_ENABLE_ERROR 0x00000080
79
80#define INT_STATUS_ENABLE_CPU_S 6
81#define INT_STATUS_ENABLE_CPU 0x00000040
82
83#define INT_STATUS_ENABLE_INT_S 5
84#define INT_STATUS_ENABLE_INT 0x00000020
85#define INT_STATUS_ENABLE_COUNTER_S 4
86#define INT_STATUS_ENABLE_COUNTER 0x00000010
87
88#define INT_STATUS_ENABLE_MBOX_DATA_S 0
89#define INT_STATUS_ENABLE_MBOX_DATA 0x0000000f
90
91#define CPU_INT_STATUS_ENABLE_ADDRESS 0x00000419
92#define CPU_INT_STATUS_ENABLE_BIT_S 0
93#define CPU_INT_STATUS_ENABLE_BIT 0x000000ff
94
95#define ERROR_STATUS_ENABLE_ADDRESS 0x0000041a
96#define ERROR_STATUS_ENABLE_RX_UNDERFLOW_S 1
97#define ERROR_STATUS_ENABLE_RX_UNDERFLOW 0x00000002
98
99#define ERROR_STATUS_ENABLE_TX_OVERFLOW_S 0
100#define ERROR_STATUS_ENABLE_TX_OVERFLOW 0x00000001
101
102#define COUNTER_INT_STATUS_ENABLE_ADDRESS 0x0000041b
103#define COUNTER_INT_STATUS_ENABLE_BIT_S 0
104#define COUNTER_INT_STATUS_ENABLE_BIT 0x000000ff
105
106#define COUNT_ADDRESS 0x00000420
107
108#define COUNT_DEC_ADDRESS 0x00000440
109
110#define WINDOW_DATA_ADDRESS 0x00000474
111#define WINDOW_WRITE_ADDR_ADDRESS 0x00000478
112#define WINDOW_READ_ADDR_ADDRESS 0x0000047c
113#define CPU_DBG_SEL_ADDRESS 0x00000483
114#define CPU_DBG_ADDRESS 0x00000484
115
116#define LOCAL_SCRATCH_ADDRESS 0x000000c0
117#define ATH6KL_OPTION_SLEEP_DISABLE 0x08
118
119#define RTC_BASE_ADDRESS 0x00004000
120#define GPIO_BASE_ADDRESS 0x00014000
121#define MBOX_BASE_ADDRESS 0x00018000
122#define ANALOG_INTF_BASE_ADDRESS 0x0001c000
123
124/* real name of the register is unknown */
125#define ATH6KL_ANALOG_PLL_REGISTER (ANALOG_INTF_BASE_ADDRESS + 0x284)
126
127#define SM(f, v) (((v) << f##_S) & f)
128#define MS(f, v) (((v) & f) >> f##_S)
129
130/*
131 * xxx_HOST_INTEREST_ADDRESS is the address in Target RAM of the
132 * host_interest structure.
133 *
134 * Host Interest is shared between Host and Target in order to coordinate
135 * between the two, and is intended to remain constant (with additions only
136 * at the end).
137 */
138#define ATH6KL_HI_START_ADDR 0x00540600
139
140/*
141 * These are items that the Host may need to access
142 * via BMI or via the Diagnostic Window. The position
143 * of items in this structure must remain constant.
144 * across firmware revisions!
145 *
146 * Types for each item must be fixed size across target and host platforms.
147 * The structure is used only to calculate offset for each register with
148 * HI_ITEM() macro, no values are stored to it.
149 *
150 * More items may be added at the end.
151 */
152struct host_interest {
153 /*
154 * Pointer to application-defined area, if any.
155 * Set by Target application during startup.
156 */
157 u32 hi_app_host_interest; /* 0x00 */
158
159 /* Pointer to register dump area, valid after Target crash. */
160 u32 hi_failure_state; /* 0x04 */
161
162 /* Pointer to debug logging header */
163 u32 hi_dbglog_hdr; /* 0x08 */
164
165 u32 hi_unused1; /* 0x0c */
166
167 /*
168 * General-purpose flag bits, similar to ATH6KL_OPTION_* flags.
169 * Can be used by application rather than by OS.
170 */
171 u32 hi_option_flag; /* 0x10 */
172
173 /*
174 * Boolean that determines whether or not to
175 * display messages on the serial port.
176 */
177 u32 hi_serial_enable; /* 0x14 */
178
179 /* Start address of DataSet index, if any */
180 u32 hi_dset_list_head; /* 0x18 */
181
182 /* Override Target application start address */
183 u32 hi_app_start; /* 0x1c */
184
185 /* Clock and voltage tuning */
186 u32 hi_skip_clock_init; /* 0x20 */
187 u32 hi_core_clock_setting; /* 0x24 */
188 u32 hi_cpu_clock_setting; /* 0x28 */
189 u32 hi_system_sleep_setting; /* 0x2c */
190 u32 hi_xtal_control_setting; /* 0x30 */
191 u32 hi_pll_ctrl_setting_24ghz; /* 0x34 */
192 u32 hi_pll_ctrl_setting_5ghz; /* 0x38 */
193 u32 hi_ref_voltage_trim_setting; /* 0x3c */
194 u32 hi_clock_info; /* 0x40 */
195
196 /*
197 * Flash configuration overrides, used only
198 * when firmware is not executing from flash.
199 * (When using flash, modify the global variables
200 * with equivalent names.)
201 */
202 u32 hi_bank0_addr_value; /* 0x44 */
203 u32 hi_bank0_read_value; /* 0x48 */
204 u32 hi_bank0_write_value; /* 0x4c */
205 u32 hi_bank0_config_value; /* 0x50 */
206
207 /* Pointer to Board Data */
208 u32 hi_board_data; /* 0x54 */
209 u32 hi_board_data_initialized; /* 0x58 */
210
211 u32 hi_dset_ram_index_tbl; /* 0x5c */
212
213 u32 hi_desired_baud_rate; /* 0x60 */
214 u32 hi_dbglog_config; /* 0x64 */
215 u32 hi_end_ram_reserve_sz; /* 0x68 */
216 u32 hi_mbox_io_block_sz; /* 0x6c */
217
218 u32 hi_num_bpatch_streams; /* 0x70 -- unused */
219 u32 hi_mbox_isr_yield_limit; /* 0x74 */
220
221 u32 hi_refclk_hz; /* 0x78 */
222 u32 hi_ext_clk_detected; /* 0x7c */
223 u32 hi_dbg_uart_txpin; /* 0x80 */
224 u32 hi_dbg_uart_rxpin; /* 0x84 */
225 u32 hi_hci_uart_baud; /* 0x88 */
226 u32 hi_hci_uart_pin_assignments; /* 0x8C */
227 /*
228 * NOTE: byte [0] = tx pin, [1] = rx pin, [2] = rts pin, [3] = cts
229 * pin
230 */
231 u32 hi_hci_uart_baud_scale_val; /* 0x90 */
232 u32 hi_hci_uart_baud_step_val; /* 0x94 */
233
234 u32 hi_allocram_start; /* 0x98 */
235 u32 hi_allocram_sz; /* 0x9c */
236 u32 hi_hci_bridge_flags; /* 0xa0 */
237 u32 hi_hci_uart_support_pins; /* 0xa4 */
238 /*
239 * NOTE: byte [0] = RESET pin (bit 7 is polarity),
240 * bytes[1]..bytes[3] are for future use
241 */
242 u32 hi_hci_uart_pwr_mgmt_params; /* 0xa8 */
243 /*
244 * 0xa8 - [1]: 0 = UART FC active low, 1 = UART FC active high
245 * [31:16]: wakeup timeout in ms
246 */
247
248 /* Pointer to extended board data */
249 u32 hi_board_ext_data; /* 0xac */
250 u32 hi_board_ext_data_config; /* 0xb0 */
251
252 /*
253 * Bit [0] : valid
254 * Bit[31:16: size
255 */
256 /*
257 * hi_reset_flag is used to do some stuff when target reset.
258 * such as restore app_start after warm reset or
259 * preserve host Interest area, or preserve ROM data, literals etc.
260 */
261 u32 hi_reset_flag; /* 0xb4 */
262 /* indicate hi_reset_flag is valid */
263 u32 hi_reset_flag_valid; /* 0xb8 */
264 u32 hi_hci_uart_pwr_mgmt_params_ext; /* 0xbc */
265 /*
266 * 0xbc - [31:0]: idle timeout in ms
267 */
268 /* ACS flags */
269 u32 hi_acs_flags; /* 0xc0 */
270 u32 hi_console_flags; /* 0xc4 */
271 u32 hi_nvram_state; /* 0xc8 */
272 u32 hi_option_flag2; /* 0xcc */
273
274 /* If non-zero, override values sent to Host in WMI_READY event. */
275 u32 hi_sw_version_override; /* 0xd0 */
276 u32 hi_abi_version_override; /* 0xd4 */
277
278 /*
279 * Percentage of high priority RX traffic to total expected RX traffic -
280 * applicable only to ar6004
281 */
282 u32 hi_hp_rx_traffic_ratio; /* 0xd8 */
283
284 /* test applications flags */
285 u32 hi_test_apps_related ; /* 0xdc */
286 /* location of test script */
287 u32 hi_ota_testscript; /* 0xe0 */
288 /* location of CAL data */
289 u32 hi_cal_data; /* 0xe4 */
290 /* Number of packet log buffers */
291 u32 hi_pktlog_num_buffers; /* 0xe8 */
292
293} __packed;
294
295#define HI_ITEM(item) offsetof(struct host_interest, item)
296
297#define HI_OPTION_MAC_ADDR_METHOD_SHIFT 3
298
299#define HI_OPTION_FW_MODE_IBSS 0x0
300#define HI_OPTION_FW_MODE_BSS_STA 0x1
301#define HI_OPTION_FW_MODE_AP 0x2
302
303#define HI_OPTION_NUM_DEV_SHIFT 0x9
304
305#define HI_OPTION_FW_BRIDGE_SHIFT 0x04
306
307/* Fw Mode/SubMode Mask
308|------------------------------------------------------------------------------|
309| SUB | SUB | SUB | SUB | | | |
310| MODE[3] | MODE[2] | MODE[1] | MODE[0] | MODE[3] | MODE[2] | MODE[1] | MODE[0|
311| (2) | (2) | (2) | (2) | (2) | (2) | (2) | (2)
312|------------------------------------------------------------------------------|
313*/
314#define HI_OPTION_FW_MODE_SHIFT 0xC
315
316/* Convert a Target virtual address into a Target physical address */
317#define TARG_VTOP(vaddr) (vaddr & 0x001fffff)
318
319#define AR6003_REV2_APP_START_OVERRIDE 0x944C00
320#define AR6003_REV2_APP_LOAD_ADDRESS 0x543180
321#define AR6003_REV2_BOARD_EXT_DATA_ADDRESS 0x57E500
322#define AR6003_REV2_DATASET_PATCH_ADDRESS 0x57e884
323#define AR6003_REV2_RAM_RESERVE_SIZE 6912
324
325#define AR6003_REV3_APP_START_OVERRIDE 0x945d00
326#define AR6003_REV3_APP_LOAD_ADDRESS 0x545000
327#define AR6003_REV3_BOARD_EXT_DATA_ADDRESS 0x542330
328#define AR6003_REV3_DATASET_PATCH_ADDRESS 0x57FF74
329#define AR6003_REV3_RAM_RESERVE_SIZE 512
330
331#endif
diff --git a/drivers/net/wireless/ath/ath6kl/txrx.c b/drivers/net/wireless/ath/ath6kl/txrx.c
new file mode 100644
index 000000000000..167bdb9cf68d
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/txrx.c
@@ -0,0 +1,1457 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include "core.h"
18#include "debug.h"
19
20static u8 ath6kl_ibss_map_epid(struct sk_buff *skb, struct net_device *dev,
21 u32 *map_no)
22{
23 struct ath6kl *ar = ath6kl_priv(dev);
24 struct ethhdr *eth_hdr;
25 u32 i, ep_map = -1;
26 u8 *datap;
27
28 *map_no = 0;
29 datap = skb->data;
30 eth_hdr = (struct ethhdr *) (datap + sizeof(struct wmi_data_hdr));
31
32 if (is_multicast_ether_addr(eth_hdr->h_dest))
33 return ENDPOINT_2;
34
35 for (i = 0; i < ar->node_num; i++) {
36 if (memcmp(eth_hdr->h_dest, ar->node_map[i].mac_addr,
37 ETH_ALEN) == 0) {
38 *map_no = i + 1;
39 ar->node_map[i].tx_pend++;
40 return ar->node_map[i].ep_id;
41 }
42
43 if ((ep_map == -1) && !ar->node_map[i].tx_pend)
44 ep_map = i;
45 }
46
47 if (ep_map == -1) {
48 ep_map = ar->node_num;
49 ar->node_num++;
50 if (ar->node_num > MAX_NODE_NUM)
51 return ENDPOINT_UNUSED;
52 }
53
54 memcpy(ar->node_map[ep_map].mac_addr, eth_hdr->h_dest, ETH_ALEN);
55
56 for (i = ENDPOINT_2; i <= ENDPOINT_5; i++) {
57 if (!ar->tx_pending[i]) {
58 ar->node_map[ep_map].ep_id = i;
59 break;
60 }
61
62 /*
63 * No free endpoint is available, start redistribution on
64 * the inuse endpoints.
65 */
66 if (i == ENDPOINT_5) {
67 ar->node_map[ep_map].ep_id = ar->next_ep_id;
68 ar->next_ep_id++;
69 if (ar->next_ep_id > ENDPOINT_5)
70 ar->next_ep_id = ENDPOINT_2;
71 }
72 }
73
74 *map_no = ep_map + 1;
75 ar->node_map[ep_map].tx_pend++;
76
77 return ar->node_map[ep_map].ep_id;
78}
79
80static bool ath6kl_powersave_ap(struct ath6kl *ar, struct sk_buff *skb,
81 bool *more_data)
82{
83 struct ethhdr *datap = (struct ethhdr *) skb->data;
84 struct ath6kl_sta *conn = NULL;
85 bool ps_queued = false, is_psq_empty = false;
86
87 if (is_multicast_ether_addr(datap->h_dest)) {
88 u8 ctr = 0;
89 bool q_mcast = false;
90
91 for (ctr = 0; ctr < AP_MAX_NUM_STA; ctr++) {
92 if (ar->sta_list[ctr].sta_flags & STA_PS_SLEEP) {
93 q_mcast = true;
94 break;
95 }
96 }
97
98 if (q_mcast) {
99 /*
100 * If this transmit is not because of a Dtim Expiry
101 * q it.
102 */
103 if (!test_bit(DTIM_EXPIRED, &ar->flag)) {
104 bool is_mcastq_empty = false;
105
106 spin_lock_bh(&ar->mcastpsq_lock);
107 is_mcastq_empty =
108 skb_queue_empty(&ar->mcastpsq);
109 skb_queue_tail(&ar->mcastpsq, skb);
110 spin_unlock_bh(&ar->mcastpsq_lock);
111
112 /*
113 * If this is the first Mcast pkt getting
114 * queued indicate to the target to set the
115 * BitmapControl LSB of the TIM IE.
116 */
117 if (is_mcastq_empty)
118 ath6kl_wmi_set_pvb_cmd(ar->wmi,
119 MCAST_AID, 1);
120
121 ps_queued = true;
122 } else {
123 /*
124 * This transmit is because of Dtim expiry.
125 * Determine if MoreData bit has to be set.
126 */
127 spin_lock_bh(&ar->mcastpsq_lock);
128 if (!skb_queue_empty(&ar->mcastpsq))
129 *more_data = true;
130 spin_unlock_bh(&ar->mcastpsq_lock);
131 }
132 }
133 } else {
134 conn = ath6kl_find_sta(ar, datap->h_dest);
135 if (!conn) {
136 dev_kfree_skb(skb);
137
138 /* Inform the caller that the skb is consumed */
139 return true;
140 }
141
142 if (conn->sta_flags & STA_PS_SLEEP) {
143 if (!(conn->sta_flags & STA_PS_POLLED)) {
144 /* Queue the frames if the STA is sleeping */
145 spin_lock_bh(&conn->psq_lock);
146 is_psq_empty = skb_queue_empty(&conn->psq);
147 skb_queue_tail(&conn->psq, skb);
148 spin_unlock_bh(&conn->psq_lock);
149
150 /*
151 * If this is the first pkt getting queued
152 * for this STA, update the PVB for this
153 * STA.
154 */
155 if (is_psq_empty)
156 ath6kl_wmi_set_pvb_cmd(ar->wmi,
157 conn->aid, 1);
158
159 ps_queued = true;
160 } else {
161 /*
162 * This tx is because of a PsPoll.
163 * Determine if MoreData bit has to be set.
164 */
165 spin_lock_bh(&conn->psq_lock);
166 if (!skb_queue_empty(&conn->psq))
167 *more_data = true;
168 spin_unlock_bh(&conn->psq_lock);
169 }
170 }
171 }
172
173 return ps_queued;
174}
175
176/* Tx functions */
177
178int ath6kl_control_tx(void *devt, struct sk_buff *skb,
179 enum htc_endpoint_id eid)
180{
181 struct ath6kl *ar = devt;
182 int status = 0;
183 struct ath6kl_cookie *cookie = NULL;
184
185 spin_lock_bh(&ar->lock);
186
187 ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
188 "%s: skb=0x%p, len=0x%x eid =%d\n", __func__,
189 skb, skb->len, eid);
190
191 if (test_bit(WMI_CTRL_EP_FULL, &ar->flag) && (eid == ar->ctrl_ep)) {
192 /*
193 * Control endpoint is full, don't allocate resources, we
194 * are just going to drop this packet.
195 */
196 cookie = NULL;
197 ath6kl_err("wmi ctrl ep full, dropping pkt : 0x%p, len:%d\n",
198 skb, skb->len);
199 } else
200 cookie = ath6kl_alloc_cookie(ar);
201
202 if (cookie == NULL) {
203 spin_unlock_bh(&ar->lock);
204 status = -ENOMEM;
205 goto fail_ctrl_tx;
206 }
207
208 ar->tx_pending[eid]++;
209
210 if (eid != ar->ctrl_ep)
211 ar->total_tx_data_pend++;
212
213 spin_unlock_bh(&ar->lock);
214
215 cookie->skb = skb;
216 cookie->map_no = 0;
217 set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len,
218 eid, ATH6KL_CONTROL_PKT_TAG);
219
220 /*
221 * This interface is asynchronous, if there is an error, cleanup
222 * will happen in the TX completion callback.
223 */
224 ath6kl_htc_tx(ar->htc_target, &cookie->htc_pkt);
225
226 return 0;
227
228fail_ctrl_tx:
229 dev_kfree_skb(skb);
230 return status;
231}
232
233int ath6kl_data_tx(struct sk_buff *skb, struct net_device *dev)
234{
235 struct ath6kl *ar = ath6kl_priv(dev);
236 struct ath6kl_cookie *cookie = NULL;
237 enum htc_endpoint_id eid = ENDPOINT_UNUSED;
238 u32 map_no = 0;
239 u16 htc_tag = ATH6KL_DATA_PKT_TAG;
240 u8 ac = 99 ; /* initialize to unmapped ac */
241 bool chk_adhoc_ps_mapping = false, more_data = false;
242 struct wmi_tx_meta_v2 meta_v2;
243 int ret;
244
245 ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
246 "%s: skb=0x%p, data=0x%p, len=0x%x\n", __func__,
247 skb, skb->data, skb->len);
248
249 /* If target is not associated */
250 if (!test_bit(CONNECTED, &ar->flag)) {
251 dev_kfree_skb(skb);
252 return 0;
253 }
254
255 if (!test_bit(WMI_READY, &ar->flag))
256 goto fail_tx;
257
258 /* AP mode Power saving processing */
259 if (ar->nw_type == AP_NETWORK) {
260 if (ath6kl_powersave_ap(ar, skb, &more_data))
261 return 0;
262 }
263
264 if (test_bit(WMI_ENABLED, &ar->flag)) {
265 memset(&meta_v2, 0, sizeof(meta_v2));
266
267 if (skb_headroom(skb) < dev->needed_headroom) {
268 WARN_ON(1);
269 goto fail_tx;
270 }
271
272 if (ath6kl_wmi_dix_2_dot3(ar->wmi, skb)) {
273 ath6kl_err("ath6kl_wmi_dix_2_dot3 failed\n");
274 goto fail_tx;
275 }
276
277 if (ath6kl_wmi_data_hdr_add(ar->wmi, skb, DATA_MSGTYPE,
278 more_data, 0, 0, NULL)) {
279 ath6kl_err("wmi_data_hdr_add failed\n");
280 goto fail_tx;
281 }
282
283 if ((ar->nw_type == ADHOC_NETWORK) &&
284 ar->ibss_ps_enable && test_bit(CONNECTED, &ar->flag))
285 chk_adhoc_ps_mapping = true;
286 else {
287 /* get the stream mapping */
288 ret = ath6kl_wmi_implicit_create_pstream(ar->wmi, skb,
289 0, test_bit(WMM_ENABLED, &ar->flag), &ac);
290 if (ret)
291 goto fail_tx;
292 }
293 } else
294 goto fail_tx;
295
296 spin_lock_bh(&ar->lock);
297
298 if (chk_adhoc_ps_mapping)
299 eid = ath6kl_ibss_map_epid(skb, dev, &map_no);
300 else
301 eid = ar->ac2ep_map[ac];
302
303 if (eid == 0 || eid == ENDPOINT_UNUSED) {
304 ath6kl_err("eid %d is not mapped!\n", eid);
305 spin_unlock_bh(&ar->lock);
306 goto fail_tx;
307 }
308
309 /* allocate resource for this packet */
310 cookie = ath6kl_alloc_cookie(ar);
311
312 if (!cookie) {
313 spin_unlock_bh(&ar->lock);
314 goto fail_tx;
315 }
316
317 /* update counts while the lock is held */
318 ar->tx_pending[eid]++;
319 ar->total_tx_data_pend++;
320
321 spin_unlock_bh(&ar->lock);
322
323 cookie->skb = skb;
324 cookie->map_no = map_no;
325 set_htc_pkt_info(&cookie->htc_pkt, cookie, skb->data, skb->len,
326 eid, htc_tag);
327
328 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len);
329
330 /*
331 * HTC interface is asynchronous, if this fails, cleanup will
332 * happen in the ath6kl_tx_complete callback.
333 */
334 ath6kl_htc_tx(ar->htc_target, &cookie->htc_pkt);
335
336 return 0;
337
338fail_tx:
339 dev_kfree_skb(skb);
340
341 ar->net_stats.tx_dropped++;
342 ar->net_stats.tx_aborted_errors++;
343
344 return 0;
345}
346
347/* indicate tx activity or inactivity on a WMI stream */
348void ath6kl_indicate_tx_activity(void *devt, u8 traffic_class, bool active)
349{
350 struct ath6kl *ar = devt;
351 enum htc_endpoint_id eid;
352 int i;
353
354 eid = ar->ac2ep_map[traffic_class];
355
356 if (!test_bit(WMI_ENABLED, &ar->flag))
357 goto notify_htc;
358
359 spin_lock_bh(&ar->lock);
360
361 ar->ac_stream_active[traffic_class] = active;
362
363 if (active) {
364 /*
365 * Keep track of the active stream with the highest
366 * priority.
367 */
368 if (ar->ac_stream_pri_map[traffic_class] >
369 ar->hiac_stream_active_pri)
370 /* set the new highest active priority */
371 ar->hiac_stream_active_pri =
372 ar->ac_stream_pri_map[traffic_class];
373
374 } else {
375 /*
376 * We may have to search for the next active stream
377 * that is the highest priority.
378 */
379 if (ar->hiac_stream_active_pri ==
380 ar->ac_stream_pri_map[traffic_class]) {
381 /*
382 * The highest priority stream just went inactive
383 * reset and search for the "next" highest "active"
384 * priority stream.
385 */
386 ar->hiac_stream_active_pri = 0;
387
388 for (i = 0; i < WMM_NUM_AC; i++) {
389 if (ar->ac_stream_active[i] &&
390 (ar->ac_stream_pri_map[i] >
391 ar->hiac_stream_active_pri))
392 /*
393 * Set the new highest active
394 * priority.
395 */
396 ar->hiac_stream_active_pri =
397 ar->ac_stream_pri_map[i];
398 }
399 }
400 }
401
402 spin_unlock_bh(&ar->lock);
403
404notify_htc:
405 /* notify HTC, this may cause credit distribution changes */
406 ath6kl_htc_indicate_activity_change(ar->htc_target, eid, active);
407}
408
409enum htc_send_full_action ath6kl_tx_queue_full(struct htc_target *target,
410 struct htc_packet *packet)
411{
412 struct ath6kl *ar = target->dev->ar;
413 enum htc_endpoint_id endpoint = packet->endpoint;
414
415 if (endpoint == ar->ctrl_ep) {
416 /*
417 * Under normal WMI if this is getting full, then something
418 * is running rampant the host should not be exhausting the
419 * WMI queue with too many commands the only exception to
420 * this is during testing using endpointping.
421 */
422 spin_lock_bh(&ar->lock);
423 set_bit(WMI_CTRL_EP_FULL, &ar->flag);
424 spin_unlock_bh(&ar->lock);
425 ath6kl_err("wmi ctrl ep is full\n");
426 return HTC_SEND_FULL_KEEP;
427 }
428
429 if (packet->info.tx.tag == ATH6KL_CONTROL_PKT_TAG)
430 return HTC_SEND_FULL_KEEP;
431
432 if (ar->nw_type == ADHOC_NETWORK)
433 /*
434 * In adhoc mode, we cannot differentiate traffic
435 * priorities so there is no need to continue, however we
436 * should stop the network.
437 */
438 goto stop_net_queues;
439
440 /*
441 * The last MAX_HI_COOKIE_NUM "batch" of cookies are reserved for
442 * the highest active stream.
443 */
444 if (ar->ac_stream_pri_map[ar->ep2ac_map[endpoint]] <
445 ar->hiac_stream_active_pri &&
446 ar->cookie_count <= MAX_HI_COOKIE_NUM)
447 /*
448 * Give preference to the highest priority stream by
449 * dropping the packets which overflowed.
450 */
451 return HTC_SEND_FULL_DROP;
452
453stop_net_queues:
454 spin_lock_bh(&ar->lock);
455 set_bit(NETQ_STOPPED, &ar->flag);
456 spin_unlock_bh(&ar->lock);
457 netif_stop_queue(ar->net_dev);
458
459 return HTC_SEND_FULL_KEEP;
460}
461
462/* TODO this needs to be looked at */
463static void ath6kl_tx_clear_node_map(struct ath6kl *ar,
464 enum htc_endpoint_id eid, u32 map_no)
465{
466 u32 i;
467
468 if (ar->nw_type != ADHOC_NETWORK)
469 return;
470
471 if (!ar->ibss_ps_enable)
472 return;
473
474 if (eid == ar->ctrl_ep)
475 return;
476
477 if (map_no == 0)
478 return;
479
480 map_no--;
481 ar->node_map[map_no].tx_pend--;
482
483 if (ar->node_map[map_no].tx_pend)
484 return;
485
486 if (map_no != (ar->node_num - 1))
487 return;
488
489 for (i = ar->node_num; i > 0; i--) {
490 if (ar->node_map[i - 1].tx_pend)
491 break;
492
493 memset(&ar->node_map[i - 1], 0,
494 sizeof(struct ath6kl_node_mapping));
495 ar->node_num--;
496 }
497}
498
499void ath6kl_tx_complete(void *context, struct list_head *packet_queue)
500{
501 struct ath6kl *ar = context;
502 struct sk_buff_head skb_queue;
503 struct htc_packet *packet;
504 struct sk_buff *skb;
505 struct ath6kl_cookie *ath6kl_cookie;
506 u32 map_no = 0;
507 int status;
508 enum htc_endpoint_id eid;
509 bool wake_event = false;
510 bool flushing = false;
511
512 skb_queue_head_init(&skb_queue);
513
514 /* lock the driver as we update internal state */
515 spin_lock_bh(&ar->lock);
516
517 /* reap completed packets */
518 while (!list_empty(packet_queue)) {
519
520 packet = list_first_entry(packet_queue, struct htc_packet,
521 list);
522 list_del(&packet->list);
523
524 ath6kl_cookie = (struct ath6kl_cookie *)packet->pkt_cntxt;
525 if (!ath6kl_cookie)
526 goto fatal;
527
528 status = packet->status;
529 skb = ath6kl_cookie->skb;
530 eid = packet->endpoint;
531 map_no = ath6kl_cookie->map_no;
532
533 if (!skb || !skb->data)
534 goto fatal;
535
536 packet->buf = skb->data;
537
538 __skb_queue_tail(&skb_queue, skb);
539
540 if (!status && (packet->act_len != skb->len))
541 goto fatal;
542
543 ar->tx_pending[eid]--;
544
545 if (eid != ar->ctrl_ep)
546 ar->total_tx_data_pend--;
547
548 if (eid == ar->ctrl_ep) {
549 if (test_bit(WMI_CTRL_EP_FULL, &ar->flag))
550 clear_bit(WMI_CTRL_EP_FULL, &ar->flag);
551
552 if (ar->tx_pending[eid] == 0)
553 wake_event = true;
554 }
555
556 if (status) {
557 if (status == -ECANCELED)
558 /* a packet was flushed */
559 flushing = true;
560
561 ar->net_stats.tx_errors++;
562
563 if (status != -ENOSPC)
564 ath6kl_err("tx error, status: 0x%x\n", status);
565 ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
566 "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n",
567 __func__, skb, packet->buf, packet->act_len,
568 eid, "error!");
569 } else {
570 ath6kl_dbg(ATH6KL_DBG_WLAN_TX,
571 "%s: skb=0x%p data=0x%p len=0x%x eid=%d %s\n",
572 __func__, skb, packet->buf, packet->act_len,
573 eid, "OK");
574
575 flushing = false;
576 ar->net_stats.tx_packets++;
577 ar->net_stats.tx_bytes += skb->len;
578 }
579
580 ath6kl_tx_clear_node_map(ar, eid, map_no);
581
582 ath6kl_free_cookie(ar, ath6kl_cookie);
583
584 if (test_bit(NETQ_STOPPED, &ar->flag))
585 clear_bit(NETQ_STOPPED, &ar->flag);
586 }
587
588 spin_unlock_bh(&ar->lock);
589
590 __skb_queue_purge(&skb_queue);
591
592 if (test_bit(CONNECTED, &ar->flag)) {
593 if (!flushing)
594 netif_wake_queue(ar->net_dev);
595 }
596
597 if (wake_event)
598 wake_up(&ar->event_wq);
599
600 return;
601
602fatal:
603 WARN_ON(1);
604 spin_unlock_bh(&ar->lock);
605 return;
606}
607
608void ath6kl_tx_data_cleanup(struct ath6kl *ar)
609{
610 int i;
611
612 /* flush all the data (non-control) streams */
613 for (i = 0; i < WMM_NUM_AC; i++)
614 ath6kl_htc_flush_txep(ar->htc_target, ar->ac2ep_map[i],
615 ATH6KL_DATA_PKT_TAG);
616}
617
618/* Rx functions */
619
620static void ath6kl_deliver_frames_to_nw_stack(struct net_device *dev,
621 struct sk_buff *skb)
622{
623 if (!skb)
624 return;
625
626 skb->dev = dev;
627
628 if (!(skb->dev->flags & IFF_UP)) {
629 dev_kfree_skb(skb);
630 return;
631 }
632
633 skb->protocol = eth_type_trans(skb, skb->dev);
634
635 netif_rx_ni(skb);
636}
637
638static void ath6kl_alloc_netbufs(struct sk_buff_head *q, u16 num)
639{
640 struct sk_buff *skb;
641
642 while (num) {
643 skb = ath6kl_buf_alloc(ATH6KL_BUFFER_SIZE);
644 if (!skb) {
645 ath6kl_err("netbuf allocation failed\n");
646 return;
647 }
648 skb_queue_tail(q, skb);
649 num--;
650 }
651}
652
653static struct sk_buff *aggr_get_free_skb(struct aggr_info *p_aggr)
654{
655 struct sk_buff *skb = NULL;
656
657 if (skb_queue_len(&p_aggr->free_q) < (AGGR_NUM_OF_FREE_NETBUFS >> 2))
658 ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS);
659
660 skb = skb_dequeue(&p_aggr->free_q);
661
662 return skb;
663}
664
665void ath6kl_rx_refill(struct htc_target *target, enum htc_endpoint_id endpoint)
666{
667 struct ath6kl *ar = target->dev->ar;
668 struct sk_buff *skb;
669 int rx_buf;
670 int n_buf_refill;
671 struct htc_packet *packet;
672 struct list_head queue;
673
674 n_buf_refill = ATH6KL_MAX_RX_BUFFERS -
675 ath6kl_htc_get_rxbuf_num(ar->htc_target, endpoint);
676
677 if (n_buf_refill <= 0)
678 return;
679
680 INIT_LIST_HEAD(&queue);
681
682 ath6kl_dbg(ATH6KL_DBG_WLAN_RX,
683 "%s: providing htc with %d buffers at eid=%d\n",
684 __func__, n_buf_refill, endpoint);
685
686 for (rx_buf = 0; rx_buf < n_buf_refill; rx_buf++) {
687 skb = ath6kl_buf_alloc(ATH6KL_BUFFER_SIZE);
688 if (!skb)
689 break;
690
691 packet = (struct htc_packet *) skb->head;
692 set_htc_rxpkt_info(packet, skb, skb->data,
693 ATH6KL_BUFFER_SIZE, endpoint);
694 list_add_tail(&packet->list, &queue);
695 }
696
697 if (!list_empty(&queue))
698 ath6kl_htc_add_rxbuf_multiple(ar->htc_target, &queue);
699}
700
701void ath6kl_refill_amsdu_rxbufs(struct ath6kl *ar, int count)
702{
703 struct htc_packet *packet;
704 struct sk_buff *skb;
705
706 while (count) {
707 skb = ath6kl_buf_alloc(ATH6KL_AMSDU_BUFFER_SIZE);
708 if (!skb)
709 return;
710
711 packet = (struct htc_packet *) skb->head;
712 set_htc_rxpkt_info(packet, skb, skb->data,
713 ATH6KL_AMSDU_BUFFER_SIZE, 0);
714 spin_lock_bh(&ar->lock);
715 list_add_tail(&packet->list, &ar->amsdu_rx_buffer_queue);
716 spin_unlock_bh(&ar->lock);
717 count--;
718 }
719}
720
721/*
722 * Callback to allocate a receive buffer for a pending packet. We use a
723 * pre-allocated list of buffers of maximum AMSDU size (4K).
724 */
725struct htc_packet *ath6kl_alloc_amsdu_rxbuf(struct htc_target *target,
726 enum htc_endpoint_id endpoint,
727 int len)
728{
729 struct ath6kl *ar = target->dev->ar;
730 struct htc_packet *packet = NULL;
731 struct list_head *pkt_pos;
732 int refill_cnt = 0, depth = 0;
733
734 ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: eid=%d, len:%d\n",
735 __func__, endpoint, len);
736
737 if ((len <= ATH6KL_BUFFER_SIZE) ||
738 (len > ATH6KL_AMSDU_BUFFER_SIZE))
739 return NULL;
740
741 spin_lock_bh(&ar->lock);
742
743 if (list_empty(&ar->amsdu_rx_buffer_queue)) {
744 spin_unlock_bh(&ar->lock);
745 refill_cnt = ATH6KL_MAX_AMSDU_RX_BUFFERS;
746 goto refill_buf;
747 }
748
749 packet = list_first_entry(&ar->amsdu_rx_buffer_queue,
750 struct htc_packet, list);
751 list_del(&packet->list);
752 list_for_each(pkt_pos, &ar->amsdu_rx_buffer_queue)
753 depth++;
754
755 refill_cnt = ATH6KL_MAX_AMSDU_RX_BUFFERS - depth;
756 spin_unlock_bh(&ar->lock);
757
758 /* set actual endpoint ID */
759 packet->endpoint = endpoint;
760
761refill_buf:
762 if (refill_cnt >= ATH6KL_AMSDU_REFILL_THRESHOLD)
763 ath6kl_refill_amsdu_rxbufs(ar, refill_cnt);
764
765 return packet;
766}
767
768static void aggr_slice_amsdu(struct aggr_info *p_aggr,
769 struct rxtid *rxtid, struct sk_buff *skb)
770{
771 struct sk_buff *new_skb;
772 struct ethhdr *hdr;
773 u16 frame_8023_len, payload_8023_len, mac_hdr_len, amsdu_len;
774 u8 *framep;
775
776 mac_hdr_len = sizeof(struct ethhdr);
777 framep = skb->data + mac_hdr_len;
778 amsdu_len = skb->len - mac_hdr_len;
779
780 while (amsdu_len > mac_hdr_len) {
781 hdr = (struct ethhdr *) framep;
782 payload_8023_len = ntohs(hdr->h_proto);
783
784 if (payload_8023_len < MIN_MSDU_SUBFRAME_PAYLOAD_LEN ||
785 payload_8023_len > MAX_MSDU_SUBFRAME_PAYLOAD_LEN) {
786 ath6kl_err("802.3 AMSDU frame bound check failed. len %d\n",
787 payload_8023_len);
788 break;
789 }
790
791 frame_8023_len = payload_8023_len + mac_hdr_len;
792 new_skb = aggr_get_free_skb(p_aggr);
793 if (!new_skb) {
794 ath6kl_err("no buffer available\n");
795 break;
796 }
797
798 memcpy(new_skb->data, framep, frame_8023_len);
799 skb_put(new_skb, frame_8023_len);
800 if (ath6kl_wmi_dot3_2_dix(new_skb)) {
801 ath6kl_err("dot3_2_dix error\n");
802 dev_kfree_skb(new_skb);
803 break;
804 }
805
806 skb_queue_tail(&rxtid->q, new_skb);
807
808 /* Is this the last subframe within this aggregate ? */
809 if ((amsdu_len - frame_8023_len) == 0)
810 break;
811
812 /* Add the length of A-MSDU subframe padding bytes -
813 * Round to nearest word.
814 */
815 frame_8023_len = ALIGN(frame_8023_len + 3, 3);
816
817 framep += frame_8023_len;
818 amsdu_len -= frame_8023_len;
819 }
820
821 dev_kfree_skb(skb);
822}
823
824static void aggr_deque_frms(struct aggr_info *p_aggr, u8 tid,
825 u16 seq_no, u8 order)
826{
827 struct sk_buff *skb;
828 struct rxtid *rxtid;
829 struct skb_hold_q *node;
830 u16 idx, idx_end, seq_end;
831 struct rxtid_stats *stats;
832
833 if (!p_aggr)
834 return;
835
836 rxtid = &p_aggr->rx_tid[tid];
837 stats = &p_aggr->stat[tid];
838
839 idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
840
841 /*
842 * idx_end is typically the last possible frame in the window,
843 * but changes to 'the' seq_no, when BAR comes. If seq_no
844 * is non-zero, we will go up to that and stop.
845 * Note: last seq no in current window will occupy the same
846 * index position as index that is just previous to start.
847 * An imp point : if win_sz is 7, for seq_no space of 4095,
848 * then, there would be holes when sequence wrap around occurs.
849 * Target should judiciously choose the win_sz, based on
850 * this condition. For 4095, (TID_WINDOW_SZ = 2 x win_sz
851 * 2, 4, 8, 16 win_sz works fine).
852 * We must deque from "idx" to "idx_end", including both.
853 */
854 seq_end = seq_no ? seq_no : rxtid->seq_next;
855 idx_end = AGGR_WIN_IDX(seq_end, rxtid->hold_q_sz);
856
857 spin_lock_bh(&rxtid->lock);
858
859 do {
860 node = &rxtid->hold_q[idx];
861 if ((order == 1) && (!node->skb))
862 break;
863
864 if (node->skb) {
865 if (node->is_amsdu)
866 aggr_slice_amsdu(p_aggr, rxtid, node->skb);
867 else
868 skb_queue_tail(&rxtid->q, node->skb);
869 node->skb = NULL;
870 } else
871 stats->num_hole++;
872
873 rxtid->seq_next = ATH6KL_NEXT_SEQ_NO(rxtid->seq_next);
874 idx = AGGR_WIN_IDX(rxtid->seq_next, rxtid->hold_q_sz);
875 } while (idx != idx_end);
876
877 spin_unlock_bh(&rxtid->lock);
878
879 stats->num_delivered += skb_queue_len(&rxtid->q);
880
881 while ((skb = skb_dequeue(&rxtid->q)))
882 ath6kl_deliver_frames_to_nw_stack(p_aggr->dev, skb);
883}
884
885static bool aggr_process_recv_frm(struct aggr_info *agg_info, u8 tid,
886 u16 seq_no,
887 bool is_amsdu, struct sk_buff *frame)
888{
889 struct rxtid *rxtid;
890 struct rxtid_stats *stats;
891 struct sk_buff *skb;
892 struct skb_hold_q *node;
893 u16 idx, st, cur, end;
894 bool is_queued = false;
895 u16 extended_end;
896
897 rxtid = &agg_info->rx_tid[tid];
898 stats = &agg_info->stat[tid];
899
900 stats->num_into_aggr++;
901
902 if (!rxtid->aggr) {
903 if (is_amsdu) {
904 aggr_slice_amsdu(agg_info, rxtid, frame);
905 is_queued = true;
906 stats->num_amsdu++;
907 while ((skb = skb_dequeue(&rxtid->q)))
908 ath6kl_deliver_frames_to_nw_stack(agg_info->dev,
909 skb);
910 }
911 return is_queued;
912 }
913
914 /* Check the incoming sequence no, if it's in the window */
915 st = rxtid->seq_next;
916 cur = seq_no;
917 end = (st + rxtid->hold_q_sz-1) & ATH6KL_MAX_SEQ_NO;
918
919 if (((st < end) && (cur < st || cur > end)) ||
920 ((st > end) && (cur > end) && (cur < st))) {
921 extended_end = (end + rxtid->hold_q_sz - 1) &
922 ATH6KL_MAX_SEQ_NO;
923
924 if (((end < extended_end) &&
925 (cur < end || cur > extended_end)) ||
926 ((end > extended_end) && (cur > extended_end) &&
927 (cur < end))) {
928 aggr_deque_frms(agg_info, tid, 0, 0);
929 if (cur >= rxtid->hold_q_sz - 1)
930 rxtid->seq_next = cur - (rxtid->hold_q_sz - 1);
931 else
932 rxtid->seq_next = ATH6KL_MAX_SEQ_NO -
933 (rxtid->hold_q_sz - 2 - cur);
934 } else {
935 /*
936 * Dequeue only those frames that are outside the
937 * new shifted window.
938 */
939 if (cur >= rxtid->hold_q_sz - 1)
940 st = cur - (rxtid->hold_q_sz - 1);
941 else
942 st = ATH6KL_MAX_SEQ_NO -
943 (rxtid->hold_q_sz - 2 - cur);
944
945 aggr_deque_frms(agg_info, tid, st, 0);
946 }
947
948 stats->num_oow++;
949 }
950
951 idx = AGGR_WIN_IDX(seq_no, rxtid->hold_q_sz);
952
953 node = &rxtid->hold_q[idx];
954
955 spin_lock_bh(&rxtid->lock);
956
957 /*
958 * Is the cur frame duplicate or something beyond our window(hold_q
959 * -> which is 2x, already)?
960 *
961 * 1. Duplicate is easy - drop incoming frame.
962 * 2. Not falling in current sliding window.
963 * 2a. is the frame_seq_no preceding current tid_seq_no?
964 * -> drop the frame. perhaps sender did not get our ACK.
965 * this is taken care of above.
966 * 2b. is the frame_seq_no beyond window(st, TID_WINDOW_SZ);
967 * -> Taken care of it above, by moving window forward.
968 */
969 dev_kfree_skb(node->skb);
970 stats->num_dups++;
971
972 node->skb = frame;
973 is_queued = true;
974 node->is_amsdu = is_amsdu;
975 node->seq_no = seq_no;
976
977 if (node->is_amsdu)
978 stats->num_amsdu++;
979 else
980 stats->num_mpdu++;
981
982 spin_unlock_bh(&rxtid->lock);
983
984 aggr_deque_frms(agg_info, tid, 0, 1);
985
986 if (agg_info->timer_scheduled)
987 rxtid->progress = true;
988 else
989 for (idx = 0 ; idx < rxtid->hold_q_sz; idx++) {
990 if (rxtid->hold_q[idx].skb) {
991 /*
992 * There is a frame in the queue and no
993 * timer so start a timer to ensure that
994 * the frame doesn't remain stuck
995 * forever.
996 */
997 agg_info->timer_scheduled = true;
998 mod_timer(&agg_info->timer,
999 (jiffies +
1000 HZ * (AGGR_RX_TIMEOUT) / 1000));
1001 rxtid->progress = false;
1002 rxtid->timer_mon = true;
1003 break;
1004 }
1005 }
1006
1007 return is_queued;
1008}
1009
1010void ath6kl_rx(struct htc_target *target, struct htc_packet *packet)
1011{
1012 struct ath6kl *ar = target->dev->ar;
1013 struct sk_buff *skb = packet->pkt_cntxt;
1014 struct wmi_rx_meta_v2 *meta;
1015 struct wmi_data_hdr *dhdr;
1016 int min_hdr_len;
1017 u8 meta_type, dot11_hdr = 0;
1018 int status = packet->status;
1019 enum htc_endpoint_id ept = packet->endpoint;
1020 bool is_amsdu, prev_ps, ps_state = false;
1021 struct ath6kl_sta *conn = NULL;
1022 struct sk_buff *skb1 = NULL;
1023 struct ethhdr *datap = NULL;
1024 u16 seq_no, offset;
1025 u8 tid;
1026
1027 ath6kl_dbg(ATH6KL_DBG_WLAN_RX,
1028 "%s: ar=0x%p eid=%d, skb=0x%p, data=0x%p, len=0x%x status:%d",
1029 __func__, ar, ept, skb, packet->buf,
1030 packet->act_len, status);
1031
1032 if (status || !(skb->data + HTC_HDR_LENGTH)) {
1033 ar->net_stats.rx_errors++;
1034 dev_kfree_skb(skb);
1035 return;
1036 }
1037
1038 /*
1039 * Take lock to protect buffer counts and adaptive power throughput
1040 * state.
1041 */
1042 spin_lock_bh(&ar->lock);
1043
1044 ar->net_stats.rx_packets++;
1045 ar->net_stats.rx_bytes += packet->act_len;
1046
1047 skb_put(skb, packet->act_len + HTC_HDR_LENGTH);
1048 skb_pull(skb, HTC_HDR_LENGTH);
1049
1050 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, __func__, skb->data, skb->len);
1051
1052 spin_unlock_bh(&ar->lock);
1053
1054 skb->dev = ar->net_dev;
1055
1056 if (!test_bit(WMI_ENABLED, &ar->flag)) {
1057 if (EPPING_ALIGNMENT_PAD > 0)
1058 skb_pull(skb, EPPING_ALIGNMENT_PAD);
1059 ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
1060 return;
1061 }
1062
1063 if (ept == ar->ctrl_ep) {
1064 ath6kl_wmi_control_rx(ar->wmi, skb);
1065 return;
1066 }
1067
1068 min_hdr_len = sizeof(struct ethhdr);
1069 min_hdr_len += sizeof(struct wmi_data_hdr) +
1070 sizeof(struct ath6kl_llc_snap_hdr);
1071
1072 dhdr = (struct wmi_data_hdr *) skb->data;
1073
1074 /*
1075 * In the case of AP mode we may receive NULL data frames
1076 * that do not have LLC hdr. They are 16 bytes in size.
1077 * Allow these frames in the AP mode.
1078 */
1079 if (ar->nw_type != AP_NETWORK &&
1080 ((packet->act_len < min_hdr_len) ||
1081 (packet->act_len > WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH))) {
1082 ath6kl_info("frame len is too short or too long\n");
1083 ar->net_stats.rx_errors++;
1084 ar->net_stats.rx_length_errors++;
1085 dev_kfree_skb(skb);
1086 return;
1087 }
1088
1089 /* Get the Power save state of the STA */
1090 if (ar->nw_type == AP_NETWORK) {
1091 meta_type = wmi_data_hdr_get_meta(dhdr);
1092
1093 ps_state = !!((dhdr->info >> WMI_DATA_HDR_PS_SHIFT) &
1094 WMI_DATA_HDR_PS_MASK);
1095
1096 offset = sizeof(struct wmi_data_hdr);
1097
1098 switch (meta_type) {
1099 case 0:
1100 break;
1101 case WMI_META_VERSION_1:
1102 offset += sizeof(struct wmi_rx_meta_v1);
1103 break;
1104 case WMI_META_VERSION_2:
1105 offset += sizeof(struct wmi_rx_meta_v2);
1106 break;
1107 default:
1108 break;
1109 }
1110
1111 datap = (struct ethhdr *) (skb->data + offset);
1112 conn = ath6kl_find_sta(ar, datap->h_source);
1113
1114 if (!conn) {
1115 dev_kfree_skb(skb);
1116 return;
1117 }
1118
1119 /*
1120 * If there is a change in PS state of the STA,
1121 * take appropriate steps:
1122 *
1123 * 1. If Sleep-->Awake, flush the psq for the STA
1124 * Clear the PVB for the STA.
1125 * 2. If Awake-->Sleep, Starting queueing frames
1126 * the STA.
1127 */
1128 prev_ps = !!(conn->sta_flags & STA_PS_SLEEP);
1129
1130 if (ps_state)
1131 conn->sta_flags |= STA_PS_SLEEP;
1132 else
1133 conn->sta_flags &= ~STA_PS_SLEEP;
1134
1135 if (prev_ps ^ !!(conn->sta_flags & STA_PS_SLEEP)) {
1136 if (!(conn->sta_flags & STA_PS_SLEEP)) {
1137 struct sk_buff *skbuff = NULL;
1138
1139 spin_lock_bh(&conn->psq_lock);
1140 while ((skbuff = skb_dequeue(&conn->psq))
1141 != NULL) {
1142 spin_unlock_bh(&conn->psq_lock);
1143 ath6kl_data_tx(skbuff, ar->net_dev);
1144 spin_lock_bh(&conn->psq_lock);
1145 }
1146 spin_unlock_bh(&conn->psq_lock);
1147 /* Clear the PVB for this STA */
1148 ath6kl_wmi_set_pvb_cmd(ar->wmi, conn->aid, 0);
1149 }
1150 }
1151
1152 /* drop NULL data frames here */
1153 if ((packet->act_len < min_hdr_len) ||
1154 (packet->act_len >
1155 WMI_MAX_AMSDU_RX_DATA_FRAME_LENGTH)) {
1156 dev_kfree_skb(skb);
1157 return;
1158 }
1159 }
1160
1161 is_amsdu = wmi_data_hdr_is_amsdu(dhdr) ? true : false;
1162 tid = wmi_data_hdr_get_up(dhdr);
1163 seq_no = wmi_data_hdr_get_seqno(dhdr);
1164 meta_type = wmi_data_hdr_get_meta(dhdr);
1165 dot11_hdr = wmi_data_hdr_get_dot11(dhdr);
1166
1167 ath6kl_wmi_data_hdr_remove(ar->wmi, skb);
1168
1169 switch (meta_type) {
1170 case WMI_META_VERSION_1:
1171 skb_pull(skb, sizeof(struct wmi_rx_meta_v1));
1172 break;
1173 case WMI_META_VERSION_2:
1174 meta = (struct wmi_rx_meta_v2 *) skb->data;
1175 if (meta->csum_flags & 0x1) {
1176 skb->ip_summed = CHECKSUM_COMPLETE;
1177 skb->csum = (__force __wsum) meta->csum;
1178 }
1179 skb_pull(skb, sizeof(struct wmi_rx_meta_v2));
1180 break;
1181 default:
1182 break;
1183 }
1184
1185 if (dot11_hdr)
1186 status = ath6kl_wmi_dot11_hdr_remove(ar->wmi, skb);
1187 else if (!is_amsdu)
1188 status = ath6kl_wmi_dot3_2_dix(skb);
1189
1190 if (status) {
1191 /*
1192 * Drop frames that could not be processed (lack of
1193 * memory, etc.)
1194 */
1195 dev_kfree_skb(skb);
1196 return;
1197 }
1198
1199 if (!(ar->net_dev->flags & IFF_UP)) {
1200 dev_kfree_skb(skb);
1201 return;
1202 }
1203
1204 if (ar->nw_type == AP_NETWORK) {
1205 datap = (struct ethhdr *) skb->data;
1206 if (is_multicast_ether_addr(datap->h_dest))
1207 /*
1208 * Bcast/Mcast frames should be sent to the
1209 * OS stack as well as on the air.
1210 */
1211 skb1 = skb_copy(skb, GFP_ATOMIC);
1212 else {
1213 /*
1214 * Search for a connected STA with dstMac
1215 * as the Mac address. If found send the
1216 * frame to it on the air else send the
1217 * frame up the stack.
1218 */
1219 struct ath6kl_sta *conn = NULL;
1220 conn = ath6kl_find_sta(ar, datap->h_dest);
1221
1222 if (conn && ar->intra_bss) {
1223 skb1 = skb;
1224 skb = NULL;
1225 } else if (conn && !ar->intra_bss) {
1226 dev_kfree_skb(skb);
1227 skb = NULL;
1228 }
1229 }
1230 if (skb1)
1231 ath6kl_data_tx(skb1, ar->net_dev);
1232 }
1233
1234 if (!aggr_process_recv_frm(ar->aggr_cntxt, tid, seq_no,
1235 is_amsdu, skb))
1236 ath6kl_deliver_frames_to_nw_stack(ar->net_dev, skb);
1237}
1238
1239static void aggr_timeout(unsigned long arg)
1240{
1241 u8 i, j;
1242 struct aggr_info *p_aggr = (struct aggr_info *) arg;
1243 struct rxtid *rxtid;
1244 struct rxtid_stats *stats;
1245
1246 for (i = 0; i < NUM_OF_TIDS; i++) {
1247 rxtid = &p_aggr->rx_tid[i];
1248 stats = &p_aggr->stat[i];
1249
1250 if (!rxtid->aggr || !rxtid->timer_mon || rxtid->progress)
1251 continue;
1252
1253 /*
1254 * FIXME: these timeouts happen quite fruently, something
1255 * line once within 60 seconds. Investigate why.
1256 */
1257 stats->num_timeouts++;
1258 ath6kl_dbg(ATH6KL_DBG_AGGR,
1259 "aggr timeout (st %d end %d)\n",
1260 rxtid->seq_next,
1261 ((rxtid->seq_next + rxtid->hold_q_sz-1) &
1262 ATH6KL_MAX_SEQ_NO));
1263 aggr_deque_frms(p_aggr, i, 0, 0);
1264 }
1265
1266 p_aggr->timer_scheduled = false;
1267
1268 for (i = 0; i < NUM_OF_TIDS; i++) {
1269 rxtid = &p_aggr->rx_tid[i];
1270
1271 if (rxtid->aggr && rxtid->hold_q) {
1272 for (j = 0; j < rxtid->hold_q_sz; j++) {
1273 if (rxtid->hold_q[j].skb) {
1274 p_aggr->timer_scheduled = true;
1275 rxtid->timer_mon = true;
1276 rxtid->progress = false;
1277 break;
1278 }
1279 }
1280
1281 if (j >= rxtid->hold_q_sz)
1282 rxtid->timer_mon = false;
1283 }
1284 }
1285
1286 if (p_aggr->timer_scheduled)
1287 mod_timer(&p_aggr->timer,
1288 jiffies + msecs_to_jiffies(AGGR_RX_TIMEOUT));
1289}
1290
1291static void aggr_delete_tid_state(struct aggr_info *p_aggr, u8 tid)
1292{
1293 struct rxtid *rxtid;
1294 struct rxtid_stats *stats;
1295
1296 if (!p_aggr || tid >= NUM_OF_TIDS)
1297 return;
1298
1299 rxtid = &p_aggr->rx_tid[tid];
1300 stats = &p_aggr->stat[tid];
1301
1302 if (rxtid->aggr)
1303 aggr_deque_frms(p_aggr, tid, 0, 0);
1304
1305 rxtid->aggr = false;
1306 rxtid->progress = false;
1307 rxtid->timer_mon = false;
1308 rxtid->win_sz = 0;
1309 rxtid->seq_next = 0;
1310 rxtid->hold_q_sz = 0;
1311
1312 kfree(rxtid->hold_q);
1313 rxtid->hold_q = NULL;
1314
1315 memset(stats, 0, sizeof(struct rxtid_stats));
1316}
1317
1318void aggr_recv_addba_req_evt(struct ath6kl *ar, u8 tid, u16 seq_no, u8 win_sz)
1319{
1320 struct aggr_info *p_aggr = ar->aggr_cntxt;
1321 struct rxtid *rxtid;
1322 struct rxtid_stats *stats;
1323 u16 hold_q_size;
1324
1325 if (!p_aggr)
1326 return;
1327
1328 rxtid = &p_aggr->rx_tid[tid];
1329 stats = &p_aggr->stat[tid];
1330
1331 if (win_sz < AGGR_WIN_SZ_MIN || win_sz > AGGR_WIN_SZ_MAX)
1332 ath6kl_dbg(ATH6KL_DBG_WLAN_RX, "%s: win_sz %d, tid %d\n",
1333 __func__, win_sz, tid);
1334
1335 if (rxtid->aggr)
1336 aggr_delete_tid_state(p_aggr, tid);
1337
1338 rxtid->seq_next = seq_no;
1339 hold_q_size = TID_WINDOW_SZ(win_sz) * sizeof(struct skb_hold_q);
1340 rxtid->hold_q = kzalloc(hold_q_size, GFP_KERNEL);
1341 if (!rxtid->hold_q)
1342 return;
1343
1344 rxtid->win_sz = win_sz;
1345 rxtid->hold_q_sz = TID_WINDOW_SZ(win_sz);
1346 if (!skb_queue_empty(&rxtid->q))
1347 return;
1348
1349 rxtid->aggr = true;
1350}
1351
1352struct aggr_info *aggr_init(struct net_device *dev)
1353{
1354 struct aggr_info *p_aggr = NULL;
1355 struct rxtid *rxtid;
1356 u8 i;
1357
1358 p_aggr = kzalloc(sizeof(struct aggr_info), GFP_KERNEL);
1359 if (!p_aggr) {
1360 ath6kl_err("failed to alloc memory for aggr_node\n");
1361 return NULL;
1362 }
1363
1364 p_aggr->aggr_sz = AGGR_SZ_DEFAULT;
1365 p_aggr->dev = dev;
1366 init_timer(&p_aggr->timer);
1367 p_aggr->timer.function = aggr_timeout;
1368 p_aggr->timer.data = (unsigned long) p_aggr;
1369
1370 p_aggr->timer_scheduled = false;
1371 skb_queue_head_init(&p_aggr->free_q);
1372
1373 ath6kl_alloc_netbufs(&p_aggr->free_q, AGGR_NUM_OF_FREE_NETBUFS);
1374
1375 for (i = 0; i < NUM_OF_TIDS; i++) {
1376 rxtid = &p_aggr->rx_tid[i];
1377 rxtid->aggr = false;
1378 rxtid->progress = false;
1379 rxtid->timer_mon = false;
1380 skb_queue_head_init(&rxtid->q);
1381 spin_lock_init(&rxtid->lock);
1382 }
1383
1384 return p_aggr;
1385}
1386
1387void aggr_recv_delba_req_evt(struct ath6kl *ar, u8 tid)
1388{
1389 struct aggr_info *p_aggr = ar->aggr_cntxt;
1390 struct rxtid *rxtid;
1391
1392 if (!p_aggr)
1393 return;
1394
1395 rxtid = &p_aggr->rx_tid[tid];
1396
1397 if (rxtid->aggr)
1398 aggr_delete_tid_state(p_aggr, tid);
1399}
1400
1401void aggr_reset_state(struct aggr_info *aggr_info)
1402{
1403 u8 tid;
1404
1405 for (tid = 0; tid < NUM_OF_TIDS; tid++)
1406 aggr_delete_tid_state(aggr_info, tid);
1407}
1408
1409/* clean up our amsdu buffer list */
1410void ath6kl_cleanup_amsdu_rxbufs(struct ath6kl *ar)
1411{
1412 struct htc_packet *packet, *tmp_pkt;
1413
1414 spin_lock_bh(&ar->lock);
1415 if (list_empty(&ar->amsdu_rx_buffer_queue)) {
1416 spin_unlock_bh(&ar->lock);
1417 return;
1418 }
1419
1420 list_for_each_entry_safe(packet, tmp_pkt, &ar->amsdu_rx_buffer_queue,
1421 list) {
1422 list_del(&packet->list);
1423 spin_unlock_bh(&ar->lock);
1424 dev_kfree_skb(packet->pkt_cntxt);
1425 spin_lock_bh(&ar->lock);
1426 }
1427
1428 spin_unlock_bh(&ar->lock);
1429}
1430
1431void aggr_module_destroy(struct aggr_info *aggr_info)
1432{
1433 struct rxtid *rxtid;
1434 u8 i, k;
1435
1436 if (!aggr_info)
1437 return;
1438
1439 if (aggr_info->timer_scheduled) {
1440 del_timer(&aggr_info->timer);
1441 aggr_info->timer_scheduled = false;
1442 }
1443
1444 for (i = 0; i < NUM_OF_TIDS; i++) {
1445 rxtid = &aggr_info->rx_tid[i];
1446 if (rxtid->hold_q) {
1447 for (k = 0; k < rxtid->hold_q_sz; k++)
1448 dev_kfree_skb(rxtid->hold_q[k].skb);
1449 kfree(rxtid->hold_q);
1450 }
1451
1452 skb_queue_purge(&rxtid->q);
1453 }
1454
1455 skb_queue_purge(&aggr_info->free_q);
1456 kfree(aggr_info);
1457}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.c b/drivers/net/wireless/ath/ath6kl/wmi.c
new file mode 100644
index 000000000000..f5aa33dd4c42
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/wmi.c
@@ -0,0 +1,2743 @@
1/*
2 * Copyright (c) 2004-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <linux/ip.h>
18#include "core.h"
19#include "debug.h"
20
21static int ath6kl_wmi_sync_point(struct wmi *wmi);
22
23static const s32 wmi_rate_tbl[][2] = {
24 /* {W/O SGI, with SGI} */
25 {1000, 1000},
26 {2000, 2000},
27 {5500, 5500},
28 {11000, 11000},
29 {6000, 6000},
30 {9000, 9000},
31 {12000, 12000},
32 {18000, 18000},
33 {24000, 24000},
34 {36000, 36000},
35 {48000, 48000},
36 {54000, 54000},
37 {6500, 7200},
38 {13000, 14400},
39 {19500, 21700},
40 {26000, 28900},
41 {39000, 43300},
42 {52000, 57800},
43 {58500, 65000},
44 {65000, 72200},
45 {13500, 15000},
46 {27000, 30000},
47 {40500, 45000},
48 {54000, 60000},
49 {81000, 90000},
50 {108000, 120000},
51 {121500, 135000},
52 {135000, 150000},
53 {0, 0}
54};
55
56/* 802.1d to AC mapping. Refer pg 57 of WMM-test-plan-v1.2 */
57static const u8 up_to_ac[] = {
58 WMM_AC_BE,
59 WMM_AC_BK,
60 WMM_AC_BK,
61 WMM_AC_BE,
62 WMM_AC_VI,
63 WMM_AC_VI,
64 WMM_AC_VO,
65 WMM_AC_VO,
66};
67
68void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id)
69{
70 if (WARN_ON(ep_id == ENDPOINT_UNUSED || ep_id >= ENDPOINT_MAX))
71 return;
72
73 wmi->ep_id = ep_id;
74}
75
76enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi)
77{
78 return wmi->ep_id;
79}
80
81/* Performs DIX to 802.3 encapsulation for transmit packets.
82 * Assumes the entire DIX header is contigous and that there is
83 * enough room in the buffer for a 802.3 mac header and LLC+SNAP headers.
84 */
85int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb)
86{
87 struct ath6kl_llc_snap_hdr *llc_hdr;
88 struct ethhdr *eth_hdr;
89 size_t new_len;
90 __be16 type;
91 u8 *datap;
92 u16 size;
93
94 if (WARN_ON(skb == NULL))
95 return -EINVAL;
96
97 size = sizeof(struct ath6kl_llc_snap_hdr) + sizeof(struct wmi_data_hdr);
98 if (skb_headroom(skb) < size)
99 return -ENOMEM;
100
101 eth_hdr = (struct ethhdr *) skb->data;
102 type = eth_hdr->h_proto;
103
104 if (!is_ethertype(be16_to_cpu(type))) {
105 ath6kl_dbg(ATH6KL_DBG_WMI,
106 "%s: pkt is already in 802.3 format\n", __func__);
107 return 0;
108 }
109
110 new_len = skb->len - sizeof(*eth_hdr) + sizeof(*llc_hdr);
111
112 skb_push(skb, sizeof(struct ath6kl_llc_snap_hdr));
113 datap = skb->data;
114
115 eth_hdr->h_proto = cpu_to_be16(new_len);
116
117 memcpy(datap, eth_hdr, sizeof(*eth_hdr));
118
119 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap + sizeof(*eth_hdr));
120 llc_hdr->dsap = 0xAA;
121 llc_hdr->ssap = 0xAA;
122 llc_hdr->cntl = 0x03;
123 llc_hdr->org_code[0] = 0x0;
124 llc_hdr->org_code[1] = 0x0;
125 llc_hdr->org_code[2] = 0x0;
126 llc_hdr->eth_type = type;
127
128 return 0;
129}
130
131static int ath6kl_wmi_meta_add(struct wmi *wmi, struct sk_buff *skb,
132 u8 *version, void *tx_meta_info)
133{
134 struct wmi_tx_meta_v1 *v1;
135 struct wmi_tx_meta_v2 *v2;
136
137 if (WARN_ON(skb == NULL || version == NULL))
138 return -EINVAL;
139
140 switch (*version) {
141 case WMI_META_VERSION_1:
142 skb_push(skb, WMI_MAX_TX_META_SZ);
143 v1 = (struct wmi_tx_meta_v1 *) skb->data;
144 v1->pkt_id = 0;
145 v1->rate_plcy_id = 0;
146 *version = WMI_META_VERSION_1;
147 break;
148 case WMI_META_VERSION_2:
149 skb_push(skb, WMI_MAX_TX_META_SZ);
150 v2 = (struct wmi_tx_meta_v2 *) skb->data;
151 memcpy(v2, (struct wmi_tx_meta_v2 *) tx_meta_info,
152 sizeof(struct wmi_tx_meta_v2));
153 break;
154 }
155
156 return 0;
157}
158
159int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
160 u8 msg_type, bool more_data,
161 enum wmi_data_hdr_data_type data_type,
162 u8 meta_ver, void *tx_meta_info)
163{
164 struct wmi_data_hdr *data_hdr;
165 int ret;
166
167 if (WARN_ON(skb == NULL))
168 return -EINVAL;
169
170 ret = ath6kl_wmi_meta_add(wmi, skb, &meta_ver, tx_meta_info);
171 if (ret)
172 return ret;
173
174 skb_push(skb, sizeof(struct wmi_data_hdr));
175
176 data_hdr = (struct wmi_data_hdr *)skb->data;
177 memset(data_hdr, 0, sizeof(struct wmi_data_hdr));
178
179 data_hdr->info = msg_type << WMI_DATA_HDR_MSG_TYPE_SHIFT;
180 data_hdr->info |= data_type << WMI_DATA_HDR_DATA_TYPE_SHIFT;
181
182 if (more_data)
183 data_hdr->info |=
184 WMI_DATA_HDR_MORE_MASK << WMI_DATA_HDR_MORE_SHIFT;
185
186 data_hdr->info2 = cpu_to_le16(meta_ver << WMI_DATA_HDR_META_SHIFT);
187 data_hdr->info3 = 0;
188
189 return 0;
190}
191
192static u8 ath6kl_wmi_determine_user_priority(u8 *pkt, u32 layer2_pri)
193{
194 struct iphdr *ip_hdr = (struct iphdr *) pkt;
195 u8 ip_pri;
196
197 /*
198 * Determine IPTOS priority
199 *
200 * IP-TOS - 8bits
201 * : DSCP(6-bits) ECN(2-bits)
202 * : DSCP - P2 P1 P0 X X X
203 * where (P2 P1 P0) form 802.1D
204 */
205 ip_pri = ip_hdr->tos >> 5;
206 ip_pri &= 0x7;
207
208 if ((layer2_pri & 0x7) > ip_pri)
209 return (u8) layer2_pri & 0x7;
210 else
211 return ip_pri;
212}
213
214int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
215 u32 layer2_priority, bool wmm_enabled,
216 u8 *ac)
217{
218 struct wmi_data_hdr *data_hdr;
219 struct ath6kl_llc_snap_hdr *llc_hdr;
220 struct wmi_create_pstream_cmd cmd;
221 u32 meta_size, hdr_size;
222 u16 ip_type = IP_ETHERTYPE;
223 u8 stream_exist, usr_pri;
224 u8 traffic_class = WMM_AC_BE;
225 u8 *datap;
226
227 if (WARN_ON(skb == NULL))
228 return -EINVAL;
229
230 datap = skb->data;
231 data_hdr = (struct wmi_data_hdr *) datap;
232
233 meta_size = ((le16_to_cpu(data_hdr->info2) >> WMI_DATA_HDR_META_SHIFT) &
234 WMI_DATA_HDR_META_MASK) ? WMI_MAX_TX_META_SZ : 0;
235
236 if (!wmm_enabled) {
237 /* If WMM is disabled all traffic goes as BE traffic */
238 usr_pri = 0;
239 } else {
240 hdr_size = sizeof(struct ethhdr);
241
242 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap +
243 sizeof(struct
244 wmi_data_hdr) +
245 meta_size + hdr_size);
246
247 if (llc_hdr->eth_type == htons(ip_type)) {
248 /*
249 * Extract the endpoint info from the TOS field
250 * in the IP header.
251 */
252 usr_pri =
253 ath6kl_wmi_determine_user_priority(((u8 *) llc_hdr) +
254 sizeof(struct ath6kl_llc_snap_hdr),
255 layer2_priority);
256 } else
257 usr_pri = layer2_priority & 0x7;
258 }
259
260 /* workaround for WMM S5 */
261 if ((wmi->traffic_class == WMM_AC_VI) &&
262 ((usr_pri == 5) || (usr_pri == 4)))
263 usr_pri = 1;
264
265 /* Convert user priority to traffic class */
266 traffic_class = up_to_ac[usr_pri & 0x7];
267
268 wmi_data_hdr_set_up(data_hdr, usr_pri);
269
270 spin_lock_bh(&wmi->lock);
271 stream_exist = wmi->fat_pipe_exist;
272 spin_unlock_bh(&wmi->lock);
273
274 if (!(stream_exist & (1 << traffic_class))) {
275 memset(&cmd, 0, sizeof(cmd));
276 cmd.traffic_class = traffic_class;
277 cmd.user_pri = usr_pri;
278 cmd.inactivity_int =
279 cpu_to_le32(WMI_IMPLICIT_PSTREAM_INACTIVITY_INT);
280 /* Implicit streams are created with TSID 0xFF */
281 cmd.tsid = WMI_IMPLICIT_PSTREAM;
282 ath6kl_wmi_create_pstream_cmd(wmi, &cmd);
283 }
284
285 *ac = traffic_class;
286
287 return 0;
288}
289
290int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
291{
292 struct ieee80211_hdr_3addr *pwh, wh;
293 struct ath6kl_llc_snap_hdr *llc_hdr;
294 struct ethhdr eth_hdr;
295 u32 hdr_size;
296 u8 *datap;
297 __le16 sub_type;
298
299 if (WARN_ON(skb == NULL))
300 return -EINVAL;
301
302 datap = skb->data;
303 pwh = (struct ieee80211_hdr_3addr *) datap;
304
305 sub_type = pwh->frame_control & cpu_to_le16(IEEE80211_FCTL_STYPE);
306
307 memcpy((u8 *) &wh, datap, sizeof(struct ieee80211_hdr_3addr));
308
309 /* Strip off the 802.11 header */
310 if (sub_type == cpu_to_le16(IEEE80211_STYPE_QOS_DATA)) {
311 hdr_size = roundup(sizeof(struct ieee80211_qos_hdr),
312 sizeof(u32));
313 skb_pull(skb, hdr_size);
314 } else if (sub_type == cpu_to_le16(IEEE80211_STYPE_DATA))
315 skb_pull(skb, sizeof(struct ieee80211_hdr_3addr));
316
317 datap = skb->data;
318 llc_hdr = (struct ath6kl_llc_snap_hdr *)(datap);
319
320 memset(&eth_hdr, 0, sizeof(eth_hdr));
321 eth_hdr.h_proto = llc_hdr->eth_type;
322
323 switch ((le16_to_cpu(wh.frame_control)) &
324 (IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS)) {
325 case 0:
326 memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
327 memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
328 break;
329 case IEEE80211_FCTL_TODS:
330 memcpy(eth_hdr.h_dest, wh.addr3, ETH_ALEN);
331 memcpy(eth_hdr.h_source, wh.addr2, ETH_ALEN);
332 break;
333 case IEEE80211_FCTL_FROMDS:
334 memcpy(eth_hdr.h_dest, wh.addr1, ETH_ALEN);
335 memcpy(eth_hdr.h_source, wh.addr3, ETH_ALEN);
336 break;
337 case IEEE80211_FCTL_FROMDS | IEEE80211_FCTL_TODS:
338 break;
339 }
340
341 skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
342 skb_push(skb, sizeof(eth_hdr));
343
344 datap = skb->data;
345
346 memcpy(datap, &eth_hdr, sizeof(eth_hdr));
347
348 return 0;
349}
350
351/*
352 * Performs 802.3 to DIX encapsulation for received packets.
353 * Assumes the entire 802.3 header is contigous.
354 */
355int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb)
356{
357 struct ath6kl_llc_snap_hdr *llc_hdr;
358 struct ethhdr eth_hdr;
359 u8 *datap;
360
361 if (WARN_ON(skb == NULL))
362 return -EINVAL;
363
364 datap = skb->data;
365
366 memcpy(&eth_hdr, datap, sizeof(eth_hdr));
367
368 llc_hdr = (struct ath6kl_llc_snap_hdr *) (datap + sizeof(eth_hdr));
369 eth_hdr.h_proto = llc_hdr->eth_type;
370
371 skb_pull(skb, sizeof(struct ath6kl_llc_snap_hdr));
372 datap = skb->data;
373
374 memcpy(datap, &eth_hdr, sizeof(eth_hdr));
375
376 return 0;
377}
378
379int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb)
380{
381 if (WARN_ON(skb == NULL))
382 return -EINVAL;
383
384 skb_pull(skb, sizeof(struct wmi_data_hdr));
385
386 return 0;
387}
388
389static void ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(struct sk_buff *skb,
390 u8 *datap)
391{
392 struct wmi_bss_info_hdr2 bih2;
393 struct wmi_bss_info_hdr *bih;
394
395 memcpy(&bih2, datap, sizeof(struct wmi_bss_info_hdr2));
396
397 skb_push(skb, 4);
398 bih = (struct wmi_bss_info_hdr *) skb->data;
399
400 bih->ch = bih2.ch;
401 bih->frame_type = bih2.frame_type;
402 bih->snr = bih2.snr;
403 bih->rssi = a_cpu_to_sle16(bih2.snr - 95);
404 bih->ie_mask = cpu_to_le32(le16_to_cpu(bih2.ie_mask));
405 memcpy(bih->bssid, bih2.bssid, ETH_ALEN);
406}
407
408static int ath6kl_wmi_tx_complete_event_rx(u8 *datap, int len)
409{
410 struct tx_complete_msg_v1 *msg_v1;
411 struct wmi_tx_complete_event *evt;
412 int index;
413 u16 size;
414
415 evt = (struct wmi_tx_complete_event *) datap;
416
417 ath6kl_dbg(ATH6KL_DBG_WMI, "comp: %d %d %d\n",
418 evt->num_msg, evt->msg_len, evt->msg_type);
419
420 if (!AR_DBG_LVL_CHECK(ATH6KL_DBG_WMI))
421 return 0;
422
423 for (index = 0; index < evt->num_msg; index++) {
424 size = sizeof(struct wmi_tx_complete_event) +
425 (index * sizeof(struct tx_complete_msg_v1));
426 msg_v1 = (struct tx_complete_msg_v1 *)(datap + size);
427
428 ath6kl_dbg(ATH6KL_DBG_WMI, "msg: %d %d %d %d\n",
429 msg_v1->status, msg_v1->pkt_id,
430 msg_v1->rate_idx, msg_v1->ack_failures);
431 }
432
433 return 0;
434}
435
436static inline struct sk_buff *ath6kl_wmi_get_new_buf(u32 size)
437{
438 struct sk_buff *skb;
439
440 skb = ath6kl_buf_alloc(size);
441 if (!skb)
442 return NULL;
443
444 skb_put(skb, size);
445 if (size)
446 memset(skb->data, 0, size);
447
448 return skb;
449}
450
451/* Send a "simple" wmi command -- one with no arguments */
452static int ath6kl_wmi_simple_cmd(struct wmi *wmi, enum wmi_cmd_id cmd_id)
453{
454 struct sk_buff *skb;
455 int ret;
456
457 skb = ath6kl_wmi_get_new_buf(0);
458 if (!skb)
459 return -ENOMEM;
460
461 ret = ath6kl_wmi_cmd_send(wmi, skb, cmd_id, NO_SYNC_WMIFLAG);
462
463 return ret;
464}
465
466static int ath6kl_wmi_ready_event_rx(struct wmi *wmi, u8 *datap, int len)
467{
468 struct wmi_ready_event_2 *ev = (struct wmi_ready_event_2 *) datap;
469
470 if (len < sizeof(struct wmi_ready_event_2))
471 return -EINVAL;
472
473 wmi->ready = true;
474 ath6kl_ready_event(wmi->parent_dev, ev->mac_addr,
475 le32_to_cpu(ev->sw_version),
476 le32_to_cpu(ev->abi_version));
477
478 return 0;
479}
480
481static int ath6kl_wmi_connect_event_rx(struct wmi *wmi, u8 *datap, int len)
482{
483 struct wmi_connect_event *ev;
484 u8 *pie, *peie;
485
486 if (len < sizeof(struct wmi_connect_event))
487 return -EINVAL;
488
489 ev = (struct wmi_connect_event *) datap;
490
491 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: freq %d bssid %pM\n",
492 __func__, ev->ch, ev->bssid);
493
494 /* Start of assoc rsp IEs */
495 pie = ev->assoc_info + ev->beacon_ie_len +
496 ev->assoc_req_len + (sizeof(u16) * 3); /* capinfo, status, aid */
497
498 /* End of assoc rsp IEs */
499 peie = ev->assoc_info + ev->beacon_ie_len + ev->assoc_req_len +
500 ev->assoc_resp_len;
501
502 while (pie < peie) {
503 switch (*pie) {
504 case WLAN_EID_VENDOR_SPECIFIC:
505 if (pie[1] > 3 && pie[2] == 0x00 && pie[3] == 0x50 &&
506 pie[4] == 0xf2 && pie[5] == WMM_OUI_TYPE) {
507 /* WMM OUT (00:50:F2) */
508 if (pie[1] > 5
509 && pie[6] == WMM_PARAM_OUI_SUBTYPE)
510 wmi->is_wmm_enabled = true;
511 }
512 break;
513 }
514
515 if (wmi->is_wmm_enabled)
516 break;
517
518 pie += pie[1] + 2;
519 }
520
521 ath6kl_connect_event(wmi->parent_dev, le16_to_cpu(ev->ch), ev->bssid,
522 le16_to_cpu(ev->listen_intvl),
523 le16_to_cpu(ev->beacon_intvl),
524 le32_to_cpu(ev->nw_type),
525 ev->beacon_ie_len, ev->assoc_req_len,
526 ev->assoc_resp_len, ev->assoc_info);
527
528 return 0;
529}
530
531static int ath6kl_wmi_disconnect_event_rx(struct wmi *wmi, u8 *datap, int len)
532{
533 struct wmi_disconnect_event *ev;
534 wmi->traffic_class = 100;
535
536 if (len < sizeof(struct wmi_disconnect_event))
537 return -EINVAL;
538
539 ev = (struct wmi_disconnect_event *) datap;
540
541 wmi->is_wmm_enabled = false;
542 wmi->pair_crypto_type = NONE_CRYPT;
543 wmi->grp_crypto_type = NONE_CRYPT;
544
545 ath6kl_disconnect_event(wmi->parent_dev, ev->disconn_reason,
546 ev->bssid, ev->assoc_resp_len, ev->assoc_info,
547 le16_to_cpu(ev->proto_reason_status));
548
549 return 0;
550}
551
552static int ath6kl_wmi_peer_node_event_rx(struct wmi *wmi, u8 *datap, int len)
553{
554 struct wmi_peer_node_event *ev;
555
556 if (len < sizeof(struct wmi_peer_node_event))
557 return -EINVAL;
558
559 ev = (struct wmi_peer_node_event *) datap;
560
561 if (ev->event_code == PEER_NODE_JOIN_EVENT)
562 ath6kl_dbg(ATH6KL_DBG_WMI, "joined node with mac addr: %pM\n",
563 ev->peer_mac_addr);
564 else if (ev->event_code == PEER_NODE_LEAVE_EVENT)
565 ath6kl_dbg(ATH6KL_DBG_WMI, "left node with mac addr: %pM\n",
566 ev->peer_mac_addr);
567
568 return 0;
569}
570
571static int ath6kl_wmi_tkip_micerr_event_rx(struct wmi *wmi, u8 *datap, int len)
572{
573 struct wmi_tkip_micerr_event *ev;
574
575 if (len < sizeof(struct wmi_tkip_micerr_event))
576 return -EINVAL;
577
578 ev = (struct wmi_tkip_micerr_event *) datap;
579
580 ath6kl_tkip_micerr_event(wmi->parent_dev, ev->key_id, ev->is_mcast);
581
582 return 0;
583}
584
585static int ath6kl_wlan_parse_beacon(u8 *buf, int frame_len,
586 struct ath6kl_common_ie *cie)
587{
588 u8 *frm, *efrm;
589 u8 elemid_ssid = false;
590
591 frm = buf;
592 efrm = (u8 *) (frm + frame_len);
593
594 /*
595 * beacon/probe response frame format
596 * [8] time stamp
597 * [2] beacon interval
598 * [2] capability information
599 * [tlv] ssid
600 * [tlv] supported rates
601 * [tlv] country information
602 * [tlv] parameter set (FH/DS)
603 * [tlv] erp information
604 * [tlv] extended supported rates
605 * [tlv] WMM
606 * [tlv] WPA or RSN
607 * [tlv] Atheros Advanced Capabilities
608 */
609 if ((efrm - frm) < 12)
610 return -EINVAL;
611
612 memset(cie, 0, sizeof(*cie));
613
614 cie->ie_tstamp = frm;
615 frm += 8;
616 cie->ie_beaconInt = *(u16 *) frm;
617 frm += 2;
618 cie->ie_capInfo = *(u16 *) frm;
619 frm += 2;
620 cie->ie_chan = 0;
621
622 while (frm < efrm) {
623 switch (*frm) {
624 case WLAN_EID_SSID:
625 if (!elemid_ssid) {
626 cie->ie_ssid = frm;
627 elemid_ssid = true;
628 }
629 break;
630 case WLAN_EID_SUPP_RATES:
631 cie->ie_rates = frm;
632 break;
633 case WLAN_EID_COUNTRY:
634 cie->ie_country = frm;
635 break;
636 case WLAN_EID_FH_PARAMS:
637 break;
638 case WLAN_EID_DS_PARAMS:
639 cie->ie_chan = frm[2];
640 break;
641 case WLAN_EID_TIM:
642 cie->ie_tim = frm;
643 break;
644 case WLAN_EID_IBSS_PARAMS:
645 break;
646 case WLAN_EID_EXT_SUPP_RATES:
647 cie->ie_xrates = frm;
648 break;
649 case WLAN_EID_ERP_INFO:
650 if (frm[1] != 1)
651 return -EINVAL;
652
653 cie->ie_erp = frm[2];
654 break;
655 case WLAN_EID_RSN:
656 cie->ie_rsn = frm;
657 break;
658 case WLAN_EID_HT_CAPABILITY:
659 cie->ie_htcap = frm;
660 break;
661 case WLAN_EID_HT_INFORMATION:
662 cie->ie_htop = frm;
663 break;
664 case WLAN_EID_VENDOR_SPECIFIC:
665 if (frm[1] > 3 && frm[2] == 0x00 && frm[3] == 0x50 &&
666 frm[4] == 0xf2) {
667 /* OUT Type (00:50:F2) */
668
669 if (frm[5] == WPA_OUI_TYPE) {
670 /* WPA OUT */
671 cie->ie_wpa = frm;
672 } else if (frm[5] == WMM_OUI_TYPE) {
673 /* WMM OUT */
674 cie->ie_wmm = frm;
675 } else if (frm[5] == WSC_OUT_TYPE) {
676 /* WSC OUT */
677 cie->ie_wsc = frm;
678 }
679
680 } else if (frm[1] > 3 && frm[2] == 0x00
681 && frm[3] == 0x03 && frm[4] == 0x7f
682 && frm[5] == ATH_OUI_TYPE) {
683 /* Atheros OUI (00:03:7f) */
684 cie->ie_ath = frm;
685 }
686 break;
687 default:
688 break;
689 }
690 frm += frm[1] + 2;
691 }
692
693 if ((cie->ie_rates == NULL)
694 || (cie->ie_rates[1] > ATH6KL_RATE_MAXSIZE))
695 return -EINVAL;
696
697 if ((cie->ie_ssid == NULL)
698 || (cie->ie_ssid[1] > IEEE80211_MAX_SSID_LEN))
699 return -EINVAL;
700
701 return 0;
702}
703
704static int ath6kl_wmi_bssinfo_event_rx(struct wmi *wmi, u8 *datap, int len)
705{
706 struct bss *bss = NULL;
707 struct wmi_bss_info_hdr *bih;
708 u8 cached_ssid_len = 0;
709 u8 cached_ssid[IEEE80211_MAX_SSID_LEN] = { 0 };
710 u8 beacon_ssid_len = 0;
711 u8 *buf, *ie_ssid;
712 u8 *ni_buf;
713 int buf_len;
714
715 int ret;
716
717 if (len <= sizeof(struct wmi_bss_info_hdr))
718 return -EINVAL;
719
720 bih = (struct wmi_bss_info_hdr *) datap;
721 bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid);
722
723 if (a_sle16_to_cpu(bih->rssi) > 0) {
724 if (bss == NULL)
725 return 0;
726 else
727 bih->rssi = a_cpu_to_sle16(bss->ni_rssi);
728 }
729
730 buf = datap + sizeof(struct wmi_bss_info_hdr);
731 len -= sizeof(struct wmi_bss_info_hdr);
732
733 ath6kl_dbg(ATH6KL_DBG_WMI,
734 "bss info evt - ch %u, rssi %02x, bssid \"%pM\"\n",
735 bih->ch, a_sle16_to_cpu(bih->rssi), bih->bssid);
736
737 if (bss != NULL) {
738 /*
739 * Free up the node. We are about to allocate a new node.
740 * In case of hidden AP, beacon will not have ssid,
741 * but a directed probe response will have it,
742 * so cache the probe-resp-ssid if already present.
743 */
744 if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE)) {
745 ie_ssid = bss->ni_cie.ie_ssid;
746 if (ie_ssid && (ie_ssid[1] <= IEEE80211_MAX_SSID_LEN) &&
747 (ie_ssid[2] != 0)) {
748 cached_ssid_len = ie_ssid[1];
749 memcpy(cached_ssid, ie_ssid + 2,
750 cached_ssid_len);
751 }
752 }
753
754 /*
755 * Use the current average rssi of associated AP base on
756 * assumption
757 * 1. Most os with GUI will update RSSI by
758 * ath6kl_wmi_get_stats_cmd() periodically.
759 * 2. ath6kl_wmi_get_stats_cmd(..) will be called when calling
760 * ath6kl_wmi_startscan_cmd(...)
761 * The average value of RSSI give end-user better feeling for
762 * instance value of scan result. It also sync up RSSI info
763 * in GUI between scan result and RSSI signal icon.
764 */
765 if (memcmp(wmi->parent_dev->bssid, bih->bssid, ETH_ALEN) == 0) {
766 bih->rssi = a_cpu_to_sle16(bss->ni_rssi);
767 bih->snr = bss->ni_snr;
768 }
769
770 wlan_node_reclaim(&wmi->parent_dev->scan_table, bss);
771 }
772
773 /*
774 * beacon/probe response frame format
775 * [8] time stamp
776 * [2] beacon interval
777 * [2] capability information
778 * [tlv] ssid
779 */
780 beacon_ssid_len = buf[SSID_IE_LEN_INDEX];
781
782 /*
783 * If ssid is cached for this hidden AP, then change
784 * buffer len accordingly.
785 */
786 if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) &&
787 (cached_ssid_len != 0) &&
788 (beacon_ssid_len == 0 || (cached_ssid_len > beacon_ssid_len &&
789 buf[SSID_IE_LEN_INDEX + 1] == 0))) {
790
791 len += (cached_ssid_len - beacon_ssid_len);
792 }
793
794 bss = wlan_node_alloc(len);
795 if (!bss)
796 return -ENOMEM;
797
798 bss->ni_snr = bih->snr;
799 bss->ni_rssi = a_sle16_to_cpu(bih->rssi);
800
801 if (WARN_ON(!bss->ni_buf))
802 return -EINVAL;
803
804 /*
805 * In case of hidden AP, beacon will not have ssid,
806 * but a directed probe response will have it,
807 * so place the cached-ssid(probe-resp) in the bss info.
808 */
809 if (wmi->is_probe_ssid && (bih->frame_type == BEACON_FTYPE) &&
810 (cached_ssid_len != 0) &&
811 (beacon_ssid_len == 0 || (beacon_ssid_len &&
812 buf[SSID_IE_LEN_INDEX + 1] == 0))) {
813 ni_buf = bss->ni_buf;
814 buf_len = len;
815
816 /*
817 * Copy the first 14 bytes:
818 * time-stamp(8), beacon-interval(2),
819 * cap-info(2), ssid-id(1), ssid-len(1).
820 */
821 memcpy(ni_buf, buf, SSID_IE_LEN_INDEX + 1);
822
823 ni_buf[SSID_IE_LEN_INDEX] = cached_ssid_len;
824 ni_buf += (SSID_IE_LEN_INDEX + 1);
825
826 buf += (SSID_IE_LEN_INDEX + 1);
827 buf_len -= (SSID_IE_LEN_INDEX + 1);
828
829 memcpy(ni_buf, cached_ssid, cached_ssid_len);
830 ni_buf += cached_ssid_len;
831
832 buf += beacon_ssid_len;
833 buf_len -= beacon_ssid_len;
834
835 if (cached_ssid_len > beacon_ssid_len)
836 buf_len -= (cached_ssid_len - beacon_ssid_len);
837
838 memcpy(ni_buf, buf, buf_len);
839 } else
840 memcpy(bss->ni_buf, buf, len);
841
842 bss->ni_framelen = len;
843
844 ret = ath6kl_wlan_parse_beacon(bss->ni_buf, len, &bss->ni_cie);
845 if (ret) {
846 wlan_node_free(bss);
847 return -EINVAL;
848 }
849
850 /*
851 * Update the frequency in ie_chan, overwriting of channel number
852 * which is done in ath6kl_wlan_parse_beacon
853 */
854 bss->ni_cie.ie_chan = le16_to_cpu(bih->ch);
855 wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid);
856
857 return 0;
858}
859
860static int ath6kl_wmi_opt_frame_event_rx(struct wmi *wmi, u8 *datap, int len)
861{
862 struct bss *bss;
863 struct wmi_opt_rx_info_hdr *bih;
864 u8 *buf;
865
866 if (len <= sizeof(struct wmi_opt_rx_info_hdr))
867 return -EINVAL;
868
869 bih = (struct wmi_opt_rx_info_hdr *) datap;
870 buf = datap + sizeof(struct wmi_opt_rx_info_hdr);
871 len -= sizeof(struct wmi_opt_rx_info_hdr);
872
873 ath6kl_dbg(ATH6KL_DBG_WMI, "opt frame event %2.2x:%2.2x\n",
874 bih->bssid[4], bih->bssid[5]);
875
876 bss = wlan_find_node(&wmi->parent_dev->scan_table, bih->bssid);
877 if (bss != NULL) {
878 /* Free up the node. We are about to allocate a new node. */
879 wlan_node_reclaim(&wmi->parent_dev->scan_table, bss);
880 }
881
882 bss = wlan_node_alloc(len);
883 if (!bss)
884 return -ENOMEM;
885
886 bss->ni_snr = bih->snr;
887 bss->ni_cie.ie_chan = le16_to_cpu(bih->ch);
888
889 if (WARN_ON(!bss->ni_buf))
890 return -EINVAL;
891
892 memcpy(bss->ni_buf, buf, len);
893 wlan_setup_node(&wmi->parent_dev->scan_table, bss, bih->bssid);
894
895 return 0;
896}
897
898/* Inactivity timeout of a fatpipe(pstream) at the target */
899static int ath6kl_wmi_pstream_timeout_event_rx(struct wmi *wmi, u8 *datap,
900 int len)
901{
902 struct wmi_pstream_timeout_event *ev;
903
904 if (len < sizeof(struct wmi_pstream_timeout_event))
905 return -EINVAL;
906
907 ev = (struct wmi_pstream_timeout_event *) datap;
908
909 /*
910 * When the pstream (fat pipe == AC) timesout, it means there were
911 * no thinStreams within this pstream & it got implicitly created
912 * due to data flow on this AC. We start the inactivity timer only
913 * for implicitly created pstream. Just reset the host state.
914 */
915 spin_lock_bh(&wmi->lock);
916 wmi->stream_exist_for_ac[ev->traffic_class] = 0;
917 wmi->fat_pipe_exist &= ~(1 << ev->traffic_class);
918 spin_unlock_bh(&wmi->lock);
919
920 /* Indicate inactivity to driver layer for this fatpipe (pstream) */
921 ath6kl_indicate_tx_activity(wmi->parent_dev, ev->traffic_class, false);
922
923 return 0;
924}
925
926static int ath6kl_wmi_bitrate_reply_rx(struct wmi *wmi, u8 *datap, int len)
927{
928 struct wmi_bit_rate_reply *reply;
929 s32 rate;
930 u32 sgi, index;
931
932 if (len < sizeof(struct wmi_bit_rate_reply))
933 return -EINVAL;
934
935 reply = (struct wmi_bit_rate_reply *) datap;
936
937 ath6kl_dbg(ATH6KL_DBG_WMI, "rateindex %d\n", reply->rate_index);
938
939 if (reply->rate_index == (s8) RATE_AUTO) {
940 rate = RATE_AUTO;
941 } else {
942 index = reply->rate_index & 0x7f;
943 sgi = (reply->rate_index & 0x80) ? 1 : 0;
944 rate = wmi_rate_tbl[index][sgi];
945 }
946
947 ath6kl_wakeup_event(wmi->parent_dev);
948
949 return 0;
950}
951
952static int ath6kl_wmi_ratemask_reply_rx(struct wmi *wmi, u8 *datap, int len)
953{
954 if (len < sizeof(struct wmi_fix_rates_reply))
955 return -EINVAL;
956
957 ath6kl_wakeup_event(wmi->parent_dev);
958
959 return 0;
960}
961
962static int ath6kl_wmi_ch_list_reply_rx(struct wmi *wmi, u8 *datap, int len)
963{
964 if (len < sizeof(struct wmi_channel_list_reply))
965 return -EINVAL;
966
967 ath6kl_wakeup_event(wmi->parent_dev);
968
969 return 0;
970}
971
972static int ath6kl_wmi_tx_pwr_reply_rx(struct wmi *wmi, u8 *datap, int len)
973{
974 struct wmi_tx_pwr_reply *reply;
975
976 if (len < sizeof(struct wmi_tx_pwr_reply))
977 return -EINVAL;
978
979 reply = (struct wmi_tx_pwr_reply *) datap;
980 ath6kl_txpwr_rx_evt(wmi->parent_dev, reply->dbM);
981
982 return 0;
983}
984
985static int ath6kl_wmi_keepalive_reply_rx(struct wmi *wmi, u8 *datap, int len)
986{
987 if (len < sizeof(struct wmi_get_keepalive_cmd))
988 return -EINVAL;
989
990 ath6kl_wakeup_event(wmi->parent_dev);
991
992 return 0;
993}
994
995static int ath6kl_wmi_scan_complete_rx(struct wmi *wmi, u8 *datap, int len)
996{
997 struct wmi_scan_complete_event *ev;
998
999 ev = (struct wmi_scan_complete_event *) datap;
1000
1001 if (a_sle32_to_cpu(ev->status) == 0)
1002 wlan_refresh_inactive_nodes(wmi->parent_dev);
1003
1004 ath6kl_scan_complete_evt(wmi->parent_dev, a_sle32_to_cpu(ev->status));
1005 wmi->is_probe_ssid = false;
1006
1007 return 0;
1008}
1009
1010/*
1011 * Target is reporting a programming error. This is for
1012 * developer aid only. Target only checks a few common violations
1013 * and it is responsibility of host to do all error checking.
1014 * Behavior of target after wmi error event is undefined.
1015 * A reset is recommended.
1016 */
1017static int ath6kl_wmi_error_event_rx(struct wmi *wmi, u8 *datap, int len)
1018{
1019 const char *type = "unknown error";
1020 struct wmi_cmd_error_event *ev;
1021 ev = (struct wmi_cmd_error_event *) datap;
1022
1023 switch (ev->err_code) {
1024 case INVALID_PARAM:
1025 type = "invalid parameter";
1026 break;
1027 case ILLEGAL_STATE:
1028 type = "invalid state";
1029 break;
1030 case INTERNAL_ERROR:
1031 type = "internal error";
1032 break;
1033 }
1034
1035 ath6kl_dbg(ATH6KL_DBG_WMI, "programming error, cmd=%d %s\n",
1036 ev->cmd_id, type);
1037
1038 return 0;
1039}
1040
1041static int ath6kl_wmi_stats_event_rx(struct wmi *wmi, u8 *datap, int len)
1042{
1043 ath6kl_tgt_stats_event(wmi->parent_dev, datap, len);
1044
1045 return 0;
1046}
1047
1048static u8 ath6kl_wmi_get_upper_threshold(s16 rssi,
1049 struct sq_threshold_params *sq_thresh,
1050 u32 size)
1051{
1052 u32 index;
1053 u8 threshold = (u8) sq_thresh->upper_threshold[size - 1];
1054
1055 /* The list is already in sorted order. Get the next lower value */
1056 for (index = 0; index < size; index++) {
1057 if (rssi < sq_thresh->upper_threshold[index]) {
1058 threshold = (u8) sq_thresh->upper_threshold[index];
1059 break;
1060 }
1061 }
1062
1063 return threshold;
1064}
1065
1066static u8 ath6kl_wmi_get_lower_threshold(s16 rssi,
1067 struct sq_threshold_params *sq_thresh,
1068 u32 size)
1069{
1070 u32 index;
1071 u8 threshold = (u8) sq_thresh->lower_threshold[size - 1];
1072
1073 /* The list is already in sorted order. Get the next lower value */
1074 for (index = 0; index < size; index++) {
1075 if (rssi > sq_thresh->lower_threshold[index]) {
1076 threshold = (u8) sq_thresh->lower_threshold[index];
1077 break;
1078 }
1079 }
1080
1081 return threshold;
1082}
1083
1084static int ath6kl_wmi_send_rssi_threshold_params(struct wmi *wmi,
1085 struct wmi_rssi_threshold_params_cmd *rssi_cmd)
1086{
1087 struct sk_buff *skb;
1088 struct wmi_rssi_threshold_params_cmd *cmd;
1089
1090 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1091 if (!skb)
1092 return -ENOMEM;
1093
1094 cmd = (struct wmi_rssi_threshold_params_cmd *) skb->data;
1095 memcpy(cmd, rssi_cmd, sizeof(struct wmi_rssi_threshold_params_cmd));
1096
1097 return ath6kl_wmi_cmd_send(wmi, skb, WMI_RSSI_THRESHOLD_PARAMS_CMDID,
1098 NO_SYNC_WMIFLAG);
1099}
1100
1101static int ath6kl_wmi_rssi_threshold_event_rx(struct wmi *wmi, u8 *datap,
1102 int len)
1103{
1104 struct wmi_rssi_threshold_event *reply;
1105 struct wmi_rssi_threshold_params_cmd cmd;
1106 struct sq_threshold_params *sq_thresh;
1107 enum wmi_rssi_threshold_val new_threshold;
1108 u8 upper_rssi_threshold, lower_rssi_threshold;
1109 s16 rssi;
1110 int ret;
1111
1112 if (len < sizeof(struct wmi_rssi_threshold_event))
1113 return -EINVAL;
1114
1115 reply = (struct wmi_rssi_threshold_event *) datap;
1116 new_threshold = (enum wmi_rssi_threshold_val) reply->range;
1117 rssi = a_sle16_to_cpu(reply->rssi);
1118
1119 sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_RSSI];
1120
1121 /*
1122 * Identify the threshold breached and communicate that to the app.
1123 * After that install a new set of thresholds based on the signal
1124 * quality reported by the target
1125 */
1126 if (new_threshold) {
1127 /* Upper threshold breached */
1128 if (rssi < sq_thresh->upper_threshold[0]) {
1129 ath6kl_dbg(ATH6KL_DBG_WMI,
1130 "spurious upper rssi threshold event: %d\n",
1131 rssi);
1132 } else if ((rssi < sq_thresh->upper_threshold[1]) &&
1133 (rssi >= sq_thresh->upper_threshold[0])) {
1134 new_threshold = WMI_RSSI_THRESHOLD1_ABOVE;
1135 } else if ((rssi < sq_thresh->upper_threshold[2]) &&
1136 (rssi >= sq_thresh->upper_threshold[1])) {
1137 new_threshold = WMI_RSSI_THRESHOLD2_ABOVE;
1138 } else if ((rssi < sq_thresh->upper_threshold[3]) &&
1139 (rssi >= sq_thresh->upper_threshold[2])) {
1140 new_threshold = WMI_RSSI_THRESHOLD3_ABOVE;
1141 } else if ((rssi < sq_thresh->upper_threshold[4]) &&
1142 (rssi >= sq_thresh->upper_threshold[3])) {
1143 new_threshold = WMI_RSSI_THRESHOLD4_ABOVE;
1144 } else if ((rssi < sq_thresh->upper_threshold[5]) &&
1145 (rssi >= sq_thresh->upper_threshold[4])) {
1146 new_threshold = WMI_RSSI_THRESHOLD5_ABOVE;
1147 } else if (rssi >= sq_thresh->upper_threshold[5]) {
1148 new_threshold = WMI_RSSI_THRESHOLD6_ABOVE;
1149 }
1150 } else {
1151 /* Lower threshold breached */
1152 if (rssi > sq_thresh->lower_threshold[0]) {
1153 ath6kl_dbg(ATH6KL_DBG_WMI,
1154 "spurious lower rssi threshold event: %d %d\n",
1155 rssi, sq_thresh->lower_threshold[0]);
1156 } else if ((rssi > sq_thresh->lower_threshold[1]) &&
1157 (rssi <= sq_thresh->lower_threshold[0])) {
1158 new_threshold = WMI_RSSI_THRESHOLD6_BELOW;
1159 } else if ((rssi > sq_thresh->lower_threshold[2]) &&
1160 (rssi <= sq_thresh->lower_threshold[1])) {
1161 new_threshold = WMI_RSSI_THRESHOLD5_BELOW;
1162 } else if ((rssi > sq_thresh->lower_threshold[3]) &&
1163 (rssi <= sq_thresh->lower_threshold[2])) {
1164 new_threshold = WMI_RSSI_THRESHOLD4_BELOW;
1165 } else if ((rssi > sq_thresh->lower_threshold[4]) &&
1166 (rssi <= sq_thresh->lower_threshold[3])) {
1167 new_threshold = WMI_RSSI_THRESHOLD3_BELOW;
1168 } else if ((rssi > sq_thresh->lower_threshold[5]) &&
1169 (rssi <= sq_thresh->lower_threshold[4])) {
1170 new_threshold = WMI_RSSI_THRESHOLD2_BELOW;
1171 } else if (rssi <= sq_thresh->lower_threshold[5]) {
1172 new_threshold = WMI_RSSI_THRESHOLD1_BELOW;
1173 }
1174 }
1175
1176 /* Calculate and install the next set of thresholds */
1177 lower_rssi_threshold = ath6kl_wmi_get_lower_threshold(rssi, sq_thresh,
1178 sq_thresh->lower_threshold_valid_count);
1179 upper_rssi_threshold = ath6kl_wmi_get_upper_threshold(rssi, sq_thresh,
1180 sq_thresh->upper_threshold_valid_count);
1181
1182 /* Issue a wmi command to install the thresholds */
1183 cmd.thresh_above1_val = a_cpu_to_sle16(upper_rssi_threshold);
1184 cmd.thresh_below1_val = a_cpu_to_sle16(lower_rssi_threshold);
1185 cmd.weight = sq_thresh->weight;
1186 cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
1187
1188 ret = ath6kl_wmi_send_rssi_threshold_params(wmi, &cmd);
1189 if (ret) {
1190 ath6kl_err("unable to configure rssi thresholds\n");
1191 return -EIO;
1192 }
1193
1194 return 0;
1195}
1196
1197static int ath6kl_wmi_cac_event_rx(struct wmi *wmi, u8 *datap, int len)
1198{
1199 struct wmi_cac_event *reply;
1200 struct ieee80211_tspec_ie *ts;
1201 u16 active_tsids, tsinfo;
1202 u8 tsid, index;
1203 u8 ts_id;
1204
1205 if (len < sizeof(struct wmi_cac_event))
1206 return -EINVAL;
1207
1208 reply = (struct wmi_cac_event *) datap;
1209
1210 if ((reply->cac_indication == CAC_INDICATION_ADMISSION_RESP) &&
1211 (reply->status_code != IEEE80211_TSPEC_STATUS_ADMISS_ACCEPTED)) {
1212
1213 ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
1214 tsinfo = le16_to_cpu(ts->tsinfo);
1215 tsid = (tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
1216 IEEE80211_WMM_IE_TSPEC_TID_MASK;
1217
1218 ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, tsid);
1219 } else if (reply->cac_indication == CAC_INDICATION_NO_RESP) {
1220 /*
1221 * Following assumes that there is only one outstanding
1222 * ADDTS request when this event is received
1223 */
1224 spin_lock_bh(&wmi->lock);
1225 active_tsids = wmi->stream_exist_for_ac[reply->ac];
1226 spin_unlock_bh(&wmi->lock);
1227
1228 for (index = 0; index < sizeof(active_tsids) * 8; index++) {
1229 if ((active_tsids >> index) & 1)
1230 break;
1231 }
1232 if (index < (sizeof(active_tsids) * 8))
1233 ath6kl_wmi_delete_pstream_cmd(wmi, reply->ac, index);
1234 }
1235
1236 /*
1237 * Clear active tsids and Add missing handling
1238 * for delete qos stream from AP
1239 */
1240 else if (reply->cac_indication == CAC_INDICATION_DELETE) {
1241
1242 ts = (struct ieee80211_tspec_ie *) &(reply->tspec_suggestion);
1243 tsinfo = le16_to_cpu(ts->tsinfo);
1244 ts_id = ((tsinfo >> IEEE80211_WMM_IE_TSPEC_TID_SHIFT) &
1245 IEEE80211_WMM_IE_TSPEC_TID_MASK);
1246
1247 spin_lock_bh(&wmi->lock);
1248 wmi->stream_exist_for_ac[reply->ac] &= ~(1 << ts_id);
1249 active_tsids = wmi->stream_exist_for_ac[reply->ac];
1250 spin_unlock_bh(&wmi->lock);
1251
1252 /* Indicate stream inactivity to driver layer only if all tsids
1253 * within this AC are deleted.
1254 */
1255 if (!active_tsids) {
1256 ath6kl_indicate_tx_activity(wmi->parent_dev, reply->ac,
1257 false);
1258 wmi->fat_pipe_exist &= ~(1 << reply->ac);
1259 }
1260 }
1261
1262 return 0;
1263}
1264
1265static int ath6kl_wmi_send_snr_threshold_params(struct wmi *wmi,
1266 struct wmi_snr_threshold_params_cmd *snr_cmd)
1267{
1268 struct sk_buff *skb;
1269 struct wmi_snr_threshold_params_cmd *cmd;
1270
1271 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1272 if (!skb)
1273 return -ENOMEM;
1274
1275 cmd = (struct wmi_snr_threshold_params_cmd *) skb->data;
1276 memcpy(cmd, snr_cmd, sizeof(struct wmi_snr_threshold_params_cmd));
1277
1278 return ath6kl_wmi_cmd_send(wmi, skb, WMI_SNR_THRESHOLD_PARAMS_CMDID,
1279 NO_SYNC_WMIFLAG);
1280}
1281
1282static int ath6kl_wmi_snr_threshold_event_rx(struct wmi *wmi, u8 *datap,
1283 int len)
1284{
1285 struct wmi_snr_threshold_event *reply;
1286 struct sq_threshold_params *sq_thresh;
1287 struct wmi_snr_threshold_params_cmd cmd;
1288 enum wmi_snr_threshold_val new_threshold;
1289 u8 upper_snr_threshold, lower_snr_threshold;
1290 s16 snr;
1291 int ret;
1292
1293 if (len < sizeof(struct wmi_snr_threshold_event))
1294 return -EINVAL;
1295
1296 reply = (struct wmi_snr_threshold_event *) datap;
1297
1298 new_threshold = (enum wmi_snr_threshold_val) reply->range;
1299 snr = reply->snr;
1300
1301 sq_thresh = &wmi->sq_threshld[SIGNAL_QUALITY_METRICS_SNR];
1302
1303 /*
1304 * Identify the threshold breached and communicate that to the app.
1305 * After that install a new set of thresholds based on the signal
1306 * quality reported by the target.
1307 */
1308 if (new_threshold) {
1309 /* Upper threshold breached */
1310 if (snr < sq_thresh->upper_threshold[0]) {
1311 ath6kl_dbg(ATH6KL_DBG_WMI,
1312 "spurious upper snr threshold event: %d\n",
1313 snr);
1314 } else if ((snr < sq_thresh->upper_threshold[1]) &&
1315 (snr >= sq_thresh->upper_threshold[0])) {
1316 new_threshold = WMI_SNR_THRESHOLD1_ABOVE;
1317 } else if ((snr < sq_thresh->upper_threshold[2]) &&
1318 (snr >= sq_thresh->upper_threshold[1])) {
1319 new_threshold = WMI_SNR_THRESHOLD2_ABOVE;
1320 } else if ((snr < sq_thresh->upper_threshold[3]) &&
1321 (snr >= sq_thresh->upper_threshold[2])) {
1322 new_threshold = WMI_SNR_THRESHOLD3_ABOVE;
1323 } else if (snr >= sq_thresh->upper_threshold[3]) {
1324 new_threshold = WMI_SNR_THRESHOLD4_ABOVE;
1325 }
1326 } else {
1327 /* Lower threshold breached */
1328 if (snr > sq_thresh->lower_threshold[0]) {
1329 ath6kl_dbg(ATH6KL_DBG_WMI,
1330 "spurious lower snr threshold event: %d\n",
1331 sq_thresh->lower_threshold[0]);
1332 } else if ((snr > sq_thresh->lower_threshold[1]) &&
1333 (snr <= sq_thresh->lower_threshold[0])) {
1334 new_threshold = WMI_SNR_THRESHOLD4_BELOW;
1335 } else if ((snr > sq_thresh->lower_threshold[2]) &&
1336 (snr <= sq_thresh->lower_threshold[1])) {
1337 new_threshold = WMI_SNR_THRESHOLD3_BELOW;
1338 } else if ((snr > sq_thresh->lower_threshold[3]) &&
1339 (snr <= sq_thresh->lower_threshold[2])) {
1340 new_threshold = WMI_SNR_THRESHOLD2_BELOW;
1341 } else if (snr <= sq_thresh->lower_threshold[3]) {
1342 new_threshold = WMI_SNR_THRESHOLD1_BELOW;
1343 }
1344 }
1345
1346 /* Calculate and install the next set of thresholds */
1347 lower_snr_threshold = ath6kl_wmi_get_lower_threshold(snr, sq_thresh,
1348 sq_thresh->lower_threshold_valid_count);
1349 upper_snr_threshold = ath6kl_wmi_get_upper_threshold(snr, sq_thresh,
1350 sq_thresh->upper_threshold_valid_count);
1351
1352 /* Issue a wmi command to install the thresholds */
1353 cmd.thresh_above1_val = upper_snr_threshold;
1354 cmd.thresh_below1_val = lower_snr_threshold;
1355 cmd.weight = sq_thresh->weight;
1356 cmd.poll_time = cpu_to_le32(sq_thresh->polling_interval);
1357
1358 ath6kl_dbg(ATH6KL_DBG_WMI,
1359 "snr: %d, threshold: %d, lower: %d, upper: %d\n",
1360 snr, new_threshold,
1361 lower_snr_threshold, upper_snr_threshold);
1362
1363 ret = ath6kl_wmi_send_snr_threshold_params(wmi, &cmd);
1364 if (ret) {
1365 ath6kl_err("unable to configure snr threshold\n");
1366 return -EIO;
1367 }
1368
1369 return 0;
1370}
1371
1372static int ath6kl_wmi_aplist_event_rx(struct wmi *wmi, u8 *datap, int len)
1373{
1374 u16 ap_info_entry_size;
1375 struct wmi_aplist_event *ev = (struct wmi_aplist_event *) datap;
1376 struct wmi_ap_info_v1 *ap_info_v1;
1377 u8 index;
1378
1379 if (len < sizeof(struct wmi_aplist_event) ||
1380 ev->ap_list_ver != APLIST_VER1)
1381 return -EINVAL;
1382
1383 ap_info_entry_size = sizeof(struct wmi_ap_info_v1);
1384 ap_info_v1 = (struct wmi_ap_info_v1 *) ev->ap_list;
1385
1386 ath6kl_dbg(ATH6KL_DBG_WMI,
1387 "number of APs in aplist event: %d\n", ev->num_ap);
1388
1389 if (len < (int) (sizeof(struct wmi_aplist_event) +
1390 (ev->num_ap - 1) * ap_info_entry_size))
1391 return -EINVAL;
1392
1393 /* AP list version 1 contents */
1394 for (index = 0; index < ev->num_ap; index++) {
1395 ath6kl_dbg(ATH6KL_DBG_WMI, "AP#%d BSSID %pM Channel %d\n",
1396 index, ap_info_v1->bssid, ap_info_v1->channel);
1397 ap_info_v1++;
1398 }
1399
1400 return 0;
1401}
1402
1403int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
1404 enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag)
1405{
1406 struct wmi_cmd_hdr *cmd_hdr;
1407 enum htc_endpoint_id ep_id = wmi->ep_id;
1408 int ret;
1409
1410 if (WARN_ON(skb == NULL))
1411 return -EINVAL;
1412
1413 if (sync_flag >= END_WMIFLAG) {
1414 dev_kfree_skb(skb);
1415 return -EINVAL;
1416 }
1417
1418 if ((sync_flag == SYNC_BEFORE_WMIFLAG) ||
1419 (sync_flag == SYNC_BOTH_WMIFLAG)) {
1420 /*
1421 * Make sure all data currently queued is transmitted before
1422 * the cmd execution. Establish a new sync point.
1423 */
1424 ath6kl_wmi_sync_point(wmi);
1425 }
1426
1427 skb_push(skb, sizeof(struct wmi_cmd_hdr));
1428
1429 cmd_hdr = (struct wmi_cmd_hdr *) skb->data;
1430 cmd_hdr->cmd_id = cpu_to_le16(cmd_id);
1431 cmd_hdr->info1 = 0; /* added for virtual interface */
1432
1433 /* Only for OPT_TX_CMD, use BE endpoint. */
1434 if (cmd_id == WMI_OPT_TX_FRAME_CMDID) {
1435 ret = ath6kl_wmi_data_hdr_add(wmi, skb, OPT_MSGTYPE,
1436 false, false, 0, NULL);
1437 if (ret) {
1438 dev_kfree_skb(skb);
1439 return ret;
1440 }
1441 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev, WMM_AC_BE);
1442 }
1443
1444 ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
1445
1446 if ((sync_flag == SYNC_AFTER_WMIFLAG) ||
1447 (sync_flag == SYNC_BOTH_WMIFLAG)) {
1448 /*
1449 * Make sure all new data queued waits for the command to
1450 * execute. Establish a new sync point.
1451 */
1452 ath6kl_wmi_sync_point(wmi);
1453 }
1454
1455 return 0;
1456}
1457
1458int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
1459 enum dot11_auth_mode dot11_auth_mode,
1460 enum auth_mode auth_mode,
1461 enum crypto_type pairwise_crypto,
1462 u8 pairwise_crypto_len,
1463 enum crypto_type group_crypto,
1464 u8 group_crypto_len, int ssid_len, u8 *ssid,
1465 u8 *bssid, u16 channel, u32 ctrl_flags)
1466{
1467 struct sk_buff *skb;
1468 struct wmi_connect_cmd *cc;
1469 int ret;
1470
1471 wmi->traffic_class = 100;
1472
1473 if ((pairwise_crypto == NONE_CRYPT) && (group_crypto != NONE_CRYPT))
1474 return -EINVAL;
1475
1476 if ((pairwise_crypto != NONE_CRYPT) && (group_crypto == NONE_CRYPT))
1477 return -EINVAL;
1478
1479 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_connect_cmd));
1480 if (!skb)
1481 return -ENOMEM;
1482
1483 cc = (struct wmi_connect_cmd *) skb->data;
1484
1485 if (ssid_len)
1486 memcpy(cc->ssid, ssid, ssid_len);
1487
1488 cc->ssid_len = ssid_len;
1489 cc->nw_type = nw_type;
1490 cc->dot11_auth_mode = dot11_auth_mode;
1491 cc->auth_mode = auth_mode;
1492 cc->prwise_crypto_type = pairwise_crypto;
1493 cc->prwise_crypto_len = pairwise_crypto_len;
1494 cc->grp_crypto_type = group_crypto;
1495 cc->grp_crypto_len = group_crypto_len;
1496 cc->ch = cpu_to_le16(channel);
1497 cc->ctrl_flags = cpu_to_le32(ctrl_flags);
1498
1499 if (bssid != NULL)
1500 memcpy(cc->bssid, bssid, ETH_ALEN);
1501
1502 wmi->pair_crypto_type = pairwise_crypto;
1503 wmi->grp_crypto_type = group_crypto;
1504
1505 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CONNECT_CMDID, NO_SYNC_WMIFLAG);
1506
1507 return ret;
1508}
1509
1510int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel)
1511{
1512 struct sk_buff *skb;
1513 struct wmi_reconnect_cmd *cc;
1514 int ret;
1515
1516 wmi->traffic_class = 100;
1517
1518 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_reconnect_cmd));
1519 if (!skb)
1520 return -ENOMEM;
1521
1522 cc = (struct wmi_reconnect_cmd *) skb->data;
1523 cc->channel = cpu_to_le16(channel);
1524
1525 if (bssid != NULL)
1526 memcpy(cc->bssid, bssid, ETH_ALEN);
1527
1528 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RECONNECT_CMDID,
1529 NO_SYNC_WMIFLAG);
1530
1531 return ret;
1532}
1533
1534int ath6kl_wmi_disconnect_cmd(struct wmi *wmi)
1535{
1536 int ret;
1537
1538 wmi->traffic_class = 100;
1539
1540 /* Disconnect command does not need to do a SYNC before. */
1541 ret = ath6kl_wmi_simple_cmd(wmi, WMI_DISCONNECT_CMDID);
1542
1543 return ret;
1544}
1545
1546int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
1547 u32 force_fgscan, u32 is_legacy,
1548 u32 home_dwell_time, u32 force_scan_interval,
1549 s8 num_chan, u16 *ch_list)
1550{
1551 struct sk_buff *skb;
1552 struct wmi_start_scan_cmd *sc;
1553 s8 size;
1554 int ret;
1555
1556 size = sizeof(struct wmi_start_scan_cmd);
1557
1558 if ((scan_type != WMI_LONG_SCAN) && (scan_type != WMI_SHORT_SCAN))
1559 return -EINVAL;
1560
1561 if (num_chan > WMI_MAX_CHANNELS)
1562 return -EINVAL;
1563
1564 if (num_chan)
1565 size += sizeof(u16) * (num_chan - 1);
1566
1567 skb = ath6kl_wmi_get_new_buf(size);
1568 if (!skb)
1569 return -ENOMEM;
1570
1571 sc = (struct wmi_start_scan_cmd *) skb->data;
1572 sc->scan_type = scan_type;
1573 sc->force_fg_scan = cpu_to_le32(force_fgscan);
1574 sc->is_legacy = cpu_to_le32(is_legacy);
1575 sc->home_dwell_time = cpu_to_le32(home_dwell_time);
1576 sc->force_scan_intvl = cpu_to_le32(force_scan_interval);
1577 sc->num_ch = num_chan;
1578
1579 if (num_chan)
1580 memcpy(sc->ch_list, ch_list, num_chan * sizeof(u16));
1581
1582 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_START_SCAN_CMDID,
1583 NO_SYNC_WMIFLAG);
1584
1585 return ret;
1586}
1587
1588int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
1589 u16 fg_end_sec, u16 bg_sec,
1590 u16 minact_chdw_msec, u16 maxact_chdw_msec,
1591 u16 pas_chdw_msec, u8 short_scan_ratio,
1592 u8 scan_ctrl_flag, u32 max_dfsch_act_time,
1593 u16 maxact_scan_per_ssid)
1594{
1595 struct sk_buff *skb;
1596 struct wmi_scan_params_cmd *sc;
1597 int ret;
1598
1599 skb = ath6kl_wmi_get_new_buf(sizeof(*sc));
1600 if (!skb)
1601 return -ENOMEM;
1602
1603 sc = (struct wmi_scan_params_cmd *) skb->data;
1604 sc->fg_start_period = cpu_to_le16(fg_start_sec);
1605 sc->fg_end_period = cpu_to_le16(fg_end_sec);
1606 sc->bg_period = cpu_to_le16(bg_sec);
1607 sc->minact_chdwell_time = cpu_to_le16(minact_chdw_msec);
1608 sc->maxact_chdwell_time = cpu_to_le16(maxact_chdw_msec);
1609 sc->pas_chdwell_time = cpu_to_le16(pas_chdw_msec);
1610 sc->short_scan_ratio = short_scan_ratio;
1611 sc->scan_ctrl_flags = scan_ctrl_flag;
1612 sc->max_dfsch_act_time = cpu_to_le32(max_dfsch_act_time);
1613 sc->maxact_scan_per_ssid = cpu_to_le16(maxact_scan_per_ssid);
1614
1615 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_SCAN_PARAMS_CMDID,
1616 NO_SYNC_WMIFLAG);
1617 return ret;
1618}
1619
1620int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask)
1621{
1622 struct sk_buff *skb;
1623 struct wmi_bss_filter_cmd *cmd;
1624 int ret;
1625
1626 if (filter >= LAST_BSS_FILTER)
1627 return -EINVAL;
1628
1629 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1630 if (!skb)
1631 return -ENOMEM;
1632
1633 cmd = (struct wmi_bss_filter_cmd *) skb->data;
1634 cmd->bss_filter = filter;
1635 cmd->ie_mask = cpu_to_le32(ie_mask);
1636
1637 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_BSS_FILTER_CMDID,
1638 NO_SYNC_WMIFLAG);
1639 return ret;
1640}
1641
1642int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
1643 u8 ssid_len, u8 *ssid)
1644{
1645 struct sk_buff *skb;
1646 struct wmi_probed_ssid_cmd *cmd;
1647 int ret;
1648
1649 if (index > MAX_PROBED_SSID_INDEX)
1650 return -EINVAL;
1651
1652 if (ssid_len > sizeof(cmd->ssid))
1653 return -EINVAL;
1654
1655 if ((flag & (DISABLE_SSID_FLAG | ANY_SSID_FLAG)) && (ssid_len > 0))
1656 return -EINVAL;
1657
1658 if ((flag & SPECIFIC_SSID_FLAG) && !ssid_len)
1659 return -EINVAL;
1660
1661 if (flag & SPECIFIC_SSID_FLAG)
1662 wmi->is_probe_ssid = true;
1663
1664 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1665 if (!skb)
1666 return -ENOMEM;
1667
1668 cmd = (struct wmi_probed_ssid_cmd *) skb->data;
1669 cmd->entry_index = index;
1670 cmd->flag = flag;
1671 cmd->ssid_len = ssid_len;
1672 memcpy(cmd->ssid, ssid, ssid_len);
1673
1674 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PROBED_SSID_CMDID,
1675 NO_SYNC_WMIFLAG);
1676 return ret;
1677}
1678
1679int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
1680 u16 listen_beacons)
1681{
1682 struct sk_buff *skb;
1683 struct wmi_listen_int_cmd *cmd;
1684 int ret;
1685
1686 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1687 if (!skb)
1688 return -ENOMEM;
1689
1690 cmd = (struct wmi_listen_int_cmd *) skb->data;
1691 cmd->listen_intvl = cpu_to_le16(listen_interval);
1692 cmd->num_beacons = cpu_to_le16(listen_beacons);
1693
1694 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LISTEN_INT_CMDID,
1695 NO_SYNC_WMIFLAG);
1696 return ret;
1697}
1698
1699int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode)
1700{
1701 struct sk_buff *skb;
1702 struct wmi_power_mode_cmd *cmd;
1703 int ret;
1704
1705 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1706 if (!skb)
1707 return -ENOMEM;
1708
1709 cmd = (struct wmi_power_mode_cmd *) skb->data;
1710 cmd->pwr_mode = pwr_mode;
1711 wmi->pwr_mode = pwr_mode;
1712
1713 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_MODE_CMDID,
1714 NO_SYNC_WMIFLAG);
1715 return ret;
1716}
1717
1718int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
1719 u16 ps_poll_num, u16 dtim_policy,
1720 u16 tx_wakeup_policy, u16 num_tx_to_wakeup,
1721 u16 ps_fail_event_policy)
1722{
1723 struct sk_buff *skb;
1724 struct wmi_power_params_cmd *pm;
1725 int ret;
1726
1727 skb = ath6kl_wmi_get_new_buf(sizeof(*pm));
1728 if (!skb)
1729 return -ENOMEM;
1730
1731 pm = (struct wmi_power_params_cmd *)skb->data;
1732 pm->idle_period = cpu_to_le16(idle_period);
1733 pm->pspoll_number = cpu_to_le16(ps_poll_num);
1734 pm->dtim_policy = cpu_to_le16(dtim_policy);
1735 pm->tx_wakeup_policy = cpu_to_le16(tx_wakeup_policy);
1736 pm->num_tx_to_wakeup = cpu_to_le16(num_tx_to_wakeup);
1737 pm->ps_fail_event_policy = cpu_to_le16(ps_fail_event_policy);
1738
1739 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_POWER_PARAMS_CMDID,
1740 NO_SYNC_WMIFLAG);
1741 return ret;
1742}
1743
1744int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout)
1745{
1746 struct sk_buff *skb;
1747 struct wmi_disc_timeout_cmd *cmd;
1748 int ret;
1749
1750 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1751 if (!skb)
1752 return -ENOMEM;
1753
1754 cmd = (struct wmi_disc_timeout_cmd *) skb->data;
1755 cmd->discon_timeout = timeout;
1756
1757 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_DISC_TIMEOUT_CMDID,
1758 NO_SYNC_WMIFLAG);
1759 return ret;
1760}
1761
1762int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
1763 enum crypto_type key_type,
1764 u8 key_usage, u8 key_len,
1765 u8 *key_rsc, u8 *key_material,
1766 u8 key_op_ctrl, u8 *mac_addr,
1767 enum wmi_sync_flag sync_flag)
1768{
1769 struct sk_buff *skb;
1770 struct wmi_add_cipher_key_cmd *cmd;
1771 int ret;
1772
1773 if ((key_index > WMI_MAX_KEY_INDEX) || (key_len > WMI_MAX_KEY_LEN) ||
1774 (key_material == NULL))
1775 return -EINVAL;
1776
1777 if ((WEP_CRYPT != key_type) && (NULL == key_rsc))
1778 return -EINVAL;
1779
1780 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1781 if (!skb)
1782 return -ENOMEM;
1783
1784 cmd = (struct wmi_add_cipher_key_cmd *) skb->data;
1785 cmd->key_index = key_index;
1786 cmd->key_type = key_type;
1787 cmd->key_usage = key_usage;
1788 cmd->key_len = key_len;
1789 memcpy(cmd->key, key_material, key_len);
1790
1791 if (key_rsc != NULL)
1792 memcpy(cmd->key_rsc, key_rsc, sizeof(cmd->key_rsc));
1793
1794 cmd->key_op_ctrl = key_op_ctrl;
1795
1796 if (mac_addr)
1797 memcpy(cmd->key_mac_addr, mac_addr, ETH_ALEN);
1798
1799 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_CIPHER_KEY_CMDID,
1800 sync_flag);
1801
1802 return ret;
1803}
1804
1805int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk)
1806{
1807 struct sk_buff *skb;
1808 struct wmi_add_krk_cmd *cmd;
1809 int ret;
1810
1811 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1812 if (!skb)
1813 return -ENOMEM;
1814
1815 cmd = (struct wmi_add_krk_cmd *) skb->data;
1816 memcpy(cmd->krk, krk, WMI_KRK_LEN);
1817
1818 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_ADD_KRK_CMDID, NO_SYNC_WMIFLAG);
1819
1820 return ret;
1821}
1822
1823int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index)
1824{
1825 struct sk_buff *skb;
1826 struct wmi_delete_cipher_key_cmd *cmd;
1827 int ret;
1828
1829 if (key_index > WMI_MAX_KEY_INDEX)
1830 return -EINVAL;
1831
1832 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1833 if (!skb)
1834 return -ENOMEM;
1835
1836 cmd = (struct wmi_delete_cipher_key_cmd *) skb->data;
1837 cmd->key_index = key_index;
1838
1839 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_CIPHER_KEY_CMDID,
1840 NO_SYNC_WMIFLAG);
1841
1842 return ret;
1843}
1844
1845int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
1846 const u8 *pmkid, bool set)
1847{
1848 struct sk_buff *skb;
1849 struct wmi_setpmkid_cmd *cmd;
1850 int ret;
1851
1852 if (bssid == NULL)
1853 return -EINVAL;
1854
1855 if (set && pmkid == NULL)
1856 return -EINVAL;
1857
1858 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1859 if (!skb)
1860 return -ENOMEM;
1861
1862 cmd = (struct wmi_setpmkid_cmd *) skb->data;
1863 memcpy(cmd->bssid, bssid, ETH_ALEN);
1864 if (set) {
1865 memcpy(cmd->pmkid, pmkid, sizeof(cmd->pmkid));
1866 cmd->enable = PMKID_ENABLE;
1867 } else {
1868 memset(cmd->pmkid, 0, sizeof(cmd->pmkid));
1869 cmd->enable = PMKID_DISABLE;
1870 }
1871
1872 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_PMKID_CMDID,
1873 NO_SYNC_WMIFLAG);
1874
1875 return ret;
1876}
1877
1878static int ath6kl_wmi_data_sync_send(struct wmi *wmi, struct sk_buff *skb,
1879 enum htc_endpoint_id ep_id)
1880{
1881 struct wmi_data_hdr *data_hdr;
1882 int ret;
1883
1884 if (WARN_ON(skb == NULL || ep_id == wmi->ep_id))
1885 return -EINVAL;
1886
1887 skb_push(skb, sizeof(struct wmi_data_hdr));
1888
1889 data_hdr = (struct wmi_data_hdr *) skb->data;
1890 data_hdr->info = SYNC_MSGTYPE << WMI_DATA_HDR_MSG_TYPE_SHIFT;
1891 data_hdr->info3 = 0;
1892
1893 ret = ath6kl_control_tx(wmi->parent_dev, skb, ep_id);
1894
1895 return ret;
1896}
1897
1898static int ath6kl_wmi_sync_point(struct wmi *wmi)
1899{
1900 struct sk_buff *skb;
1901 struct wmi_sync_cmd *cmd;
1902 struct wmi_data_sync_bufs data_sync_bufs[WMM_NUM_AC];
1903 enum htc_endpoint_id ep_id;
1904 u8 index, num_pri_streams = 0;
1905 int ret = 0;
1906
1907 memset(data_sync_bufs, 0, sizeof(data_sync_bufs));
1908
1909 spin_lock_bh(&wmi->lock);
1910
1911 for (index = 0; index < WMM_NUM_AC; index++) {
1912 if (wmi->fat_pipe_exist & (1 << index)) {
1913 num_pri_streams++;
1914 data_sync_bufs[num_pri_streams - 1].traffic_class =
1915 index;
1916 }
1917 }
1918
1919 spin_unlock_bh(&wmi->lock);
1920
1921 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
1922 if (!skb) {
1923 ret = -ENOMEM;
1924 goto free_skb;
1925 }
1926
1927 cmd = (struct wmi_sync_cmd *) skb->data;
1928
1929 /*
1930 * In the SYNC cmd sent on the control Ep, send a bitmap
1931 * of the data eps on which the Data Sync will be sent
1932 */
1933 cmd->data_sync_map = wmi->fat_pipe_exist;
1934
1935 for (index = 0; index < num_pri_streams; index++) {
1936 data_sync_bufs[index].skb = ath6kl_buf_alloc(0);
1937 if (data_sync_bufs[index].skb == NULL) {
1938 ret = -ENOMEM;
1939 break;
1940 }
1941 }
1942
1943 /*
1944 * If buffer allocation for any of the dataSync fails,
1945 * then do not send the Synchronize cmd on the control ep
1946 */
1947 if (ret)
1948 goto free_skb;
1949
1950 /*
1951 * Send sync cmd followed by sync data messages on all
1952 * endpoints being used
1953 */
1954 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SYNCHRONIZE_CMDID,
1955 NO_SYNC_WMIFLAG);
1956
1957 if (ret)
1958 goto free_skb;
1959
1960 /* cmd buffer sent, we no longer own it */
1961 skb = NULL;
1962
1963 for (index = 0; index < num_pri_streams; index++) {
1964
1965 if (WARN_ON(!data_sync_bufs[index].skb))
1966 break;
1967
1968 ep_id = ath6kl_ac2_endpoint_id(wmi->parent_dev,
1969 data_sync_bufs[index].
1970 traffic_class);
1971 ret =
1972 ath6kl_wmi_data_sync_send(wmi, data_sync_bufs[index].skb,
1973 ep_id);
1974
1975 if (ret)
1976 break;
1977
1978 data_sync_bufs[index].skb = NULL;
1979 }
1980
1981free_skb:
1982 /* free up any resources left over (possibly due to an error) */
1983 if (skb)
1984 dev_kfree_skb(skb);
1985
1986 for (index = 0; index < num_pri_streams; index++) {
1987 if (data_sync_bufs[index].skb != NULL) {
1988 dev_kfree_skb((struct sk_buff *)data_sync_bufs[index].
1989 skb);
1990 }
1991 }
1992
1993 return ret;
1994}
1995
1996int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
1997 struct wmi_create_pstream_cmd *params)
1998{
1999 struct sk_buff *skb;
2000 struct wmi_create_pstream_cmd *cmd;
2001 u8 fatpipe_exist_for_ac = 0;
2002 s32 min_phy = 0;
2003 s32 nominal_phy = 0;
2004 int ret;
2005
2006 if (!((params->user_pri < 8) &&
2007 (params->user_pri <= 0x7) &&
2008 (up_to_ac[params->user_pri & 0x7] == params->traffic_class) &&
2009 (params->traffic_direc == UPLINK_TRAFFIC ||
2010 params->traffic_direc == DNLINK_TRAFFIC ||
2011 params->traffic_direc == BIDIR_TRAFFIC) &&
2012 (params->traffic_type == TRAFFIC_TYPE_APERIODIC ||
2013 params->traffic_type == TRAFFIC_TYPE_PERIODIC) &&
2014 (params->voice_psc_cap == DISABLE_FOR_THIS_AC ||
2015 params->voice_psc_cap == ENABLE_FOR_THIS_AC ||
2016 params->voice_psc_cap == ENABLE_FOR_ALL_AC) &&
2017 (params->tsid == WMI_IMPLICIT_PSTREAM ||
2018 params->tsid <= WMI_MAX_THINSTREAM))) {
2019 return -EINVAL;
2020 }
2021
2022 /*
2023 * Check nominal PHY rate is >= minimalPHY,
2024 * so that DUT can allow TSRS IE
2025 */
2026
2027 /* Get the physical rate (units of bps) */
2028 min_phy = ((le32_to_cpu(params->min_phy_rate) / 1000) / 1000);
2029
2030 /* Check minimal phy < nominal phy rate */
2031 if (params->nominal_phy >= min_phy) {
2032 /* unit of 500 kbps */
2033 nominal_phy = (params->nominal_phy * 1000) / 500;
2034 ath6kl_dbg(ATH6KL_DBG_WMI,
2035 "TSRS IE enabled::MinPhy %x->NominalPhy ===> %x\n",
2036 min_phy, nominal_phy);
2037
2038 params->nominal_phy = nominal_phy;
2039 } else {
2040 params->nominal_phy = 0;
2041 }
2042
2043 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2044 if (!skb)
2045 return -ENOMEM;
2046
2047 ath6kl_dbg(ATH6KL_DBG_WMI,
2048 "sending create_pstream_cmd: ac=%d tsid:%d\n",
2049 params->traffic_class, params->tsid);
2050
2051 cmd = (struct wmi_create_pstream_cmd *) skb->data;
2052 memcpy(cmd, params, sizeof(*cmd));
2053
2054 /* This is an implicitly created Fat pipe */
2055 if ((u32) params->tsid == (u32) WMI_IMPLICIT_PSTREAM) {
2056 spin_lock_bh(&wmi->lock);
2057 fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
2058 (1 << params->traffic_class));
2059 wmi->fat_pipe_exist |= (1 << params->traffic_class);
2060 spin_unlock_bh(&wmi->lock);
2061 } else {
2062 /* explicitly created thin stream within a fat pipe */
2063 spin_lock_bh(&wmi->lock);
2064 fatpipe_exist_for_ac = (wmi->fat_pipe_exist &
2065 (1 << params->traffic_class));
2066 wmi->stream_exist_for_ac[params->traffic_class] |=
2067 (1 << params->tsid);
2068 /*
2069 * If a thinstream becomes active, the fat pipe automatically
2070 * becomes active
2071 */
2072 wmi->fat_pipe_exist |= (1 << params->traffic_class);
2073 spin_unlock_bh(&wmi->lock);
2074 }
2075
2076 /*
2077 * Indicate activty change to driver layer only if this is the
2078 * first TSID to get created in this AC explicitly or an implicit
2079 * fat pipe is getting created.
2080 */
2081 if (!fatpipe_exist_for_ac)
2082 ath6kl_indicate_tx_activity(wmi->parent_dev,
2083 params->traffic_class, true);
2084
2085 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_CREATE_PSTREAM_CMDID,
2086 NO_SYNC_WMIFLAG);
2087 return ret;
2088}
2089
2090int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid)
2091{
2092 struct sk_buff *skb;
2093 struct wmi_delete_pstream_cmd *cmd;
2094 u16 active_tsids = 0;
2095 int ret;
2096
2097 if (traffic_class > 3) {
2098 ath6kl_err("invalid traffic class: %d\n", traffic_class);
2099 return -EINVAL;
2100 }
2101
2102 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2103 if (!skb)
2104 return -ENOMEM;
2105
2106 cmd = (struct wmi_delete_pstream_cmd *) skb->data;
2107 cmd->traffic_class = traffic_class;
2108 cmd->tsid = tsid;
2109
2110 spin_lock_bh(&wmi->lock);
2111 active_tsids = wmi->stream_exist_for_ac[traffic_class];
2112 spin_unlock_bh(&wmi->lock);
2113
2114 if (!(active_tsids & (1 << tsid))) {
2115 dev_kfree_skb(skb);
2116 ath6kl_dbg(ATH6KL_DBG_WMI,
2117 "TSID %d doesn't exist for traffic class: %d\n",
2118 tsid, traffic_class);
2119 return -ENODATA;
2120 }
2121
2122 ath6kl_dbg(ATH6KL_DBG_WMI,
2123 "sending delete_pstream_cmd: traffic class: %d tsid=%d\n",
2124 traffic_class, tsid);
2125
2126 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_DELETE_PSTREAM_CMDID,
2127 SYNC_BEFORE_WMIFLAG);
2128
2129 spin_lock_bh(&wmi->lock);
2130 wmi->stream_exist_for_ac[traffic_class] &= ~(1 << tsid);
2131 active_tsids = wmi->stream_exist_for_ac[traffic_class];
2132 spin_unlock_bh(&wmi->lock);
2133
2134 /*
2135 * Indicate stream inactivity to driver layer only if all tsids
2136 * within this AC are deleted.
2137 */
2138 if (!active_tsids) {
2139 ath6kl_indicate_tx_activity(wmi->parent_dev,
2140 traffic_class, false);
2141 wmi->fat_pipe_exist &= ~(1 << traffic_class);
2142 }
2143
2144 return ret;
2145}
2146
2147int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd)
2148{
2149 struct sk_buff *skb;
2150 struct wmi_set_ip_cmd *cmd;
2151 int ret;
2152
2153 /* Multicast address are not valid */
2154 if ((*((u8 *) &ip_cmd->ips[0]) >= 0xE0) ||
2155 (*((u8 *) &ip_cmd->ips[1]) >= 0xE0))
2156 return -EINVAL;
2157
2158 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_ip_cmd));
2159 if (!skb)
2160 return -ENOMEM;
2161
2162 cmd = (struct wmi_set_ip_cmd *) skb->data;
2163 memcpy(cmd, ip_cmd, sizeof(struct wmi_set_ip_cmd));
2164
2165 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_IP_CMDID, NO_SYNC_WMIFLAG);
2166 return ret;
2167}
2168
2169static int ath6kl_wmi_get_wow_list_event_rx(struct wmi *wmi, u8 * datap,
2170 int len)
2171{
2172 if (len < sizeof(struct wmi_get_wow_list_reply))
2173 return -EINVAL;
2174
2175 return 0;
2176}
2177
2178static int ath6kl_wmi_cmd_send_xtnd(struct wmi *wmi, struct sk_buff *skb,
2179 enum wmix_command_id cmd_id,
2180 enum wmi_sync_flag sync_flag)
2181{
2182 struct wmix_cmd_hdr *cmd_hdr;
2183 int ret;
2184
2185 skb_push(skb, sizeof(struct wmix_cmd_hdr));
2186
2187 cmd_hdr = (struct wmix_cmd_hdr *) skb->data;
2188 cmd_hdr->cmd_id = cpu_to_le32(cmd_id);
2189
2190 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_EXTENSION_CMDID, sync_flag);
2191
2192 return ret;
2193}
2194
2195int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source)
2196{
2197 struct sk_buff *skb;
2198 struct wmix_hb_challenge_resp_cmd *cmd;
2199 int ret;
2200
2201 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2202 if (!skb)
2203 return -ENOMEM;
2204
2205 cmd = (struct wmix_hb_challenge_resp_cmd *) skb->data;
2206 cmd->cookie = cpu_to_le32(cookie);
2207 cmd->source = cpu_to_le32(source);
2208
2209 ret = ath6kl_wmi_cmd_send_xtnd(wmi, skb, WMIX_HB_CHALLENGE_RESP_CMDID,
2210 NO_SYNC_WMIFLAG);
2211 return ret;
2212}
2213
2214int ath6kl_wmi_get_stats_cmd(struct wmi *wmi)
2215{
2216 return ath6kl_wmi_simple_cmd(wmi, WMI_GET_STATISTICS_CMDID);
2217}
2218
2219int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM)
2220{
2221 struct sk_buff *skb;
2222 struct wmi_set_tx_pwr_cmd *cmd;
2223 int ret;
2224
2225 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_tx_pwr_cmd));
2226 if (!skb)
2227 return -ENOMEM;
2228
2229 cmd = (struct wmi_set_tx_pwr_cmd *) skb->data;
2230 cmd->dbM = dbM;
2231
2232 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_TX_PWR_CMDID,
2233 NO_SYNC_WMIFLAG);
2234
2235 return ret;
2236}
2237
2238int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi)
2239{
2240 return ath6kl_wmi_simple_cmd(wmi, WMI_GET_TX_PWR_CMDID);
2241}
2242
2243int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status, u8 preamble_policy)
2244{
2245 struct sk_buff *skb;
2246 struct wmi_set_lpreamble_cmd *cmd;
2247 int ret;
2248
2249 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_lpreamble_cmd));
2250 if (!skb)
2251 return -ENOMEM;
2252
2253 cmd = (struct wmi_set_lpreamble_cmd *) skb->data;
2254 cmd->status = status;
2255 cmd->preamble_policy = preamble_policy;
2256
2257 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_LPREAMBLE_CMDID,
2258 NO_SYNC_WMIFLAG);
2259 return ret;
2260}
2261
2262int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold)
2263{
2264 struct sk_buff *skb;
2265 struct wmi_set_rts_cmd *cmd;
2266 int ret;
2267
2268 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_rts_cmd));
2269 if (!skb)
2270 return -ENOMEM;
2271
2272 cmd = (struct wmi_set_rts_cmd *) skb->data;
2273 cmd->threshold = cpu_to_le16(threshold);
2274
2275 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_RTS_CMDID, NO_SYNC_WMIFLAG);
2276 return ret;
2277}
2278
2279int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg)
2280{
2281 struct sk_buff *skb;
2282 struct wmi_set_wmm_txop_cmd *cmd;
2283 int ret;
2284
2285 if (!((cfg == WMI_TXOP_DISABLED) || (cfg == WMI_TXOP_ENABLED)))
2286 return -EINVAL;
2287
2288 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_set_wmm_txop_cmd));
2289 if (!skb)
2290 return -ENOMEM;
2291
2292 cmd = (struct wmi_set_wmm_txop_cmd *) skb->data;
2293 cmd->txop_enable = cfg;
2294
2295 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_WMM_TXOP_CMDID,
2296 NO_SYNC_WMIFLAG);
2297 return ret;
2298}
2299
2300int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl)
2301{
2302 struct sk_buff *skb;
2303 struct wmi_set_keepalive_cmd *cmd;
2304 int ret;
2305
2306 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2307 if (!skb)
2308 return -ENOMEM;
2309
2310 cmd = (struct wmi_set_keepalive_cmd *) skb->data;
2311 cmd->keep_alive_intvl = keep_alive_intvl;
2312 wmi->keep_alive_intvl = keep_alive_intvl;
2313
2314 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_SET_KEEPALIVE_CMDID,
2315 NO_SYNC_WMIFLAG);
2316 return ret;
2317}
2318
2319s32 ath6kl_wmi_get_rate(s8 rate_index)
2320{
2321 if (rate_index == RATE_AUTO)
2322 return 0;
2323
2324 return wmi_rate_tbl[(u32) rate_index][0];
2325}
2326
2327void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss)
2328{
2329 if (bss)
2330 wlan_node_return(&wmi->parent_dev->scan_table, bss);
2331}
2332
2333struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 * ssid,
2334 u32 ssid_len, bool is_wpa2,
2335 bool match_ssid)
2336{
2337 struct bss *node = NULL;
2338
2339 node = wlan_find_ssid_node(&wmi->parent_dev->scan_table, ssid,
2340 ssid_len, is_wpa2, match_ssid);
2341 return node;
2342}
2343
2344struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 * mac_addr)
2345{
2346 struct bss *ni = NULL;
2347
2348 ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr);
2349
2350 return ni;
2351}
2352
2353void ath6kl_wmi_node_free(struct wmi *wmi, const u8 * mac_addr)
2354{
2355 struct bss *ni = NULL;
2356
2357 ni = wlan_find_node(&wmi->parent_dev->scan_table, mac_addr);
2358 if (ni != NULL)
2359 wlan_node_reclaim(&wmi->parent_dev->scan_table, ni);
2360
2361 return;
2362}
2363
2364static int ath6kl_wmi_get_pmkid_list_event_rx(struct wmi *wmi, u8 *datap,
2365 u32 len)
2366{
2367 struct wmi_pmkid_list_reply *reply;
2368 u32 expected_len;
2369
2370 if (len < sizeof(struct wmi_pmkid_list_reply))
2371 return -EINVAL;
2372
2373 reply = (struct wmi_pmkid_list_reply *)datap;
2374 expected_len = sizeof(reply->num_pmkid) +
2375 le32_to_cpu(reply->num_pmkid) * WMI_PMKID_LEN;
2376
2377 if (len < expected_len)
2378 return -EINVAL;
2379
2380 return 0;
2381}
2382
2383static int ath6kl_wmi_addba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
2384{
2385 struct wmi_addba_req_event *cmd = (struct wmi_addba_req_event *) datap;
2386
2387 aggr_recv_addba_req_evt(wmi->parent_dev, cmd->tid,
2388 le16_to_cpu(cmd->st_seq_no), cmd->win_sz);
2389
2390 return 0;
2391}
2392
2393static int ath6kl_wmi_delba_req_event_rx(struct wmi *wmi, u8 *datap, int len)
2394{
2395 struct wmi_delba_event *cmd = (struct wmi_delba_event *) datap;
2396
2397 aggr_recv_delba_req_evt(wmi->parent_dev, cmd->tid);
2398
2399 return 0;
2400}
2401
2402/* AP mode functions */
2403static int ath6kl_wmi_pspoll_event_rx(struct wmi *wmi, u8 *datap, int len)
2404{
2405 struct wmi_pspoll_event *ev;
2406
2407 if (len < sizeof(struct wmi_pspoll_event))
2408 return -EINVAL;
2409
2410 ev = (struct wmi_pspoll_event *) datap;
2411
2412 ath6kl_pspoll_event(wmi->parent_dev, le16_to_cpu(ev->aid));
2413
2414 return 0;
2415}
2416
2417static int ath6kl_wmi_dtimexpiry_event_rx(struct wmi *wmi, u8 *datap, int len)
2418{
2419 ath6kl_dtimexpiry_event(wmi->parent_dev);
2420
2421 return 0;
2422}
2423
2424int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag)
2425{
2426 struct sk_buff *skb;
2427 struct wmi_ap_set_pvb_cmd *cmd;
2428 int ret;
2429
2430 skb = ath6kl_wmi_get_new_buf(sizeof(struct wmi_ap_set_pvb_cmd));
2431 if (!skb)
2432 return -ENOMEM;
2433
2434 cmd = (struct wmi_ap_set_pvb_cmd *) skb->data;
2435 cmd->aid = cpu_to_le16(aid);
2436 cmd->flag = cpu_to_le32(flag);
2437
2438 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_AP_SET_PVB_CMDID,
2439 NO_SYNC_WMIFLAG);
2440
2441 return 0;
2442}
2443
2444int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_ver,
2445 bool rx_dot11_hdr, bool defrag_on_host)
2446{
2447 struct sk_buff *skb;
2448 struct wmi_rx_frame_format_cmd *cmd;
2449 int ret;
2450
2451 skb = ath6kl_wmi_get_new_buf(sizeof(*cmd));
2452 if (!skb)
2453 return -ENOMEM;
2454
2455 cmd = (struct wmi_rx_frame_format_cmd *) skb->data;
2456 cmd->dot11_hdr = rx_dot11_hdr ? 1 : 0;
2457 cmd->defrag_on_host = defrag_on_host ? 1 : 0;
2458 cmd->meta_ver = rx_meta_ver;
2459
2460 /* Delete the local aggr state, on host */
2461 ret = ath6kl_wmi_cmd_send(wmi, skb, WMI_RX_FRAME_FORMAT_CMDID,
2462 NO_SYNC_WMIFLAG);
2463
2464 return ret;
2465}
2466
2467static int ath6kl_wmi_control_rx_xtnd(struct wmi *wmi, struct sk_buff *skb)
2468{
2469 struct wmix_cmd_hdr *cmd;
2470 u32 len;
2471 u16 id;
2472 u8 *datap;
2473 int ret = 0;
2474
2475 if (skb->len < sizeof(struct wmix_cmd_hdr)) {
2476 ath6kl_err("bad packet 1\n");
2477 wmi->stat.cmd_len_err++;
2478 return -EINVAL;
2479 }
2480
2481 cmd = (struct wmix_cmd_hdr *) skb->data;
2482 id = le32_to_cpu(cmd->cmd_id);
2483
2484 skb_pull(skb, sizeof(struct wmix_cmd_hdr));
2485
2486 datap = skb->data;
2487 len = skb->len;
2488
2489 switch (id) {
2490 case WMIX_HB_CHALLENGE_RESP_EVENTID:
2491 break;
2492 case WMIX_DBGLOG_EVENTID:
2493 break;
2494 default:
2495 ath6kl_err("unknown cmd id 0x%x\n", id);
2496 wmi->stat.cmd_id_err++;
2497 ret = -EINVAL;
2498 break;
2499 }
2500
2501 return ret;
2502}
2503
2504/* Control Path */
2505int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb)
2506{
2507 struct wmi_cmd_hdr *cmd;
2508 u32 len;
2509 u16 id;
2510 u8 *datap;
2511 int ret = 0;
2512
2513 if (WARN_ON(skb == NULL))
2514 return -EINVAL;
2515
2516 if (skb->len < sizeof(struct wmi_cmd_hdr)) {
2517 ath6kl_err("bad packet 1\n");
2518 dev_kfree_skb(skb);
2519 wmi->stat.cmd_len_err++;
2520 return -EINVAL;
2521 }
2522
2523 cmd = (struct wmi_cmd_hdr *) skb->data;
2524 id = le16_to_cpu(cmd->cmd_id);
2525
2526 skb_pull(skb, sizeof(struct wmi_cmd_hdr));
2527
2528 datap = skb->data;
2529 len = skb->len;
2530
2531 ath6kl_dbg(ATH6KL_DBG_WMI, "%s: wmi id: %d\n", __func__, id);
2532 ath6kl_dbg_dump(ATH6KL_DBG_RAW_BYTES, "msg payload ", datap, len);
2533
2534 switch (id) {
2535 case WMI_GET_BITRATE_CMDID:
2536 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_BITRATE_CMDID\n");
2537 ret = ath6kl_wmi_bitrate_reply_rx(wmi, datap, len);
2538 break;
2539 case WMI_GET_CHANNEL_LIST_CMDID:
2540 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_CHANNEL_LIST_CMDID\n");
2541 ret = ath6kl_wmi_ch_list_reply_rx(wmi, datap, len);
2542 break;
2543 case WMI_GET_TX_PWR_CMDID:
2544 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_TX_PWR_CMDID\n");
2545 ret = ath6kl_wmi_tx_pwr_reply_rx(wmi, datap, len);
2546 break;
2547 case WMI_READY_EVENTID:
2548 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_READY_EVENTID\n");
2549 ret = ath6kl_wmi_ready_event_rx(wmi, datap, len);
2550 break;
2551 case WMI_CONNECT_EVENTID:
2552 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CONNECT_EVENTID\n");
2553 ret = ath6kl_wmi_connect_event_rx(wmi, datap, len);
2554 break;
2555 case WMI_DISCONNECT_EVENTID:
2556 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DISCONNECT_EVENTID\n");
2557 ret = ath6kl_wmi_disconnect_event_rx(wmi, datap, len);
2558 break;
2559 case WMI_PEER_NODE_EVENTID:
2560 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PEER_NODE_EVENTID\n");
2561 ret = ath6kl_wmi_peer_node_event_rx(wmi, datap, len);
2562 break;
2563 case WMI_TKIP_MICERR_EVENTID:
2564 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TKIP_MICERR_EVENTID\n");
2565 ret = ath6kl_wmi_tkip_micerr_event_rx(wmi, datap, len);
2566 break;
2567 case WMI_BSSINFO_EVENTID:
2568 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_BSSINFO_EVENTID\n");
2569 ath6kl_wmi_convert_bssinfo_hdr2_to_hdr(skb, datap);
2570 ret = ath6kl_wmi_bssinfo_event_rx(wmi, skb->data, skb->len);
2571 break;
2572 case WMI_REGDOMAIN_EVENTID:
2573 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REGDOMAIN_EVENTID\n");
2574 break;
2575 case WMI_PSTREAM_TIMEOUT_EVENTID:
2576 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSTREAM_TIMEOUT_EVENTID\n");
2577 ret = ath6kl_wmi_pstream_timeout_event_rx(wmi, datap, len);
2578 break;
2579 case WMI_NEIGHBOR_REPORT_EVENTID:
2580 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_NEIGHBOR_REPORT_EVENTID\n");
2581 break;
2582 case WMI_SCAN_COMPLETE_EVENTID:
2583 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SCAN_COMPLETE_EVENTID\n");
2584 ret = ath6kl_wmi_scan_complete_rx(wmi, datap, len);
2585 break;
2586 case WMI_CMDERROR_EVENTID:
2587 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CMDERROR_EVENTID\n");
2588 ret = ath6kl_wmi_error_event_rx(wmi, datap, len);
2589 break;
2590 case WMI_REPORT_STATISTICS_EVENTID:
2591 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_STATISTICS_EVENTID\n");
2592 ret = ath6kl_wmi_stats_event_rx(wmi, datap, len);
2593 break;
2594 case WMI_RSSI_THRESHOLD_EVENTID:
2595 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_RSSI_THRESHOLD_EVENTID\n");
2596 ret = ath6kl_wmi_rssi_threshold_event_rx(wmi, datap, len);
2597 break;
2598 case WMI_ERROR_REPORT_EVENTID:
2599 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ERROR_REPORT_EVENTID\n");
2600 break;
2601 case WMI_OPT_RX_FRAME_EVENTID:
2602 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_OPT_RX_FRAME_EVENTID\n");
2603 ret = ath6kl_wmi_opt_frame_event_rx(wmi, datap, len);
2604 break;
2605 case WMI_REPORT_ROAM_TBL_EVENTID:
2606 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_TBL_EVENTID\n");
2607 break;
2608 case WMI_EXTENSION_EVENTID:
2609 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_EXTENSION_EVENTID\n");
2610 ret = ath6kl_wmi_control_rx_xtnd(wmi, skb);
2611 break;
2612 case WMI_CAC_EVENTID:
2613 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CAC_EVENTID\n");
2614 ret = ath6kl_wmi_cac_event_rx(wmi, datap, len);
2615 break;
2616 case WMI_CHANNEL_CHANGE_EVENTID:
2617 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_CHANNEL_CHANGE_EVENTID\n");
2618 break;
2619 case WMI_REPORT_ROAM_DATA_EVENTID:
2620 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_REPORT_ROAM_DATA_EVENTID\n");
2621 break;
2622 case WMI_GET_FIXRATES_CMDID:
2623 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_FIXRATES_CMDID\n");
2624 ret = ath6kl_wmi_ratemask_reply_rx(wmi, datap, len);
2625 break;
2626 case WMI_TX_RETRY_ERR_EVENTID:
2627 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_RETRY_ERR_EVENTID\n");
2628 break;
2629 case WMI_SNR_THRESHOLD_EVENTID:
2630 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SNR_THRESHOLD_EVENTID\n");
2631 ret = ath6kl_wmi_snr_threshold_event_rx(wmi, datap, len);
2632 break;
2633 case WMI_LQ_THRESHOLD_EVENTID:
2634 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_LQ_THRESHOLD_EVENTID\n");
2635 break;
2636 case WMI_APLIST_EVENTID:
2637 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_APLIST_EVENTID\n");
2638 ret = ath6kl_wmi_aplist_event_rx(wmi, datap, len);
2639 break;
2640 case WMI_GET_KEEPALIVE_CMDID:
2641 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_KEEPALIVE_CMDID\n");
2642 ret = ath6kl_wmi_keepalive_reply_rx(wmi, datap, len);
2643 break;
2644 case WMI_GET_WOW_LIST_EVENTID:
2645 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_WOW_LIST_EVENTID\n");
2646 ret = ath6kl_wmi_get_wow_list_event_rx(wmi, datap, len);
2647 break;
2648 case WMI_GET_PMKID_LIST_EVENTID:
2649 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_GET_PMKID_LIST_EVENTID\n");
2650 ret = ath6kl_wmi_get_pmkid_list_event_rx(wmi, datap, len);
2651 break;
2652 case WMI_PSPOLL_EVENTID:
2653 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_PSPOLL_EVENTID\n");
2654 ret = ath6kl_wmi_pspoll_event_rx(wmi, datap, len);
2655 break;
2656 case WMI_DTIMEXPIRY_EVENTID:
2657 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DTIMEXPIRY_EVENTID\n");
2658 ret = ath6kl_wmi_dtimexpiry_event_rx(wmi, datap, len);
2659 break;
2660 case WMI_SET_PARAMS_REPLY_EVENTID:
2661 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_SET_PARAMS_REPLY_EVENTID\n");
2662 break;
2663 case WMI_ADDBA_REQ_EVENTID:
2664 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_REQ_EVENTID\n");
2665 ret = ath6kl_wmi_addba_req_event_rx(wmi, datap, len);
2666 break;
2667 case WMI_ADDBA_RESP_EVENTID:
2668 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_ADDBA_RESP_EVENTID\n");
2669 break;
2670 case WMI_DELBA_REQ_EVENTID:
2671 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_DELBA_REQ_EVENTID\n");
2672 ret = ath6kl_wmi_delba_req_event_rx(wmi, datap, len);
2673 break;
2674 case WMI_REPORT_BTCOEX_CONFIG_EVENTID:
2675 ath6kl_dbg(ATH6KL_DBG_WMI,
2676 "WMI_REPORT_BTCOEX_CONFIG_EVENTID\n");
2677 break;
2678 case WMI_REPORT_BTCOEX_STATS_EVENTID:
2679 ath6kl_dbg(ATH6KL_DBG_WMI,
2680 "WMI_REPORT_BTCOEX_STATS_EVENTID\n");
2681 break;
2682 case WMI_TX_COMPLETE_EVENTID:
2683 ath6kl_dbg(ATH6KL_DBG_WMI, "WMI_TX_COMPLETE_EVENTID\n");
2684 ret = ath6kl_wmi_tx_complete_event_rx(datap, len);
2685 break;
2686 default:
2687 ath6kl_dbg(ATH6KL_DBG_WMI, "unknown cmd id 0x%x\n", id);
2688 wmi->stat.cmd_id_err++;
2689 ret = -EINVAL;
2690 break;
2691 }
2692
2693 dev_kfree_skb(skb);
2694
2695 return ret;
2696}
2697
2698static void ath6kl_wmi_qos_state_init(struct wmi *wmi)
2699{
2700 if (!wmi)
2701 return;
2702
2703 spin_lock_bh(&wmi->lock);
2704
2705 wmi->fat_pipe_exist = 0;
2706 memset(wmi->stream_exist_for_ac, 0, sizeof(wmi->stream_exist_for_ac));
2707
2708 spin_unlock_bh(&wmi->lock);
2709}
2710
2711void *ath6kl_wmi_init(struct ath6kl *dev)
2712{
2713 struct wmi *wmi;
2714
2715 wmi = kzalloc(sizeof(struct wmi), GFP_KERNEL);
2716 if (!wmi)
2717 return NULL;
2718
2719 spin_lock_init(&wmi->lock);
2720
2721 wmi->parent_dev = dev;
2722
2723 ath6kl_wmi_qos_state_init(wmi);
2724
2725 wmi->pwr_mode = REC_POWER;
2726 wmi->phy_mode = WMI_11G_MODE;
2727
2728 wmi->pair_crypto_type = NONE_CRYPT;
2729 wmi->grp_crypto_type = NONE_CRYPT;
2730
2731 wmi->ht_allowed[A_BAND_24GHZ] = 1;
2732 wmi->ht_allowed[A_BAND_5GHZ] = 1;
2733
2734 return wmi;
2735}
2736
2737void ath6kl_wmi_shutdown(struct wmi *wmi)
2738{
2739 if (!wmi)
2740 return;
2741
2742 kfree(wmi);
2743}
diff --git a/drivers/net/wireless/ath/ath6kl/wmi.h b/drivers/net/wireless/ath/ath6kl/wmi.h
new file mode 100644
index 000000000000..fe3ddce64087
--- /dev/null
+++ b/drivers/net/wireless/ath/ath6kl/wmi.h
@@ -0,0 +1,2018 @@
1/*
2 * Copyright (c) 2010-2011 Atheros Communications Inc.
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17/*
18 * This file contains the definitions of the WMI protocol specified in the
19 * Wireless Module Interface (WMI). It includes definitions of all the
20 * commands and events. Commands are messages from the host to the WM.
21 * Events and Replies are messages from the WM to the host.
22 */
23
24#ifndef WMI_H
25#define WMI_H
26
27#include <linux/ieee80211.h>
28
29#include "htc.h"
30
31#define HTC_PROTOCOL_VERSION 0x0002
32#define WMI_PROTOCOL_VERSION 0x0002
33#define WMI_CONTROL_MSG_MAX_LEN 256
34#define is_ethertype(type_or_len) ((type_or_len) >= 0x0600)
35
36#define IP_ETHERTYPE 0x0800
37
38#define WMI_IMPLICIT_PSTREAM 0xFF
39#define WMI_MAX_THINSTREAM 15
40
41#define SSID_IE_LEN_INDEX 13
42
43/* Host side link management data structures */
44#define SIG_QUALITY_THRESH_LVLS 6
45#define SIG_QUALITY_UPPER_THRESH_LVLS SIG_QUALITY_THRESH_LVLS
46#define SIG_QUALITY_LOWER_THRESH_LVLS SIG_QUALITY_THRESH_LVLS
47
48#define A_BAND_24GHZ 0
49#define A_BAND_5GHZ 1
50#define A_NUM_BANDS 2
51
52/* in ms */
53#define WMI_IMPLICIT_PSTREAM_INACTIVITY_INT 5000
54
55/*
56 * There are no signed versions of __le16 and __le32, so for a temporary
57 * solution come up with our own version. The idea is from fs/ntfs/types.h.
58 *
59 * Use a_ prefix so that it doesn't conflict if we get proper support to
60 * linux/types.h.
61 */
62typedef __s16 __bitwise a_sle16;
63typedef __s32 __bitwise a_sle32;
64
65static inline a_sle32 a_cpu_to_sle32(s32 val)
66{
67 return (__force a_sle32) cpu_to_le32(val);
68}
69
70static inline s32 a_sle32_to_cpu(a_sle32 val)
71{
72 return le32_to_cpu((__force __le32) val);
73}
74
75static inline a_sle16 a_cpu_to_sle16(s16 val)
76{
77 return (__force a_sle16) cpu_to_le16(val);
78}
79
80static inline s16 a_sle16_to_cpu(a_sle16 val)
81{
82 return le16_to_cpu((__force __le16) val);
83}
84
85struct sq_threshold_params {
86 s16 upper_threshold[SIG_QUALITY_UPPER_THRESH_LVLS];
87 s16 lower_threshold[SIG_QUALITY_LOWER_THRESH_LVLS];
88 u32 upper_threshold_valid_count;
89 u32 lower_threshold_valid_count;
90 u32 polling_interval;
91 u8 weight;
92 u8 last_rssi;
93 u8 last_rssi_poll_event;
94};
95
96struct wmi_stats {
97 u32 cmd_len_err;
98 u32 cmd_id_err;
99};
100
101struct wmi_data_sync_bufs {
102 u8 traffic_class;
103 struct sk_buff *skb;
104};
105
106/* WMM stream classes */
107#define WMM_NUM_AC 4
108#define WMM_AC_BE 0 /* best effort */
109#define WMM_AC_BK 1 /* background */
110#define WMM_AC_VI 2 /* video */
111#define WMM_AC_VO 3 /* voice */
112
113struct wmi {
114 bool ready;
115 u16 stream_exist_for_ac[WMM_NUM_AC];
116 u8 fat_pipe_exist;
117 struct ath6kl *parent_dev;
118 struct wmi_stats stat;
119 u8 pwr_mode;
120 u8 phy_mode;
121 u8 keep_alive_intvl;
122 spinlock_t lock;
123 enum htc_endpoint_id ep_id;
124 struct sq_threshold_params
125 sq_threshld[SIGNAL_QUALITY_METRICS_NUM_MAX];
126 enum crypto_type pair_crypto_type;
127 enum crypto_type grp_crypto_type;
128 bool is_wmm_enabled;
129 u8 ht_allowed[A_NUM_BANDS];
130 u8 traffic_class;
131 bool is_probe_ssid;
132};
133
134struct host_app_area {
135 u32 wmi_protocol_ver;
136};
137
138enum wmi_msg_type {
139 DATA_MSGTYPE = 0x0,
140 CNTL_MSGTYPE,
141 SYNC_MSGTYPE,
142 OPT_MSGTYPE,
143};
144
145/*
146 * Macros for operating on WMI_DATA_HDR (info) field
147 */
148
149#define WMI_DATA_HDR_MSG_TYPE_MASK 0x03
150#define WMI_DATA_HDR_MSG_TYPE_SHIFT 0
151#define WMI_DATA_HDR_UP_MASK 0x07
152#define WMI_DATA_HDR_UP_SHIFT 2
153
154/* In AP mode, the same bit (b5) is used to indicate Power save state in
155 * the Rx dir and More data bit state in the tx direction.
156 */
157#define WMI_DATA_HDR_PS_MASK 0x1
158#define WMI_DATA_HDR_PS_SHIFT 5
159
160#define WMI_DATA_HDR_MORE_MASK 0x1
161#define WMI_DATA_HDR_MORE_SHIFT 5
162
163enum wmi_data_hdr_data_type {
164 WMI_DATA_HDR_DATA_TYPE_802_3 = 0,
165 WMI_DATA_HDR_DATA_TYPE_802_11,
166
167 /* used to be used for the PAL */
168 WMI_DATA_HDR_DATA_TYPE_ACL,
169};
170
171#define WMI_DATA_HDR_DATA_TYPE_MASK 0x3
172#define WMI_DATA_HDR_DATA_TYPE_SHIFT 6
173
174/* Macros for operating on WMI_DATA_HDR (info2) field */
175#define WMI_DATA_HDR_SEQNO_MASK 0xFFF
176#define WMI_DATA_HDR_SEQNO_SHIFT 0
177
178#define WMI_DATA_HDR_AMSDU_MASK 0x1
179#define WMI_DATA_HDR_AMSDU_SHIFT 12
180
181#define WMI_DATA_HDR_META_MASK 0x7
182#define WMI_DATA_HDR_META_SHIFT 13
183
184struct wmi_data_hdr {
185 s8 rssi;
186
187 /*
188 * usage of 'info' field(8-bit):
189 *
190 * b1:b0 - WMI_MSG_TYPE
191 * b4:b3:b2 - UP(tid)
192 * b5 - Used in AP mode.
193 * More-data in tx dir, PS in rx.
194 * b7:b6 - Dot3 header(0),
195 * Dot11 Header(1),
196 * ACL data(2)
197 */
198 u8 info;
199
200 /*
201 * usage of 'info2' field(16-bit):
202 *
203 * b11:b0 - seq_no
204 * b12 - A-MSDU?
205 * b15:b13 - META_DATA_VERSION 0 - 7
206 */
207 __le16 info2;
208 __le16 info3;
209} __packed;
210
211static inline u8 wmi_data_hdr_get_up(struct wmi_data_hdr *dhdr)
212{
213 return (dhdr->info >> WMI_DATA_HDR_UP_SHIFT) & WMI_DATA_HDR_UP_MASK;
214}
215
216static inline void wmi_data_hdr_set_up(struct wmi_data_hdr *dhdr,
217 u8 usr_pri)
218{
219 dhdr->info &= ~(WMI_DATA_HDR_UP_MASK << WMI_DATA_HDR_UP_SHIFT);
220 dhdr->info |= usr_pri << WMI_DATA_HDR_UP_SHIFT;
221}
222
223static inline u8 wmi_data_hdr_get_dot11(struct wmi_data_hdr *dhdr)
224{
225 u8 data_type;
226
227 data_type = (dhdr->info >> WMI_DATA_HDR_DATA_TYPE_SHIFT) &
228 WMI_DATA_HDR_DATA_TYPE_MASK;
229 return (data_type == WMI_DATA_HDR_DATA_TYPE_802_11);
230}
231
232static inline u16 wmi_data_hdr_get_seqno(struct wmi_data_hdr *dhdr)
233{
234 return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_SEQNO_SHIFT) &
235 WMI_DATA_HDR_SEQNO_MASK;
236}
237
238static inline u8 wmi_data_hdr_is_amsdu(struct wmi_data_hdr *dhdr)
239{
240 return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_AMSDU_SHIFT) &
241 WMI_DATA_HDR_AMSDU_MASK;
242}
243
244static inline u8 wmi_data_hdr_get_meta(struct wmi_data_hdr *dhdr)
245{
246 return (le16_to_cpu(dhdr->info2) >> WMI_DATA_HDR_META_SHIFT) &
247 WMI_DATA_HDR_META_MASK;
248}
249
250/* Tx meta version definitions */
251#define WMI_MAX_TX_META_SZ 12
252#define WMI_META_VERSION_1 0x01
253#define WMI_META_VERSION_2 0x02
254
255struct wmi_tx_meta_v1 {
256 /* packet ID to identify the tx request */
257 u8 pkt_id;
258
259 /* rate policy to be used for the tx of this frame */
260 u8 rate_plcy_id;
261} __packed;
262
263struct wmi_tx_meta_v2 {
264 /*
265 * Offset from start of the WMI header for csum calculation to
266 * begin.
267 */
268 u8 csum_start;
269
270 /* offset from start of WMI header where final csum goes */
271 u8 csum_dest;
272
273 /* no of bytes over which csum is calculated */
274 u8 csum_flags;
275} __packed;
276
277struct wmi_rx_meta_v1 {
278 u8 status;
279
280 /* rate index mapped to rate at which this packet was received. */
281 u8 rix;
282
283 /* rssi of packet */
284 u8 rssi;
285
286 /* rf channel during packet reception */
287 u8 channel;
288
289 __le16 flags;
290} __packed;
291
292struct wmi_rx_meta_v2 {
293 __le16 csum;
294
295 /* bit 0 set -partial csum valid bit 1 set -test mode */
296 u8 csum_flags;
297} __packed;
298
299/* Control Path */
300struct wmi_cmd_hdr {
301 __le16 cmd_id;
302
303 /* info1 - 16 bits
304 * b03:b00 - id
305 * b15:b04 - unused */
306 __le16 info1;
307
308 /* for alignment */
309 __le16 reserved;
310} __packed;
311
312/* List of WMI commands */
313enum wmi_cmd_id {
314 WMI_CONNECT_CMDID = 0x0001,
315 WMI_RECONNECT_CMDID,
316 WMI_DISCONNECT_CMDID,
317 WMI_SYNCHRONIZE_CMDID,
318 WMI_CREATE_PSTREAM_CMDID,
319 WMI_DELETE_PSTREAM_CMDID,
320 WMI_START_SCAN_CMDID,
321 WMI_SET_SCAN_PARAMS_CMDID,
322 WMI_SET_BSS_FILTER_CMDID,
323 WMI_SET_PROBED_SSID_CMDID, /* 10 */
324 WMI_SET_LISTEN_INT_CMDID,
325 WMI_SET_BMISS_TIME_CMDID,
326 WMI_SET_DISC_TIMEOUT_CMDID,
327 WMI_GET_CHANNEL_LIST_CMDID,
328 WMI_SET_BEACON_INT_CMDID,
329 WMI_GET_STATISTICS_CMDID,
330 WMI_SET_CHANNEL_PARAMS_CMDID,
331 WMI_SET_POWER_MODE_CMDID,
332 WMI_SET_IBSS_PM_CAPS_CMDID,
333 WMI_SET_POWER_PARAMS_CMDID, /* 20 */
334 WMI_SET_POWERSAVE_TIMERS_POLICY_CMDID,
335 WMI_ADD_CIPHER_KEY_CMDID,
336 WMI_DELETE_CIPHER_KEY_CMDID,
337 WMI_ADD_KRK_CMDID,
338 WMI_DELETE_KRK_CMDID,
339 WMI_SET_PMKID_CMDID,
340 WMI_SET_TX_PWR_CMDID,
341 WMI_GET_TX_PWR_CMDID,
342 WMI_SET_ASSOC_INFO_CMDID,
343 WMI_ADD_BAD_AP_CMDID, /* 30 */
344 WMI_DELETE_BAD_AP_CMDID,
345 WMI_SET_TKIP_COUNTERMEASURES_CMDID,
346 WMI_RSSI_THRESHOLD_PARAMS_CMDID,
347 WMI_TARGET_ERROR_REPORT_BITMASK_CMDID,
348 WMI_SET_ACCESS_PARAMS_CMDID,
349 WMI_SET_RETRY_LIMITS_CMDID,
350 WMI_SET_OPT_MODE_CMDID,
351 WMI_OPT_TX_FRAME_CMDID,
352 WMI_SET_VOICE_PKT_SIZE_CMDID,
353 WMI_SET_MAX_SP_LEN_CMDID, /* 40 */
354 WMI_SET_ROAM_CTRL_CMDID,
355 WMI_GET_ROAM_TBL_CMDID,
356 WMI_GET_ROAM_DATA_CMDID,
357 WMI_ENABLE_RM_CMDID,
358 WMI_SET_MAX_OFFHOME_DURATION_CMDID,
359 WMI_EXTENSION_CMDID, /* Non-wireless extensions */
360 WMI_SNR_THRESHOLD_PARAMS_CMDID,
361 WMI_LQ_THRESHOLD_PARAMS_CMDID,
362 WMI_SET_LPREAMBLE_CMDID,
363 WMI_SET_RTS_CMDID, /* 50 */
364 WMI_CLR_RSSI_SNR_CMDID,
365 WMI_SET_FIXRATES_CMDID,
366 WMI_GET_FIXRATES_CMDID,
367 WMI_SET_AUTH_MODE_CMDID,
368 WMI_SET_REASSOC_MODE_CMDID,
369 WMI_SET_WMM_CMDID,
370 WMI_SET_WMM_TXOP_CMDID,
371 WMI_TEST_CMDID,
372
373 /* COEX AR6002 only */
374 WMI_SET_BT_STATUS_CMDID,
375 WMI_SET_BT_PARAMS_CMDID, /* 60 */
376
377 WMI_SET_KEEPALIVE_CMDID,
378 WMI_GET_KEEPALIVE_CMDID,
379 WMI_SET_APPIE_CMDID,
380 WMI_GET_APPIE_CMDID,
381 WMI_SET_WSC_STATUS_CMDID,
382
383 /* Wake on Wireless */
384 WMI_SET_HOST_SLEEP_MODE_CMDID,
385 WMI_SET_WOW_MODE_CMDID,
386 WMI_GET_WOW_LIST_CMDID,
387 WMI_ADD_WOW_PATTERN_CMDID,
388 WMI_DEL_WOW_PATTERN_CMDID, /* 70 */
389
390 WMI_SET_FRAMERATES_CMDID,
391 WMI_SET_AP_PS_CMDID,
392 WMI_SET_QOS_SUPP_CMDID,
393
394 /* WMI_THIN_RESERVED_... mark the start and end
395 * values for WMI_THIN_RESERVED command IDs. These
396 * command IDs can be found in wmi_thin.h */
397 WMI_THIN_RESERVED_START = 0x8000,
398 WMI_THIN_RESERVED_END = 0x8fff,
399
400 /* Developer commands starts at 0xF000 */
401 WMI_SET_BITRATE_CMDID = 0xF000,
402 WMI_GET_BITRATE_CMDID,
403 WMI_SET_WHALPARAM_CMDID,
404 WMI_SET_MAC_ADDRESS_CMDID,
405 WMI_SET_AKMP_PARAMS_CMDID,
406 WMI_SET_PMKID_LIST_CMDID,
407 WMI_GET_PMKID_LIST_CMDID,
408 WMI_ABORT_SCAN_CMDID,
409 WMI_SET_TARGET_EVENT_REPORT_CMDID,
410
411 /* Unused */
412 WMI_UNUSED1,
413 WMI_UNUSED2,
414
415 /* AP mode commands */
416 WMI_AP_HIDDEN_SSID_CMDID,
417 WMI_AP_SET_NUM_STA_CMDID,
418 WMI_AP_ACL_POLICY_CMDID,
419 WMI_AP_ACL_MAC_LIST_CMDID,
420 WMI_AP_CONFIG_COMMIT_CMDID,
421 WMI_AP_SET_MLME_CMDID,
422 WMI_AP_SET_PVB_CMDID,
423 WMI_AP_CONN_INACT_CMDID,
424 WMI_AP_PROT_SCAN_TIME_CMDID,
425 WMI_AP_SET_COUNTRY_CMDID,
426 WMI_AP_SET_DTIM_CMDID,
427 WMI_AP_MODE_STAT_CMDID,
428
429 WMI_SET_IP_CMDID,
430 WMI_SET_PARAMS_CMDID,
431 WMI_SET_MCAST_FILTER_CMDID,
432 WMI_DEL_MCAST_FILTER_CMDID,
433
434 WMI_ALLOW_AGGR_CMDID,
435 WMI_ADDBA_REQ_CMDID,
436 WMI_DELBA_REQ_CMDID,
437 WMI_SET_HT_CAP_CMDID,
438 WMI_SET_HT_OP_CMDID,
439 WMI_SET_TX_SELECT_RATES_CMDID,
440 WMI_SET_TX_SGI_PARAM_CMDID,
441 WMI_SET_RATE_POLICY_CMDID,
442
443 WMI_HCI_CMD_CMDID,
444 WMI_RX_FRAME_FORMAT_CMDID,
445 WMI_SET_THIN_MODE_CMDID,
446 WMI_SET_BT_WLAN_CONN_PRECEDENCE_CMDID,
447
448 WMI_AP_SET_11BG_RATESET_CMDID,
449 WMI_SET_PMK_CMDID,
450 WMI_MCAST_FILTER_CMDID,
451
452 /* COEX CMDID AR6003 */
453 WMI_SET_BTCOEX_FE_ANT_CMDID,
454 WMI_SET_BTCOEX_COLOCATED_BT_DEV_CMDID,
455 WMI_SET_BTCOEX_SCO_CONFIG_CMDID,
456 WMI_SET_BTCOEX_A2DP_CONFIG_CMDID,
457 WMI_SET_BTCOEX_ACLCOEX_CONFIG_CMDID,
458 WMI_SET_BTCOEX_BTINQUIRY_PAGE_CONFIG_CMDID,
459 WMI_SET_BTCOEX_DEBUG_CMDID,
460 WMI_SET_BTCOEX_BT_OPERATING_STATUS_CMDID,
461 WMI_GET_BTCOEX_STATS_CMDID,
462 WMI_GET_BTCOEX_CONFIG_CMDID,
463
464 WMI_SET_DFS_ENABLE_CMDID, /* F034 */
465 WMI_SET_DFS_MINRSSITHRESH_CMDID,
466 WMI_SET_DFS_MAXPULSEDUR_CMDID,
467 WMI_DFS_RADAR_DETECTED_CMDID,
468
469 /* P2P commands */
470 WMI_P2P_SET_CONFIG_CMDID, /* F038 */
471 WMI_WPS_SET_CONFIG_CMDID,
472 WMI_SET_REQ_DEV_ATTR_CMDID,
473 WMI_P2P_FIND_CMDID,
474 WMI_P2P_STOP_FIND_CMDID,
475 WMI_P2P_GO_NEG_START_CMDID,
476 WMI_P2P_LISTEN_CMDID,
477
478 WMI_CONFIG_TX_MAC_RULES_CMDID, /* F040 */
479 WMI_SET_PROMISCUOUS_MODE_CMDID,
480 WMI_RX_FRAME_FILTER_CMDID,
481 WMI_SET_CHANNEL_CMDID,
482
483 /* WAC commands */
484 WMI_ENABLE_WAC_CMDID,
485 WMI_WAC_SCAN_REPLY_CMDID,
486 WMI_WAC_CTRL_REQ_CMDID,
487 WMI_SET_DIV_PARAMS_CMDID,
488
489 WMI_GET_PMK_CMDID,
490 WMI_SET_PASSPHRASE_CMDID,
491 WMI_SEND_ASSOC_RES_CMDID,
492 WMI_SET_ASSOC_REQ_RELAY_CMDID,
493 WMI_GET_RFKILL_MODE_CMDID,
494
495 /* ACS command, consists of sub-commands */
496 WMI_ACS_CTRL_CMDID,
497
498 /* Ultra low power store / recall commands */
499 WMI_STORERECALL_CONFIGURE_CMDID,
500 WMI_STORERECALL_RECALL_CMDID,
501 WMI_STORERECALL_HOST_READY_CMDID,
502 WMI_FORCE_TARGET_ASSERT_CMDID,
503 WMI_SET_EXCESS_TX_RETRY_THRES_CMDID,
504};
505
506/* WMI_CONNECT_CMDID */
507enum network_type {
508 INFRA_NETWORK = 0x01,
509 ADHOC_NETWORK = 0x02,
510 ADHOC_CREATOR = 0x04,
511 AP_NETWORK = 0x10,
512};
513
514enum dot11_auth_mode {
515 OPEN_AUTH = 0x01,
516 SHARED_AUTH = 0x02,
517
518 /* different from IEEE_AUTH_MODE definitions */
519 LEAP_AUTH = 0x04,
520};
521
522enum {
523 AUTH_IDLE,
524 AUTH_OPEN_IN_PROGRESS,
525};
526
527enum auth_mode {
528 NONE_AUTH = 0x01,
529 WPA_AUTH = 0x02,
530 WPA2_AUTH = 0x04,
531 WPA_PSK_AUTH = 0x08,
532 WPA2_PSK_AUTH = 0x10,
533 WPA_AUTH_CCKM = 0x20,
534 WPA2_AUTH_CCKM = 0x40,
535};
536
537#define WMI_MIN_CRYPTO_TYPE NONE_CRYPT
538#define WMI_MAX_CRYPTO_TYPE (AES_CRYPT + 1)
539
540#define WMI_MIN_KEY_INDEX 0
541#define WMI_MAX_KEY_INDEX 3
542
543#define WMI_MAX_KEY_LEN 32
544
545/*
546 * NB: these values are ordered carefully; there are lots of
547 * of implications in any reordering. In particular beware
548 * that 4 is not used to avoid conflicting with IEEE80211_F_PRIVACY.
549 */
550#define ATH6KL_CIPHER_WEP 0
551#define ATH6KL_CIPHER_TKIP 1
552#define ATH6KL_CIPHER_AES_OCB 2
553#define ATH6KL_CIPHER_AES_CCM 3
554#define ATH6KL_CIPHER_CKIP 5
555#define ATH6KL_CIPHER_CCKM_KRK 6
556#define ATH6KL_CIPHER_NONE 7 /* pseudo value */
557
558/*
559 * 802.11 rate set.
560 */
561#define ATH6KL_RATE_MAXSIZE 15 /* max rates we'll handle */
562
563#define ATH_OUI_TYPE 0x01
564#define WPA_OUI_TYPE 0x01
565#define WMM_PARAM_OUI_SUBTYPE 0x01
566#define WMM_OUI_TYPE 0x02
567#define WSC_OUT_TYPE 0x04
568
569enum wmi_connect_ctrl_flags_bits {
570 CONNECT_ASSOC_POLICY_USER = 0x0001,
571 CONNECT_SEND_REASSOC = 0x0002,
572 CONNECT_IGNORE_WPAx_GROUP_CIPHER = 0x0004,
573 CONNECT_PROFILE_MATCH_DONE = 0x0008,
574 CONNECT_IGNORE_AAC_BEACON = 0x0010,
575 CONNECT_CSA_FOLLOW_BSS = 0x0020,
576 CONNECT_DO_WPA_OFFLOAD = 0x0040,
577 CONNECT_DO_NOT_DEAUTH = 0x0080,
578};
579
580struct wmi_connect_cmd {
581 u8 nw_type;
582 u8 dot11_auth_mode;
583 u8 auth_mode;
584 u8 prwise_crypto_type;
585 u8 prwise_crypto_len;
586 u8 grp_crypto_type;
587 u8 grp_crypto_len;
588 u8 ssid_len;
589 u8 ssid[IEEE80211_MAX_SSID_LEN];
590 __le16 ch;
591 u8 bssid[ETH_ALEN];
592 __le32 ctrl_flags;
593} __packed;
594
595/* WMI_RECONNECT_CMDID */
596struct wmi_reconnect_cmd {
597 /* channel hint */
598 __le16 channel;
599
600 /* mandatory if set */
601 u8 bssid[ETH_ALEN];
602} __packed;
603
604/* WMI_ADD_CIPHER_KEY_CMDID */
605enum key_usage {
606 PAIRWISE_USAGE = 0x00,
607 GROUP_USAGE = 0x01,
608
609 /* default Tx Key - static WEP only */
610 TX_USAGE = 0x02,
611};
612
613/*
614 * Bit Flag
615 * Bit 0 - Initialise TSC - default is Initialize
616 */
617#define KEY_OP_INIT_TSC 0x01
618#define KEY_OP_INIT_RSC 0x02
619
620/* default initialise the TSC & RSC */
621#define KEY_OP_INIT_VAL 0x03
622#define KEY_OP_VALID_MASK 0x03
623
624struct wmi_add_cipher_key_cmd {
625 u8 key_index;
626 u8 key_type;
627
628 /* enum key_usage */
629 u8 key_usage;
630
631 u8 key_len;
632
633 /* key replay sequence counter */
634 u8 key_rsc[8];
635
636 u8 key[WLAN_MAX_KEY_LEN];
637
638 /* additional key control info */
639 u8 key_op_ctrl;
640
641 u8 key_mac_addr[ETH_ALEN];
642} __packed;
643
644/* WMI_DELETE_CIPHER_KEY_CMDID */
645struct wmi_delete_cipher_key_cmd {
646 u8 key_index;
647} __packed;
648
649#define WMI_KRK_LEN 16
650
651/* WMI_ADD_KRK_CMDID */
652struct wmi_add_krk_cmd {
653 u8 krk[WMI_KRK_LEN];
654} __packed;
655
656/* WMI_SETPMKID_CMDID */
657
658#define WMI_PMKID_LEN 16
659
660enum pmkid_enable_flg {
661 PMKID_DISABLE = 0,
662 PMKID_ENABLE = 1,
663};
664
665struct wmi_setpmkid_cmd {
666 u8 bssid[ETH_ALEN];
667
668 /* enum pmkid_enable_flg */
669 u8 enable;
670
671 u8 pmkid[WMI_PMKID_LEN];
672} __packed;
673
674/* WMI_START_SCAN_CMD */
675enum wmi_scan_type {
676 WMI_LONG_SCAN = 0,
677 WMI_SHORT_SCAN = 1,
678};
679
680struct wmi_start_scan_cmd {
681 __le32 force_fg_scan;
682
683 /* for legacy cisco AP compatibility */
684 __le32 is_legacy;
685
686 /* max duration in the home channel(msec) */
687 __le32 home_dwell_time;
688
689 /* time interval between scans (msec) */
690 __le32 force_scan_intvl;
691
692 /* enum wmi_scan_type */
693 u8 scan_type;
694
695 /* how many channels follow */
696 u8 num_ch;
697
698 /* channels in Mhz */
699 __le16 ch_list[1];
700} __packed;
701
702/* WMI_SET_SCAN_PARAMS_CMDID */
703#define WMI_SHORTSCANRATIO_DEFAULT 3
704
705/*
706 * Warning: scan control flag value of 0xFF is used to disable
707 * all flags in WMI_SCAN_PARAMS_CMD. Do not add any more
708 * flags here
709 */
710enum wmi_scan_ctrl_flags_bits {
711
712 /* set if can scan in the connect cmd */
713 CONNECT_SCAN_CTRL_FLAGS = 0x01,
714
715 /* set if scan for the SSID it is already connected to */
716 SCAN_CONNECTED_CTRL_FLAGS = 0x02,
717
718 /* set if enable active scan */
719 ACTIVE_SCAN_CTRL_FLAGS = 0x04,
720
721 /* set if enable roam scan when bmiss and lowrssi */
722 ROAM_SCAN_CTRL_FLAGS = 0x08,
723
724 /* set if follows customer BSSINFO reporting rule */
725 REPORT_BSSINFO_CTRL_FLAGS = 0x10,
726
727 /* if disabled, target doesn't scan after a disconnect event */
728 ENABLE_AUTO_CTRL_FLAGS = 0x20,
729
730 /*
731 * Scan complete event with canceled status will be generated when
732 * a scan is prempted before it gets completed.
733 */
734 ENABLE_SCAN_ABORT_EVENT = 0x40
735};
736
737#define DEFAULT_SCAN_CTRL_FLAGS \
738 (CONNECT_SCAN_CTRL_FLAGS | \
739 SCAN_CONNECTED_CTRL_FLAGS | \
740 ACTIVE_SCAN_CTRL_FLAGS | \
741 ROAM_SCAN_CTRL_FLAGS | \
742 ENABLE_AUTO_CTRL_FLAGS)
743
744struct wmi_scan_params_cmd {
745 /* sec */
746 __le16 fg_start_period;
747
748 /* sec */
749 __le16 fg_end_period;
750
751 /* sec */
752 __le16 bg_period;
753
754 /* msec */
755 __le16 maxact_chdwell_time;
756
757 /* msec */
758 __le16 pas_chdwell_time;
759
760 /* how many shorts scan for one long */
761 u8 short_scan_ratio;
762
763 u8 scan_ctrl_flags;
764
765 /* msec */
766 __le16 minact_chdwell_time;
767
768 /* max active scans per ssid */
769 __le16 maxact_scan_per_ssid;
770
771 /* msecs */
772 __le32 max_dfsch_act_time;
773} __packed;
774
775/* WMI_SET_BSS_FILTER_CMDID */
776enum wmi_bss_filter {
777 /* no beacons forwarded */
778 NONE_BSS_FILTER = 0x0,
779
780 /* all beacons forwarded */
781 ALL_BSS_FILTER,
782
783 /* only beacons matching profile */
784 PROFILE_FILTER,
785
786 /* all but beacons matching profile */
787 ALL_BUT_PROFILE_FILTER,
788
789 /* only beacons matching current BSS */
790 CURRENT_BSS_FILTER,
791
792 /* all but beacons matching BSS */
793 ALL_BUT_BSS_FILTER,
794
795 /* beacons matching probed ssid */
796 PROBED_SSID_FILTER,
797
798 /* marker only */
799 LAST_BSS_FILTER,
800};
801
802struct wmi_bss_filter_cmd {
803 /* see, enum wmi_bss_filter */
804 u8 bss_filter;
805
806 /* for alignment */
807 u8 reserved1;
808
809 /* for alignment */
810 __le16 reserved2;
811
812 __le32 ie_mask;
813} __packed;
814
815/* WMI_SET_PROBED_SSID_CMDID */
816#define MAX_PROBED_SSID_INDEX 9
817
818enum wmi_ssid_flag {
819 /* disables entry */
820 DISABLE_SSID_FLAG = 0,
821
822 /* probes specified ssid */
823 SPECIFIC_SSID_FLAG = 0x01,
824
825 /* probes for any ssid */
826 ANY_SSID_FLAG = 0x02,
827};
828
829struct wmi_probed_ssid_cmd {
830 /* 0 to MAX_PROBED_SSID_INDEX */
831 u8 entry_index;
832
833 /* see, enum wmi_ssid_flg */
834 u8 flag;
835
836 u8 ssid_len;
837 u8 ssid[IEEE80211_MAX_SSID_LEN];
838} __packed;
839
840/*
841 * WMI_SET_LISTEN_INT_CMDID
842 * The Listen interval is between 15 and 3000 TUs
843 */
844struct wmi_listen_int_cmd {
845 __le16 listen_intvl;
846 __le16 num_beacons;
847} __packed;
848
849/* WMI_SET_POWER_MODE_CMDID */
850enum wmi_power_mode {
851 REC_POWER = 0x01,
852 MAX_PERF_POWER,
853};
854
855struct wmi_power_mode_cmd {
856 /* see, enum wmi_power_mode */
857 u8 pwr_mode;
858} __packed;
859
860/*
861 * Policy to determnine whether power save failure event should be sent to
862 * host during scanning
863 */
864enum power_save_fail_event_policy {
865 SEND_POWER_SAVE_FAIL_EVENT_ALWAYS = 1,
866 IGNORE_POWER_SAVE_FAIL_EVENT_DURING_SCAN = 2,
867};
868
869struct wmi_power_params_cmd {
870 /* msec */
871 __le16 idle_period;
872
873 __le16 pspoll_number;
874 __le16 dtim_policy;
875 __le16 tx_wakeup_policy;
876 __le16 num_tx_to_wakeup;
877 __le16 ps_fail_event_policy;
878} __packed;
879
880/* WMI_SET_DISC_TIMEOUT_CMDID */
881struct wmi_disc_timeout_cmd {
882 /* seconds */
883 u8 discon_timeout;
884} __packed;
885
886enum dir_type {
887 UPLINK_TRAFFIC = 0,
888 DNLINK_TRAFFIC = 1,
889 BIDIR_TRAFFIC = 2,
890};
891
892enum voiceps_cap_type {
893 DISABLE_FOR_THIS_AC = 0,
894 ENABLE_FOR_THIS_AC = 1,
895 ENABLE_FOR_ALL_AC = 2,
896};
897
898enum traffic_type {
899 TRAFFIC_TYPE_APERIODIC = 0,
900 TRAFFIC_TYPE_PERIODIC = 1,
901};
902
903/* WMI_SYNCHRONIZE_CMDID */
904struct wmi_sync_cmd {
905 u8 data_sync_map;
906} __packed;
907
908/* WMI_CREATE_PSTREAM_CMDID */
909struct wmi_create_pstream_cmd {
910 /* msec */
911 __le32 min_service_int;
912
913 /* msec */
914 __le32 max_service_int;
915
916 /* msec */
917 __le32 inactivity_int;
918
919 /* msec */
920 __le32 suspension_int;
921
922 __le32 service_start_time;
923
924 /* in bps */
925 __le32 min_data_rate;
926
927 /* in bps */
928 __le32 mean_data_rate;
929
930 /* in bps */
931 __le32 peak_data_rate;
932
933 __le32 max_burst_size;
934 __le32 delay_bound;
935
936 /* in bps */
937 __le32 min_phy_rate;
938
939 __le32 sba;
940 __le32 medium_time;
941
942 /* in octects */
943 __le16 nominal_msdu;
944
945 /* in octects */
946 __le16 max_msdu;
947
948 u8 traffic_class;
949
950 /* see, enum dir_type */
951 u8 traffic_direc;
952
953 u8 rx_queue_num;
954
955 /* see, enum traffic_type */
956 u8 traffic_type;
957
958 /* see, enum voiceps_cap_type */
959 u8 voice_psc_cap;
960 u8 tsid;
961
962 /* 802.1D user priority */
963 u8 user_pri;
964
965 /* nominal phy rate */
966 u8 nominal_phy;
967} __packed;
968
969/* WMI_DELETE_PSTREAM_CMDID */
970struct wmi_delete_pstream_cmd {
971 u8 tx_queue_num;
972 u8 rx_queue_num;
973 u8 traffic_direc;
974 u8 traffic_class;
975 u8 tsid;
976} __packed;
977
978/* WMI_SET_CHANNEL_PARAMS_CMDID */
979enum wmi_phy_mode {
980 WMI_11A_MODE = 0x1,
981 WMI_11G_MODE = 0x2,
982 WMI_11AG_MODE = 0x3,
983 WMI_11B_MODE = 0x4,
984 WMI_11GONLY_MODE = 0x5,
985};
986
987#define WMI_MAX_CHANNELS 32
988
989/*
990 * WMI_RSSI_THRESHOLD_PARAMS_CMDID
991 * Setting the polltime to 0 would disable polling. Threshold values are
992 * in the ascending order, and should agree to:
993 * (lowThreshold_lowerVal < lowThreshold_upperVal < highThreshold_lowerVal
994 * < highThreshold_upperVal)
995 */
996
997struct wmi_rssi_threshold_params_cmd {
998 /* polling time as a factor of LI */
999 __le32 poll_time;
1000
1001 /* lowest of upper */
1002 a_sle16 thresh_above1_val;
1003
1004 a_sle16 thresh_above2_val;
1005 a_sle16 thresh_above3_val;
1006 a_sle16 thresh_above4_val;
1007 a_sle16 thresh_above5_val;
1008
1009 /* highest of upper */
1010 a_sle16 thresh_above6_val;
1011
1012 /* lowest of bellow */
1013 a_sle16 thresh_below1_val;
1014
1015 a_sle16 thresh_below2_val;
1016 a_sle16 thresh_below3_val;
1017 a_sle16 thresh_below4_val;
1018 a_sle16 thresh_below5_val;
1019
1020 /* highest of bellow */
1021 a_sle16 thresh_below6_val;
1022
1023 /* "alpha" */
1024 u8 weight;
1025
1026 u8 reserved[3];
1027} __packed;
1028
1029/*
1030 * WMI_SNR_THRESHOLD_PARAMS_CMDID
1031 * Setting the polltime to 0 would disable polling.
1032 */
1033
1034struct wmi_snr_threshold_params_cmd {
1035 /* polling time as a factor of LI */
1036 __le32 poll_time;
1037
1038 /* "alpha" */
1039 u8 weight;
1040
1041 /* lowest of uppper */
1042 u8 thresh_above1_val;
1043
1044 u8 thresh_above2_val;
1045 u8 thresh_above3_val;
1046
1047 /* highest of upper */
1048 u8 thresh_above4_val;
1049
1050 /* lowest of bellow */
1051 u8 thresh_below1_val;
1052
1053 u8 thresh_below2_val;
1054 u8 thresh_below3_val;
1055
1056 /* highest of bellow */
1057 u8 thresh_below4_val;
1058
1059 u8 reserved[3];
1060} __packed;
1061
1062enum wmi_preamble_policy {
1063 WMI_IGNORE_BARKER_IN_ERP = 0,
1064 WMI_DONOT_IGNORE_BARKER_IN_ERP
1065};
1066
1067struct wmi_set_lpreamble_cmd {
1068 u8 status;
1069 u8 preamble_policy;
1070} __packed;
1071
1072struct wmi_set_rts_cmd {
1073 __le16 threshold;
1074} __packed;
1075
1076/* WMI_SET_TX_PWR_CMDID */
1077struct wmi_set_tx_pwr_cmd {
1078 /* in dbM units */
1079 u8 dbM;
1080} __packed;
1081
1082struct wmi_tx_pwr_reply {
1083 /* in dbM units */
1084 u8 dbM;
1085} __packed;
1086
1087struct wmi_report_sleep_state_event {
1088 __le32 sleep_state;
1089};
1090
1091enum wmi_report_sleep_status {
1092 WMI_REPORT_SLEEP_STATUS_IS_DEEP_SLEEP = 0,
1093 WMI_REPORT_SLEEP_STATUS_IS_AWAKE
1094};
1095enum target_event_report_config {
1096 /* default */
1097 DISCONN_EVT_IN_RECONN = 0,
1098
1099 NO_DISCONN_EVT_IN_RECONN
1100};
1101
1102/* Command Replies */
1103
1104/* WMI_GET_CHANNEL_LIST_CMDID reply */
1105struct wmi_channel_list_reply {
1106 u8 reserved;
1107
1108 /* number of channels in reply */
1109 u8 num_ch;
1110
1111 /* channel in Mhz */
1112 __le16 ch_list[1];
1113} __packed;
1114
1115/* List of Events (target to host) */
1116enum wmi_event_id {
1117 WMI_READY_EVENTID = 0x1001,
1118 WMI_CONNECT_EVENTID,
1119 WMI_DISCONNECT_EVENTID,
1120 WMI_BSSINFO_EVENTID,
1121 WMI_CMDERROR_EVENTID,
1122 WMI_REGDOMAIN_EVENTID,
1123 WMI_PSTREAM_TIMEOUT_EVENTID,
1124 WMI_NEIGHBOR_REPORT_EVENTID,
1125 WMI_TKIP_MICERR_EVENTID,
1126 WMI_SCAN_COMPLETE_EVENTID, /* 0x100a */
1127 WMI_REPORT_STATISTICS_EVENTID,
1128 WMI_RSSI_THRESHOLD_EVENTID,
1129 WMI_ERROR_REPORT_EVENTID,
1130 WMI_OPT_RX_FRAME_EVENTID,
1131 WMI_REPORT_ROAM_TBL_EVENTID,
1132 WMI_EXTENSION_EVENTID,
1133 WMI_CAC_EVENTID,
1134 WMI_SNR_THRESHOLD_EVENTID,
1135 WMI_LQ_THRESHOLD_EVENTID,
1136 WMI_TX_RETRY_ERR_EVENTID, /* 0x1014 */
1137 WMI_REPORT_ROAM_DATA_EVENTID,
1138 WMI_TEST_EVENTID,
1139 WMI_APLIST_EVENTID,
1140 WMI_GET_WOW_LIST_EVENTID,
1141 WMI_GET_PMKID_LIST_EVENTID,
1142 WMI_CHANNEL_CHANGE_EVENTID,
1143 WMI_PEER_NODE_EVENTID,
1144 WMI_PSPOLL_EVENTID,
1145 WMI_DTIMEXPIRY_EVENTID,
1146 WMI_WLAN_VERSION_EVENTID,
1147 WMI_SET_PARAMS_REPLY_EVENTID,
1148 WMI_ADDBA_REQ_EVENTID, /*0x1020 */
1149 WMI_ADDBA_RESP_EVENTID,
1150 WMI_DELBA_REQ_EVENTID,
1151 WMI_TX_COMPLETE_EVENTID,
1152 WMI_HCI_EVENT_EVENTID,
1153 WMI_ACL_DATA_EVENTID,
1154 WMI_REPORT_SLEEP_STATE_EVENTID,
1155 WMI_REPORT_BTCOEX_STATS_EVENTID,
1156 WMI_REPORT_BTCOEX_CONFIG_EVENTID,
1157 WMI_GET_PMK_EVENTID,
1158
1159 /* DFS Events */
1160 WMI_DFS_HOST_ATTACH_EVENTID,
1161 WMI_DFS_HOST_INIT_EVENTID,
1162 WMI_DFS_RESET_DELAYLINES_EVENTID,
1163 WMI_DFS_RESET_RADARQ_EVENTID,
1164 WMI_DFS_RESET_AR_EVENTID,
1165 WMI_DFS_RESET_ARQ_EVENTID,
1166 WMI_DFS_SET_DUR_MULTIPLIER_EVENTID,
1167 WMI_DFS_SET_BANGRADAR_EVENTID,
1168 WMI_DFS_SET_DEBUGLEVEL_EVENTID,
1169 WMI_DFS_PHYERR_EVENTID,
1170
1171 /* CCX Evants */
1172 WMI_CCX_RM_STATUS_EVENTID,
1173
1174 /* P2P Events */
1175 WMI_P2P_GO_NEG_RESULT_EVENTID,
1176
1177 WMI_WAC_SCAN_DONE_EVENTID,
1178 WMI_WAC_REPORT_BSS_EVENTID,
1179 WMI_WAC_START_WPS_EVENTID,
1180 WMI_WAC_CTRL_REQ_REPLY_EVENTID,
1181
1182 /* RFKILL Events */
1183 WMI_RFKILL_STATE_CHANGE_EVENTID,
1184 WMI_RFKILL_GET_MODE_CMD_EVENTID,
1185 WMI_THIN_RESERVED_START_EVENTID = 0x8000,
1186
1187 /*
1188 * Events in this range are reserved for thinmode
1189 * See wmi_thin.h for actual definitions
1190 */
1191 WMI_THIN_RESERVED_END_EVENTID = 0x8fff,
1192
1193 WMI_SET_CHANNEL_EVENTID,
1194 WMI_ASSOC_REQ_EVENTID,
1195
1196 /* Generic ACS event */
1197 WMI_ACS_EVENTID,
1198 WMI_REPORT_WMM_PARAMS_EVENTID
1199};
1200
1201struct wmi_ready_event_2 {
1202 __le32 sw_version;
1203 __le32 abi_version;
1204 u8 mac_addr[ETH_ALEN];
1205 u8 phy_cap;
1206} __packed;
1207
1208/* Connect Event */
1209struct wmi_connect_event {
1210 __le16 ch;
1211 u8 bssid[ETH_ALEN];
1212 __le16 listen_intvl;
1213 __le16 beacon_intvl;
1214 __le32 nw_type;
1215 u8 beacon_ie_len;
1216 u8 assoc_req_len;
1217 u8 assoc_resp_len;
1218 u8 assoc_info[1];
1219} __packed;
1220
1221/* Disconnect Event */
1222enum wmi_disconnect_reason {
1223 NO_NETWORK_AVAIL = 0x01,
1224
1225 /* bmiss */
1226 LOST_LINK = 0x02,
1227
1228 DISCONNECT_CMD = 0x03,
1229 BSS_DISCONNECTED = 0x04,
1230 AUTH_FAILED = 0x05,
1231 ASSOC_FAILED = 0x06,
1232 NO_RESOURCES_AVAIL = 0x07,
1233 CSERV_DISCONNECT = 0x08,
1234 INVALID_PROFILE = 0x0a,
1235 DOT11H_CHANNEL_SWITCH = 0x0b,
1236 PROFILE_MISMATCH = 0x0c,
1237 CONNECTION_EVICTED = 0x0d,
1238 IBSS_MERGE = 0xe,
1239};
1240
1241struct wmi_disconnect_event {
1242 /* reason code, see 802.11 spec. */
1243 __le16 proto_reason_status;
1244
1245 /* set if known */
1246 u8 bssid[ETH_ALEN];
1247
1248 /* see WMI_DISCONNECT_REASON */
1249 u8 disconn_reason;
1250
1251 u8 assoc_resp_len;
1252 u8 assoc_info[1];
1253} __packed;
1254
1255/*
1256 * BSS Info Event.
1257 * Mechanism used to inform host of the presence and characteristic of
1258 * wireless networks present. Consists of bss info header followed by
1259 * the beacon or probe-response frame body. The 802.11 header is no included.
1260 */
1261enum wmi_bi_ftype {
1262 BEACON_FTYPE = 0x1,
1263 PROBERESP_FTYPE,
1264 ACTION_MGMT_FTYPE,
1265 PROBEREQ_FTYPE,
1266};
1267
1268struct wmi_bss_info_hdr {
1269 __le16 ch;
1270
1271 /* see, enum wmi_bi_ftype */
1272 u8 frame_type;
1273
1274 u8 snr;
1275 a_sle16 rssi;
1276 u8 bssid[ETH_ALEN];
1277 __le32 ie_mask;
1278} __packed;
1279
1280/*
1281 * BSS INFO HDR version 2.0
1282 * With 6 bytes HTC header and 6 bytes of WMI header
1283 * WMI_BSS_INFO_HDR cannot be accommodated in the removed 802.11 management
1284 * header space.
1285 * - Reduce the ie_mask to 2 bytes as only two bit flags are used
1286 * - Remove rssi and compute it on the host. rssi = snr - 95
1287 */
1288struct wmi_bss_info_hdr2 {
1289 __le16 ch;
1290
1291 /* see, enum wmi_bi_ftype */
1292 u8 frame_type;
1293
1294 u8 snr;
1295 u8 bssid[ETH_ALEN];
1296 __le16 ie_mask;
1297} __packed;
1298
1299/* Command Error Event */
1300enum wmi_error_code {
1301 INVALID_PARAM = 0x01,
1302 ILLEGAL_STATE = 0x02,
1303 INTERNAL_ERROR = 0x03,
1304};
1305
1306struct wmi_cmd_error_event {
1307 __le16 cmd_id;
1308 u8 err_code;
1309} __packed;
1310
1311struct wmi_pstream_timeout_event {
1312 u8 tx_queue_num;
1313 u8 rx_queue_num;
1314 u8 traffic_direc;
1315 u8 traffic_class;
1316} __packed;
1317
1318/*
1319 * The WMI_NEIGHBOR_REPORT Event is generated by the target to inform
1320 * the host of BSS's it has found that matches the current profile.
1321 * It can be used by the host to cache PMKs and/to initiate pre-authentication
1322 * if the BSS supports it. The first bssid is always the current associated
1323 * BSS.
1324 * The bssid and bssFlags information repeats according to the number
1325 * or APs reported.
1326 */
1327enum wmi_bss_flags {
1328 WMI_DEFAULT_BSS_FLAGS = 0x00,
1329 WMI_PREAUTH_CAPABLE_BSS = 0x01,
1330 WMI_PMKID_VALID_BSS = 0x02,
1331};
1332
1333/* TKIP MIC Error Event */
1334struct wmi_tkip_micerr_event {
1335 u8 key_id;
1336 u8 is_mcast;
1337} __packed;
1338
1339/* WMI_SCAN_COMPLETE_EVENTID */
1340struct wmi_scan_complete_event {
1341 a_sle32 status;
1342} __packed;
1343
1344#define MAX_OPT_DATA_LEN 1400
1345
1346/*
1347 * Special frame receive Event.
1348 * Mechanism used to inform host of the receiption of the special frames.
1349 * Consists of special frame info header followed by special frame body.
1350 * The 802.11 header is not included.
1351 */
1352struct wmi_opt_rx_info_hdr {
1353 __le16 ch;
1354 u8 frame_type;
1355 s8 snr;
1356 u8 src_addr[ETH_ALEN];
1357 u8 bssid[ETH_ALEN];
1358} __packed;
1359
1360/* Reporting statistic */
1361struct tx_stats {
1362 __le32 pkt;
1363 __le32 byte;
1364 __le32 ucast_pkt;
1365 __le32 ucast_byte;
1366 __le32 mcast_pkt;
1367 __le32 mcast_byte;
1368 __le32 bcast_pkt;
1369 __le32 bcast_byte;
1370 __le32 rts_success_cnt;
1371 __le32 pkt_per_ac[4];
1372 __le32 err_per_ac[4];
1373
1374 __le32 err;
1375 __le32 fail_cnt;
1376 __le32 retry_cnt;
1377 __le32 mult_retry_cnt;
1378 __le32 rts_fail_cnt;
1379 a_sle32 ucast_rate;
1380} __packed;
1381
1382struct rx_stats {
1383 __le32 pkt;
1384 __le32 byte;
1385 __le32 ucast_pkt;
1386 __le32 ucast_byte;
1387 __le32 mcast_pkt;
1388 __le32 mcast_byte;
1389 __le32 bcast_pkt;
1390 __le32 bcast_byte;
1391 __le32 frgment_pkt;
1392
1393 __le32 err;
1394 __le32 crc_err;
1395 __le32 key_cache_miss;
1396 __le32 decrypt_err;
1397 __le32 dupl_frame;
1398 a_sle32 ucast_rate;
1399} __packed;
1400
1401struct tkip_ccmp_stats {
1402 __le32 tkip_local_mic_fail;
1403 __le32 tkip_cnter_measures_invoked;
1404 __le32 tkip_replays;
1405 __le32 tkip_fmt_err;
1406 __le32 ccmp_fmt_err;
1407 __le32 ccmp_replays;
1408} __packed;
1409
1410struct pm_stats {
1411 __le32 pwr_save_failure_cnt;
1412 __le16 stop_tx_failure_cnt;
1413 __le16 atim_tx_failure_cnt;
1414 __le16 atim_rx_failure_cnt;
1415 __le16 bcn_rx_failure_cnt;
1416} __packed;
1417
1418struct cserv_stats {
1419 __le32 cs_bmiss_cnt;
1420 __le32 cs_low_rssi_cnt;
1421 __le16 cs_connect_cnt;
1422 __le16 cs_discon_cnt;
1423 a_sle16 cs_ave_beacon_rssi;
1424 __le16 cs_roam_count;
1425 a_sle16 cs_rssi;
1426 u8 cs_snr;
1427 u8 cs_ave_beacon_snr;
1428 u8 cs_last_roam_msec;
1429} __packed;
1430
1431struct wlan_net_stats {
1432 struct tx_stats tx;
1433 struct rx_stats rx;
1434 struct tkip_ccmp_stats tkip_ccmp_stats;
1435} __packed;
1436
1437struct arp_stats {
1438 __le32 arp_received;
1439 __le32 arp_matched;
1440 __le32 arp_replied;
1441} __packed;
1442
1443struct wlan_wow_stats {
1444 __le32 wow_pkt_dropped;
1445 __le16 wow_evt_discarded;
1446 u8 wow_host_pkt_wakeups;
1447 u8 wow_host_evt_wakeups;
1448} __packed;
1449
1450struct wmi_target_stats {
1451 __le32 lq_val;
1452 a_sle32 noise_floor_calib;
1453 struct pm_stats pm_stats;
1454 struct wlan_net_stats stats;
1455 struct wlan_wow_stats wow_stats;
1456 struct arp_stats arp_stats;
1457 struct cserv_stats cserv_stats;
1458} __packed;
1459
1460/*
1461 * WMI_RSSI_THRESHOLD_EVENTID.
1462 * Indicate the RSSI events to host. Events are indicated when we breach a
1463 * thresold value.
1464 */
1465enum wmi_rssi_threshold_val {
1466 WMI_RSSI_THRESHOLD1_ABOVE = 0,
1467 WMI_RSSI_THRESHOLD2_ABOVE,
1468 WMI_RSSI_THRESHOLD3_ABOVE,
1469 WMI_RSSI_THRESHOLD4_ABOVE,
1470 WMI_RSSI_THRESHOLD5_ABOVE,
1471 WMI_RSSI_THRESHOLD6_ABOVE,
1472 WMI_RSSI_THRESHOLD1_BELOW,
1473 WMI_RSSI_THRESHOLD2_BELOW,
1474 WMI_RSSI_THRESHOLD3_BELOW,
1475 WMI_RSSI_THRESHOLD4_BELOW,
1476 WMI_RSSI_THRESHOLD5_BELOW,
1477 WMI_RSSI_THRESHOLD6_BELOW
1478};
1479
1480struct wmi_rssi_threshold_event {
1481 a_sle16 rssi;
1482 u8 range;
1483} __packed;
1484
1485enum wmi_snr_threshold_val {
1486 WMI_SNR_THRESHOLD1_ABOVE = 1,
1487 WMI_SNR_THRESHOLD1_BELOW,
1488 WMI_SNR_THRESHOLD2_ABOVE,
1489 WMI_SNR_THRESHOLD2_BELOW,
1490 WMI_SNR_THRESHOLD3_ABOVE,
1491 WMI_SNR_THRESHOLD3_BELOW,
1492 WMI_SNR_THRESHOLD4_ABOVE,
1493 WMI_SNR_THRESHOLD4_BELOW
1494};
1495
1496struct wmi_snr_threshold_event {
1497 /* see, enum wmi_snr_threshold_val */
1498 u8 range;
1499
1500 u8 snr;
1501} __packed;
1502
1503/* WMI_REPORT_ROAM_TBL_EVENTID */
1504#define MAX_ROAM_TBL_CAND 5
1505
1506struct wmi_bss_roam_info {
1507 a_sle32 roam_util;
1508 u8 bssid[ETH_ALEN];
1509 s8 rssi;
1510 s8 rssidt;
1511 s8 last_rssi;
1512 s8 util;
1513 s8 bias;
1514
1515 /* for alignment */
1516 u8 reserved;
1517} __packed;
1518
1519/* WMI_CAC_EVENTID */
1520enum cac_indication {
1521 CAC_INDICATION_ADMISSION = 0x00,
1522 CAC_INDICATION_ADMISSION_RESP = 0x01,
1523 CAC_INDICATION_DELETE = 0x02,
1524 CAC_INDICATION_NO_RESP = 0x03,
1525};
1526
1527#define WMM_TSPEC_IE_LEN 63
1528
1529struct wmi_cac_event {
1530 u8 ac;
1531 u8 cac_indication;
1532 u8 status_code;
1533 u8 tspec_suggestion[WMM_TSPEC_IE_LEN];
1534} __packed;
1535
1536/* WMI_APLIST_EVENTID */
1537
1538enum aplist_ver {
1539 APLIST_VER1 = 1,
1540};
1541
1542struct wmi_ap_info_v1 {
1543 u8 bssid[ETH_ALEN];
1544 __le16 channel;
1545} __packed;
1546
1547union wmi_ap_info {
1548 struct wmi_ap_info_v1 ap_info_v1;
1549} __packed;
1550
1551struct wmi_aplist_event {
1552 u8 ap_list_ver;
1553 u8 num_ap;
1554 union wmi_ap_info ap_list[1];
1555} __packed;
1556
1557/* Developer Commands */
1558
1559/*
1560 * WMI_SET_BITRATE_CMDID
1561 *
1562 * Get bit rate cmd uses same definition as set bit rate cmd
1563 */
1564enum wmi_bit_rate {
1565 RATE_AUTO = -1,
1566 RATE_1Mb = 0,
1567 RATE_2Mb = 1,
1568 RATE_5_5Mb = 2,
1569 RATE_11Mb = 3,
1570 RATE_6Mb = 4,
1571 RATE_9Mb = 5,
1572 RATE_12Mb = 6,
1573 RATE_18Mb = 7,
1574 RATE_24Mb = 8,
1575 RATE_36Mb = 9,
1576 RATE_48Mb = 10,
1577 RATE_54Mb = 11,
1578 RATE_MCS_0_20 = 12,
1579 RATE_MCS_1_20 = 13,
1580 RATE_MCS_2_20 = 14,
1581 RATE_MCS_3_20 = 15,
1582 RATE_MCS_4_20 = 16,
1583 RATE_MCS_5_20 = 17,
1584 RATE_MCS_6_20 = 18,
1585 RATE_MCS_7_20 = 19,
1586 RATE_MCS_0_40 = 20,
1587 RATE_MCS_1_40 = 21,
1588 RATE_MCS_2_40 = 22,
1589 RATE_MCS_3_40 = 23,
1590 RATE_MCS_4_40 = 24,
1591 RATE_MCS_5_40 = 25,
1592 RATE_MCS_6_40 = 26,
1593 RATE_MCS_7_40 = 27,
1594};
1595
1596struct wmi_bit_rate_reply {
1597 /* see, enum wmi_bit_rate */
1598 s8 rate_index;
1599} __packed;
1600
1601/*
1602 * WMI_SET_FIXRATES_CMDID
1603 *
1604 * Get fix rates cmd uses same definition as set fix rates cmd
1605 */
1606struct wmi_fix_rates_reply {
1607 /* see wmi_bit_rate */
1608 __le32 fix_rate_mask;
1609} __packed;
1610
1611enum roam_data_type {
1612 /* get the roam time data */
1613 ROAM_DATA_TIME = 1,
1614};
1615
1616struct wmi_target_roam_time {
1617 __le32 disassoc_time;
1618 __le32 no_txrx_time;
1619 __le32 assoc_time;
1620 __le32 allow_txrx_time;
1621 u8 disassoc_bssid[ETH_ALEN];
1622 s8 disassoc_bss_rssi;
1623 u8 assoc_bssid[ETH_ALEN];
1624 s8 assoc_bss_rssi;
1625} __packed;
1626
1627enum wmi_txop_cfg {
1628 WMI_TXOP_DISABLED = 0,
1629 WMI_TXOP_ENABLED
1630};
1631
1632struct wmi_set_wmm_txop_cmd {
1633 u8 txop_enable;
1634} __packed;
1635
1636struct wmi_set_keepalive_cmd {
1637 u8 keep_alive_intvl;
1638} __packed;
1639
1640struct wmi_get_keepalive_cmd {
1641 __le32 configured;
1642 u8 keep_alive_intvl;
1643} __packed;
1644
1645/* Notify the WSC registration status to the target */
1646#define WSC_REG_ACTIVE 1
1647#define WSC_REG_INACTIVE 0
1648
1649#define WOW_MAX_FILTER_LISTS 1
1650#define WOW_MAX_FILTERS_PER_LIST 4
1651#define WOW_PATTERN_SIZE 64
1652#define WOW_MASK_SIZE 64
1653
1654#define MAC_MAX_FILTERS_PER_LIST 4
1655
1656struct wow_filter {
1657 u8 wow_valid_filter;
1658 u8 wow_filter_id;
1659 u8 wow_filter_size;
1660 u8 wow_filter_offset;
1661 u8 wow_filter_mask[WOW_MASK_SIZE];
1662 u8 wow_filter_pattern[WOW_PATTERN_SIZE];
1663} __packed;
1664
1665#define MAX_IP_ADDRS 2
1666
1667struct wmi_set_ip_cmd {
1668 /* IP in network byte order */
1669 __le32 ips[MAX_IP_ADDRS];
1670} __packed;
1671
1672/* WMI_GET_WOW_LIST_CMD reply */
1673struct wmi_get_wow_list_reply {
1674 /* number of patterns in reply */
1675 u8 num_filters;
1676
1677 /* this is filter # x of total num_filters */
1678 u8 this_filter_num;
1679
1680 u8 wow_mode;
1681 u8 host_mode;
1682 struct wow_filter wow_filters[1];
1683} __packed;
1684
1685/* WMI_SET_AKMP_PARAMS_CMD */
1686
1687struct wmi_pmkid {
1688 u8 pmkid[WMI_PMKID_LEN];
1689} __packed;
1690
1691/* WMI_GET_PMKID_LIST_CMD Reply */
1692struct wmi_pmkid_list_reply {
1693 __le32 num_pmkid;
1694 u8 bssid_list[ETH_ALEN][1];
1695 struct wmi_pmkid pmkid_list[1];
1696} __packed;
1697
1698/* WMI_ADDBA_REQ_EVENTID */
1699struct wmi_addba_req_event {
1700 u8 tid;
1701 u8 win_sz;
1702 __le16 st_seq_no;
1703
1704 /* f/w response for ADDBA Req; OK (0) or failure (!=0) */
1705 u8 status;
1706} __packed;
1707
1708/* WMI_ADDBA_RESP_EVENTID */
1709struct wmi_addba_resp_event {
1710 u8 tid;
1711
1712 /* OK (0), failure (!=0) */
1713 u8 status;
1714
1715 /* three values: not supported(0), 3839, 8k */
1716 __le16 amsdu_sz;
1717} __packed;
1718
1719/* WMI_DELBA_EVENTID
1720 * f/w received a DELBA for peer and processed it.
1721 * Host is notified of this
1722 */
1723struct wmi_delba_event {
1724 u8 tid;
1725 u8 is_peer_initiator;
1726 __le16 reason_code;
1727} __packed;
1728
1729#define PEER_NODE_JOIN_EVENT 0x00
1730#define PEER_NODE_LEAVE_EVENT 0x01
1731#define PEER_FIRST_NODE_JOIN_EVENT 0x10
1732#define PEER_LAST_NODE_LEAVE_EVENT 0x11
1733
1734struct wmi_peer_node_event {
1735 u8 event_code;
1736 u8 peer_mac_addr[ETH_ALEN];
1737} __packed;
1738
1739/* Transmit complete event data structure(s) */
1740
1741/* version 1 of tx complete msg */
1742struct tx_complete_msg_v1 {
1743#define TX_COMPLETE_STATUS_SUCCESS 0
1744#define TX_COMPLETE_STATUS_RETRIES 1
1745#define TX_COMPLETE_STATUS_NOLINK 2
1746#define TX_COMPLETE_STATUS_TIMEOUT 3
1747#define TX_COMPLETE_STATUS_OTHER 4
1748
1749 u8 status;
1750
1751 /* packet ID to identify parent packet */
1752 u8 pkt_id;
1753
1754 /* rate index on successful transmission */
1755 u8 rate_idx;
1756
1757 /* number of ACK failures in tx attempt */
1758 u8 ack_failures;
1759} __packed;
1760
1761struct wmi_tx_complete_event {
1762 /* no of tx comp msgs following this struct */
1763 u8 num_msg;
1764
1765 /* length in bytes for each individual msg following this struct */
1766 u8 msg_len;
1767
1768 /* version of tx complete msg data following this struct */
1769 u8 msg_type;
1770
1771 /* individual messages follow this header */
1772 u8 reserved;
1773} __packed;
1774
1775/*
1776 * ------- AP Mode definitions --------------
1777 */
1778
1779/*
1780 * !!! Warning !!!
1781 * -Changing the following values needs compilation of both driver and firmware
1782 */
1783#define AP_MAX_NUM_STA 8
1784
1785/* Spl. AID used to set DTIM flag in the beacons */
1786#define MCAST_AID 0xFF
1787
1788#define DEF_AP_COUNTRY_CODE "US "
1789
1790/* Used with WMI_AP_SET_NUM_STA_CMDID */
1791
1792struct wmi_ap_set_pvb_cmd {
1793 __le32 flag;
1794 __le16 aid;
1795} __packed;
1796
1797struct wmi_rx_frame_format_cmd {
1798 /* version of meta data for rx packets <0 = default> (0-7 = valid) */
1799 u8 meta_ver;
1800
1801 /*
1802 * 1 == leave .11 header intact,
1803 * 0 == replace .11 header with .3 <default>
1804 */
1805 u8 dot11_hdr;
1806
1807 /*
1808 * 1 == defragmentation is performed by host,
1809 * 0 == performed by target <default>
1810 */
1811 u8 defrag_on_host;
1812
1813 /* for alignment */
1814 u8 reserved[1];
1815} __packed;
1816
1817/* AP mode events */
1818
1819/* WMI_PS_POLL_EVENT */
1820struct wmi_pspoll_event {
1821 __le16 aid;
1822} __packed;
1823
1824struct wmi_per_sta_stat {
1825 __le32 tx_bytes;
1826 __le32 tx_pkts;
1827 __le32 tx_error;
1828 __le32 tx_discard;
1829 __le32 rx_bytes;
1830 __le32 rx_pkts;
1831 __le32 rx_error;
1832 __le32 rx_discard;
1833 __le32 aid;
1834} __packed;
1835
1836struct wmi_ap_mode_stat {
1837 __le32 action;
1838 struct wmi_per_sta_stat sta[AP_MAX_NUM_STA + 1];
1839} __packed;
1840
1841/* End of AP mode definitions */
1842
1843/* Extended WMI (WMIX)
1844 *
1845 * Extended WMIX commands are encapsulated in a WMI message with
1846 * cmd=WMI_EXTENSION_CMD.
1847 *
1848 * Extended WMI commands are those that are needed during wireless
1849 * operation, but which are not really wireless commands. This allows,
1850 * for instance, platform-specific commands. Extended WMI commands are
1851 * embedded in a WMI command message with WMI_COMMAND_ID=WMI_EXTENSION_CMDID.
1852 * Extended WMI events are similarly embedded in a WMI event message with
1853 * WMI_EVENT_ID=WMI_EXTENSION_EVENTID.
1854 */
1855struct wmix_cmd_hdr {
1856 __le32 cmd_id;
1857} __packed;
1858
1859enum wmix_command_id {
1860 WMIX_DSETOPEN_REPLY_CMDID = 0x2001,
1861 WMIX_DSETDATA_REPLY_CMDID,
1862 WMIX_GPIO_OUTPUT_SET_CMDID,
1863 WMIX_GPIO_INPUT_GET_CMDID,
1864 WMIX_GPIO_REGISTER_SET_CMDID,
1865 WMIX_GPIO_REGISTER_GET_CMDID,
1866 WMIX_GPIO_INTR_ACK_CMDID,
1867 WMIX_HB_CHALLENGE_RESP_CMDID,
1868 WMIX_DBGLOG_CFG_MODULE_CMDID,
1869 WMIX_PROF_CFG_CMDID, /* 0x200a */
1870 WMIX_PROF_ADDR_SET_CMDID,
1871 WMIX_PROF_START_CMDID,
1872 WMIX_PROF_STOP_CMDID,
1873 WMIX_PROF_COUNT_GET_CMDID,
1874};
1875
1876enum wmix_event_id {
1877 WMIX_DSETOPENREQ_EVENTID = 0x3001,
1878 WMIX_DSETCLOSE_EVENTID,
1879 WMIX_DSETDATAREQ_EVENTID,
1880 WMIX_GPIO_INTR_EVENTID,
1881 WMIX_GPIO_DATA_EVENTID,
1882 WMIX_GPIO_ACK_EVENTID,
1883 WMIX_HB_CHALLENGE_RESP_EVENTID,
1884 WMIX_DBGLOG_EVENTID,
1885 WMIX_PROF_COUNT_EVENTID,
1886};
1887
1888/*
1889 * ------Error Detection support-------
1890 */
1891
1892/*
1893 * WMIX_HB_CHALLENGE_RESP_CMDID
1894 * Heartbeat Challenge Response command
1895 */
1896struct wmix_hb_challenge_resp_cmd {
1897 __le32 cookie;
1898 __le32 source;
1899} __packed;
1900
1901/* End of Extended WMI (WMIX) */
1902
1903enum wmi_sync_flag {
1904 NO_SYNC_WMIFLAG = 0,
1905
1906 /* transmit all queued data before cmd */
1907 SYNC_BEFORE_WMIFLAG,
1908
1909 /* any new data waits until cmd execs */
1910 SYNC_AFTER_WMIFLAG,
1911
1912 SYNC_BOTH_WMIFLAG,
1913
1914 /* end marker */
1915 END_WMIFLAG
1916};
1917
1918enum htc_endpoint_id ath6kl_wmi_get_control_ep(struct wmi *wmi);
1919void ath6kl_wmi_set_control_ep(struct wmi *wmi, enum htc_endpoint_id ep_id);
1920int ath6kl_wmi_dix_2_dot3(struct wmi *wmi, struct sk_buff *skb);
1921int ath6kl_wmi_data_hdr_add(struct wmi *wmi, struct sk_buff *skb,
1922 u8 msg_type, bool more_data,
1923 enum wmi_data_hdr_data_type data_type,
1924 u8 meta_ver, void *tx_meta_info);
1925
1926int ath6kl_wmi_dot11_hdr_remove(struct wmi *wmi, struct sk_buff *skb);
1927int ath6kl_wmi_dot3_2_dix(struct sk_buff *skb);
1928int ath6kl_wmi_data_hdr_remove(struct wmi *wmi, struct sk_buff *skb);
1929int ath6kl_wmi_implicit_create_pstream(struct wmi *wmi, struct sk_buff *skb,
1930 u32 layer2_priority, bool wmm_enabled,
1931 u8 *ac);
1932
1933int ath6kl_wmi_control_rx(struct wmi *wmi, struct sk_buff *skb);
1934struct bss *ath6kl_wmi_find_node(struct wmi *wmi, const u8 *mac_addr);
1935void ath6kl_wmi_node_free(struct wmi *wmi, const u8 *mac_addr);
1936
1937int ath6kl_wmi_cmd_send(struct wmi *wmi, struct sk_buff *skb,
1938 enum wmi_cmd_id cmd_id, enum wmi_sync_flag sync_flag);
1939
1940int ath6kl_wmi_connect_cmd(struct wmi *wmi, enum network_type nw_type,
1941 enum dot11_auth_mode dot11_auth_mode,
1942 enum auth_mode auth_mode,
1943 enum crypto_type pairwise_crypto,
1944 u8 pairwise_crypto_len,
1945 enum crypto_type group_crypto,
1946 u8 group_crypto_len, int ssid_len, u8 *ssid,
1947 u8 *bssid, u16 channel, u32 ctrl_flags);
1948
1949int ath6kl_wmi_reconnect_cmd(struct wmi *wmi, u8 *bssid, u16 channel);
1950int ath6kl_wmi_disconnect_cmd(struct wmi *wmi);
1951int ath6kl_wmi_startscan_cmd(struct wmi *wmi, enum wmi_scan_type scan_type,
1952 u32 force_fgscan, u32 is_legacy,
1953 u32 home_dwell_time, u32 force_scan_interval,
1954 s8 num_chan, u16 *ch_list);
1955int ath6kl_wmi_scanparams_cmd(struct wmi *wmi, u16 fg_start_sec,
1956 u16 fg_end_sec, u16 bg_sec,
1957 u16 minact_chdw_msec, u16 maxact_chdw_msec,
1958 u16 pas_chdw_msec, u8 short_scan_ratio,
1959 u8 scan_ctrl_flag, u32 max_dfsch_act_time,
1960 u16 maxact_scan_per_ssid);
1961int ath6kl_wmi_bssfilter_cmd(struct wmi *wmi, u8 filter, u32 ie_mask);
1962int ath6kl_wmi_probedssid_cmd(struct wmi *wmi, u8 index, u8 flag,
1963 u8 ssid_len, u8 *ssid);
1964int ath6kl_wmi_listeninterval_cmd(struct wmi *wmi, u16 listen_interval,
1965 u16 listen_beacons);
1966int ath6kl_wmi_powermode_cmd(struct wmi *wmi, u8 pwr_mode);
1967int ath6kl_wmi_pmparams_cmd(struct wmi *wmi, u16 idle_period,
1968 u16 ps_poll_num, u16 dtim_policy,
1969 u16 tx_wakup_policy, u16 num_tx_to_wakeup,
1970 u16 ps_fail_event_policy);
1971int ath6kl_wmi_disctimeout_cmd(struct wmi *wmi, u8 timeout);
1972int ath6kl_wmi_create_pstream_cmd(struct wmi *wmi,
1973 struct wmi_create_pstream_cmd *pstream);
1974int ath6kl_wmi_delete_pstream_cmd(struct wmi *wmi, u8 traffic_class, u8 tsid);
1975
1976int ath6kl_wmi_set_rts_cmd(struct wmi *wmi, u16 threshold);
1977int ath6kl_wmi_set_lpreamble_cmd(struct wmi *wmi, u8 status,
1978 u8 preamble_policy);
1979
1980int ath6kl_wmi_get_challenge_resp_cmd(struct wmi *wmi, u32 cookie, u32 source);
1981
1982int ath6kl_wmi_get_stats_cmd(struct wmi *wmi);
1983int ath6kl_wmi_addkey_cmd(struct wmi *wmi, u8 key_index,
1984 enum crypto_type key_type,
1985 u8 key_usage, u8 key_len,
1986 u8 *key_rsc, u8 *key_material,
1987 u8 key_op_ctrl, u8 *mac_addr,
1988 enum wmi_sync_flag sync_flag);
1989int ath6kl_wmi_add_krk_cmd(struct wmi *wmi, u8 *krk);
1990int ath6kl_wmi_deletekey_cmd(struct wmi *wmi, u8 key_index);
1991int ath6kl_wmi_setpmkid_cmd(struct wmi *wmi, const u8 *bssid,
1992 const u8 *pmkid, bool set);
1993int ath6kl_wmi_set_tx_pwr_cmd(struct wmi *wmi, u8 dbM);
1994int ath6kl_wmi_get_tx_pwr_cmd(struct wmi *wmi);
1995
1996int ath6kl_wmi_set_wmm_txop(struct wmi *wmi, enum wmi_txop_cfg cfg);
1997int ath6kl_wmi_set_keepalive_cmd(struct wmi *wmi, u8 keep_alive_intvl);
1998
1999s32 ath6kl_wmi_get_rate(s8 rate_index);
2000
2001int ath6kl_wmi_set_ip_cmd(struct wmi *wmi, struct wmi_set_ip_cmd *ip_cmd);
2002
2003struct bss *ath6kl_wmi_find_ssid_node(struct wmi *wmi, u8 *ssid,
2004 u32 ssid_len, bool is_wpa2,
2005 bool match_ssid);
2006
2007void ath6kl_wmi_node_return(struct wmi *wmi, struct bss *bss);
2008
2009/* AP mode */
2010int ath6kl_wmi_set_pvb_cmd(struct wmi *wmi, u16 aid, bool flag);
2011
2012int ath6kl_wmi_set_rx_frame_format_cmd(struct wmi *wmi, u8 rx_meta_version,
2013 bool rx_dot11_hdr, bool defrag_on_host);
2014
2015void *ath6kl_wmi_init(struct ath6kl *devt);
2016void ath6kl_wmi_shutdown(struct wmi *wmi);
2017
2018#endif /* WMI_H */
diff --git a/drivers/net/wireless/ath/ath9k/ahb.c b/drivers/net/wireless/ath/ath9k/ahb.c
index 0b36fcf8a280..85a54cd2b083 100644
--- a/drivers/net/wireless/ath/ath9k/ahb.c
+++ b/drivers/net/wireless/ath/ath9k/ahb.c
@@ -133,7 +133,7 @@ static int ath_ahb_probe(struct platform_device *pdev)
133 goto err_free_hw; 133 goto err_free_hw;
134 } 134 }
135 135
136 ret = ath9k_init_device(id->driver_data, sc, 0x0, &ath_ahb_bus_ops); 136 ret = ath9k_init_device(id->driver_data, sc, &ath_ahb_bus_ops);
137 if (ret) { 137 if (ret) {
138 dev_err(&pdev->dev, "failed to initialize device\n"); 138 dev_err(&pdev->dev, "failed to initialize device\n");
139 goto err_irq; 139 goto err_irq;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
index 2339728a7306..a0aadaddd071 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9003_2p2_initvals.h
@@ -835,108 +835,108 @@ static const u32 ar9300_2p2_baseband_core[][2] = {
835 835
836static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = { 836static const u32 ar9300Modes_high_power_tx_gain_table_2p2[][5] = {
837 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */ 837 /* Addr 5G_HT20 5G_HT40 2G_HT40 2G_HT20 */
838 {0x0000a2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, 838 {0x0000a2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
839 {0x0000a2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, 839 {0x0000a2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
840 {0x0000a2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, 840 {0x0000a2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
841 {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, 841 {0x0000a2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
842 {0x0000a410, 0x000050d8, 0x000050d8, 0x000050d9, 0x000050d9}, 842 {0x0000a410, 0x000050d9, 0x000050d9, 0x000050d9, 0x000050d9},
843 {0x0000a500, 0x00002220, 0x00002220, 0x00000000, 0x00000000}, 843 {0x0000a500, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
844 {0x0000a504, 0x04002222, 0x04002222, 0x04000002, 0x04000002}, 844 {0x0000a504, 0x06000003, 0x06000003, 0x04000002, 0x04000002},
845 {0x0000a508, 0x09002421, 0x09002421, 0x08000004, 0x08000004}, 845 {0x0000a508, 0x0a000020, 0x0a000020, 0x08000004, 0x08000004},
846 {0x0000a50c, 0x0d002621, 0x0d002621, 0x0b000200, 0x0b000200}, 846 {0x0000a50c, 0x10000023, 0x10000023, 0x0b000200, 0x0b000200},
847 {0x0000a510, 0x13004620, 0x13004620, 0x0f000202, 0x0f000202}, 847 {0x0000a510, 0x16000220, 0x16000220, 0x0f000202, 0x0f000202},
848 {0x0000a514, 0x19004a20, 0x19004a20, 0x11000400, 0x11000400}, 848 {0x0000a514, 0x1c000223, 0x1c000223, 0x12000400, 0x12000400},
849 {0x0000a518, 0x1d004e20, 0x1d004e20, 0x15000402, 0x15000402}, 849 {0x0000a518, 0x21002220, 0x21002220, 0x16000402, 0x16000402},
850 {0x0000a51c, 0x21005420, 0x21005420, 0x19000404, 0x19000404}, 850 {0x0000a51c, 0x27002223, 0x27002223, 0x19000404, 0x19000404},
851 {0x0000a520, 0x26005e20, 0x26005e20, 0x1b000603, 0x1b000603}, 851 {0x0000a520, 0x2b022220, 0x2b022220, 0x1c000603, 0x1c000603},
852 {0x0000a524, 0x2b005e40, 0x2b005e40, 0x1f000a02, 0x1f000a02}, 852 {0x0000a524, 0x2f022222, 0x2f022222, 0x21000a02, 0x21000a02},
853 {0x0000a528, 0x2f005e42, 0x2f005e42, 0x23000a04, 0x23000a04}, 853 {0x0000a528, 0x34022225, 0x34022225, 0x25000a04, 0x25000a04},
854 {0x0000a52c, 0x33005e44, 0x33005e44, 0x26000a20, 0x26000a20}, 854 {0x0000a52c, 0x3a02222a, 0x3a02222a, 0x28000a20, 0x28000a20},
855 {0x0000a530, 0x38005e65, 0x38005e65, 0x2a000e20, 0x2a000e20}, 855 {0x0000a530, 0x3e02222c, 0x3e02222c, 0x2c000e20, 0x2c000e20},
856 {0x0000a534, 0x3c005e69, 0x3c005e69, 0x2e000e22, 0x2e000e22}, 856 {0x0000a534, 0x4202242a, 0x4202242a, 0x30000e22, 0x30000e22},
857 {0x0000a538, 0x40005e6b, 0x40005e6b, 0x31000e24, 0x31000e24}, 857 {0x0000a538, 0x4702244a, 0x4702244a, 0x34000e24, 0x34000e24},
858 {0x0000a53c, 0x44005e6d, 0x44005e6d, 0x34001640, 0x34001640}, 858 {0x0000a53c, 0x4b02244c, 0x4b02244c, 0x38001640, 0x38001640},
859 {0x0000a540, 0x49005e72, 0x49005e72, 0x38001660, 0x38001660}, 859 {0x0000a540, 0x4e02246c, 0x4e02246c, 0x3c001660, 0x3c001660},
860 {0x0000a544, 0x4e005eb2, 0x4e005eb2, 0x3b001861, 0x3b001861}, 860 {0x0000a544, 0x52022470, 0x52022470, 0x3f001861, 0x3f001861},
861 {0x0000a548, 0x53005f12, 0x53005f12, 0x3e001a81, 0x3e001a81}, 861 {0x0000a548, 0x55022490, 0x55022490, 0x43001a81, 0x43001a81},
862 {0x0000a54c, 0x59025eb2, 0x59025eb2, 0x42001a83, 0x42001a83}, 862 {0x0000a54c, 0x59022492, 0x59022492, 0x47001a83, 0x47001a83},
863 {0x0000a550, 0x5e025f12, 0x5e025f12, 0x44001c84, 0x44001c84}, 863 {0x0000a550, 0x5d022692, 0x5d022692, 0x4a001c84, 0x4a001c84},
864 {0x0000a554, 0x61027f12, 0x61027f12, 0x48001ce3, 0x48001ce3}, 864 {0x0000a554, 0x61022892, 0x61022892, 0x4e001ce3, 0x4e001ce3},
865 {0x0000a558, 0x6702bf12, 0x6702bf12, 0x4c001ce5, 0x4c001ce5}, 865 {0x0000a558, 0x65024890, 0x65024890, 0x52001ce5, 0x52001ce5},
866 {0x0000a55c, 0x6b02bf14, 0x6b02bf14, 0x50001ce9, 0x50001ce9}, 866 {0x0000a55c, 0x69024892, 0x69024892, 0x56001ce9, 0x56001ce9},
867 {0x0000a560, 0x6f02bf16, 0x6f02bf16, 0x54001ceb, 0x54001ceb}, 867 {0x0000a560, 0x6e024c92, 0x6e024c92, 0x5a001ceb, 0x5a001ceb},
868 {0x0000a564, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 868 {0x0000a564, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
869 {0x0000a568, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 869 {0x0000a568, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
870 {0x0000a56c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 870 {0x0000a56c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
871 {0x0000a570, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 871 {0x0000a570, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
872 {0x0000a574, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 872 {0x0000a574, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
873 {0x0000a578, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 873 {0x0000a578, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
874 {0x0000a57c, 0x6f02bf16, 0x6f02bf16, 0x56001eec, 0x56001eec}, 874 {0x0000a57c, 0x74026e92, 0x74026e92, 0x5d001eec, 0x5d001eec},
875 {0x0000a580, 0x00802220, 0x00802220, 0x00800000, 0x00800000}, 875 {0x0000a580, 0x00800000, 0x00800000, 0x00800000, 0x00800000},
876 {0x0000a584, 0x04802222, 0x04802222, 0x04800002, 0x04800002}, 876 {0x0000a584, 0x06800003, 0x06800003, 0x04800002, 0x04800002},
877 {0x0000a588, 0x09802421, 0x09802421, 0x08800004, 0x08800004}, 877 {0x0000a588, 0x0a800020, 0x0a800020, 0x08800004, 0x08800004},
878 {0x0000a58c, 0x0d802621, 0x0d802621, 0x0b800200, 0x0b800200}, 878 {0x0000a58c, 0x10800023, 0x10800023, 0x0b800200, 0x0b800200},
879 {0x0000a590, 0x13804620, 0x13804620, 0x0f800202, 0x0f800202}, 879 {0x0000a590, 0x16800220, 0x16800220, 0x0f800202, 0x0f800202},
880 {0x0000a594, 0x19804a20, 0x19804a20, 0x11800400, 0x11800400}, 880 {0x0000a594, 0x1c800223, 0x1c800223, 0x12800400, 0x12800400},
881 {0x0000a598, 0x1d804e20, 0x1d804e20, 0x15800402, 0x15800402}, 881 {0x0000a598, 0x21802220, 0x21802220, 0x16800402, 0x16800402},
882 {0x0000a59c, 0x21805420, 0x21805420, 0x19800404, 0x19800404}, 882 {0x0000a59c, 0x27802223, 0x27802223, 0x19800404, 0x19800404},
883 {0x0000a5a0, 0x26805e20, 0x26805e20, 0x1b800603, 0x1b800603}, 883 {0x0000a5a0, 0x2b822220, 0x2b822220, 0x1c800603, 0x1c800603},
884 {0x0000a5a4, 0x2b805e40, 0x2b805e40, 0x1f800a02, 0x1f800a02}, 884 {0x0000a5a4, 0x2f822222, 0x2f822222, 0x21800a02, 0x21800a02},
885 {0x0000a5a8, 0x2f805e42, 0x2f805e42, 0x23800a04, 0x23800a04}, 885 {0x0000a5a8, 0x34822225, 0x34822225, 0x25800a04, 0x25800a04},
886 {0x0000a5ac, 0x33805e44, 0x33805e44, 0x26800a20, 0x26800a20}, 886 {0x0000a5ac, 0x3a82222a, 0x3a82222a, 0x28800a20, 0x28800a20},
887 {0x0000a5b0, 0x38805e65, 0x38805e65, 0x2a800e20, 0x2a800e20}, 887 {0x0000a5b0, 0x3e82222c, 0x3e82222c, 0x2c800e20, 0x2c800e20},
888 {0x0000a5b4, 0x3c805e69, 0x3c805e69, 0x2e800e22, 0x2e800e22}, 888 {0x0000a5b4, 0x4282242a, 0x4282242a, 0x30800e22, 0x30800e22},
889 {0x0000a5b8, 0x40805e6b, 0x40805e6b, 0x31800e24, 0x31800e24}, 889 {0x0000a5b8, 0x4782244a, 0x4782244a, 0x34800e24, 0x34800e24},
890 {0x0000a5bc, 0x44805e6d, 0x44805e6d, 0x34801640, 0x34801640}, 890 {0x0000a5bc, 0x4b82244c, 0x4b82244c, 0x38801640, 0x38801640},
891 {0x0000a5c0, 0x49805e72, 0x49805e72, 0x38801660, 0x38801660}, 891 {0x0000a5c0, 0x4e82246c, 0x4e82246c, 0x3c801660, 0x3c801660},
892 {0x0000a5c4, 0x4e805eb2, 0x4e805eb2, 0x3b801861, 0x3b801861}, 892 {0x0000a5c4, 0x52822470, 0x52822470, 0x3f801861, 0x3f801861},
893 {0x0000a5c8, 0x53805f12, 0x53805f12, 0x3e801a81, 0x3e801a81}, 893 {0x0000a5c8, 0x55822490, 0x55822490, 0x43801a81, 0x43801a81},
894 {0x0000a5cc, 0x59825eb2, 0x59825eb2, 0x42801a83, 0x42801a83}, 894 {0x0000a5cc, 0x59822492, 0x59822492, 0x47801a83, 0x47801a83},
895 {0x0000a5d0, 0x5e825f12, 0x5e825f12, 0x44801c84, 0x44801c84}, 895 {0x0000a5d0, 0x5d822692, 0x5d822692, 0x4a801c84, 0x4a801c84},
896 {0x0000a5d4, 0x61827f12, 0x61827f12, 0x48801ce3, 0x48801ce3}, 896 {0x0000a5d4, 0x61822892, 0x61822892, 0x4e801ce3, 0x4e801ce3},
897 {0x0000a5d8, 0x6782bf12, 0x6782bf12, 0x4c801ce5, 0x4c801ce5}, 897 {0x0000a5d8, 0x65824890, 0x65824890, 0x52801ce5, 0x52801ce5},
898 {0x0000a5dc, 0x6b82bf14, 0x6b82bf14, 0x50801ce9, 0x50801ce9}, 898 {0x0000a5dc, 0x69824892, 0x69824892, 0x56801ce9, 0x56801ce9},
899 {0x0000a5e0, 0x6f82bf16, 0x6f82bf16, 0x54801ceb, 0x54801ceb}, 899 {0x0000a5e0, 0x6e824c92, 0x6e824c92, 0x5a801ceb, 0x5a801ceb},
900 {0x0000a5e4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 900 {0x0000a5e4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
901 {0x0000a5e8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 901 {0x0000a5e8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
902 {0x0000a5ec, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 902 {0x0000a5ec, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
903 {0x0000a5f0, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 903 {0x0000a5f0, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
904 {0x0000a5f4, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 904 {0x0000a5f4, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
905 {0x0000a5f8, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 905 {0x0000a5f8, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
906 {0x0000a5fc, 0x6f82bf16, 0x6f82bf16, 0x56801eec, 0x56801eec}, 906 {0x0000a5fc, 0x74826e92, 0x74826e92, 0x5d801eec, 0x5d801eec},
907 {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, 907 {0x0000a600, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
908 {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, 908 {0x0000a604, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
909 {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, 909 {0x0000a608, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
910 {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000}, 910 {0x0000a60c, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
911 {0x0000a610, 0x00804000, 0x00804000, 0x00000000, 0x00000000}, 911 {0x0000a610, 0x00000000, 0x00000000, 0x00000000, 0x00000000},
912 {0x0000a614, 0x00804201, 0x00804201, 0x01404000, 0x01404000}, 912 {0x0000a614, 0x02004000, 0x02004000, 0x01404000, 0x01404000},
913 {0x0000a618, 0x0280c802, 0x0280c802, 0x01404501, 0x01404501}, 913 {0x0000a618, 0x02004801, 0x02004801, 0x01404501, 0x01404501},
914 {0x0000a61c, 0x0280ca03, 0x0280ca03, 0x02008501, 0x02008501}, 914 {0x0000a61c, 0x02808a02, 0x02808a02, 0x02008501, 0x02008501},
915 {0x0000a620, 0x04c15104, 0x04c15104, 0x0280ca03, 0x0280ca03}, 915 {0x0000a620, 0x0380ce03, 0x0380ce03, 0x0280ca03, 0x0280ca03},
916 {0x0000a624, 0x04c15305, 0x04c15305, 0x03010c04, 0x03010c04}, 916 {0x0000a624, 0x04411104, 0x04411104, 0x03010c04, 0x03010c04},
917 {0x0000a628, 0x04c15305, 0x04c15305, 0x04014c04, 0x04014c04}, 917 {0x0000a628, 0x04411104, 0x04411104, 0x04014c04, 0x04014c04},
918 {0x0000a62c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, 918 {0x0000a62c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
919 {0x0000a630, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, 919 {0x0000a630, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
920 {0x0000a634, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, 920 {0x0000a634, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
921 {0x0000a638, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, 921 {0x0000a638, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
922 {0x0000a63c, 0x04c15305, 0x04c15305, 0x04015005, 0x04015005}, 922 {0x0000a63c, 0x04411104, 0x04411104, 0x04015005, 0x04015005},
923 {0x0000b2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, 923 {0x0000b2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
924 {0x0000b2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, 924 {0x0000b2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
925 {0x0000b2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, 925 {0x0000b2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
926 {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, 926 {0x0000b2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
927 {0x0000c2dc, 0x0380c7fc, 0x0380c7fc, 0x03aaa352, 0x03aaa352}, 927 {0x0000c2dc, 0x00033800, 0x00033800, 0x03aaa352, 0x03aaa352},
928 {0x0000c2e0, 0x0000f800, 0x0000f800, 0x03ccc584, 0x03ccc584}, 928 {0x0000c2e0, 0x0003c000, 0x0003c000, 0x03ccc584, 0x03ccc584},
929 {0x0000c2e4, 0x03ff0000, 0x03ff0000, 0x03f0f800, 0x03f0f800}, 929 {0x0000c2e4, 0x03fc0000, 0x03fc0000, 0x03f0f800, 0x03f0f800},
930 {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000}, 930 {0x0000c2e8, 0x00000000, 0x00000000, 0x03ff0000, 0x03ff0000},
931 {0x00016044, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, 931 {0x00016044, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
932 {0x00016048, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, 932 {0x00016048, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
933 {0x00016068, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, 933 {0x00016068, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
934 {0x00016444, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, 934 {0x00016444, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
935 {0x00016448, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, 935 {0x00016448, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
936 {0x00016468, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, 936 {0x00016468, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
937 {0x00016844, 0x056db2e6, 0x056db2e6, 0x056db2e6, 0x056db2e6}, 937 {0x00016844, 0x012492d4, 0x012492d4, 0x012492d4, 0x012492d4},
938 {0x00016848, 0xae480001, 0xae480001, 0xae480001, 0xae480001}, 938 {0x00016848, 0x66480001, 0x66480001, 0x66480001, 0x66480001},
939 {0x00016868, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c, 0x6eb6db6c}, 939 {0x00016868, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c, 0x6db6db6c},
940}; 940};
941 941
942static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = { 942static const u32 ar9300Modes_high_ob_db_tx_gain_table_2p2[][5] = {
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
index c34bef1bf2b0..cb8bcc4e6091 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_eeprom.c
@@ -3418,6 +3418,133 @@ static bool ath9k_hw_ar9300_fill_eeprom(struct ath_hw *ah)
3418 return true; 3418 return true;
3419} 3419}
3420 3420
3421#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
3422static u32 ar9003_dump_modal_eeprom(char *buf, u32 len, u32 size,
3423 struct ar9300_modal_eep_header *modal_hdr)
3424{
3425 PR_EEP("Chain0 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[0]));
3426 PR_EEP("Chain1 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[1]));
3427 PR_EEP("Chain2 Ant. Control", le16_to_cpu(modal_hdr->antCtrlChain[2]));
3428 PR_EEP("Ant. Common Control", le32_to_cpu(modal_hdr->antCtrlCommon));
3429 PR_EEP("Ant. Common Control2", le32_to_cpu(modal_hdr->antCtrlCommon2));
3430 PR_EEP("Ant. Gain", modal_hdr->antennaGain);
3431 PR_EEP("Switch Settle", modal_hdr->switchSettling);
3432 PR_EEP("Chain0 xatten1DB", modal_hdr->xatten1DB[0]);
3433 PR_EEP("Chain1 xatten1DB", modal_hdr->xatten1DB[1]);
3434 PR_EEP("Chain2 xatten1DB", modal_hdr->xatten1DB[2]);
3435 PR_EEP("Chain0 xatten1Margin", modal_hdr->xatten1Margin[0]);
3436 PR_EEP("Chain1 xatten1Margin", modal_hdr->xatten1Margin[1]);
3437 PR_EEP("Chain2 xatten1Margin", modal_hdr->xatten1Margin[2]);
3438 PR_EEP("Temp Slope", modal_hdr->tempSlope);
3439 PR_EEP("Volt Slope", modal_hdr->voltSlope);
3440 PR_EEP("spur Channels0", modal_hdr->spurChans[0]);
3441 PR_EEP("spur Channels1", modal_hdr->spurChans[1]);
3442 PR_EEP("spur Channels2", modal_hdr->spurChans[2]);
3443 PR_EEP("spur Channels3", modal_hdr->spurChans[3]);
3444 PR_EEP("spur Channels4", modal_hdr->spurChans[4]);
3445 PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
3446 PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
3447 PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
3448 PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
3449 PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
3450 PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
3451 PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
3452 PR_EEP("txClip", modal_hdr->txClip);
3453 PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
3454 PR_EEP("Chain0 ob", modal_hdr->ob[0]);
3455 PR_EEP("Chain1 ob", modal_hdr->ob[1]);
3456 PR_EEP("Chain2 ob", modal_hdr->ob[2]);
3457
3458 PR_EEP("Chain0 db_stage2", modal_hdr->db_stage2[0]);
3459 PR_EEP("Chain1 db_stage2", modal_hdr->db_stage2[1]);
3460 PR_EEP("Chain2 db_stage2", modal_hdr->db_stage2[2]);
3461 PR_EEP("Chain0 db_stage3", modal_hdr->db_stage3[0]);
3462 PR_EEP("Chain1 db_stage3", modal_hdr->db_stage3[1]);
3463 PR_EEP("Chain2 db_stage3", modal_hdr->db_stage3[2]);
3464 PR_EEP("Chain0 db_stage4", modal_hdr->db_stage4[0]);
3465 PR_EEP("Chain1 db_stage4", modal_hdr->db_stage4[1]);
3466 PR_EEP("Chain2 db_stage4", modal_hdr->db_stage4[2]);
3467
3468 return len;
3469}
3470
3471static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
3472 u8 *buf, u32 len, u32 size)
3473{
3474 struct ar9300_eeprom *eep = &ah->eeprom.ar9300_eep;
3475 struct ar9300_base_eep_hdr *pBase;
3476
3477 if (!dump_base_hdr) {
3478 len += snprintf(buf + len, size - len,
3479 "%20s :\n", "2GHz modal Header");
3480 len += ar9003_dump_modal_eeprom(buf, len, size,
3481 &eep->modalHeader2G);
3482 len += snprintf(buf + len, size - len,
3483 "%20s :\n", "5GHz modal Header");
3484 len += ar9003_dump_modal_eeprom(buf, len, size,
3485 &eep->modalHeader5G);
3486 goto out;
3487 }
3488
3489 pBase = &eep->baseEepHeader;
3490
3491 PR_EEP("EEPROM Version", ah->eeprom.ar9300_eep.eepromVersion);
3492 PR_EEP("RegDomain1", le16_to_cpu(pBase->regDmn[0]));
3493 PR_EEP("RegDomain2", le16_to_cpu(pBase->regDmn[1]));
3494 PR_EEP("TX Mask", (pBase->txrxMask >> 4));
3495 PR_EEP("RX Mask", (pBase->txrxMask & 0x0f));
3496 PR_EEP("Allow 5GHz", !!(pBase->opCapFlags.opFlags &
3497 AR5416_OPFLAGS_11A));
3498 PR_EEP("Allow 2GHz", !!(pBase->opCapFlags.opFlags &
3499 AR5416_OPFLAGS_11G));
3500 PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags.opFlags &
3501 AR5416_OPFLAGS_N_2G_HT20));
3502 PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags.opFlags &
3503 AR5416_OPFLAGS_N_2G_HT40));
3504 PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags.opFlags &
3505 AR5416_OPFLAGS_N_5G_HT20));
3506 PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags.opFlags &
3507 AR5416_OPFLAGS_N_5G_HT40));
3508 PR_EEP("Big Endian", !!(pBase->opCapFlags.eepMisc & 0x01));
3509 PR_EEP("RF Silent", pBase->rfSilent);
3510 PR_EEP("BT option", pBase->blueToothOptions);
3511 PR_EEP("Device Cap", pBase->deviceCap);
3512 PR_EEP("Device Type", pBase->deviceType);
3513 PR_EEP("Power Table Offset", pBase->pwrTableOffset);
3514 PR_EEP("Tuning Caps1", pBase->params_for_tuning_caps[0]);
3515 PR_EEP("Tuning Caps2", pBase->params_for_tuning_caps[1]);
3516 PR_EEP("Enable Tx Temp Comp", !!(pBase->featureEnable & BIT(0)));
3517 PR_EEP("Enable Tx Volt Comp", !!(pBase->featureEnable & BIT(1)));
3518 PR_EEP("Enable fast clock", !!(pBase->featureEnable & BIT(2)));
3519 PR_EEP("Enable doubling", !!(pBase->featureEnable & BIT(3)));
3520 PR_EEP("Internal regulator", !!(pBase->featureEnable & BIT(4)));
3521 PR_EEP("Enable Paprd", !!(pBase->featureEnable & BIT(5)));
3522 PR_EEP("Driver Strength", !!(pBase->miscConfiguration & BIT(0)));
3523 PR_EEP("Chain mask Reduce", (pBase->miscConfiguration >> 0x3) & 0x1);
3524 PR_EEP("Write enable Gpio", pBase->eepromWriteEnableGpio);
3525 PR_EEP("WLAN Disable Gpio", pBase->wlanDisableGpio);
3526 PR_EEP("WLAN LED Gpio", pBase->wlanLedGpio);
3527 PR_EEP("Rx Band Select Gpio", pBase->rxBandSelectGpio);
3528 PR_EEP("Tx Gain", pBase->txrxgain >> 4);
3529 PR_EEP("Rx Gain", pBase->txrxgain & 0xf);
3530 PR_EEP("SW Reg", le32_to_cpu(pBase->swreg));
3531
3532 len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
3533 ah->eeprom.ar9300_eep.macAddr);
3534out:
3535 if (len > size)
3536 len = size;
3537
3538 return len;
3539}
3540#else
3541static u32 ath9k_hw_ar9003_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
3542 u8 *buf, u32 len, u32 size)
3543{
3544 return 0;
3545}
3546#endif
3547
3421/* XXX: review hardware docs */ 3548/* XXX: review hardware docs */
3422static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah) 3549static int ath9k_hw_ar9300_get_eeprom_ver(struct ath_hw *ah)
3423{ 3550{
@@ -4061,7 +4188,7 @@ static int ar9003_hw_tx_power_regwrite(struct ath_hw *ah, u8 * pPwrArray)
4061 /* Write the power for duplicated frames - HT40 */ 4188 /* Write the power for duplicated frames - HT40 */
4062 4189
4063 /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */ 4190 /* dup40_cck (LSB), dup40_ofdm, ext20_cck, ext20_ofdm (MSB) */
4064 REG_WRITE(ah, 0xa3e0, 4191 REG_WRITE(ah, AR_PHY_POWER_TX_RATE(8),
4065 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) | 4192 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 24) |
4066 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) | 4193 POW_SM(pPwrArray[ALL_TARGET_LEGACY_1L_5L], 16) |
4067 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) | 4194 POW_SM(pPwrArray[ALL_TARGET_LEGACY_6_24], 8) |
@@ -4922,25 +5049,7 @@ static void ath9k_hw_ar9300_set_txpower(struct ath_hw *ah,
4922 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]); 5049 "TPC[%02d] 0x%08x\n", i, targetPowerValT2[i]);
4923 } 5050 }
4924 5051
4925 /* 5052 ah->txpower_limit = regulatory->max_power_level;
4926 * This is the TX power we send back to driver core,
4927 * and it can use to pass to userspace to display our
4928 * currently configured TX power setting.
4929 *
4930 * Since power is rate dependent, use one of the indices
4931 * from the AR9300_Rates enum to select an entry from
4932 * targetPowerValT2[] to report. Currently returns the
4933 * power for HT40 MCS 0, HT20 MCS 0, or OFDM 6 Mbps
4934 * as CCK power is less interesting (?).
4935 */
4936 i = ALL_TARGET_LEGACY_6_24; /* legacy */
4937 if (IS_CHAN_HT40(chan))
4938 i = ALL_TARGET_HT40_0_8_16; /* ht40 */
4939 else if (IS_CHAN_HT20(chan))
4940 i = ALL_TARGET_HT20_0_8_16; /* ht20 */
4941
4942 ah->txpower_limit = targetPowerValT2[i];
4943 regulatory->max_power_level = targetPowerValT2[i];
4944 5053
4945 /* Write target power array to registers */ 5054 /* Write target power array to registers */
4946 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2); 5055 ar9003_hw_tx_power_regwrite(ah, targetPowerValT2);
@@ -5015,6 +5124,7 @@ const struct eeprom_ops eep_ar9300_ops = {
5015 .check_eeprom = ath9k_hw_ar9300_check_eeprom, 5124 .check_eeprom = ath9k_hw_ar9300_check_eeprom,
5016 .get_eeprom = ath9k_hw_ar9300_get_eeprom, 5125 .get_eeprom = ath9k_hw_ar9300_get_eeprom,
5017 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom, 5126 .fill_eeprom = ath9k_hw_ar9300_fill_eeprom,
5127 .dump_eeprom = ath9k_hw_ar9003_dump_eeprom,
5018 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver, 5128 .get_eeprom_ver = ath9k_hw_ar9300_get_eeprom_ver,
5019 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev, 5129 .get_eeprom_rev = ath9k_hw_ar9300_get_eeprom_rev,
5020 .set_board_values = ath9k_hw_ar9300_set_board_values, 5130 .set_board_values = ath9k_hw_ar9300_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_mac.c b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
index 8ff0b88a29b9..1aadc4757e67 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_mac.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_mac.c
@@ -531,17 +531,18 @@ int ath9k_hw_process_rxdesc_edma(struct ath_hw *ah, struct ath_rx_status *rxs,
531 531
532 /* TODO: byte swap on big endian for ar9300_10 */ 532 /* TODO: byte swap on big endian for ar9300_10 */
533 533
534 if ((rxsp->status11 & AR_RxDone) == 0) 534 if (!rxs) {
535 return -EINPROGRESS; 535 if ((rxsp->status11 & AR_RxDone) == 0)
536 return -EINPROGRESS;
536 537
537 if (MS(rxsp->ds_info, AR_DescId) != 0x168c) 538 if (MS(rxsp->ds_info, AR_DescId) != 0x168c)
538 return -EINVAL; 539 return -EINVAL;
539 540
540 if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0) 541 if ((rxsp->ds_info & (AR_TxRxDesc | AR_CtrlStat)) != 0)
541 return -EINPROGRESS; 542 return -EINPROGRESS;
542 543
543 if (!rxs)
544 return 0; 544 return 0;
545 }
545 546
546 rxs->rs_status = 0; 547 rxs->rs_status = 0;
547 rxs->rs_flags = 0; 548 rxs->rs_flags = 0;
diff --git a/drivers/net/wireless/ath/ath9k/ar9003_phy.c b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
index 1baca8e4715d..a0aaa6855486 100644
--- a/drivers/net/wireless/ath/ath9k/ar9003_phy.c
+++ b/drivers/net/wireless/ath/ath9k/ar9003_phy.c
@@ -370,7 +370,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
370 else 370 else
371 spur_subchannel_sd = 0; 371 spur_subchannel_sd = 0;
372 372
373 spur_freq_sd = ((freq_offset + 10) << 9) / 11; 373 spur_freq_sd = (freq_offset << 9) / 11;
374 374
375 } else { 375 } else {
376 if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL, 376 if (REG_READ_FIELD(ah, AR_PHY_GEN_CTRL,
@@ -379,7 +379,7 @@ static void ar9003_hw_spur_ofdm_work(struct ath_hw *ah,
379 else 379 else
380 spur_subchannel_sd = 1; 380 spur_subchannel_sd = 1;
381 381
382 spur_freq_sd = ((freq_offset - 10) << 9) / 11; 382 spur_freq_sd = (freq_offset << 9) / 11;
383 383
384 } 384 }
385 385
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 46393f90f16c..c03949eb37c8 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -217,7 +217,6 @@ struct ath_buf_state {
217 u8 bf_type; 217 u8 bf_type;
218 u8 bfs_paprd; 218 u8 bfs_paprd;
219 unsigned long bfs_paprd_timestamp; 219 unsigned long bfs_paprd_timestamp;
220 enum ath9k_internal_frame_type bfs_ftype;
221}; 220};
222 221
223struct ath_buf { 222struct ath_buf {
@@ -273,8 +272,6 @@ struct ath_node {
273struct ath_tx_control { 272struct ath_tx_control {
274 struct ath_txq *txq; 273 struct ath_txq *txq;
275 struct ath_node *an; 274 struct ath_node *an;
276 int if_id;
277 enum ath9k_internal_frame_type frame_type;
278 u8 paprd; 275 u8 paprd;
279}; 276};
280 277
@@ -570,7 +567,6 @@ struct ath_ant_comb {
570#define PS_WAIT_FOR_PSPOLL_DATA BIT(2) 567#define PS_WAIT_FOR_PSPOLL_DATA BIT(2)
571#define PS_WAIT_FOR_TX_ACK BIT(3) 568#define PS_WAIT_FOR_TX_ACK BIT(3)
572#define PS_BEACON_SYNC BIT(4) 569#define PS_BEACON_SYNC BIT(4)
573#define PS_TSFOOR_SYNC BIT(5)
574 570
575struct ath_rate_table; 571struct ath_rate_table;
576 572
@@ -669,7 +665,7 @@ extern bool is_ath9k_unloaded;
669 665
670irqreturn_t ath_isr(int irq, void *dev); 666irqreturn_t ath_isr(int irq, void *dev);
671void ath9k_init_crypto(struct ath_softc *sc); 667void ath9k_init_crypto(struct ath_softc *sc);
672int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, 668int ath9k_init_device(u16 devid, struct ath_softc *sc,
673 const struct ath_bus_ops *bus_ops); 669 const struct ath_bus_ops *bus_ops);
674void ath9k_deinit_device(struct ath_softc *sc); 670void ath9k_deinit_device(struct ath_softc *sc);
675void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); 671void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index 0d13ff74a68b..086c9c816bf7 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -522,6 +522,7 @@ static void ath_beacon_config_ap(struct ath_softc *sc,
522 ath9k_beacon_init(sc, nexttbtt, intval); 522 ath9k_beacon_init(sc, nexttbtt, intval);
523 sc->beacon.bmisscnt = 0; 523 sc->beacon.bmisscnt = 0;
524 ath9k_hw_set_interrupts(ah, ah->imask); 524 ath9k_hw_set_interrupts(ah, ah->imask);
525 ath9k_hw_enable_interrupts(ah);
525} 526}
526 527
527/* 528/*
@@ -648,12 +649,8 @@ static void ath_beacon_config_sta(struct ath_softc *sc,
648 ath9k_hw_set_sta_beacon_timers(ah, &bs); 649 ath9k_hw_set_sta_beacon_timers(ah, &bs);
649 ah->imask |= ATH9K_INT_BMISS; 650 ah->imask |= ATH9K_INT_BMISS;
650 651
651 /* 652 ath9k_hw_set_interrupts(ah, ah->imask);
652 * If the beacon config is called beacause of TSFOOR, 653 ath9k_hw_enable_interrupts(ah);
653 * Interrupts will be enabled back at the end of ath9k_tasklet
654 */
655 if (!(sc->ps_flags & PS_TSFOOR_SYNC))
656 ath9k_hw_set_interrupts(ah, ah->imask);
657} 654}
658 655
659static void ath_beacon_config_adhoc(struct ath_softc *sc, 656static void ath_beacon_config_adhoc(struct ath_softc *sc,
@@ -687,12 +684,9 @@ static void ath_beacon_config_adhoc(struct ath_softc *sc,
687 ath9k_hw_disable_interrupts(ah); 684 ath9k_hw_disable_interrupts(ah);
688 ath9k_beacon_init(sc, nexttbtt, intval); 685 ath9k_beacon_init(sc, nexttbtt, intval);
689 sc->beacon.bmisscnt = 0; 686 sc->beacon.bmisscnt = 0;
690 /* 687
691 * If the beacon config is called beacause of TSFOOR, 688 ath9k_hw_set_interrupts(ah, ah->imask);
692 * Interrupts will be enabled back at the end of ath9k_tasklet 689 ath9k_hw_enable_interrupts(ah);
693 */
694 if (!(sc->ps_flags & PS_TSFOOR_SYNC))
695 ath9k_hw_set_interrupts(ah, ah->imask);
696} 690}
697 691
698static bool ath9k_allow_beacon_config(struct ath_softc *sc, 692static bool ath9k_allow_beacon_config(struct ath_softc *sc,
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index a1250c586e40..ac2da3cce788 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -63,6 +63,19 @@ static s16 ath9k_hw_get_default_nf(struct ath_hw *ah,
63 return ath9k_hw_get_nf_limits(ah, chan)->nominal; 63 return ath9k_hw_get_nf_limits(ah, chan)->nominal;
64} 64}
65 65
66s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan)
67{
68 s8 noise = ATH_DEFAULT_NOISE_FLOOR;
69
70 if (chan && chan->noisefloor) {
71 s8 delta = chan->noisefloor -
72 ath9k_hw_get_default_nf(ah, chan);
73 if (delta > 0)
74 noise += delta;
75 }
76 return noise;
77}
78EXPORT_SYMBOL(ath9k_hw_getchan_noise);
66 79
67static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah, 80static void ath9k_hw_update_nfcal_hist_buffer(struct ath_hw *ah,
68 struct ath9k_hw_cal_data *cal, 81 struct ath9k_hw_cal_data *cal,
@@ -378,6 +391,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
378 391
379 if (!caldata) { 392 if (!caldata) {
380 chan->noisefloor = nf; 393 chan->noisefloor = nf;
394 ah->noise = ath9k_hw_getchan_noise(ah, chan);
381 return false; 395 return false;
382 } 396 }
383 397
@@ -385,6 +399,7 @@ bool ath9k_hw_getnf(struct ath_hw *ah, struct ath9k_channel *chan)
385 caldata->nfcal_pending = false; 399 caldata->nfcal_pending = false;
386 ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray); 400 ath9k_hw_update_nfcal_hist_buffer(ah, caldata, nfarray);
387 chan->noisefloor = h[0].privNF; 401 chan->noisefloor = h[0].privNF;
402 ah->noise = ath9k_hw_getchan_noise(ah, chan);
388 return true; 403 return true;
389} 404}
390 405
diff --git a/drivers/net/wireless/ath/ath9k/calib.h b/drivers/net/wireless/ath/ath9k/calib.h
index 1bef41d1b1ff..05b9dbf81850 100644
--- a/drivers/net/wireless/ath/ath9k/calib.h
+++ b/drivers/net/wireless/ath/ath9k/calib.h
@@ -108,6 +108,7 @@ void ath9k_init_nfcal_hist_buffer(struct ath_hw *ah,
108void ath9k_hw_bstuck_nfcal(struct ath_hw *ah); 108void ath9k_hw_bstuck_nfcal(struct ath_hw *ah);
109void ath9k_hw_reset_calibration(struct ath_hw *ah, 109void ath9k_hw_reset_calibration(struct ath_hw *ah,
110 struct ath9k_cal_list *currCal); 110 struct ath9k_cal_list *currCal);
111s16 ath9k_hw_getchan_noise(struct ath_hw *ah, struct ath9k_channel *chan);
111 112
112 113
113#endif /* CALIB_H */ 114#endif /* CALIB_H */
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index d1eb89611ff7..9bec3b89fb68 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -1163,6 +1163,62 @@ static const struct file_operations fops_regdump = {
1163 .llseek = default_llseek,/* read accesses f_pos */ 1163 .llseek = default_llseek,/* read accesses f_pos */
1164}; 1164};
1165 1165
1166static ssize_t read_file_base_eeprom(struct file *file, char __user *user_buf,
1167 size_t count, loff_t *ppos)
1168{
1169 struct ath_softc *sc = file->private_data;
1170 struct ath_hw *ah = sc->sc_ah;
1171 u32 len = 0, size = 1500;
1172 ssize_t retval = 0;
1173 char *buf;
1174
1175 buf = kzalloc(size, GFP_KERNEL);
1176 if (!buf)
1177 return -ENOMEM;
1178
1179 len = ah->eep_ops->dump_eeprom(ah, true, buf, len, size);
1180
1181 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1182 kfree(buf);
1183
1184 return retval;
1185}
1186
1187static const struct file_operations fops_base_eeprom = {
1188 .read = read_file_base_eeprom,
1189 .open = ath9k_debugfs_open,
1190 .owner = THIS_MODULE,
1191 .llseek = default_llseek,
1192};
1193
1194static ssize_t read_file_modal_eeprom(struct file *file, char __user *user_buf,
1195 size_t count, loff_t *ppos)
1196{
1197 struct ath_softc *sc = file->private_data;
1198 struct ath_hw *ah = sc->sc_ah;
1199 u32 len = 0, size = 6000;
1200 char *buf;
1201 size_t retval;
1202
1203 buf = kzalloc(size, GFP_KERNEL);
1204 if (buf == NULL)
1205 return -ENOMEM;
1206
1207 len = ah->eep_ops->dump_eeprom(ah, false, buf, len, size);
1208
1209 retval = simple_read_from_buffer(user_buf, count, ppos, buf, len);
1210 kfree(buf);
1211
1212 return retval;
1213}
1214
1215static const struct file_operations fops_modal_eeprom = {
1216 .read = read_file_modal_eeprom,
1217 .open = ath9k_debugfs_open,
1218 .owner = THIS_MODULE,
1219 .llseek = default_llseek,
1220};
1221
1166int ath9k_init_debug(struct ath_hw *ah) 1222int ath9k_init_debug(struct ath_hw *ah)
1167{ 1223{
1168 struct ath_common *common = ath9k_hw_common(ah); 1224 struct ath_common *common = ath9k_hw_common(ah);
@@ -1206,6 +1262,10 @@ int ath9k_init_debug(struct ath_hw *ah)
1206 &ah->config.cwm_ignore_extcca); 1262 &ah->config.cwm_ignore_extcca);
1207 debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc, 1263 debugfs_create_file("regdump", S_IRUSR, sc->debug.debugfs_phy, sc,
1208 &fops_regdump); 1264 &fops_regdump);
1265 debugfs_create_file("base_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
1266 &fops_base_eeprom);
1267 debugfs_create_file("modal_eeprom", S_IRUSR, sc->debug.debugfs_phy, sc,
1268 &fops_modal_eeprom);
1209 1269
1210 debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR, 1270 debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
1211 sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask); 1271 sc->debug.debugfs_phy, &sc->sc_ah->gpio_mask);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom.h b/drivers/net/wireless/ath/ath9k/eeprom.h
index de99c0da52e4..a3c7d0c247a3 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom.h
+++ b/drivers/net/wireless/ath/ath9k/eeprom.h
@@ -649,6 +649,8 @@ struct eeprom_ops {
649 int (*check_eeprom)(struct ath_hw *hw); 649 int (*check_eeprom)(struct ath_hw *hw);
650 u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param); 650 u32 (*get_eeprom)(struct ath_hw *hw, enum eeprom_param param);
651 bool (*fill_eeprom)(struct ath_hw *hw); 651 bool (*fill_eeprom)(struct ath_hw *hw);
652 u32 (*dump_eeprom)(struct ath_hw *hw, bool dump_base_hdr, u8 *buf,
653 u32 len, u32 size);
652 int (*get_eeprom_ver)(struct ath_hw *hw); 654 int (*get_eeprom_ver)(struct ath_hw *hw);
653 int (*get_eeprom_rev)(struct ath_hw *hw); 655 int (*get_eeprom_rev)(struct ath_hw *hw);
654 void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan); 656 void (*set_board_values)(struct ath_hw *hw, struct ath9k_channel *chan);
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_4k.c b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
index 47cc95086e6e..ea658e794cbd 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_4k.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_4k.c
@@ -72,6 +72,117 @@ static bool ath9k_hw_4k_fill_eeprom(struct ath_hw *ah)
72 return __ath9k_hw_4k_fill_eeprom(ah); 72 return __ath9k_hw_4k_fill_eeprom(ah);
73} 73}
74 74
75#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
76static u32 ath9k_dump_4k_modal_eeprom(char *buf, u32 len, u32 size,
77 struct modal_eep_4k_header *modal_hdr)
78{
79 PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
80 PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
81 PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
82 PR_EEP("Switch Settle", modal_hdr->switchSettling);
83 PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
84 PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
85 PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
86 PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
87 PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
88 PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
89 PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
90 PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
91 PR_EEP("CCA Threshold)", modal_hdr->thresh62);
92 PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
93 PR_EEP("xpdGain", modal_hdr->xpdGain);
94 PR_EEP("External PD", modal_hdr->xpd);
95 PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
96 PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
97 PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
98 PR_EEP("O/D Bias Version", modal_hdr->version);
99 PR_EEP("CCK OutputBias", modal_hdr->ob_0);
100 PR_EEP("BPSK OutputBias", modal_hdr->ob_1);
101 PR_EEP("QPSK OutputBias", modal_hdr->ob_2);
102 PR_EEP("16QAM OutputBias", modal_hdr->ob_3);
103 PR_EEP("64QAM OutputBias", modal_hdr->ob_4);
104 PR_EEP("CCK Driver1_Bias", modal_hdr->db1_0);
105 PR_EEP("BPSK Driver1_Bias", modal_hdr->db1_1);
106 PR_EEP("QPSK Driver1_Bias", modal_hdr->db1_2);
107 PR_EEP("16QAM Driver1_Bias", modal_hdr->db1_3);
108 PR_EEP("64QAM Driver1_Bias", modal_hdr->db1_4);
109 PR_EEP("CCK Driver2_Bias", modal_hdr->db2_0);
110 PR_EEP("BPSK Driver2_Bias", modal_hdr->db2_1);
111 PR_EEP("QPSK Driver2_Bias", modal_hdr->db2_2);
112 PR_EEP("16QAM Driver2_Bias", modal_hdr->db2_3);
113 PR_EEP("64QAM Driver2_Bias", modal_hdr->db2_4);
114 PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
115 PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
116 PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
117 PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
118 PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
119 PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
120 PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
121 PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
122 PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
123 PR_EEP("Ant. Diversity ctl1", modal_hdr->antdiv_ctl1);
124 PR_EEP("Ant. Diversity ctl2", modal_hdr->antdiv_ctl2);
125 PR_EEP("TX Diversity", modal_hdr->tx_diversity);
126
127 return len;
128}
129
130static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
131 u8 *buf, u32 len, u32 size)
132{
133 struct ar5416_eeprom_4k *eep = &ah->eeprom.map4k;
134 struct base_eep_header_4k *pBase = &eep->baseEepHeader;
135
136 if (!dump_base_hdr) {
137 len += snprintf(buf + len, size - len,
138 "%20s :\n", "2GHz modal Header");
139 len += ath9k_dump_4k_modal_eeprom(buf, len, size,
140 &eep->modalHeader);
141 goto out;
142 }
143
144 PR_EEP("Major Version", pBase->version >> 12);
145 PR_EEP("Minor Version", pBase->version & 0xFFF);
146 PR_EEP("Checksum", pBase->checksum);
147 PR_EEP("Length", pBase->length);
148 PR_EEP("RegDomain1", pBase->regDmn[0]);
149 PR_EEP("RegDomain2", pBase->regDmn[1]);
150 PR_EEP("TX Mask", pBase->txMask);
151 PR_EEP("RX Mask", pBase->rxMask);
152 PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
153 PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
154 PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
155 AR5416_OPFLAGS_N_2G_HT20));
156 PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
157 AR5416_OPFLAGS_N_2G_HT40));
158 PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
159 AR5416_OPFLAGS_N_5G_HT20));
160 PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
161 AR5416_OPFLAGS_N_5G_HT40));
162 PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
163 PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
164 PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
165 PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
166 PR_EEP("TX Gain type", pBase->txGainType);
167
168 len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
169 pBase->macAddr);
170
171out:
172 if (len > size)
173 len = size;
174
175 return len;
176}
177#else
178static u32 ath9k_hw_4k_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
179 u8 *buf, u32 len, u32 size)
180{
181 return 0;
182}
183#endif
184
185
75#undef SIZE_EEPROM_4K 186#undef SIZE_EEPROM_4K
76 187
77static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah) 188static int ath9k_hw_4k_check_eeprom(struct ath_hw *ah)
@@ -238,18 +349,14 @@ static u32 ath9k_hw_4k_get_eeprom(struct ath_hw *ah,
238 case EEP_ANT_DIV_CTL1: 349 case EEP_ANT_DIV_CTL1:
239 return pModal->antdiv_ctl1; 350 return pModal->antdiv_ctl1;
240 case EEP_TXGAIN_TYPE: 351 case EEP_TXGAIN_TYPE:
241 if (ver_minor >= AR5416_EEP_MINOR_VER_19) 352 return pBase->txGainType;
242 return pBase->txGainType;
243 else
244 return AR5416_EEP_TXGAIN_ORIGINAL;
245 default: 353 default:
246 return 0; 354 return 0;
247 } 355 }
248} 356}
249 357
250static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah, 358static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
251 struct ath9k_channel *chan, 359 struct ath9k_channel *chan)
252 int16_t *pTxPowerIndexOffset)
253{ 360{
254 struct ath_common *common = ath9k_hw_common(ah); 361 struct ath_common *common = ath9k_hw_common(ah);
255 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; 362 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
@@ -356,8 +463,6 @@ static void ath9k_hw_set_4k_power_cal_table(struct ath_hw *ah,
356 REGWRITE_BUFFER_FLUSH(ah); 463 REGWRITE_BUFFER_FLUSH(ah);
357 } 464 }
358 } 465 }
359
360 *pTxPowerIndexOffset = 0;
361} 466}
362 467
363static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah, 468static void ath9k_hw_set_4k_power_per_rate_table(struct ath_hw *ah,
@@ -580,7 +685,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
580 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k; 685 struct ar5416_eeprom_4k *pEepData = &ah->eeprom.map4k;
581 struct modal_eep_4k_header *pModal = &pEepData->modalHeader; 686 struct modal_eep_4k_header *pModal = &pEepData->modalHeader;
582 int16_t ratesArray[Ar5416RateSize]; 687 int16_t ratesArray[Ar5416RateSize];
583 int16_t txPowerIndexOffset = 0;
584 u8 ht40PowerIncForPdadc = 2; 688 u8 ht40PowerIncForPdadc = 2;
585 int i; 689 int i;
586 690
@@ -597,11 +701,10 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
597 twiceMaxRegulatoryPower, 701 twiceMaxRegulatoryPower,
598 powerLimit); 702 powerLimit);
599 703
600 ath9k_hw_set_4k_power_cal_table(ah, chan, &txPowerIndexOffset); 704 ath9k_hw_set_4k_power_cal_table(ah, chan);
601 705
602 regulatory->max_power_level = 0; 706 regulatory->max_power_level = 0;
603 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { 707 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
604 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
605 if (ratesArray[i] > MAX_RATE_POWER) 708 if (ratesArray[i] > MAX_RATE_POWER)
606 ratesArray[i] = MAX_RATE_POWER; 709 ratesArray[i] = MAX_RATE_POWER;
607 710
@@ -612,15 +715,6 @@ static void ath9k_hw_4k_set_txpower(struct ath_hw *ah,
612 if (test) 715 if (test)
613 return; 716 return;
614 717
615 /* Update regulatory */
616 i = rate6mb;
617 if (IS_CHAN_HT40(chan))
618 i = rateHt40_0;
619 else if (IS_CHAN_HT20(chan))
620 i = rateHt20_0;
621
622 regulatory->max_power_level = ratesArray[i];
623
624 if (AR_SREV_9280_20_OR_LATER(ah)) { 718 if (AR_SREV_9280_20_OR_LATER(ah)) {
625 for (i = 0; i < Ar5416RateSize; i++) 719 for (i = 0; i < Ar5416RateSize; i++)
626 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2; 720 ratesArray[i] -= AR5416_PWR_TABLE_OFFSET_DB * 2;
@@ -1063,6 +1157,7 @@ const struct eeprom_ops eep_4k_ops = {
1063 .check_eeprom = ath9k_hw_4k_check_eeprom, 1157 .check_eeprom = ath9k_hw_4k_check_eeprom,
1064 .get_eeprom = ath9k_hw_4k_get_eeprom, 1158 .get_eeprom = ath9k_hw_4k_get_eeprom,
1065 .fill_eeprom = ath9k_hw_4k_fill_eeprom, 1159 .fill_eeprom = ath9k_hw_4k_fill_eeprom,
1160 .dump_eeprom = ath9k_hw_4k_dump_eeprom,
1066 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver, 1161 .get_eeprom_ver = ath9k_hw_4k_get_eeprom_ver,
1067 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev, 1162 .get_eeprom_rev = ath9k_hw_4k_get_eeprom_rev,
1068 .set_board_values = ath9k_hw_4k_set_board_values, 1163 .set_board_values = ath9k_hw_4k_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_9287.c b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
index d6f6b192f450..21f180db2381 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_9287.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_9287.c
@@ -76,6 +76,111 @@ static bool ath9k_hw_ar9287_fill_eeprom(struct ath_hw *ah)
76 return __ath9k_hw_ar9287_fill_eeprom(ah); 76 return __ath9k_hw_ar9287_fill_eeprom(ah);
77} 77}
78 78
79#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
80static u32 ar9287_dump_modal_eeprom(char *buf, u32 len, u32 size,
81 struct modal_eep_ar9287_header *modal_hdr)
82{
83 PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
84 PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
85 PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
86 PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
87 PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
88 PR_EEP("Switch Settle", modal_hdr->switchSettling);
89 PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
90 PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
91 PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
92 PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
93 PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
94 PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
95 PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
96 PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
97 PR_EEP("CCA Threshold)", modal_hdr->thresh62);
98 PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
99 PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
100 PR_EEP("xpdGain", modal_hdr->xpdGain);
101 PR_EEP("External PD", modal_hdr->xpd);
102 PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
103 PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
104 PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
105 PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
106 PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
107 PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
108 PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
109 PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
110 PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
111 PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
112 PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
113 PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
114 PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
115 PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
116 PR_EEP("AR92x7 Version", modal_hdr->version);
117 PR_EEP("DriverBias1", modal_hdr->db1);
118 PR_EEP("DriverBias2", modal_hdr->db1);
119 PR_EEP("CCK OutputBias", modal_hdr->ob_cck);
120 PR_EEP("PSK OutputBias", modal_hdr->ob_psk);
121 PR_EEP("QAM OutputBias", modal_hdr->ob_qam);
122 PR_EEP("PAL_OFF OutputBias", modal_hdr->ob_pal_off);
123
124 return len;
125}
126
127static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
128 u8 *buf, u32 len, u32 size)
129{
130 struct ar9287_eeprom *eep = &ah->eeprom.map9287;
131 struct base_eep_ar9287_header *pBase = &eep->baseEepHeader;
132
133 if (!dump_base_hdr) {
134 len += snprintf(buf + len, size - len,
135 "%20s :\n", "2GHz modal Header");
136 len += ar9287_dump_modal_eeprom(buf, len, size,
137 &eep->modalHeader);
138 goto out;
139 }
140
141 PR_EEP("Major Version", pBase->version >> 12);
142 PR_EEP("Minor Version", pBase->version & 0xFFF);
143 PR_EEP("Checksum", pBase->checksum);
144 PR_EEP("Length", pBase->length);
145 PR_EEP("RegDomain1", pBase->regDmn[0]);
146 PR_EEP("RegDomain2", pBase->regDmn[1]);
147 PR_EEP("TX Mask", pBase->txMask);
148 PR_EEP("RX Mask", pBase->rxMask);
149 PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
150 PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
151 PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
152 AR5416_OPFLAGS_N_2G_HT20));
153 PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
154 AR5416_OPFLAGS_N_2G_HT40));
155 PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
156 AR5416_OPFLAGS_N_5G_HT20));
157 PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
158 AR5416_OPFLAGS_N_5G_HT40));
159 PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
160 PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
161 PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
162 PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
163 PR_EEP("Power Table Offset", pBase->pwrTableOffset);
164 PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
165
166 len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
167 pBase->macAddr);
168
169out:
170 if (len > size)
171 len = size;
172
173 return len;
174}
175#else
176static u32 ath9k_hw_ar9287_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
177 u8 *buf, u32 len, u32 size)
178{
179 return 0;
180}
181#endif
182
183
79static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah) 184static int ath9k_hw_ar9287_check_eeprom(struct ath_hw *ah)
80{ 185{
81 u32 sum = 0, el, integer; 186 u32 sum = 0, el, integer;
@@ -307,8 +412,7 @@ static void ar9287_eeprom_olpc_set_pdadcs(struct ath_hw *ah,
307} 412}
308 413
309static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah, 414static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
310 struct ath9k_channel *chan, 415 struct ath9k_channel *chan)
311 int16_t *pTxPowerIndexOffset)
312{ 416{
313 struct cal_data_per_freq_ar9287 *pRawDataset; 417 struct cal_data_per_freq_ar9287 *pRawDataset;
314 struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop; 418 struct cal_data_op_loop_ar9287 *pRawDatasetOpenLoop;
@@ -444,8 +548,6 @@ static void ath9k_hw_set_ar9287_power_cal_table(struct ath_hw *ah,
444 REGWRITE_BUFFER_FLUSH(ah); 548 REGWRITE_BUFFER_FLUSH(ah);
445 } 549 }
446 } 550 }
447
448 *pTxPowerIndexOffset = 0;
449} 551}
450 552
451static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah, 553static void ath9k_hw_set_ar9287_power_per_rate_table(struct ath_hw *ah,
@@ -720,7 +822,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
720 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287; 822 struct ar9287_eeprom *pEepData = &ah->eeprom.map9287;
721 struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader; 823 struct modal_eep_ar9287_header *pModal = &pEepData->modalHeader;
722 int16_t ratesArray[Ar5416RateSize]; 824 int16_t ratesArray[Ar5416RateSize];
723 int16_t txPowerIndexOffset = 0;
724 u8 ht40PowerIncForPdadc = 2; 825 u8 ht40PowerIncForPdadc = 2;
725 int i; 826 int i;
726 827
@@ -736,11 +837,10 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
736 twiceMaxRegulatoryPower, 837 twiceMaxRegulatoryPower,
737 powerLimit); 838 powerLimit);
738 839
739 ath9k_hw_set_ar9287_power_cal_table(ah, chan, &txPowerIndexOffset); 840 ath9k_hw_set_ar9287_power_cal_table(ah, chan);
740 841
741 regulatory->max_power_level = 0; 842 regulatory->max_power_level = 0;
742 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { 843 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
743 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
744 if (ratesArray[i] > MAX_RATE_POWER) 844 if (ratesArray[i] > MAX_RATE_POWER)
745 ratesArray[i] = MAX_RATE_POWER; 845 ratesArray[i] = MAX_RATE_POWER;
746 846
@@ -751,13 +851,6 @@ static void ath9k_hw_ar9287_set_txpower(struct ath_hw *ah,
751 if (test) 851 if (test)
752 return; 852 return;
753 853
754 if (IS_CHAN_2GHZ(chan))
755 i = rate1l;
756 else
757 i = rate6mb;
758
759 regulatory->max_power_level = ratesArray[i];
760
761 if (AR_SREV_9280_20_OR_LATER(ah)) { 854 if (AR_SREV_9280_20_OR_LATER(ah)) {
762 for (i = 0; i < Ar5416RateSize; i++) 855 for (i = 0; i < Ar5416RateSize; i++)
763 ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2; 856 ratesArray[i] -= AR9287_PWR_TABLE_OFFSET_DB * 2;
@@ -1003,6 +1096,7 @@ const struct eeprom_ops eep_ar9287_ops = {
1003 .check_eeprom = ath9k_hw_ar9287_check_eeprom, 1096 .check_eeprom = ath9k_hw_ar9287_check_eeprom,
1004 .get_eeprom = ath9k_hw_ar9287_get_eeprom, 1097 .get_eeprom = ath9k_hw_ar9287_get_eeprom,
1005 .fill_eeprom = ath9k_hw_ar9287_fill_eeprom, 1098 .fill_eeprom = ath9k_hw_ar9287_fill_eeprom,
1099 .dump_eeprom = ath9k_hw_ar9287_dump_eeprom,
1006 .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver, 1100 .get_eeprom_ver = ath9k_hw_ar9287_get_eeprom_ver,
1007 .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev, 1101 .get_eeprom_rev = ath9k_hw_ar9287_get_eeprom_rev,
1008 .set_board_values = ath9k_hw_ar9287_set_board_values, 1102 .set_board_values = ath9k_hw_ar9287_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/eeprom_def.c b/drivers/net/wireless/ath/ath9k/eeprom_def.c
index b9540a992616..e7e84be8beed 100644
--- a/drivers/net/wireless/ath/ath9k/eeprom_def.c
+++ b/drivers/net/wireless/ath/ath9k/eeprom_def.c
@@ -133,6 +133,136 @@ static bool ath9k_hw_def_fill_eeprom(struct ath_hw *ah)
133 133
134#undef SIZE_EEPROM_DEF 134#undef SIZE_EEPROM_DEF
135 135
136#if defined(CONFIG_ATH9K_DEBUGFS) || defined(CONFIG_ATH9K_HTC_DEBUGFS)
137static u32 ath9k_def_dump_modal_eeprom(char *buf, u32 len, u32 size,
138 struct modal_eep_header *modal_hdr)
139{
140 PR_EEP("Chain0 Ant. Control", modal_hdr->antCtrlChain[0]);
141 PR_EEP("Chain1 Ant. Control", modal_hdr->antCtrlChain[1]);
142 PR_EEP("Chain2 Ant. Control", modal_hdr->antCtrlChain[2]);
143 PR_EEP("Ant. Common Control", modal_hdr->antCtrlCommon);
144 PR_EEP("Chain0 Ant. Gain", modal_hdr->antennaGainCh[0]);
145 PR_EEP("Chain1 Ant. Gain", modal_hdr->antennaGainCh[1]);
146 PR_EEP("Chain2 Ant. Gain", modal_hdr->antennaGainCh[2]);
147 PR_EEP("Switch Settle", modal_hdr->switchSettling);
148 PR_EEP("Chain0 TxRxAtten", modal_hdr->txRxAttenCh[0]);
149 PR_EEP("Chain1 TxRxAtten", modal_hdr->txRxAttenCh[1]);
150 PR_EEP("Chain2 TxRxAtten", modal_hdr->txRxAttenCh[2]);
151 PR_EEP("Chain0 RxTxMargin", modal_hdr->rxTxMarginCh[0]);
152 PR_EEP("Chain1 RxTxMargin", modal_hdr->rxTxMarginCh[1]);
153 PR_EEP("Chain2 RxTxMargin", modal_hdr->rxTxMarginCh[2]);
154 PR_EEP("ADC Desired size", modal_hdr->adcDesiredSize);
155 PR_EEP("PGA Desired size", modal_hdr->pgaDesiredSize);
156 PR_EEP("Chain0 xlna Gain", modal_hdr->xlnaGainCh[0]);
157 PR_EEP("Chain1 xlna Gain", modal_hdr->xlnaGainCh[1]);
158 PR_EEP("Chain2 xlna Gain", modal_hdr->xlnaGainCh[2]);
159 PR_EEP("txEndToXpaOff", modal_hdr->txEndToXpaOff);
160 PR_EEP("txEndToRxOn", modal_hdr->txEndToRxOn);
161 PR_EEP("txFrameToXpaOn", modal_hdr->txFrameToXpaOn);
162 PR_EEP("CCA Threshold)", modal_hdr->thresh62);
163 PR_EEP("Chain0 NF Threshold", modal_hdr->noiseFloorThreshCh[0]);
164 PR_EEP("Chain1 NF Threshold", modal_hdr->noiseFloorThreshCh[1]);
165 PR_EEP("Chain2 NF Threshold", modal_hdr->noiseFloorThreshCh[2]);
166 PR_EEP("xpdGain", modal_hdr->xpdGain);
167 PR_EEP("External PD", modal_hdr->xpd);
168 PR_EEP("Chain0 I Coefficient", modal_hdr->iqCalICh[0]);
169 PR_EEP("Chain1 I Coefficient", modal_hdr->iqCalICh[1]);
170 PR_EEP("Chain2 I Coefficient", modal_hdr->iqCalICh[2]);
171 PR_EEP("Chain0 Q Coefficient", modal_hdr->iqCalQCh[0]);
172 PR_EEP("Chain1 Q Coefficient", modal_hdr->iqCalQCh[1]);
173 PR_EEP("Chain2 Q Coefficient", modal_hdr->iqCalQCh[2]);
174 PR_EEP("pdGainOverlap", modal_hdr->pdGainOverlap);
175 PR_EEP("Chain0 OutputBias", modal_hdr->ob);
176 PR_EEP("Chain0 DriverBias", modal_hdr->db);
177 PR_EEP("xPA Bias Level", modal_hdr->xpaBiasLvl);
178 PR_EEP("2chain pwr decrease", modal_hdr->pwrDecreaseFor2Chain);
179 PR_EEP("3chain pwr decrease", modal_hdr->pwrDecreaseFor3Chain);
180 PR_EEP("txFrameToDataStart", modal_hdr->txFrameToDataStart);
181 PR_EEP("txFrameToPaOn", modal_hdr->txFrameToPaOn);
182 PR_EEP("HT40 Power Inc.", modal_hdr->ht40PowerIncForPdadc);
183 PR_EEP("Chain0 bswAtten", modal_hdr->bswAtten[0]);
184 PR_EEP("Chain1 bswAtten", modal_hdr->bswAtten[1]);
185 PR_EEP("Chain2 bswAtten", modal_hdr->bswAtten[2]);
186 PR_EEP("Chain0 bswMargin", modal_hdr->bswMargin[0]);
187 PR_EEP("Chain1 bswMargin", modal_hdr->bswMargin[1]);
188 PR_EEP("Chain2 bswMargin", modal_hdr->bswMargin[2]);
189 PR_EEP("HT40 Switch Settle", modal_hdr->swSettleHt40);
190 PR_EEP("Chain0 xatten2Db", modal_hdr->xatten2Db[0]);
191 PR_EEP("Chain1 xatten2Db", modal_hdr->xatten2Db[1]);
192 PR_EEP("Chain2 xatten2Db", modal_hdr->xatten2Db[2]);
193 PR_EEP("Chain0 xatten2Margin", modal_hdr->xatten2Margin[0]);
194 PR_EEP("Chain1 xatten2Margin", modal_hdr->xatten2Margin[1]);
195 PR_EEP("Chain2 xatten2Margin", modal_hdr->xatten2Margin[2]);
196 PR_EEP("Chain1 OutputBias", modal_hdr->ob_ch1);
197 PR_EEP("Chain1 DriverBias", modal_hdr->db_ch1);
198 PR_EEP("LNA Control", modal_hdr->lna_ctl);
199 PR_EEP("XPA Bias Freq0", modal_hdr->xpaBiasLvlFreq[0]);
200 PR_EEP("XPA Bias Freq1", modal_hdr->xpaBiasLvlFreq[1]);
201 PR_EEP("XPA Bias Freq2", modal_hdr->xpaBiasLvlFreq[2]);
202
203 return len;
204}
205
206static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
207 u8 *buf, u32 len, u32 size)
208{
209 struct ar5416_eeprom_def *eep = &ah->eeprom.def;
210 struct base_eep_header *pBase = &eep->baseEepHeader;
211
212 if (!dump_base_hdr) {
213 len += snprintf(buf + len, size - len,
214 "%20s :\n", "2GHz modal Header");
215 len += ath9k_def_dump_modal_eeprom(buf, len, size,
216 &eep->modalHeader[0]);
217 len += snprintf(buf + len, size - len,
218 "%20s :\n", "5GHz modal Header");
219 len += ath9k_def_dump_modal_eeprom(buf, len, size,
220 &eep->modalHeader[1]);
221 goto out;
222 }
223
224 PR_EEP("Major Version", pBase->version >> 12);
225 PR_EEP("Minor Version", pBase->version & 0xFFF);
226 PR_EEP("Checksum", pBase->checksum);
227 PR_EEP("Length", pBase->length);
228 PR_EEP("RegDomain1", pBase->regDmn[0]);
229 PR_EEP("RegDomain2", pBase->regDmn[1]);
230 PR_EEP("TX Mask", pBase->txMask);
231 PR_EEP("RX Mask", pBase->rxMask);
232 PR_EEP("Allow 5GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11A));
233 PR_EEP("Allow 2GHz", !!(pBase->opCapFlags & AR5416_OPFLAGS_11G));
234 PR_EEP("Disable 2GHz HT20", !!(pBase->opCapFlags &
235 AR5416_OPFLAGS_N_2G_HT20));
236 PR_EEP("Disable 2GHz HT40", !!(pBase->opCapFlags &
237 AR5416_OPFLAGS_N_2G_HT40));
238 PR_EEP("Disable 5Ghz HT20", !!(pBase->opCapFlags &
239 AR5416_OPFLAGS_N_5G_HT20));
240 PR_EEP("Disable 5Ghz HT40", !!(pBase->opCapFlags &
241 AR5416_OPFLAGS_N_5G_HT40));
242 PR_EEP("Big Endian", !!(pBase->eepMisc & 0x01));
243 PR_EEP("Cal Bin Major Ver", (pBase->binBuildNumber >> 24) & 0xFF);
244 PR_EEP("Cal Bin Minor Ver", (pBase->binBuildNumber >> 16) & 0xFF);
245 PR_EEP("Cal Bin Build", (pBase->binBuildNumber >> 8) & 0xFF);
246 PR_EEP("OpenLoop Power Ctrl", pBase->openLoopPwrCntl);
247
248 len += snprintf(buf + len, size - len, "%20s : %pM\n", "MacAddress",
249 pBase->macAddr);
250
251out:
252 if (len > size)
253 len = size;
254
255 return len;
256}
257#else
258static u32 ath9k_hw_def_dump_eeprom(struct ath_hw *ah, bool dump_base_hdr,
259 u8 *buf, u32 len, u32 size)
260{
261 return 0;
262}
263#endif
264
265
136static int ath9k_hw_def_check_eeprom(struct ath_hw *ah) 266static int ath9k_hw_def_check_eeprom(struct ath_hw *ah)
137{ 267{
138 struct ar5416_eeprom_def *eep = 268 struct ar5416_eeprom_def *eep =
@@ -693,8 +823,7 @@ static void ath9k_adjust_pdadc_values(struct ath_hw *ah,
693} 823}
694 824
695static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah, 825static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
696 struct ath9k_channel *chan, 826 struct ath9k_channel *chan)
697 int16_t *pTxPowerIndexOffset)
698{ 827{
699#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x) 828#define SM_PD_GAIN(x) SM(0x38, AR_PHY_TPCRG5_PD_GAIN_BOUNDARY_##x)
700#define SM_PDGAIN_B(x, y) \ 829#define SM_PDGAIN_B(x, y) \
@@ -855,7 +984,6 @@ static void ath9k_hw_set_def_power_cal_table(struct ath_hw *ah,
855 } 984 }
856 } 985 }
857 986
858 *pTxPowerIndexOffset = 0;
859#undef SM_PD_GAIN 987#undef SM_PD_GAIN
860#undef SM_PDGAIN_B 988#undef SM_PDGAIN_B
861} 989}
@@ -1143,7 +1271,6 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
1143 struct modal_eep_header *pModal = 1271 struct modal_eep_header *pModal =
1144 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]); 1272 &(pEepData->modalHeader[IS_CHAN_2GHZ(chan)]);
1145 int16_t ratesArray[Ar5416RateSize]; 1273 int16_t ratesArray[Ar5416RateSize];
1146 int16_t txPowerIndexOffset = 0;
1147 u8 ht40PowerIncForPdadc = 2; 1274 u8 ht40PowerIncForPdadc = 2;
1148 int i, cck_ofdm_delta = 0; 1275 int i, cck_ofdm_delta = 0;
1149 1276
@@ -1160,28 +1287,16 @@ static void ath9k_hw_def_set_txpower(struct ath_hw *ah,
1160 twiceMaxRegulatoryPower, 1287 twiceMaxRegulatoryPower,
1161 powerLimit); 1288 powerLimit);
1162 1289
1163 ath9k_hw_set_def_power_cal_table(ah, chan, &txPowerIndexOffset); 1290 ath9k_hw_set_def_power_cal_table(ah, chan);
1164 1291
1165 regulatory->max_power_level = 0; 1292 regulatory->max_power_level = 0;
1166 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) { 1293 for (i = 0; i < ARRAY_SIZE(ratesArray); i++) {
1167 ratesArray[i] = (int16_t)(txPowerIndexOffset + ratesArray[i]);
1168 if (ratesArray[i] > MAX_RATE_POWER) 1294 if (ratesArray[i] > MAX_RATE_POWER)
1169 ratesArray[i] = MAX_RATE_POWER; 1295 ratesArray[i] = MAX_RATE_POWER;
1170 if (ratesArray[i] > regulatory->max_power_level) 1296 if (ratesArray[i] > regulatory->max_power_level)
1171 regulatory->max_power_level = ratesArray[i]; 1297 regulatory->max_power_level = ratesArray[i];
1172 } 1298 }
1173 1299
1174 if (!test) {
1175 i = rate6mb;
1176
1177 if (IS_CHAN_HT40(chan))
1178 i = rateHt40_0;
1179 else if (IS_CHAN_HT20(chan))
1180 i = rateHt20_0;
1181
1182 regulatory->max_power_level = ratesArray[i];
1183 }
1184
1185 switch(ar5416_get_ntxchains(ah->txchainmask)) { 1300 switch(ar5416_get_ntxchains(ah->txchainmask)) {
1186 case 1: 1301 case 1:
1187 break; 1302 break;
@@ -1336,6 +1451,7 @@ const struct eeprom_ops eep_def_ops = {
1336 .check_eeprom = ath9k_hw_def_check_eeprom, 1451 .check_eeprom = ath9k_hw_def_check_eeprom,
1337 .get_eeprom = ath9k_hw_def_get_eeprom, 1452 .get_eeprom = ath9k_hw_def_get_eeprom,
1338 .fill_eeprom = ath9k_hw_def_fill_eeprom, 1453 .fill_eeprom = ath9k_hw_def_fill_eeprom,
1454 .dump_eeprom = ath9k_hw_def_dump_eeprom,
1339 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver, 1455 .get_eeprom_ver = ath9k_hw_def_get_eeprom_ver,
1340 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev, 1456 .get_eeprom_rev = ath9k_hw_def_get_eeprom_rev,
1341 .set_board_values = ath9k_hw_def_set_board_values, 1457 .set_board_values = ath9k_hw_def_set_board_values,
diff --git a/drivers/net/wireless/ath/ath9k/gpio.c b/drivers/net/wireless/ath/ath9k/gpio.c
index bc713fc28191..5113dd80c99f 100644
--- a/drivers/net/wireless/ath/ath9k/gpio.c
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
@@ -149,6 +149,7 @@ static void ath9k_gen_timer_start(struct ath_hw *ah,
149 ath9k_hw_disable_interrupts(ah); 149 ath9k_hw_disable_interrupts(ah);
150 ah->imask |= ATH9K_INT_GENTIMER; 150 ah->imask |= ATH9K_INT_GENTIMER;
151 ath9k_hw_set_interrupts(ah, ah->imask); 151 ath9k_hw_set_interrupts(ah, ah->imask);
152 ath9k_hw_enable_interrupts(ah);
152 } 153 }
153} 154}
154 155
@@ -163,6 +164,7 @@ static void ath9k_gen_timer_stop(struct ath_hw *ah, struct ath_gen_timer *timer)
163 ath9k_hw_disable_interrupts(ah); 164 ath9k_hw_disable_interrupts(ah);
164 ah->imask &= ~ATH9K_INT_GENTIMER; 165 ah->imask &= ~ATH9K_INT_GENTIMER;
165 ath9k_hw_set_interrupts(ah, ah->imask); 166 ath9k_hw_set_interrupts(ah, ah->imask);
167 ath9k_hw_enable_interrupts(ah);
166 } 168 }
167} 169}
168 170
diff --git a/drivers/net/wireless/ath/ath9k/htc.h b/drivers/net/wireless/ath/ath9k/htc.h
index 5bc022087e65..da5596766d82 100644
--- a/drivers/net/wireless/ath/ath9k/htc.h
+++ b/drivers/net/wireless/ath/ath9k/htc.h
@@ -521,8 +521,6 @@ void ath9k_htc_beaconep(void *drv_priv, struct sk_buff *skb,
521 521
522int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv, 522int ath9k_htc_update_cap_target(struct ath9k_htc_priv *priv,
523 u8 enable_coex); 523 u8 enable_coex);
524void ath9k_htc_station_work(struct work_struct *work);
525void ath9k_htc_aggr_work(struct work_struct *work);
526void ath9k_htc_ani_work(struct work_struct *work); 524void ath9k_htc_ani_work(struct work_struct *work);
527void ath9k_htc_start_ani(struct ath9k_htc_priv *priv); 525void ath9k_htc_start_ani(struct ath9k_htc_priv *priv);
528void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv); 526void ath9k_htc_stop_ani(struct ath9k_htc_priv *priv);
@@ -542,7 +540,6 @@ int ath9k_htc_tx_get_slot(struct ath9k_htc_priv *priv);
542void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot); 540void ath9k_htc_tx_clear_slot(struct ath9k_htc_priv *priv, int slot);
543void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv); 541void ath9k_htc_tx_drain(struct ath9k_htc_priv *priv);
544void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event); 542void ath9k_htc_txstatus(struct ath9k_htc_priv *priv, void *wmi_event);
545void ath9k_htc_tx_failed(struct ath9k_htc_priv *priv);
546void ath9k_tx_failed_tasklet(unsigned long data); 543void ath9k_tx_failed_tasklet(unsigned long data);
547void ath9k_htc_tx_cleanup_timer(unsigned long data); 544void ath9k_htc_tx_cleanup_timer(unsigned long data);
548 545
diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_init.c b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
index 3bea7ea86f0a..19aa5b724887 100644
--- a/drivers/net/wireless/ath/ath9k/htc_drv_init.c
+++ b/drivers/net/wireless/ath/ath9k/htc_drv_init.c
@@ -666,7 +666,6 @@ static int ath9k_init_priv(struct ath9k_htc_priv *priv,
666 return -ENOMEM; 666 return -ENOMEM;
667 667
668 ah->hw_version.devid = devid; 668 ah->hw_version.devid = devid;
669 ah->hw_version.subsysid = 0; /* FIXME */
670 ah->hw_version.usbdev = drv_info; 669 ah->hw_version.usbdev = drv_info;
671 ah->ah_flags |= AH_USE_EEPROM; 670 ah->ah_flags |= AH_USE_EEPROM;
672 ah->reg_ops.read = ath9k_regread; 671 ah->reg_ops.read = ath9k_regread;
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 8dcefe74f4c3..db44e5b0c98b 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -1486,6 +1486,7 @@ int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
1486 memset(caldata, 0, sizeof(*caldata)); 1486 memset(caldata, 0, sizeof(*caldata));
1487 ath9k_init_nfcal_hist_buffer(ah, chan); 1487 ath9k_init_nfcal_hist_buffer(ah, chan);
1488 } 1488 }
1489 ah->noise = ath9k_hw_getchan_noise(ah, chan);
1489 1490
1490 if (bChannelChange && 1491 if (bChannelChange &&
1491 (ah->chip_fullsleep != true) && 1492 (ah->chip_fullsleep != true) &&
@@ -2439,15 +2440,18 @@ void ath9k_hw_set_txpowerlimit(struct ath_hw *ah, u32 limit, bool test)
2439 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 2440 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
2440 struct ath9k_channel *chan = ah->curchan; 2441 struct ath9k_channel *chan = ah->curchan;
2441 struct ieee80211_channel *channel = chan->chan; 2442 struct ieee80211_channel *channel = chan->chan;
2443 int reg_pwr = min_t(int, MAX_RATE_POWER, regulatory->power_limit);
2444 int chan_pwr = channel->max_power * 2;
2445
2446 if (test)
2447 reg_pwr = chan_pwr = MAX_RATE_POWER;
2442 2448
2443 regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER); 2449 regulatory->power_limit = min(limit, (u32) MAX_RATE_POWER);
2444 2450
2445 ah->eep_ops->set_txpower(ah, chan, 2451 ah->eep_ops->set_txpower(ah, chan,
2446 ath9k_regd_get_ctl(regulatory, chan), 2452 ath9k_regd_get_ctl(regulatory, chan),
2447 channel->max_antenna_gain * 2, 2453 channel->max_antenna_gain * 2,
2448 channel->max_power * 2, 2454 chan_pwr, reg_pwr, test);
2449 min((u32) MAX_RATE_POWER,
2450 (u32) regulatory->power_limit), test);
2451} 2455}
2452EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit); 2456EXPORT_SYMBOL(ath9k_hw_set_txpowerlimit);
2453 2457
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index c79889036ec4..4fbcced2828c 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -93,6 +93,12 @@
93 (_ah)->reg_ops.write_flush((_ah)); \ 93 (_ah)->reg_ops.write_flush((_ah)); \
94 } while (0) 94 } while (0)
95 95
96#define PR_EEP(_s, _val) \
97 do { \
98 len += snprintf(buf + len, size - len, "%20s : %10d\n", \
99 _s, (_val)); \
100 } while (0)
101
96#define SM(_v, _f) (((_v) << _f##_S) & _f) 102#define SM(_v, _f) (((_v) << _f##_S) & _f)
97#define MS(_v, _f) (((_v) & _f) >> _f##_S) 103#define MS(_v, _f) (((_v) & _f) >> _f##_S)
98#define REG_RMW_FIELD(_a, _r, _f, _v) \ 104#define REG_RMW_FIELD(_a, _r, _f, _v) \
@@ -438,7 +444,6 @@ struct ath9k_hw_version {
438 u16 phyRev; 444 u16 phyRev;
439 u16 analog5GhzRev; 445 u16 analog5GhzRev;
440 u16 analog2GhzRev; 446 u16 analog2GhzRev;
441 u16 subsysid;
442 enum ath_usb_dev usbdev; 447 enum ath_usb_dev usbdev;
443}; 448};
444 449
@@ -690,6 +695,7 @@ struct ath_hw {
690 enum nl80211_iftype opmode; 695 enum nl80211_iftype opmode;
691 enum ath9k_power_mode power_mode; 696 enum ath9k_power_mode power_mode;
692 697
698 s8 noise;
693 struct ath9k_hw_cal_data *caldata; 699 struct ath9k_hw_cal_data *caldata;
694 struct ath9k_pacal_info pacal_info; 700 struct ath9k_pacal_info pacal_info;
695 struct ar5416Stats stats; 701 struct ar5416Stats stats;
@@ -703,6 +709,7 @@ struct ath_hw {
703 u32 txdesc_interrupt_mask; 709 u32 txdesc_interrupt_mask;
704 u32 txeol_interrupt_mask; 710 u32 txeol_interrupt_mask;
705 u32 txurn_interrupt_mask; 711 u32 txurn_interrupt_mask;
712 atomic_t intr_ref_cnt;
706 bool chip_fullsleep; 713 bool chip_fullsleep;
707 u32 atim_window; 714 u32 atim_window;
708 715
diff --git a/drivers/net/wireless/ath/ath9k/init.c b/drivers/net/wireless/ath/ath9k/init.c
index aa0ff7e2c922..db38a58e752d 100644
--- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -548,7 +548,7 @@ static void ath9k_init_misc(struct ath_softc *sc)
548 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT; 548 sc->ant_comb.count = ATH_ANT_DIV_COMB_INIT_COUNT;
549} 549}
550 550
551static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid, 551static int ath9k_init_softc(u16 devid, struct ath_softc *sc,
552 const struct ath_bus_ops *bus_ops) 552 const struct ath_bus_ops *bus_ops)
553{ 553{
554 struct ath9k_platform_data *pdata = sc->dev->platform_data; 554 struct ath9k_platform_data *pdata = sc->dev->platform_data;
@@ -563,10 +563,10 @@ static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
563 563
564 ah->hw = sc->hw; 564 ah->hw = sc->hw;
565 ah->hw_version.devid = devid; 565 ah->hw_version.devid = devid;
566 ah->hw_version.subsysid = subsysid;
567 ah->reg_ops.read = ath9k_ioread32; 566 ah->reg_ops.read = ath9k_ioread32;
568 ah->reg_ops.write = ath9k_iowrite32; 567 ah->reg_ops.write = ath9k_iowrite32;
569 ah->reg_ops.rmw = ath9k_reg_rmw; 568 ah->reg_ops.rmw = ath9k_reg_rmw;
569 atomic_set(&ah->intr_ref_cnt, -1);
570 sc->sc_ah = ah; 570 sc->sc_ah = ah;
571 571
572 if (!pdata) { 572 if (!pdata) {
@@ -743,7 +743,7 @@ void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
743 SET_IEEE80211_PERM_ADDR(hw, common->macaddr); 743 SET_IEEE80211_PERM_ADDR(hw, common->macaddr);
744} 744}
745 745
746int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid, 746int ath9k_init_device(u16 devid, struct ath_softc *sc,
747 const struct ath_bus_ops *bus_ops) 747 const struct ath_bus_ops *bus_ops)
748{ 748{
749 struct ieee80211_hw *hw = sc->hw; 749 struct ieee80211_hw *hw = sc->hw;
@@ -753,7 +753,7 @@ int ath9k_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
753 struct ath_regulatory *reg; 753 struct ath_regulatory *reg;
754 754
755 /* Bring up device */ 755 /* Bring up device */
756 error = ath9k_init_softc(devid, sc, subsysid, bus_ops); 756 error = ath9k_init_softc(devid, sc, bus_ops);
757 if (error != 0) 757 if (error != 0)
758 goto error_init; 758 goto error_init;
759 759
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index b6b523a897e5..0f90e1521ffe 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -800,6 +800,11 @@ void ath9k_hw_disable_interrupts(struct ath_hw *ah)
800{ 800{
801 struct ath_common *common = ath9k_hw_common(ah); 801 struct ath_common *common = ath9k_hw_common(ah);
802 802
803 if (!(ah->imask & ATH9K_INT_GLOBAL))
804 atomic_set(&ah->intr_ref_cnt, -1);
805 else
806 atomic_dec(&ah->intr_ref_cnt);
807
803 ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n"); 808 ath_dbg(common, ATH_DBG_INTERRUPT, "disable IER\n");
804 REG_WRITE(ah, AR_IER, AR_IER_DISABLE); 809 REG_WRITE(ah, AR_IER, AR_IER_DISABLE);
805 (void) REG_READ(ah, AR_IER); 810 (void) REG_READ(ah, AR_IER);
@@ -821,6 +826,13 @@ void ath9k_hw_enable_interrupts(struct ath_hw *ah)
821 if (!(ah->imask & ATH9K_INT_GLOBAL)) 826 if (!(ah->imask & ATH9K_INT_GLOBAL))
822 return; 827 return;
823 828
829 if (!atomic_inc_and_test(&ah->intr_ref_cnt)) {
830 ath_dbg(common, ATH_DBG_INTERRUPT,
831 "Do not enable IER ref count %d\n",
832 atomic_read(&ah->intr_ref_cnt));
833 return;
834 }
835
824 if (AR_SREV_9340(ah)) 836 if (AR_SREV_9340(ah))
825 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL; 837 sync_default &= ~AR_INTR_SYNC_HOST1_FATAL;
826 838
@@ -852,7 +864,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
852 864
853 ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints); 865 ath_dbg(common, ATH_DBG_INTERRUPT, "0x%x => 0x%x\n", omask, ints);
854 866
855 /* TODO: global int Ref count */
856 mask = ints & ATH9K_INT_COMMON; 867 mask = ints & ATH9K_INT_COMMON;
857 mask2 = 0; 868 mask2 = 0;
858 869
@@ -929,9 +940,6 @@ void ath9k_hw_set_interrupts(struct ath_hw *ah, enum ath9k_int ints)
929 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER); 940 REG_CLR_BIT(ah, AR_IMR_S5, AR_IMR_S5_TIM_TIMER);
930 } 941 }
931 942
932 if (ints & ATH9K_INT_GLOBAL)
933 ath9k_hw_enable_interrupts(ah);
934
935 return; 943 return;
936} 944}
937EXPORT_SYMBOL(ath9k_hw_set_interrupts); 945EXPORT_SYMBOL(ath9k_hw_set_interrupts);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 9098aaad97a9..1e7fe8c0e119 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -163,7 +163,7 @@ static void ath_update_survey_nf(struct ath_softc *sc, int channel)
163 163
164 if (chan->noisefloor) { 164 if (chan->noisefloor) {
165 survey->filled |= SURVEY_INFO_NOISE_DBM; 165 survey->filled |= SURVEY_INFO_NOISE_DBM;
166 survey->noise = chan->noisefloor; 166 survey->noise = ath9k_hw_getchan_noise(ah, chan);
167 } 167 }
168} 168}
169 169
@@ -294,6 +294,7 @@ static int ath_set_channel(struct ath_softc *sc, struct ieee80211_hw *hw,
294 ath9k_cmn_update_txpow(ah, sc->curtxpow, 294 ath9k_cmn_update_txpow(ah, sc->curtxpow,
295 sc->config.txpowlimit, &sc->curtxpow); 295 sc->config.txpowlimit, &sc->curtxpow);
296 ath9k_hw_set_interrupts(ah, ah->imask); 296 ath9k_hw_set_interrupts(ah, ah->imask);
297 ath9k_hw_enable_interrupts(ah);
297 298
298 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) { 299 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL))) {
299 if (sc->sc_flags & SC_OP_BEACONS) 300 if (sc->sc_flags & SC_OP_BEACONS)
@@ -706,8 +707,7 @@ void ath9k_tasklet(unsigned long data)
706 */ 707 */
707 ath_dbg(common, ATH_DBG_PS, 708 ath_dbg(common, ATH_DBG_PS,
708 "TSFOOR - Sync with next Beacon\n"); 709 "TSFOOR - Sync with next Beacon\n");
709 sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC | 710 sc->ps_flags |= PS_WAIT_FOR_BEACON | PS_BEACON_SYNC;
710 PS_TSFOOR_SYNC;
711 } 711 }
712 712
713 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA) 713 if (ah->caps.hw_caps & ATH9K_HW_CAP_EDMA)
@@ -886,6 +886,7 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
886 886
887 ath9k_ps_wakeup(sc); 887 ath9k_ps_wakeup(sc);
888 spin_lock_bh(&sc->sc_pcu_lock); 888 spin_lock_bh(&sc->sc_pcu_lock);
889 atomic_set(&ah->intr_ref_cnt, -1);
889 890
890 ath9k_hw_configpcipowersave(ah, 0, 0); 891 ath9k_hw_configpcipowersave(ah, 0, 0);
891 892
@@ -910,6 +911,7 @@ static void ath_radio_enable(struct ath_softc *sc, struct ieee80211_hw *hw)
910 911
911 /* Re-Enable interrupts */ 912 /* Re-Enable interrupts */
912 ath9k_hw_set_interrupts(ah, ah->imask); 913 ath9k_hw_set_interrupts(ah, ah->imask);
914 ath9k_hw_enable_interrupts(ah);
913 915
914 /* Enable LED */ 916 /* Enable LED */
915 ath9k_hw_cfg_output(ah, ah->led_pin, 917 ath9k_hw_cfg_output(ah, ah->led_pin,
@@ -1016,6 +1018,7 @@ int ath_reset(struct ath_softc *sc, bool retry_tx)
1016 ath_set_beacon(sc); /* restart beacons */ 1018 ath_set_beacon(sc); /* restart beacons */
1017 1019
1018 ath9k_hw_set_interrupts(ah, ah->imask); 1020 ath9k_hw_set_interrupts(ah, ah->imask);
1021 ath9k_hw_enable_interrupts(ah);
1019 1022
1020 if (retry_tx) { 1023 if (retry_tx) {
1021 int i; 1024 int i;
@@ -1130,6 +1133,7 @@ static int ath9k_start(struct ieee80211_hw *hw)
1130 /* Disable BMISS interrupt when we're not associated */ 1133 /* Disable BMISS interrupt when we're not associated */
1131 ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS); 1134 ah->imask &= ~(ATH9K_INT_SWBA | ATH9K_INT_BMISS);
1132 ath9k_hw_set_interrupts(ah, ah->imask); 1135 ath9k_hw_set_interrupts(ah, ah->imask);
1136 ath9k_hw_enable_interrupts(ah);
1133 1137
1134 ieee80211_wake_queues(hw); 1138 ieee80211_wake_queues(hw);
1135 1139
diff --git a/drivers/net/wireless/ath/ath9k/pci.c b/drivers/net/wireless/ath/ath9k/pci.c
index be4ea1329813..5685cf11cfe3 100644
--- a/drivers/net/wireless/ath/ath9k/pci.c
+++ b/drivers/net/wireless/ath/ath9k/pci.c
@@ -156,7 +156,6 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
156 struct ath_softc *sc; 156 struct ath_softc *sc;
157 struct ieee80211_hw *hw; 157 struct ieee80211_hw *hw;
158 u8 csz; 158 u8 csz;
159 u16 subsysid;
160 u32 val; 159 u32 val;
161 int ret = 0; 160 int ret = 0;
162 char hw_name[64]; 161 char hw_name[64];
@@ -250,8 +249,7 @@ static int ath_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
250 249
251 sc->irq = pdev->irq; 250 sc->irq = pdev->irq;
252 251
253 pci_read_config_word(pdev, PCI_SUBSYSTEM_ID, &subsysid); 252 ret = ath9k_init_device(id->device, sc, &ath_pci_bus_ops);
254 ret = ath9k_init_device(id->device, sc, subsysid, &ath_pci_bus_ops);
255 if (ret) { 253 if (ret) {
256 dev_err(&pdev->dev, "Failed to initialize device\n"); 254 dev_err(&pdev->dev, "Failed to initialize device\n");
257 goto err_init; 255 goto err_init;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index c04a6c3cac7f..9e3649a3d5ca 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -1484,7 +1484,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
1484 if (rc->rate_table == NULL) 1484 if (rc->rate_table == NULL)
1485 return 0; 1485 return 0;
1486 1486
1487 max = 80 + rc->rate_table->rate_cnt * 1024 + 1; 1487 max = 80 + rc->rate_table_size * 1024 + 1;
1488 buf = kmalloc(max, GFP_KERNEL); 1488 buf = kmalloc(max, GFP_KERNEL);
1489 if (buf == NULL) 1489 if (buf == NULL)
1490 return -ENOMEM; 1490 return -ENOMEM;
@@ -1494,7 +1494,7 @@ static ssize_t read_file_rcstat(struct file *file, char __user *user_buf,
1494 "HT", "MCS", "Rate", 1494 "HT", "MCS", "Rate",
1495 "Success", "Retries", "XRetries", "PER"); 1495 "Success", "Retries", "XRetries", "PER");
1496 1496
1497 for (i = 0; i < rc->rate_table->rate_cnt; i++) { 1497 for (i = 0; i < rc->rate_table_size; i++) {
1498 u32 ratekbps = rc->rate_table->info[i].ratekbps; 1498 u32 ratekbps = rc->rate_table->info[i].ratekbps;
1499 struct ath_rc_stats *stats = &rc->rcstats[i]; 1499 struct ath_rc_stats *stats = &rc->rcstats[i];
1500 char mcs[5]; 1500 char mcs[5];
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index c3d850207bee..b7a4bcd3eec7 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -221,12 +221,6 @@ struct ath_rate_priv {
221 struct ath_rc_stats rcstats[RATE_TABLE_SIZE]; 221 struct ath_rc_stats rcstats[RATE_TABLE_SIZE];
222}; 222};
223 223
224enum ath9k_internal_frame_type {
225 ATH9K_IFT_NOT_INTERNAL,
226 ATH9K_IFT_PAUSE,
227 ATH9K_IFT_UNPAUSE
228};
229
230#ifdef CONFIG_ATH9K_RATE_CONTROL 224#ifdef CONFIG_ATH9K_RATE_CONTROL
231int ath_rate_control_register(void); 225int ath_rate_control_register(void);
232void ath_rate_control_unregister(void); 226void ath_rate_control_unregister(void);
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index 9a4850154fb2..74094022b654 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -601,7 +601,6 @@ static void ath_rx_ps_beacon(struct ath_softc *sc, struct sk_buff *skb)
601 ath_dbg(common, ATH_DBG_PS, 601 ath_dbg(common, ATH_DBG_PS,
602 "Reconfigure Beacon timers based on timestamp from the AP\n"); 602 "Reconfigure Beacon timers based on timestamp from the AP\n");
603 ath_set_beacon(sc); 603 ath_set_beacon(sc);
604 sc->ps_flags &= ~PS_TSFOOR_SYNC;
605 } 604 }
606 605
607 if (ath_beacon_dtim_pending_cab(skb)) { 606 if (ath_beacon_dtim_pending_cab(skb)) {
@@ -995,6 +994,8 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
995 struct ieee80211_rx_status *rx_status, 994 struct ieee80211_rx_status *rx_status,
996 bool *decrypt_error) 995 bool *decrypt_error)
997{ 996{
997 struct ath_hw *ah = common->ah;
998
998 memset(rx_status, 0, sizeof(struct ieee80211_rx_status)); 999 memset(rx_status, 0, sizeof(struct ieee80211_rx_status));
999 1000
1000 /* 1001 /*
@@ -1015,7 +1016,7 @@ static int ath9k_rx_skb_preprocess(struct ath_common *common,
1015 1016
1016 rx_status->band = hw->conf.channel->band; 1017 rx_status->band = hw->conf.channel->band;
1017 rx_status->freq = hw->conf.channel->center_freq; 1018 rx_status->freq = hw->conf.channel->center_freq;
1018 rx_status->signal = ATH_DEFAULT_NOISE_FLOOR + rx_stats->rs_rssi; 1019 rx_status->signal = ah->noise + rx_stats->rs_rssi;
1019 rx_status->antenna = rx_stats->rs_antenna; 1020 rx_status->antenna = rx_stats->rs_antenna;
1020 rx_status->flag |= RX_FLAG_MACTIME_MPDU; 1021 rx_status->flag |= RX_FLAG_MACTIME_MPDU;
1021 1022
@@ -1783,11 +1784,6 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush, bool hp)
1783 struct ieee80211_rx_status *rxs; 1784 struct ieee80211_rx_status *rxs;
1784 struct ath_hw *ah = sc->sc_ah; 1785 struct ath_hw *ah = sc->sc_ah;
1785 struct ath_common *common = ath9k_hw_common(ah); 1786 struct ath_common *common = ath9k_hw_common(ah);
1786 /*
1787 * The hw can technically differ from common->hw when using ath9k
1788 * virtual wiphy so to account for that we iterate over the active
1789 * wiphys and find the appropriate wiphy and therefore hw.
1790 */
1791 struct ieee80211_hw *hw = sc->hw; 1787 struct ieee80211_hw *hw = sc->hw;
1792 struct ieee80211_hdr *hdr; 1788 struct ieee80211_hdr *hdr;
1793 int retval; 1789 int retval;
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index cc595712f518..e1d1e903229b 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -551,7 +551,8 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
551 if (clear_filter) 551 if (clear_filter)
552 tid->ac->clear_ps_filter = true; 552 tid->ac->clear_ps_filter = true;
553 list_splice(&bf_pending, &tid->buf_q); 553 list_splice(&bf_pending, &tid->buf_q);
554 ath_tx_queue_tid(txq, tid); 554 if (!an->sleeping)
555 ath_tx_queue_tid(txq, tid);
555 spin_unlock_bh(&txq->axq_lock); 556 spin_unlock_bh(&txq->axq_lock);
556 } 557 }
557 558
@@ -1413,7 +1414,8 @@ static void ath_tx_send_ampdu(struct ath_softc *sc, struct ath_atx_tid *tid,
1413 */ 1414 */
1414 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw); 1415 TX_STAT_INC(txctl->txq->axq_qnum, a_queued_sw);
1415 list_add_tail(&bf->list, &tid->buf_q); 1416 list_add_tail(&bf->list, &tid->buf_q);
1416 ath_tx_queue_tid(txctl->txq, tid); 1417 if (!txctl->an || !txctl->an->sleeping)
1418 ath_tx_queue_tid(txctl->txq, tid);
1417 return; 1419 return;
1418 } 1420 }
1419 1421
@@ -1777,7 +1779,6 @@ static void ath_tx_start_dma(struct ath_softc *sc, struct ath_buf *bf,
1777 INIT_LIST_HEAD(&bf_head); 1779 INIT_LIST_HEAD(&bf_head);
1778 list_add_tail(&bf->list, &bf_head); 1780 list_add_tail(&bf->list, &bf_head);
1779 1781
1780 bf->bf_state.bfs_ftype = txctl->frame_type;
1781 bf->bf_state.bfs_paprd = txctl->paprd; 1782 bf->bf_state.bfs_paprd = txctl->paprd;
1782 1783
1783 if (bf->bf_state.bfs_paprd) 1784 if (bf->bf_state.bfs_paprd)
@@ -1876,7 +1877,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb,
1876/*****************/ 1877/*****************/
1877 1878
1878static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, 1879static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb,
1879 int tx_flags, int ftype, struct ath_txq *txq) 1880 int tx_flags, struct ath_txq *txq)
1880{ 1881{
1881 struct ieee80211_hw *hw = sc->hw; 1882 struct ieee80211_hw *hw = sc->hw;
1882 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 1883 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
@@ -1961,8 +1962,7 @@ static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
1961 complete(&sc->paprd_complete); 1962 complete(&sc->paprd_complete);
1962 } else { 1963 } else {
1963 ath_debug_stat_tx(sc, bf, ts, txq); 1964 ath_debug_stat_tx(sc, bf, ts, txq);
1964 ath_tx_complete(sc, skb, tx_flags, 1965 ath_tx_complete(sc, skb, tx_flags, txq);
1965 bf->bf_state.bfs_ftype, txq);
1966 } 1966 }
1967 /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't 1967 /* At this point, skb (bf->bf_mpdu) is consumed...make sure we don't
1968 * accidentally reference it later. 1968 * accidentally reference it later.
diff --git a/drivers/net/wireless/ath/regd.h b/drivers/net/wireless/ath/regd.h
index 172f63f671cf..03a8268ccf21 100644
--- a/drivers/net/wireless/ath/regd.h
+++ b/drivers/net/wireless/ath/regd.h
@@ -101,7 +101,7 @@ enum CountryCode {
101 CTRY_GERMANY = 276, 101 CTRY_GERMANY = 276,
102 CTRY_GREECE = 300, 102 CTRY_GREECE = 300,
103 CTRY_GREENLAND = 304, 103 CTRY_GREENLAND = 304,
104 CTRY_GRENEDA = 308, 104 CTRY_GRENADA = 308,
105 CTRY_GUAM = 316, 105 CTRY_GUAM = 316,
106 CTRY_GUATEMALA = 320, 106 CTRY_GUATEMALA = 320,
107 CTRY_HAITI = 332, 107 CTRY_HAITI = 332,
diff --git a/drivers/net/wireless/ath/regd_common.h b/drivers/net/wireless/ath/regd_common.h
index 24b53839fc3a..bdd2b4d61f2f 100644
--- a/drivers/net/wireless/ath/regd_common.h
+++ b/drivers/net/wireless/ath/regd_common.h
@@ -332,7 +332,7 @@ static struct country_code_to_enum_rd allCountries[] = {
332 {CTRY_GERMANY, ETSI1_WORLD, "DE"}, 332 {CTRY_GERMANY, ETSI1_WORLD, "DE"},
333 {CTRY_GREECE, ETSI1_WORLD, "GR"}, 333 {CTRY_GREECE, ETSI1_WORLD, "GR"},
334 {CTRY_GREENLAND, ETSI1_WORLD, "GL"}, 334 {CTRY_GREENLAND, ETSI1_WORLD, "GL"},
335 {CTRY_GRENEDA, FCC3_FCCA, "GD"}, 335 {CTRY_GRENADA, FCC3_FCCA, "GD"},
336 {CTRY_GUAM, FCC1_FCCA, "GU"}, 336 {CTRY_GUAM, FCC1_FCCA, "GU"},
337 {CTRY_GUATEMALA, FCC1_FCCA, "GT"}, 337 {CTRY_GUATEMALA, FCC1_FCCA, "GT"},
338 {CTRY_HAITI, ETSI1_WORLD, "HT"}, 338 {CTRY_HAITI, ETSI1_WORLD, "HT"},
diff --git a/drivers/net/wireless/b43/Kconfig b/drivers/net/wireless/b43/Kconfig
index 3cab843afb05..b81a2a1c2618 100644
--- a/drivers/net/wireless/b43/Kconfig
+++ b/drivers/net/wireless/b43/Kconfig
@@ -114,13 +114,13 @@ config B43_PHY_N
114 affect other devices support and may provide support for basic needs. 114 affect other devices support and may provide support for basic needs.
115 115
116config B43_PHY_LP 116config B43_PHY_LP
117 bool "Support for low-power (LP-PHY) devices (EXPERIMENTAL)" 117 bool "Support for low-power (LP-PHY) devices"
118 depends on B43 && EXPERIMENTAL 118 depends on B43
119 default y 119 default y
120 ---help--- 120 ---help---
121 Support for the LP-PHY. 121 Support for the LP-PHY.
122 The LP-PHY is a low-power PHY built into some notebooks 122 The LP-PHY is a low-power PHY built into some notebooks
123 and embedded devices. It supports 802.11a/g 123 and embedded devices. It supports 802.11a/b/g
124 (802.11a support is optional, and currently disabled). 124 (802.11a support is optional, and currently disabled).
125 125
126config B43_PHY_HT 126config B43_PHY_HT
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c
index 26f1ab840cc7..d2661aaff50f 100644
--- a/drivers/net/wireless/b43/main.c
+++ b/drivers/net/wireless/b43/main.c
@@ -37,7 +37,6 @@
37#include <linux/if_arp.h> 37#include <linux/if_arp.h>
38#include <linux/etherdevice.h> 38#include <linux/etherdevice.h>
39#include <linux/firmware.h> 39#include <linux/firmware.h>
40#include <linux/wireless.h>
41#include <linux/workqueue.h> 40#include <linux/workqueue.h>
42#include <linux/skbuff.h> 41#include <linux/skbuff.h>
43#include <linux/io.h> 42#include <linux/io.h>
@@ -115,6 +114,7 @@ MODULE_PARM_DESC(pio, "Use PIO accesses by default: 0=DMA, 1=PIO");
115 114
116#ifdef CONFIG_B43_BCMA 115#ifdef CONFIG_B43_BCMA
117static const struct bcma_device_id b43_bcma_tbl[] = { 116static const struct bcma_device_id b43_bcma_tbl[] = {
117 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x11, BCMA_ANY_CLASS),
118 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS), 118 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x17, BCMA_ANY_CLASS),
119 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS), 119 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x18, BCMA_ANY_CLASS),
120 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS), 120 BCMA_CORE(BCMA_MANUF_BCM, BCMA_CORE_80211, 0x1D, BCMA_ANY_CLASS),
diff --git a/drivers/net/wireless/b43legacy/b43legacy.h b/drivers/net/wireless/b43legacy/b43legacy.h
index a610a352102a..ad4e743e4765 100644
--- a/drivers/net/wireless/b43legacy/b43legacy.h
+++ b/drivers/net/wireless/b43legacy/b43legacy.h
@@ -14,7 +14,6 @@
14#include <linux/ssb/ssb.h> 14#include <linux/ssb/ssb.h>
15#include <linux/ssb/ssb_driver_chipcommon.h> 15#include <linux/ssb/ssb_driver_chipcommon.h>
16 16
17#include <linux/wireless.h>
18#include <net/mac80211.h> 17#include <net/mac80211.h>
19 18
20#include "debugfs.h" 19#include "debugfs.h"
diff --git a/drivers/net/wireless/b43legacy/dma.c b/drivers/net/wireless/b43legacy/dma.c
index 5010c477abdf..c5535adf6991 100644
--- a/drivers/net/wireless/b43legacy/dma.c
+++ b/drivers/net/wireless/b43legacy/dma.c
@@ -42,10 +42,9 @@
42 42
43/* 32bit DMA ops. */ 43/* 32bit DMA ops. */
44static 44static
45struct b43legacy_dmadesc_generic *op32_idx2desc( 45struct b43legacy_dmadesc32 *op32_idx2desc(struct b43legacy_dmaring *ring,
46 struct b43legacy_dmaring *ring, 46 int slot,
47 int slot, 47 struct b43legacy_dmadesc_meta **meta)
48 struct b43legacy_dmadesc_meta **meta)
49{ 48{
50 struct b43legacy_dmadesc32 *desc; 49 struct b43legacy_dmadesc32 *desc;
51 50
@@ -53,11 +52,11 @@ struct b43legacy_dmadesc_generic *op32_idx2desc(
53 desc = ring->descbase; 52 desc = ring->descbase;
54 desc = &(desc[slot]); 53 desc = &(desc[slot]);
55 54
56 return (struct b43legacy_dmadesc_generic *)desc; 55 return (struct b43legacy_dmadesc32 *)desc;
57} 56}
58 57
59static void op32_fill_descriptor(struct b43legacy_dmaring *ring, 58static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
60 struct b43legacy_dmadesc_generic *desc, 59 struct b43legacy_dmadesc32 *desc,
61 dma_addr_t dmaaddr, u16 bufsize, 60 dma_addr_t dmaaddr, u16 bufsize,
62 int start, int end, int irq) 61 int start, int end, int irq)
63{ 62{
@@ -67,7 +66,7 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
67 u32 addr; 66 u32 addr;
68 u32 addrext; 67 u32 addrext;
69 68
70 slot = (int)(&(desc->dma32) - descbase); 69 slot = (int)(desc - descbase);
71 B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); 70 B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
72 71
73 addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK); 72 addr = (u32)(dmaaddr & ~SSB_DMA_TRANSLATION_MASK);
@@ -87,8 +86,8 @@ static void op32_fill_descriptor(struct b43legacy_dmaring *ring,
87 ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT) 86 ctl |= (addrext << B43legacy_DMA32_DCTL_ADDREXT_SHIFT)
88 & B43legacy_DMA32_DCTL_ADDREXT_MASK; 87 & B43legacy_DMA32_DCTL_ADDREXT_MASK;
89 88
90 desc->dma32.control = cpu_to_le32(ctl); 89 desc->control = cpu_to_le32(ctl);
91 desc->dma32.address = cpu_to_le32(addr); 90 desc->address = cpu_to_le32(addr);
92} 91}
93 92
94static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot) 93static void op32_poke_tx(struct b43legacy_dmaring *ring, int slot)
@@ -128,121 +127,6 @@ static void op32_set_current_rxslot(struct b43legacy_dmaring *ring,
128 (u32)(slot * sizeof(struct b43legacy_dmadesc32))); 127 (u32)(slot * sizeof(struct b43legacy_dmadesc32)));
129} 128}
130 129
131static const struct b43legacy_dma_ops dma32_ops = {
132 .idx2desc = op32_idx2desc,
133 .fill_descriptor = op32_fill_descriptor,
134 .poke_tx = op32_poke_tx,
135 .tx_suspend = op32_tx_suspend,
136 .tx_resume = op32_tx_resume,
137 .get_current_rxslot = op32_get_current_rxslot,
138 .set_current_rxslot = op32_set_current_rxslot,
139};
140
141/* 64bit DMA ops. */
142static
143struct b43legacy_dmadesc_generic *op64_idx2desc(
144 struct b43legacy_dmaring *ring,
145 int slot,
146 struct b43legacy_dmadesc_meta
147 **meta)
148{
149 struct b43legacy_dmadesc64 *desc;
150
151 *meta = &(ring->meta[slot]);
152 desc = ring->descbase;
153 desc = &(desc[slot]);
154
155 return (struct b43legacy_dmadesc_generic *)desc;
156}
157
158static void op64_fill_descriptor(struct b43legacy_dmaring *ring,
159 struct b43legacy_dmadesc_generic *desc,
160 dma_addr_t dmaaddr, u16 bufsize,
161 int start, int end, int irq)
162{
163 struct b43legacy_dmadesc64 *descbase = ring->descbase;
164 int slot;
165 u32 ctl0 = 0;
166 u32 ctl1 = 0;
167 u32 addrlo;
168 u32 addrhi;
169 u32 addrext;
170
171 slot = (int)(&(desc->dma64) - descbase);
172 B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
173
174 addrlo = (u32)(dmaaddr & 0xFFFFFFFF);
175 addrhi = (((u64)dmaaddr >> 32) & ~SSB_DMA_TRANSLATION_MASK);
176 addrext = (((u64)dmaaddr >> 32) & SSB_DMA_TRANSLATION_MASK)
177 >> SSB_DMA_TRANSLATION_SHIFT;
178 addrhi |= ring->dev->dma.translation;
179 if (slot == ring->nr_slots - 1)
180 ctl0 |= B43legacy_DMA64_DCTL0_DTABLEEND;
181 if (start)
182 ctl0 |= B43legacy_DMA64_DCTL0_FRAMESTART;
183 if (end)
184 ctl0 |= B43legacy_DMA64_DCTL0_FRAMEEND;
185 if (irq)
186 ctl0 |= B43legacy_DMA64_DCTL0_IRQ;
187 ctl1 |= (bufsize - ring->frameoffset)
188 & B43legacy_DMA64_DCTL1_BYTECNT;
189 ctl1 |= (addrext << B43legacy_DMA64_DCTL1_ADDREXT_SHIFT)
190 & B43legacy_DMA64_DCTL1_ADDREXT_MASK;
191
192 desc->dma64.control0 = cpu_to_le32(ctl0);
193 desc->dma64.control1 = cpu_to_le32(ctl1);
194 desc->dma64.address_low = cpu_to_le32(addrlo);
195 desc->dma64.address_high = cpu_to_le32(addrhi);
196}
197
198static void op64_poke_tx(struct b43legacy_dmaring *ring, int slot)
199{
200 b43legacy_dma_write(ring, B43legacy_DMA64_TXINDEX,
201 (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
202}
203
204static void op64_tx_suspend(struct b43legacy_dmaring *ring)
205{
206 b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
207 b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
208 | B43legacy_DMA64_TXSUSPEND);
209}
210
211static void op64_tx_resume(struct b43legacy_dmaring *ring)
212{
213 b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL,
214 b43legacy_dma_read(ring, B43legacy_DMA64_TXCTL)
215 & ~B43legacy_DMA64_TXSUSPEND);
216}
217
218static int op64_get_current_rxslot(struct b43legacy_dmaring *ring)
219{
220 u32 val;
221
222 val = b43legacy_dma_read(ring, B43legacy_DMA64_RXSTATUS);
223 val &= B43legacy_DMA64_RXSTATDPTR;
224
225 return (val / sizeof(struct b43legacy_dmadesc64));
226}
227
228static void op64_set_current_rxslot(struct b43legacy_dmaring *ring,
229 int slot)
230{
231 b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
232 (u32)(slot * sizeof(struct b43legacy_dmadesc64)));
233}
234
235static const struct b43legacy_dma_ops dma64_ops = {
236 .idx2desc = op64_idx2desc,
237 .fill_descriptor = op64_fill_descriptor,
238 .poke_tx = op64_poke_tx,
239 .tx_suspend = op64_tx_suspend,
240 .tx_resume = op64_tx_resume,
241 .get_current_rxslot = op64_get_current_rxslot,
242 .set_current_rxslot = op64_set_current_rxslot,
243};
244
245
246static inline int free_slots(struct b43legacy_dmaring *ring) 130static inline int free_slots(struct b43legacy_dmaring *ring)
247{ 131{
248 return (ring->nr_slots - ring->used_slots); 132 return (ring->nr_slots - ring->used_slots);
@@ -358,14 +242,6 @@ return 0;
358static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type, 242static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
359 int controller_idx) 243 int controller_idx)
360{ 244{
361 static const u16 map64[] = {
362 B43legacy_MMIO_DMA64_BASE0,
363 B43legacy_MMIO_DMA64_BASE1,
364 B43legacy_MMIO_DMA64_BASE2,
365 B43legacy_MMIO_DMA64_BASE3,
366 B43legacy_MMIO_DMA64_BASE4,
367 B43legacy_MMIO_DMA64_BASE5,
368 };
369 static const u16 map32[] = { 245 static const u16 map32[] = {
370 B43legacy_MMIO_DMA32_BASE0, 246 B43legacy_MMIO_DMA32_BASE0,
371 B43legacy_MMIO_DMA32_BASE1, 247 B43legacy_MMIO_DMA32_BASE1,
@@ -375,11 +251,6 @@ static u16 b43legacy_dmacontroller_base(enum b43legacy_dmatype type,
375 B43legacy_MMIO_DMA32_BASE5, 251 B43legacy_MMIO_DMA32_BASE5,
376 }; 252 };
377 253
378 if (type == B43legacy_DMA_64BIT) {
379 B43legacy_WARN_ON(!(controller_idx >= 0 &&
380 controller_idx < ARRAY_SIZE(map64)));
381 return map64[controller_idx];
382 }
383 B43legacy_WARN_ON(!(controller_idx >= 0 && 254 B43legacy_WARN_ON(!(controller_idx >= 0 &&
384 controller_idx < ARRAY_SIZE(map32))); 255 controller_idx < ARRAY_SIZE(map32)));
385 return map32[controller_idx]; 256 return map32[controller_idx];
@@ -491,25 +362,15 @@ static int b43legacy_dmacontroller_rx_reset(struct b43legacy_wldev *dev,
491 362
492 might_sleep(); 363 might_sleep();
493 364
494 offset = (type == B43legacy_DMA_64BIT) ? 365 offset = B43legacy_DMA32_RXCTL;
495 B43legacy_DMA64_RXCTL : B43legacy_DMA32_RXCTL;
496 b43legacy_write32(dev, mmio_base + offset, 0); 366 b43legacy_write32(dev, mmio_base + offset, 0);
497 for (i = 0; i < 10; i++) { 367 for (i = 0; i < 10; i++) {
498 offset = (type == B43legacy_DMA_64BIT) ? 368 offset = B43legacy_DMA32_RXSTATUS;
499 B43legacy_DMA64_RXSTATUS : B43legacy_DMA32_RXSTATUS;
500 value = b43legacy_read32(dev, mmio_base + offset); 369 value = b43legacy_read32(dev, mmio_base + offset);
501 if (type == B43legacy_DMA_64BIT) { 370 value &= B43legacy_DMA32_RXSTATE;
502 value &= B43legacy_DMA64_RXSTAT; 371 if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
503 if (value == B43legacy_DMA64_RXSTAT_DISABLED) { 372 i = -1;
504 i = -1; 373 break;
505 break;
506 }
507 } else {
508 value &= B43legacy_DMA32_RXSTATE;
509 if (value == B43legacy_DMA32_RXSTAT_DISABLED) {
510 i = -1;
511 break;
512 }
513 } 374 }
514 msleep(1); 375 msleep(1);
515 } 376 }
@@ -533,43 +394,24 @@ static int b43legacy_dmacontroller_tx_reset(struct b43legacy_wldev *dev,
533 might_sleep(); 394 might_sleep();
534 395
535 for (i = 0; i < 10; i++) { 396 for (i = 0; i < 10; i++) {
536 offset = (type == B43legacy_DMA_64BIT) ? 397 offset = B43legacy_DMA32_TXSTATUS;
537 B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
538 value = b43legacy_read32(dev, mmio_base + offset); 398 value = b43legacy_read32(dev, mmio_base + offset);
539 if (type == B43legacy_DMA_64BIT) { 399 value &= B43legacy_DMA32_TXSTATE;
540 value &= B43legacy_DMA64_TXSTAT; 400 if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
541 if (value == B43legacy_DMA64_TXSTAT_DISABLED || 401 value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
542 value == B43legacy_DMA64_TXSTAT_IDLEWAIT || 402 value == B43legacy_DMA32_TXSTAT_STOPPED)
543 value == B43legacy_DMA64_TXSTAT_STOPPED) 403 break;
544 break;
545 } else {
546 value &= B43legacy_DMA32_TXSTATE;
547 if (value == B43legacy_DMA32_TXSTAT_DISABLED ||
548 value == B43legacy_DMA32_TXSTAT_IDLEWAIT ||
549 value == B43legacy_DMA32_TXSTAT_STOPPED)
550 break;
551 }
552 msleep(1); 404 msleep(1);
553 } 405 }
554 offset = (type == B43legacy_DMA_64BIT) ? B43legacy_DMA64_TXCTL : 406 offset = B43legacy_DMA32_TXCTL;
555 B43legacy_DMA32_TXCTL;
556 b43legacy_write32(dev, mmio_base + offset, 0); 407 b43legacy_write32(dev, mmio_base + offset, 0);
557 for (i = 0; i < 10; i++) { 408 for (i = 0; i < 10; i++) {
558 offset = (type == B43legacy_DMA_64BIT) ? 409 offset = B43legacy_DMA32_TXSTATUS;
559 B43legacy_DMA64_TXSTATUS : B43legacy_DMA32_TXSTATUS;
560 value = b43legacy_read32(dev, mmio_base + offset); 410 value = b43legacy_read32(dev, mmio_base + offset);
561 if (type == B43legacy_DMA_64BIT) { 411 value &= B43legacy_DMA32_TXSTATE;
562 value &= B43legacy_DMA64_TXSTAT; 412 if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
563 if (value == B43legacy_DMA64_TXSTAT_DISABLED) { 413 i = -1;
564 i = -1; 414 break;
565 break;
566 }
567 } else {
568 value &= B43legacy_DMA32_TXSTATE;
569 if (value == B43legacy_DMA32_TXSTAT_DISABLED) {
570 i = -1;
571 break;
572 }
573 } 415 }
574 msleep(1); 416 msleep(1);
575 } 417 }
@@ -601,9 +443,6 @@ static bool b43legacy_dma_mapping_error(struct b43legacy_dmaring *ring,
601 if ((u64)addr + buffersize > (1ULL << 32)) 443 if ((u64)addr + buffersize > (1ULL << 32))
602 goto address_error; 444 goto address_error;
603 break; 445 break;
604 case B43legacy_DMA_64BIT:
605 /* Currently we can't have addresses beyond 64 bits in the kernel. */
606 break;
607 } 446 }
608 447
609 /* The address is OK. */ 448 /* The address is OK. */
@@ -617,7 +456,7 @@ address_error:
617} 456}
618 457
619static int setup_rx_descbuffer(struct b43legacy_dmaring *ring, 458static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
620 struct b43legacy_dmadesc_generic *desc, 459 struct b43legacy_dmadesc32 *desc,
621 struct b43legacy_dmadesc_meta *meta, 460 struct b43legacy_dmadesc_meta *meta,
622 gfp_t gfp_flags) 461 gfp_t gfp_flags)
623{ 462{
@@ -653,8 +492,7 @@ static int setup_rx_descbuffer(struct b43legacy_dmaring *ring,
653 492
654 meta->skb = skb; 493 meta->skb = skb;
655 meta->dmaaddr = dmaaddr; 494 meta->dmaaddr = dmaaddr;
656 ring->ops->fill_descriptor(ring, desc, dmaaddr, 495 op32_fill_descriptor(ring, desc, dmaaddr, ring->rx_buffersize, 0, 0, 0);
657 ring->rx_buffersize, 0, 0, 0);
658 496
659 rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data); 497 rxhdr = (struct b43legacy_rxhdr_fw3 *)(skb->data);
660 rxhdr->frame_len = 0; 498 rxhdr->frame_len = 0;
@@ -671,11 +509,11 @@ static int alloc_initial_descbuffers(struct b43legacy_dmaring *ring)
671{ 509{
672 int i; 510 int i;
673 int err = -ENOMEM; 511 int err = -ENOMEM;
674 struct b43legacy_dmadesc_generic *desc; 512 struct b43legacy_dmadesc32 *desc;
675 struct b43legacy_dmadesc_meta *meta; 513 struct b43legacy_dmadesc_meta *meta;
676 514
677 for (i = 0; i < ring->nr_slots; i++) { 515 for (i = 0; i < ring->nr_slots; i++) {
678 desc = ring->ops->idx2desc(ring, i, &meta); 516 desc = op32_idx2desc(ring, i, &meta);
679 517
680 err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL); 518 err = setup_rx_descbuffer(ring, desc, meta, GFP_KERNEL);
681 if (err) { 519 if (err) {
@@ -692,7 +530,7 @@ out:
692 530
693err_unwind: 531err_unwind:
694 for (i--; i >= 0; i--) { 532 for (i--; i >= 0; i--) {
695 desc = ring->ops->idx2desc(ring, i, &meta); 533 desc = op32_idx2desc(ring, i, &meta);
696 534
697 unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0); 535 unmap_descbuffer(ring, meta->dmaaddr, ring->rx_buffersize, 0);
698 dev_kfree_skb(meta->skb); 536 dev_kfree_skb(meta->skb);
@@ -710,83 +548,35 @@ static int dmacontroller_setup(struct b43legacy_dmaring *ring)
710 u32 value; 548 u32 value;
711 u32 addrext; 549 u32 addrext;
712 u32 trans = ring->dev->dma.translation; 550 u32 trans = ring->dev->dma.translation;
551 u32 ringbase = (u32)(ring->dmabase);
713 552
714 if (ring->tx) { 553 if (ring->tx) {
715 if (ring->type == B43legacy_DMA_64BIT) { 554 addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
716 u64 ringbase = (u64)(ring->dmabase); 555 >> SSB_DMA_TRANSLATION_SHIFT;
717 556 value = B43legacy_DMA32_TXENABLE;
718 addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) 557 value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
719 >> SSB_DMA_TRANSLATION_SHIFT; 558 & B43legacy_DMA32_TXADDREXT_MASK;
720 value = B43legacy_DMA64_TXENABLE; 559 b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL, value);
721 value |= (addrext << B43legacy_DMA64_TXADDREXT_SHIFT) 560 b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
722 & B43legacy_DMA64_TXADDREXT_MASK; 561 (ringbase & ~SSB_DMA_TRANSLATION_MASK)
723 b43legacy_dma_write(ring, B43legacy_DMA64_TXCTL, 562 | trans);
724 value);
725 b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO,
726 (ringbase & 0xFFFFFFFF));
727 b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI,
728 ((ringbase >> 32)
729 & ~SSB_DMA_TRANSLATION_MASK)
730 | trans);
731 } else {
732 u32 ringbase = (u32)(ring->dmabase);
733
734 addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
735 >> SSB_DMA_TRANSLATION_SHIFT;
736 value = B43legacy_DMA32_TXENABLE;
737 value |= (addrext << B43legacy_DMA32_TXADDREXT_SHIFT)
738 & B43legacy_DMA32_TXADDREXT_MASK;
739 b43legacy_dma_write(ring, B43legacy_DMA32_TXCTL,
740 value);
741 b43legacy_dma_write(ring, B43legacy_DMA32_TXRING,
742 (ringbase &
743 ~SSB_DMA_TRANSLATION_MASK)
744 | trans);
745 }
746 } else { 563 } else {
747 err = alloc_initial_descbuffers(ring); 564 err = alloc_initial_descbuffers(ring);
748 if (err) 565 if (err)
749 goto out; 566 goto out;
750 if (ring->type == B43legacy_DMA_64BIT) { 567
751 u64 ringbase = (u64)(ring->dmabase); 568 addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
752 569 >> SSB_DMA_TRANSLATION_SHIFT;
753 addrext = ((ringbase >> 32) & SSB_DMA_TRANSLATION_MASK) 570 value = (ring->frameoffset <<
754 >> SSB_DMA_TRANSLATION_SHIFT; 571 B43legacy_DMA32_RXFROFF_SHIFT);
755 value = (ring->frameoffset << 572 value |= B43legacy_DMA32_RXENABLE;
756 B43legacy_DMA64_RXFROFF_SHIFT); 573 value |= (addrext << B43legacy_DMA32_RXADDREXT_SHIFT)
757 value |= B43legacy_DMA64_RXENABLE; 574 & B43legacy_DMA32_RXADDREXT_MASK;
758 value |= (addrext << B43legacy_DMA64_RXADDREXT_SHIFT) 575 b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL, value);
759 & B43legacy_DMA64_RXADDREXT_MASK; 576 b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
760 b43legacy_dma_write(ring, B43legacy_DMA64_RXCTL, 577 (ringbase & ~SSB_DMA_TRANSLATION_MASK)
761 value); 578 | trans);
762 b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 579 b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX, 200);
763 (ringbase & 0xFFFFFFFF));
764 b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI,
765 ((ringbase >> 32) &
766 ~SSB_DMA_TRANSLATION_MASK) |
767 trans);
768 b43legacy_dma_write(ring, B43legacy_DMA64_RXINDEX,
769 200);
770 } else {
771 u32 ringbase = (u32)(ring->dmabase);
772
773 addrext = (ringbase & SSB_DMA_TRANSLATION_MASK)
774 >> SSB_DMA_TRANSLATION_SHIFT;
775 value = (ring->frameoffset <<
776 B43legacy_DMA32_RXFROFF_SHIFT);
777 value |= B43legacy_DMA32_RXENABLE;
778 value |= (addrext <<
779 B43legacy_DMA32_RXADDREXT_SHIFT)
780 & B43legacy_DMA32_RXADDREXT_MASK;
781 b43legacy_dma_write(ring, B43legacy_DMA32_RXCTL,
782 value);
783 b43legacy_dma_write(ring, B43legacy_DMA32_RXRING,
784 (ringbase &
785 ~SSB_DMA_TRANSLATION_MASK)
786 | trans);
787 b43legacy_dma_write(ring, B43legacy_DMA32_RXINDEX,
788 200);
789 }
790 } 580 }
791 581
792out: 582out:
@@ -799,19 +589,11 @@ static void dmacontroller_cleanup(struct b43legacy_dmaring *ring)
799 if (ring->tx) { 589 if (ring->tx) {
800 b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base, 590 b43legacy_dmacontroller_tx_reset(ring->dev, ring->mmio_base,
801 ring->type); 591 ring->type);
802 if (ring->type == B43legacy_DMA_64BIT) { 592 b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
803 b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGLO, 0);
804 b43legacy_dma_write(ring, B43legacy_DMA64_TXRINGHI, 0);
805 } else
806 b43legacy_dma_write(ring, B43legacy_DMA32_TXRING, 0);
807 } else { 593 } else {
808 b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base, 594 b43legacy_dmacontroller_rx_reset(ring->dev, ring->mmio_base,
809 ring->type); 595 ring->type);
810 if (ring->type == B43legacy_DMA_64BIT) { 596 b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
811 b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGLO, 0);
812 b43legacy_dma_write(ring, B43legacy_DMA64_RXRINGHI, 0);
813 } else
814 b43legacy_dma_write(ring, B43legacy_DMA32_RXRING, 0);
815 } 597 }
816} 598}
817 599
@@ -823,7 +605,7 @@ static void free_all_descbuffers(struct b43legacy_dmaring *ring)
823 if (!ring->used_slots) 605 if (!ring->used_slots)
824 return; 606 return;
825 for (i = 0; i < ring->nr_slots; i++) { 607 for (i = 0; i < ring->nr_slots; i++) {
826 ring->ops->idx2desc(ring, i, &meta); 608 op32_idx2desc(ring, i, &meta);
827 609
828 if (!meta->skb) { 610 if (!meta->skb) {
829 B43legacy_WARN_ON(!ring->tx); 611 B43legacy_WARN_ON(!ring->tx);
@@ -844,9 +626,6 @@ static u64 supported_dma_mask(struct b43legacy_wldev *dev)
844 u32 tmp; 626 u32 tmp;
845 u16 mmio_base; 627 u16 mmio_base;
846 628
847 tmp = b43legacy_read32(dev, SSB_TMSHIGH);
848 if (tmp & SSB_TMSHIGH_DMA64)
849 return DMA_BIT_MASK(64);
850 mmio_base = b43legacy_dmacontroller_base(0, 0); 629 mmio_base = b43legacy_dmacontroller_base(0, 0);
851 b43legacy_write32(dev, 630 b43legacy_write32(dev,
852 mmio_base + B43legacy_DMA32_TXCTL, 631 mmio_base + B43legacy_DMA32_TXCTL,
@@ -865,8 +644,6 @@ static enum b43legacy_dmatype dma_mask_to_engine_type(u64 dmamask)
865 return B43legacy_DMA_30BIT; 644 return B43legacy_DMA_30BIT;
866 if (dmamask == DMA_BIT_MASK(32)) 645 if (dmamask == DMA_BIT_MASK(32))
867 return B43legacy_DMA_32BIT; 646 return B43legacy_DMA_32BIT;
868 if (dmamask == DMA_BIT_MASK(64))
869 return B43legacy_DMA_64BIT;
870 B43legacy_WARN_ON(1); 647 B43legacy_WARN_ON(1);
871 return B43legacy_DMA_30BIT; 648 return B43legacy_DMA_30BIT;
872} 649}
@@ -937,10 +714,6 @@ struct b43legacy_dmaring *b43legacy_setup_dmaring(struct b43legacy_wldev *dev,
937 ring->nr_slots = nr_slots; 714 ring->nr_slots = nr_slots;
938 ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index); 715 ring->mmio_base = b43legacy_dmacontroller_base(type, controller_index);
939 ring->index = controller_index; 716 ring->index = controller_index;
940 if (type == B43legacy_DMA_64BIT)
941 ring->ops = &dma64_ops;
942 else
943 ring->ops = &dma32_ops;
944 if (for_tx) { 717 if (for_tx) {
945 ring->tx = 1; 718 ring->tx = 1;
946 ring->current_slot = -1; 719 ring->current_slot = -1;
@@ -1247,12 +1020,11 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
1247 struct sk_buff **in_skb) 1020 struct sk_buff **in_skb)
1248{ 1021{
1249 struct sk_buff *skb = *in_skb; 1022 struct sk_buff *skb = *in_skb;
1250 const struct b43legacy_dma_ops *ops = ring->ops;
1251 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 1023 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
1252 u8 *header; 1024 u8 *header;
1253 int slot, old_top_slot, old_used_slots; 1025 int slot, old_top_slot, old_used_slots;
1254 int err; 1026 int err;
1255 struct b43legacy_dmadesc_generic *desc; 1027 struct b43legacy_dmadesc32 *desc;
1256 struct b43legacy_dmadesc_meta *meta; 1028 struct b43legacy_dmadesc_meta *meta;
1257 struct b43legacy_dmadesc_meta *meta_hdr; 1029 struct b43legacy_dmadesc_meta *meta_hdr;
1258 struct sk_buff *bounce_skb; 1030 struct sk_buff *bounce_skb;
@@ -1265,7 +1037,7 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
1265 1037
1266 /* Get a slot for the header. */ 1038 /* Get a slot for the header. */
1267 slot = request_slot(ring); 1039 slot = request_slot(ring);
1268 desc = ops->idx2desc(ring, slot, &meta_hdr); 1040 desc = op32_idx2desc(ring, slot, &meta_hdr);
1269 memset(meta_hdr, 0, sizeof(*meta_hdr)); 1041 memset(meta_hdr, 0, sizeof(*meta_hdr));
1270 1042
1271 header = &(ring->txhdr_cache[slot * sizeof( 1043 header = &(ring->txhdr_cache[slot * sizeof(
@@ -1287,12 +1059,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
1287 ring->used_slots = old_used_slots; 1059 ring->used_slots = old_used_slots;
1288 return -EIO; 1060 return -EIO;
1289 } 1061 }
1290 ops->fill_descriptor(ring, desc, meta_hdr->dmaaddr, 1062 op32_fill_descriptor(ring, desc, meta_hdr->dmaaddr,
1291 sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0); 1063 sizeof(struct b43legacy_txhdr_fw3), 1, 0, 0);
1292 1064
1293 /* Get a slot for the payload. */ 1065 /* Get a slot for the payload. */
1294 slot = request_slot(ring); 1066 slot = request_slot(ring);
1295 desc = ops->idx2desc(ring, slot, &meta); 1067 desc = op32_idx2desc(ring, slot, &meta);
1296 memset(meta, 0, sizeof(*meta)); 1068 memset(meta, 0, sizeof(*meta));
1297 1069
1298 meta->skb = skb; 1070 meta->skb = skb;
@@ -1328,12 +1100,12 @@ static int dma_tx_fragment(struct b43legacy_dmaring *ring,
1328 } 1100 }
1329 } 1101 }
1330 1102
1331 ops->fill_descriptor(ring, desc, meta->dmaaddr, 1103 op32_fill_descriptor(ring, desc, meta->dmaaddr,
1332 skb->len, 0, 1, 1); 1104 skb->len, 0, 1, 1);
1333 1105
1334 wmb(); /* previous stuff MUST be done */ 1106 wmb(); /* previous stuff MUST be done */
1335 /* Now transfer the whole frame. */ 1107 /* Now transfer the whole frame. */
1336 ops->poke_tx(ring, next_slot(ring, slot)); 1108 op32_poke_tx(ring, next_slot(ring, slot));
1337 return 0; 1109 return 0;
1338 1110
1339out_free_bounce: 1111out_free_bounce:
@@ -1429,7 +1201,6 @@ out_unlock:
1429void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev, 1201void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
1430 const struct b43legacy_txstatus *status) 1202 const struct b43legacy_txstatus *status)
1431{ 1203{
1432 const struct b43legacy_dma_ops *ops;
1433 struct b43legacy_dmaring *ring; 1204 struct b43legacy_dmaring *ring;
1434 struct b43legacy_dmadesc_meta *meta; 1205 struct b43legacy_dmadesc_meta *meta;
1435 int retry_limit; 1206 int retry_limit;
@@ -1442,10 +1213,9 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
1442 spin_lock(&ring->lock); 1213 spin_lock(&ring->lock);
1443 1214
1444 B43legacy_WARN_ON(!ring->tx); 1215 B43legacy_WARN_ON(!ring->tx);
1445 ops = ring->ops;
1446 while (1) { 1216 while (1) {
1447 B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots)); 1217 B43legacy_WARN_ON(!(slot >= 0 && slot < ring->nr_slots));
1448 ops->idx2desc(ring, slot, &meta); 1218 op32_idx2desc(ring, slot, &meta);
1449 1219
1450 if (meta->skb) 1220 if (meta->skb)
1451 unmap_descbuffer(ring, meta->dmaaddr, 1221 unmap_descbuffer(ring, meta->dmaaddr,
@@ -1528,8 +1298,7 @@ void b43legacy_dma_handle_txstatus(struct b43legacy_wldev *dev,
1528static void dma_rx(struct b43legacy_dmaring *ring, 1298static void dma_rx(struct b43legacy_dmaring *ring,
1529 int *slot) 1299 int *slot)
1530{ 1300{
1531 const struct b43legacy_dma_ops *ops = ring->ops; 1301 struct b43legacy_dmadesc32 *desc;
1532 struct b43legacy_dmadesc_generic *desc;
1533 struct b43legacy_dmadesc_meta *meta; 1302 struct b43legacy_dmadesc_meta *meta;
1534 struct b43legacy_rxhdr_fw3 *rxhdr; 1303 struct b43legacy_rxhdr_fw3 *rxhdr;
1535 struct sk_buff *skb; 1304 struct sk_buff *skb;
@@ -1537,7 +1306,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
1537 int err; 1306 int err;
1538 dma_addr_t dmaaddr; 1307 dma_addr_t dmaaddr;
1539 1308
1540 desc = ops->idx2desc(ring, *slot, &meta); 1309 desc = op32_idx2desc(ring, *slot, &meta);
1541 1310
1542 sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize); 1311 sync_descbuffer_for_cpu(ring, meta->dmaaddr, ring->rx_buffersize);
1543 skb = meta->skb; 1312 skb = meta->skb;
@@ -1589,7 +1358,7 @@ static void dma_rx(struct b43legacy_dmaring *ring,
1589 s32 tmp = len; 1358 s32 tmp = len;
1590 1359
1591 while (1) { 1360 while (1) {
1592 desc = ops->idx2desc(ring, *slot, &meta); 1361 desc = op32_idx2desc(ring, *slot, &meta);
1593 /* recycle the descriptor buffer. */ 1362 /* recycle the descriptor buffer. */
1594 sync_descbuffer_for_device(ring, meta->dmaaddr, 1363 sync_descbuffer_for_device(ring, meta->dmaaddr,
1595 ring->rx_buffersize); 1364 ring->rx_buffersize);
@@ -1626,13 +1395,12 @@ drop:
1626 1395
1627void b43legacy_dma_rx(struct b43legacy_dmaring *ring) 1396void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
1628{ 1397{
1629 const struct b43legacy_dma_ops *ops = ring->ops;
1630 int slot; 1398 int slot;
1631 int current_slot; 1399 int current_slot;
1632 int used_slots = 0; 1400 int used_slots = 0;
1633 1401
1634 B43legacy_WARN_ON(ring->tx); 1402 B43legacy_WARN_ON(ring->tx);
1635 current_slot = ops->get_current_rxslot(ring); 1403 current_slot = op32_get_current_rxslot(ring);
1636 B43legacy_WARN_ON(!(current_slot >= 0 && current_slot < 1404 B43legacy_WARN_ON(!(current_slot >= 0 && current_slot <
1637 ring->nr_slots)); 1405 ring->nr_slots));
1638 1406
@@ -1641,7 +1409,7 @@ void b43legacy_dma_rx(struct b43legacy_dmaring *ring)
1641 dma_rx(ring, &slot); 1409 dma_rx(ring, &slot);
1642 update_max_used_slots(ring, ++used_slots); 1410 update_max_used_slots(ring, ++used_slots);
1643 } 1411 }
1644 ops->set_current_rxslot(ring, slot); 1412 op32_set_current_rxslot(ring, slot);
1645 ring->current_slot = slot; 1413 ring->current_slot = slot;
1646} 1414}
1647 1415
@@ -1651,7 +1419,7 @@ static void b43legacy_dma_tx_suspend_ring(struct b43legacy_dmaring *ring)
1651 1419
1652 spin_lock_irqsave(&ring->lock, flags); 1420 spin_lock_irqsave(&ring->lock, flags);
1653 B43legacy_WARN_ON(!ring->tx); 1421 B43legacy_WARN_ON(!ring->tx);
1654 ring->ops->tx_suspend(ring); 1422 op32_tx_suspend(ring);
1655 spin_unlock_irqrestore(&ring->lock, flags); 1423 spin_unlock_irqrestore(&ring->lock, flags);
1656} 1424}
1657 1425
@@ -1661,7 +1429,7 @@ static void b43legacy_dma_tx_resume_ring(struct b43legacy_dmaring *ring)
1661 1429
1662 spin_lock_irqsave(&ring->lock, flags); 1430 spin_lock_irqsave(&ring->lock, flags);
1663 B43legacy_WARN_ON(!ring->tx); 1431 B43legacy_WARN_ON(!ring->tx);
1664 ring->ops->tx_resume(ring); 1432 op32_tx_resume(ring);
1665 spin_unlock_irqrestore(&ring->lock, flags); 1433 spin_unlock_irqrestore(&ring->lock, flags);
1666} 1434}
1667 1435
diff --git a/drivers/net/wireless/b43legacy/dma.h b/drivers/net/wireless/b43legacy/dma.h
index 686941c242fc..504a58767e95 100644
--- a/drivers/net/wireless/b43legacy/dma.h
+++ b/drivers/net/wireless/b43legacy/dma.h
@@ -82,90 +82,6 @@ struct b43legacy_dmadesc32 {
82#define B43legacy_DMA32_DCTL_FRAMESTART 0x80000000 82#define B43legacy_DMA32_DCTL_FRAMESTART 0x80000000
83 83
84 84
85
86/*** 64-bit DMA Engine. ***/
87
88/* 64-bit DMA controller registers. */
89#define B43legacy_DMA64_TXCTL 0x00
90#define B43legacy_DMA64_TXENABLE 0x00000001
91#define B43legacy_DMA64_TXSUSPEND 0x00000002
92#define B43legacy_DMA64_TXLOOPBACK 0x00000004
93#define B43legacy_DMA64_TXFLUSH 0x00000010
94#define B43legacy_DMA64_TXADDREXT_MASK 0x00030000
95#define B43legacy_DMA64_TXADDREXT_SHIFT 16
96#define B43legacy_DMA64_TXINDEX 0x04
97#define B43legacy_DMA64_TXRINGLO 0x08
98#define B43legacy_DMA64_TXRINGHI 0x0C
99#define B43legacy_DMA64_TXSTATUS 0x10
100#define B43legacy_DMA64_TXSTATDPTR 0x00001FFF
101#define B43legacy_DMA64_TXSTAT 0xF0000000
102#define B43legacy_DMA64_TXSTAT_DISABLED 0x00000000
103#define B43legacy_DMA64_TXSTAT_ACTIVE 0x10000000
104#define B43legacy_DMA64_TXSTAT_IDLEWAIT 0x20000000
105#define B43legacy_DMA64_TXSTAT_STOPPED 0x30000000
106#define B43legacy_DMA64_TXSTAT_SUSP 0x40000000
107#define B43legacy_DMA64_TXERROR 0x14
108#define B43legacy_DMA64_TXERRDPTR 0x0001FFFF
109#define B43legacy_DMA64_TXERR 0xF0000000
110#define B43legacy_DMA64_TXERR_NOERR 0x00000000
111#define B43legacy_DMA64_TXERR_PROT 0x10000000
112#define B43legacy_DMA64_TXERR_UNDERRUN 0x20000000
113#define B43legacy_DMA64_TXERR_TRANSFER 0x30000000
114#define B43legacy_DMA64_TXERR_DESCREAD 0x40000000
115#define B43legacy_DMA64_TXERR_CORE 0x50000000
116#define B43legacy_DMA64_RXCTL 0x20
117#define B43legacy_DMA64_RXENABLE 0x00000001
118#define B43legacy_DMA64_RXFROFF_MASK 0x000000FE
119#define B43legacy_DMA64_RXFROFF_SHIFT 1
120#define B43legacy_DMA64_RXDIRECTFIFO 0x00000100
121#define B43legacy_DMA64_RXADDREXT_MASK 0x00030000
122#define B43legacy_DMA64_RXADDREXT_SHIFT 16
123#define B43legacy_DMA64_RXINDEX 0x24
124#define B43legacy_DMA64_RXRINGLO 0x28
125#define B43legacy_DMA64_RXRINGHI 0x2C
126#define B43legacy_DMA64_RXSTATUS 0x30
127#define B43legacy_DMA64_RXSTATDPTR 0x00001FFF
128#define B43legacy_DMA64_RXSTAT 0xF0000000
129#define B43legacy_DMA64_RXSTAT_DISABLED 0x00000000
130#define B43legacy_DMA64_RXSTAT_ACTIVE 0x10000000
131#define B43legacy_DMA64_RXSTAT_IDLEWAIT 0x20000000
132#define B43legacy_DMA64_RXSTAT_STOPPED 0x30000000
133#define B43legacy_DMA64_RXSTAT_SUSP 0x40000000
134#define B43legacy_DMA64_RXERROR 0x34
135#define B43legacy_DMA64_RXERRDPTR 0x0001FFFF
136#define B43legacy_DMA64_RXERR 0xF0000000
137#define B43legacy_DMA64_RXERR_NOERR 0x00000000
138#define B43legacy_DMA64_RXERR_PROT 0x10000000
139#define B43legacy_DMA64_RXERR_UNDERRUN 0x20000000
140#define B43legacy_DMA64_RXERR_TRANSFER 0x30000000
141#define B43legacy_DMA64_RXERR_DESCREAD 0x40000000
142#define B43legacy_DMA64_RXERR_CORE 0x50000000
143
144/* 64-bit DMA descriptor. */
145struct b43legacy_dmadesc64 {
146 __le32 control0;
147 __le32 control1;
148 __le32 address_low;
149 __le32 address_high;
150} __packed;
151#define B43legacy_DMA64_DCTL0_DTABLEEND 0x10000000
152#define B43legacy_DMA64_DCTL0_IRQ 0x20000000
153#define B43legacy_DMA64_DCTL0_FRAMEEND 0x40000000
154#define B43legacy_DMA64_DCTL0_FRAMESTART 0x80000000
155#define B43legacy_DMA64_DCTL1_BYTECNT 0x00001FFF
156#define B43legacy_DMA64_DCTL1_ADDREXT_MASK 0x00030000
157#define B43legacy_DMA64_DCTL1_ADDREXT_SHIFT 16
158
159
160
161struct b43legacy_dmadesc_generic {
162 union {
163 struct b43legacy_dmadesc32 dma32;
164 struct b43legacy_dmadesc64 dma64;
165 } __packed;
166} __packed;
167
168
169/* Misc DMA constants */ 85/* Misc DMA constants */
170#define B43legacy_DMA_RINGMEMSIZE PAGE_SIZE 86#define B43legacy_DMA_RINGMEMSIZE PAGE_SIZE
171#define B43legacy_DMA0_RX_FRAMEOFFSET 30 87#define B43legacy_DMA0_RX_FRAMEOFFSET 30
@@ -197,35 +113,12 @@ struct b43legacy_dmadesc_meta {
197 bool is_last_fragment; 113 bool is_last_fragment;
198}; 114};
199 115
200struct b43legacy_dmaring;
201
202/* Lowlevel DMA operations that differ between 32bit and 64bit DMA. */
203struct b43legacy_dma_ops {
204 struct b43legacy_dmadesc_generic * (*idx2desc)
205 (struct b43legacy_dmaring *ring,
206 int slot,
207 struct b43legacy_dmadesc_meta
208 **meta);
209 void (*fill_descriptor)(struct b43legacy_dmaring *ring,
210 struct b43legacy_dmadesc_generic *desc,
211 dma_addr_t dmaaddr, u16 bufsize,
212 int start, int end, int irq);
213 void (*poke_tx)(struct b43legacy_dmaring *ring, int slot);
214 void (*tx_suspend)(struct b43legacy_dmaring *ring);
215 void (*tx_resume)(struct b43legacy_dmaring *ring);
216 int (*get_current_rxslot)(struct b43legacy_dmaring *ring);
217 void (*set_current_rxslot)(struct b43legacy_dmaring *ring, int slot);
218};
219
220enum b43legacy_dmatype { 116enum b43legacy_dmatype {
221 B43legacy_DMA_30BIT = 30, 117 B43legacy_DMA_30BIT = 30,
222 B43legacy_DMA_32BIT = 32, 118 B43legacy_DMA_32BIT = 32,
223 B43legacy_DMA_64BIT = 64,
224}; 119};
225 120
226struct b43legacy_dmaring { 121struct b43legacy_dmaring {
227 /* Lowlevel DMA ops. */
228 const struct b43legacy_dma_ops *ops;
229 /* Kernel virtual base address of the ring memory. */ 122 /* Kernel virtual base address of the ring memory. */
230 void *descbase; 123 void *descbase;
231 /* Meta data about all descriptors. */ 124 /* Meta data about all descriptors. */
diff --git a/drivers/net/wireless/b43legacy/main.c b/drivers/net/wireless/b43legacy/main.c
index 04c03b212a5e..aae8dfcb852e 100644
--- a/drivers/net/wireless/b43legacy/main.c
+++ b/drivers/net/wireless/b43legacy/main.c
@@ -35,7 +35,6 @@
35#include <linux/if_arp.h> 35#include <linux/if_arp.h>
36#include <linux/etherdevice.h> 36#include <linux/etherdevice.h>
37#include <linux/firmware.h> 37#include <linux/firmware.h>
38#include <linux/wireless.h>
39#include <linux/workqueue.h> 38#include <linux/workqueue.h>
40#include <linux/sched.h> 39#include <linux/sched.h>
41#include <linux/skbuff.h> 40#include <linux/skbuff.h>
@@ -3785,7 +3784,8 @@ static int b43legacy_wireless_init(struct ssb_device *dev)
3785 INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work); 3784 INIT_WORK(&wl->beacon_update_trigger, b43legacy_beacon_update_trigger_work);
3786 3785
3787 ssb_set_devtypedata(dev, wl); 3786 ssb_set_devtypedata(dev, wl);
3788 b43legacyinfo(wl, "Broadcom %04X WLAN found\n", dev->bus->chip_id); 3787 b43legacyinfo(wl, "Broadcom %04X WLAN found (core revision %u)\n",
3788 dev->bus->chip_id, dev->id.revision);
3789 err = 0; 3789 err = 0;
3790out: 3790out:
3791 return err; 3791 return err;
diff --git a/drivers/net/wireless/ipw2x00/ipw2200.c b/drivers/net/wireless/ipw2x00/ipw2200.c
index 553f66b67c16..f303df43ed3f 100644
--- a/drivers/net/wireless/ipw2x00/ipw2200.c
+++ b/drivers/net/wireless/ipw2x00/ipw2200.c
@@ -32,6 +32,7 @@
32 32
33#include <linux/sched.h> 33#include <linux/sched.h>
34#include <linux/slab.h> 34#include <linux/slab.h>
35#include <net/cfg80211-wext.h>
35#include "ipw2200.h" 36#include "ipw2200.h"
36 37
37 38
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-led.c b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
index abd923558d48..7a7f0f38c8ab 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-led.c
@@ -32,7 +32,6 @@
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <linux/netdevice.h> 34#include <linux/netdevice.h>
35#include <linux/wireless.h>
36#include <net/mac80211.h> 35#include <net/mac80211.h>
37#include <linux/etherdevice.h> 36#include <linux/etherdevice.h>
38#include <asm/unaligned.h> 37#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
index 977bd2477c6a..0cc5177d738d 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945-rs.c
@@ -28,7 +28,6 @@
28#include <linux/init.h> 28#include <linux/init.h>
29#include <linux/skbuff.h> 29#include <linux/skbuff.h>
30#include <linux/slab.h> 30#include <linux/slab.h>
31#include <linux/wireless.h>
32#include <net/mac80211.h> 31#include <net/mac80211.h>
33 32
34#include <linux/netdevice.h> 33#include <linux/netdevice.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-3945.c b/drivers/net/wireless/iwlegacy/iwl-3945.c
index 73fe3cdf796b..f7c0a7438476 100644
--- a/drivers/net/wireless/iwlegacy/iwl-3945.c
+++ b/drivers/net/wireless/iwlegacy/iwl-3945.c
@@ -34,7 +34,6 @@
34#include <linux/sched.h> 34#include <linux/sched.h>
35#include <linux/skbuff.h> 35#include <linux/skbuff.h>
36#include <linux/netdevice.h> 36#include <linux/netdevice.h>
37#include <linux/wireless.h>
38#include <linux/firmware.h> 37#include <linux/firmware.h>
39#include <linux/etherdevice.h> 38#include <linux/etherdevice.h>
40#include <asm/unaligned.h> 39#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-led.c b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
index 26d324e30692..6862fdcaee62 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-led.c
@@ -32,7 +32,6 @@
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/skbuff.h> 33#include <linux/skbuff.h>
34#include <linux/netdevice.h> 34#include <linux/netdevice.h>
35#include <linux/wireless.h>
36#include <net/mac80211.h> 35#include <net/mac80211.h>
37#include <linux/etherdevice.h> 36#include <linux/etherdevice.h>
38#include <asm/unaligned.h> 37#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
index 9b65153bdd01..57ebe214e68c 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965-rs.c
@@ -27,7 +27,6 @@
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/skbuff.h> 28#include <linux/skbuff.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/wireless.h>
31#include <net/mac80211.h> 30#include <net/mac80211.h>
32 31
33#include <linux/netdevice.h> 32#include <linux/netdevice.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-4965.c b/drivers/net/wireless/iwlegacy/iwl-4965.c
index ecdc6e557428..86f4fce193e4 100644
--- a/drivers/net/wireless/iwlegacy/iwl-4965.c
+++ b/drivers/net/wireless/iwlegacy/iwl-4965.c
@@ -33,7 +33,6 @@
33#include <linux/sched.h> 33#include <linux/sched.h>
34#include <linux/skbuff.h> 34#include <linux/skbuff.h>
35#include <linux/netdevice.h> 35#include <linux/netdevice.h>
36#include <linux/wireless.h>
37#include <net/mac80211.h> 36#include <net/mac80211.h>
38#include <linux/etherdevice.h> 37#include <linux/etherdevice.h>
39#include <asm/unaligned.h> 38#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl-led.c b/drivers/net/wireless/iwlegacy/iwl-led.c
index bda0d61b2c0d..dc568a474c5d 100644
--- a/drivers/net/wireless/iwlegacy/iwl-led.c
+++ b/drivers/net/wireless/iwlegacy/iwl-led.c
@@ -33,7 +33,6 @@
33#include <linux/delay.h> 33#include <linux/delay.h>
34#include <linux/skbuff.h> 34#include <linux/skbuff.h>
35#include <linux/netdevice.h> 35#include <linux/netdevice.h>
36#include <linux/wireless.h>
37#include <net/mac80211.h> 36#include <net/mac80211.h>
38#include <linux/etherdevice.h> 37#include <linux/etherdevice.h>
39#include <asm/unaligned.h> 38#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl3945-base.c b/drivers/net/wireless/iwlegacy/iwl3945-base.c
index 795826a014ed..015739d204f2 100644
--- a/drivers/net/wireless/iwlegacy/iwl3945-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl3945-base.c
@@ -40,7 +40,6 @@
40#include <linux/sched.h> 40#include <linux/sched.h>
41#include <linux/skbuff.h> 41#include <linux/skbuff.h>
42#include <linux/netdevice.h> 42#include <linux/netdevice.h>
43#include <linux/wireless.h>
44#include <linux/firmware.h> 43#include <linux/firmware.h>
45#include <linux/etherdevice.h> 44#include <linux/etherdevice.h>
46#include <linux/if_arp.h> 45#include <linux/if_arp.h>
diff --git a/drivers/net/wireless/iwlegacy/iwl4965-base.c b/drivers/net/wireless/iwlegacy/iwl4965-base.c
index 14334668034e..6bc5575c8dff 100644
--- a/drivers/net/wireless/iwlegacy/iwl4965-base.c
+++ b/drivers/net/wireless/iwlegacy/iwl4965-base.c
@@ -40,7 +40,6 @@
40#include <linux/sched.h> 40#include <linux/sched.h>
41#include <linux/skbuff.h> 41#include <linux/skbuff.h>
42#include <linux/netdevice.h> 42#include <linux/netdevice.h>
43#include <linux/wireless.h>
44#include <linux/firmware.h> 43#include <linux/firmware.h>
45#include <linux/etherdevice.h> 44#include <linux/etherdevice.h>
46#include <linux/if_arp.h> 45#include <linux/if_arp.h>
diff --git a/drivers/net/wireless/iwlwifi/Kconfig b/drivers/net/wireless/iwlwifi/Kconfig
index ad3bdba6beed..1d7572f9887f 100644
--- a/drivers/net/wireless/iwlwifi/Kconfig
+++ b/drivers/net/wireless/iwlwifi/Kconfig
@@ -111,20 +111,3 @@ config IWLWIFI_DEVICE_SVTOOL
111 NL80211_TESTMODE. svtool is a software validation tool that runs in 111 NL80211_TESTMODE. svtool is a software validation tool that runs in
112 the user space and interacts with the device in the kernel space 112 the user space and interacts with the device in the kernel space
113 through the generic netlink message via NL80211_TESTMODE channel. 113 through the generic netlink message via NL80211_TESTMODE channel.
114
115config IWL_P2P
116 bool "iwlwifi experimental P2P support"
117 depends on IWLAGN
118 help
119 This option enables experimental P2P support for some devices
120 based on microcode support. Since P2P support is still under
121 development, this option may even enable it for some devices
122 now that turn out to not support it in the future due to
123 microcode restrictions.
124
125 To determine if your microcode supports the experimental P2P
126 offered by this option, check if the driver advertises AP
127 support when it is loaded.
128
129 Say Y only if you want to experiment with P2P.
130
diff --git a/drivers/net/wireless/iwlwifi/iwl-1000.c b/drivers/net/wireless/iwlwifi/iwl-1000.c
index 01b49eb8c8ec..ccdbed567171 100644
--- a/drivers/net/wireless/iwlwifi/iwl-1000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-1000.c
@@ -30,7 +30,6 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/skbuff.h> 31#include <linux/skbuff.h>
32#include <linux/netdevice.h> 32#include <linux/netdevice.h>
33#include <linux/wireless.h>
34#include <net/mac80211.h> 33#include <net/mac80211.h>
35#include <linux/etherdevice.h> 34#include <linux/etherdevice.h>
36#include <asm/unaligned.h> 35#include <asm/unaligned.h>
@@ -46,8 +45,12 @@
46#include "iwl-agn-hw.h" 45#include "iwl-agn-hw.h"
47 46
48/* Highest firmware API version supported */ 47/* Highest firmware API version supported */
49#define IWL1000_UCODE_API_MAX 5 48#define IWL1000_UCODE_API_MAX 6
50#define IWL100_UCODE_API_MAX 5 49#define IWL100_UCODE_API_MAX 6
50
51/* Oldest version we won't warn about */
52#define IWL1000_UCODE_API_OK 5
53#define IWL100_UCODE_API_OK 5
51 54
52/* Lowest firmware API version supported */ 55/* Lowest firmware API version supported */
53#define IWL1000_UCODE_API_MIN 1 56#define IWL1000_UCODE_API_MIN 1
@@ -135,8 +138,7 @@ static int iwl1000_hw_set_hw_params(struct iwl_priv *priv)
135 priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE; 138 priv->hw_params.max_data_size = IWLAGN_RTC_DATA_SIZE;
136 priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE; 139 priv->hw_params.max_inst_size = IWLAGN_RTC_INST_SIZE;
137 140
138 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | 141 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ);
139 BIT(IEEE80211_BAND_5GHZ);
140 142
141 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); 143 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
142 if (priv->cfg->rx_with_siso_diversity) 144 if (priv->cfg->rx_with_siso_diversity)
@@ -201,12 +203,13 @@ static struct iwl_base_params iwl1000_base_params = {
201static struct iwl_ht_params iwl1000_ht_params = { 203static struct iwl_ht_params iwl1000_ht_params = {
202 .ht_greenfield_support = true, 204 .ht_greenfield_support = true,
203 .use_rts_for_aggregation = true, /* use rts/cts protection */ 205 .use_rts_for_aggregation = true, /* use rts/cts protection */
204 .smps_mode = IEEE80211_SMPS_STATIC, 206 .smps_mode = IEEE80211_SMPS_DYNAMIC,
205}; 207};
206 208
207#define IWL_DEVICE_1000 \ 209#define IWL_DEVICE_1000 \
208 .fw_name_pre = IWL1000_FW_PRE, \ 210 .fw_name_pre = IWL1000_FW_PRE, \
209 .ucode_api_max = IWL1000_UCODE_API_MAX, \ 211 .ucode_api_max = IWL1000_UCODE_API_MAX, \
212 .ucode_api_ok = IWL1000_UCODE_API_OK, \
210 .ucode_api_min = IWL1000_UCODE_API_MIN, \ 213 .ucode_api_min = IWL1000_UCODE_API_MIN, \
211 .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ 214 .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
212 .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ 215 .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
@@ -228,6 +231,7 @@ struct iwl_cfg iwl1000_bg_cfg = {
228#define IWL_DEVICE_100 \ 231#define IWL_DEVICE_100 \
229 .fw_name_pre = IWL100_FW_PRE, \ 232 .fw_name_pre = IWL100_FW_PRE, \
230 .ucode_api_max = IWL100_UCODE_API_MAX, \ 233 .ucode_api_max = IWL100_UCODE_API_MAX, \
234 .ucode_api_ok = IWL100_UCODE_API_OK, \
231 .ucode_api_min = IWL100_UCODE_API_MIN, \ 235 .ucode_api_min = IWL100_UCODE_API_MIN, \
232 .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \ 236 .eeprom_ver = EEPROM_1000_EEPROM_VERSION, \
233 .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \ 237 .eeprom_calib_ver = EEPROM_1000_TX_POWER_VERSION, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-2000.c b/drivers/net/wireless/iwlwifi/iwl-2000.c
index 0e13f0bb2e17..54d931d614fb 100644
--- a/drivers/net/wireless/iwlwifi/iwl-2000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-2000.c
@@ -30,7 +30,6 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/skbuff.h> 31#include <linux/skbuff.h>
32#include <linux/netdevice.h> 32#include <linux/netdevice.h>
33#include <linux/wireless.h>
34#include <net/mac80211.h> 33#include <net/mac80211.h>
35#include <linux/etherdevice.h> 34#include <linux/etherdevice.h>
36#include <asm/unaligned.h> 35#include <asm/unaligned.h>
@@ -47,10 +46,16 @@
47#include "iwl-6000-hw.h" 46#include "iwl-6000-hw.h"
48 47
49/* Highest firmware API version supported */ 48/* Highest firmware API version supported */
50#define IWL2030_UCODE_API_MAX 5 49#define IWL2030_UCODE_API_MAX 6
51#define IWL2000_UCODE_API_MAX 5 50#define IWL2000_UCODE_API_MAX 6
52#define IWL105_UCODE_API_MAX 5 51#define IWL105_UCODE_API_MAX 6
53#define IWL135_UCODE_API_MAX 5 52#define IWL135_UCODE_API_MAX 6
53
54/* Oldest version we won't warn about */
55#define IWL2030_UCODE_API_OK 5
56#define IWL2000_UCODE_API_OK 5
57#define IWL105_UCODE_API_OK 5
58#define IWL135_UCODE_API_OK 5
54 59
55/* Lowest firmware API version supported */ 60/* Lowest firmware API version supported */
56#define IWL2030_UCODE_API_MIN 5 61#define IWL2030_UCODE_API_MIN 5
@@ -130,8 +135,7 @@ static int iwl2000_hw_set_hw_params(struct iwl_priv *priv)
130 priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE; 135 priv->hw_params.max_data_size = IWL60_RTC_DATA_SIZE;
131 priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE; 136 priv->hw_params.max_inst_size = IWL60_RTC_INST_SIZE;
132 137
133 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ) | 138 priv->hw_params.ht40_channel = BIT(IEEE80211_BAND_2GHZ);
134 BIT(IEEE80211_BAND_5GHZ);
135 139
136 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant); 140 priv->hw_params.tx_chains_num = num_of_ant(priv->cfg->valid_tx_ant);
137 if (priv->cfg->rx_with_siso_diversity) 141 if (priv->cfg->rx_with_siso_diversity)
@@ -217,6 +221,7 @@ static struct iwl_base_params iwl2000_base_params = {
217 .wd_timeout = IWL_DEF_WD_TIMEOUT, 221 .wd_timeout = IWL_DEF_WD_TIMEOUT,
218 .max_event_log_size = 512, 222 .max_event_log_size = 512,
219 .shadow_reg_enable = true, 223 .shadow_reg_enable = true,
224 .hd_v2 = true,
220}; 225};
221 226
222 227
@@ -236,6 +241,7 @@ static struct iwl_base_params iwl2030_base_params = {
236 .wd_timeout = IWL_LONG_WD_TIMEOUT, 241 .wd_timeout = IWL_LONG_WD_TIMEOUT,
237 .max_event_log_size = 512, 242 .max_event_log_size = 512,
238 .shadow_reg_enable = true, 243 .shadow_reg_enable = true,
244 .hd_v2 = true,
239}; 245};
240 246
241static struct iwl_ht_params iwl2000_ht_params = { 247static struct iwl_ht_params iwl2000_ht_params = {
@@ -256,6 +262,7 @@ static struct iwl_bt_params iwl2030_bt_params = {
256#define IWL_DEVICE_2000 \ 262#define IWL_DEVICE_2000 \
257 .fw_name_pre = IWL2000_FW_PRE, \ 263 .fw_name_pre = IWL2000_FW_PRE, \
258 .ucode_api_max = IWL2000_UCODE_API_MAX, \ 264 .ucode_api_max = IWL2000_UCODE_API_MAX, \
265 .ucode_api_ok = IWL2000_UCODE_API_OK, \
259 .ucode_api_min = IWL2000_UCODE_API_MIN, \ 266 .ucode_api_min = IWL2000_UCODE_API_MIN, \
260 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ 267 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
261 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ 268 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -280,6 +287,7 @@ struct iwl_cfg iwl2000_2bg_cfg = {
280#define IWL_DEVICE_2030 \ 287#define IWL_DEVICE_2030 \
281 .fw_name_pre = IWL2030_FW_PRE, \ 288 .fw_name_pre = IWL2030_FW_PRE, \
282 .ucode_api_max = IWL2030_UCODE_API_MAX, \ 289 .ucode_api_max = IWL2030_UCODE_API_MAX, \
290 .ucode_api_ok = IWL2030_UCODE_API_OK, \
283 .ucode_api_min = IWL2030_UCODE_API_MIN, \ 291 .ucode_api_min = IWL2030_UCODE_API_MIN, \
284 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ 292 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
285 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ 293 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -306,6 +314,7 @@ struct iwl_cfg iwl2030_2bg_cfg = {
306#define IWL_DEVICE_105 \ 314#define IWL_DEVICE_105 \
307 .fw_name_pre = IWL105_FW_PRE, \ 315 .fw_name_pre = IWL105_FW_PRE, \
308 .ucode_api_max = IWL105_UCODE_API_MAX, \ 316 .ucode_api_max = IWL105_UCODE_API_MAX, \
317 .ucode_api_ok = IWL105_UCODE_API_OK, \
309 .ucode_api_min = IWL105_UCODE_API_MIN, \ 318 .ucode_api_min = IWL105_UCODE_API_MIN, \
310 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ 319 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
311 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ 320 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
@@ -332,6 +341,7 @@ struct iwl_cfg iwl105_bgn_cfg = {
332#define IWL_DEVICE_135 \ 341#define IWL_DEVICE_135 \
333 .fw_name_pre = IWL135_FW_PRE, \ 342 .fw_name_pre = IWL135_FW_PRE, \
334 .ucode_api_max = IWL135_UCODE_API_MAX, \ 343 .ucode_api_max = IWL135_UCODE_API_MAX, \
344 .ucode_api_ok = IWL135_UCODE_API_OK, \
335 .ucode_api_min = IWL135_UCODE_API_MIN, \ 345 .ucode_api_min = IWL135_UCODE_API_MIN, \
336 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \ 346 .eeprom_ver = EEPROM_2000_EEPROM_VERSION, \
337 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \ 347 .eeprom_calib_ver = EEPROM_2000_TX_POWER_VERSION, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c
index c95cefd529dc..a9adee5634d8 100644
--- a/drivers/net/wireless/iwlwifi/iwl-5000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-5000.c
@@ -31,7 +31,6 @@
31#include <linux/sched.h> 31#include <linux/sched.h>
32#include <linux/skbuff.h> 32#include <linux/skbuff.h>
33#include <linux/netdevice.h> 33#include <linux/netdevice.h>
34#include <linux/wireless.h>
35#include <net/mac80211.h> 34#include <net/mac80211.h>
36#include <linux/etherdevice.h> 35#include <linux/etherdevice.h>
37#include <asm/unaligned.h> 36#include <asm/unaligned.h>
@@ -84,12 +83,12 @@ static void iwl5000_nic_config(struct iwl_priv *priv)
84} 83}
85 84
86static struct iwl_sensitivity_ranges iwl5000_sensitivity = { 85static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
87 .min_nrg_cck = 95, 86 .min_nrg_cck = 100,
88 .max_nrg_cck = 0, /* not used, set to 0 */ 87 .max_nrg_cck = 0, /* not used, set to 0 */
89 .auto_corr_min_ofdm = 90, 88 .auto_corr_min_ofdm = 90,
90 .auto_corr_min_ofdm_mrc = 170, 89 .auto_corr_min_ofdm_mrc = 170,
91 .auto_corr_min_ofdm_x1 = 120, 90 .auto_corr_min_ofdm_x1 = 105,
92 .auto_corr_min_ofdm_mrc_x1 = 240, 91 .auto_corr_min_ofdm_mrc_x1 = 220,
93 92
94 .auto_corr_max_ofdm = 120, 93 .auto_corr_max_ofdm = 120,
95 .auto_corr_max_ofdm_mrc = 210, 94 .auto_corr_max_ofdm_mrc = 210,
@@ -98,10 +97,10 @@ static struct iwl_sensitivity_ranges iwl5000_sensitivity = {
98 97
99 .auto_corr_min_cck = 125, 98 .auto_corr_min_cck = 125,
100 .auto_corr_max_cck = 200, 99 .auto_corr_max_cck = 200,
101 .auto_corr_min_cck_mrc = 170, 100 .auto_corr_min_cck_mrc = 200,
102 .auto_corr_max_cck_mrc = 400, 101 .auto_corr_max_cck_mrc = 400,
103 .nrg_th_cck = 95, 102 .nrg_th_cck = 100,
104 .nrg_th_ofdm = 95, 103 .nrg_th_ofdm = 100,
105 104
106 .barker_corr_th_min = 190, 105 .barker_corr_th_min = 190,
107 .barker_corr_th_min_mrc = 390, 106 .barker_corr_th_min_mrc = 390,
diff --git a/drivers/net/wireless/iwlwifi/iwl-6000.c b/drivers/net/wireless/iwlwifi/iwl-6000.c
index 973d1972e8cc..339de88d9ae2 100644
--- a/drivers/net/wireless/iwlwifi/iwl-6000.c
+++ b/drivers/net/wireless/iwlwifi/iwl-6000.c
@@ -30,7 +30,6 @@
30#include <linux/delay.h> 30#include <linux/delay.h>
31#include <linux/skbuff.h> 31#include <linux/skbuff.h>
32#include <linux/netdevice.h> 32#include <linux/netdevice.h>
33#include <linux/wireless.h>
34#include <net/mac80211.h> 33#include <net/mac80211.h>
35#include <linux/etherdevice.h> 34#include <linux/etherdevice.h>
36#include <asm/unaligned.h> 35#include <asm/unaligned.h>
@@ -50,7 +49,10 @@
50/* Highest firmware API version supported */ 49/* Highest firmware API version supported */
51#define IWL6000_UCODE_API_MAX 4 50#define IWL6000_UCODE_API_MAX 4
52#define IWL6050_UCODE_API_MAX 5 51#define IWL6050_UCODE_API_MAX 5
53#define IWL6000G2_UCODE_API_MAX 5 52#define IWL6000G2_UCODE_API_MAX 6
53
54/* Oldest version we won't warn about */
55#define IWL6000G2_UCODE_API_OK 5
54 56
55/* Lowest firmware API version supported */ 57/* Lowest firmware API version supported */
56#define IWL6000_UCODE_API_MIN 4 58#define IWL6000_UCODE_API_MIN 4
@@ -111,7 +113,7 @@ static void iwl6000_nic_config(struct iwl_priv *priv)
111} 113}
112 114
113static struct iwl_sensitivity_ranges iwl6000_sensitivity = { 115static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
114 .min_nrg_cck = 97, 116 .min_nrg_cck = 110,
115 .max_nrg_cck = 0, /* not used, set to 0 */ 117 .max_nrg_cck = 0, /* not used, set to 0 */
116 .auto_corr_min_ofdm = 80, 118 .auto_corr_min_ofdm = 80,
117 .auto_corr_min_ofdm_mrc = 128, 119 .auto_corr_min_ofdm_mrc = 128,
@@ -127,11 +129,11 @@ static struct iwl_sensitivity_ranges iwl6000_sensitivity = {
127 .auto_corr_max_cck = 175, 129 .auto_corr_max_cck = 175,
128 .auto_corr_min_cck_mrc = 160, 130 .auto_corr_min_cck_mrc = 160,
129 .auto_corr_max_cck_mrc = 310, 131 .auto_corr_max_cck_mrc = 310,
130 .nrg_th_cck = 97, 132 .nrg_th_cck = 110,
131 .nrg_th_ofdm = 100, 133 .nrg_th_ofdm = 110,
132 134
133 .barker_corr_th_min = 190, 135 .barker_corr_th_min = 190,
134 .barker_corr_th_min_mrc = 390, 136 .barker_corr_th_min_mrc = 336,
135 .nrg_th_cca = 62, 137 .nrg_th_cca = 62,
136}; 138};
137 139
@@ -365,8 +367,9 @@ static struct iwl_bt_params iwl6000_bt_params = {
365}; 367};
366 368
367#define IWL_DEVICE_6005 \ 369#define IWL_DEVICE_6005 \
368 .fw_name_pre = IWL6005_FW_PRE, \ 370 .fw_name_pre = IWL6005_FW_PRE, \
369 .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ 371 .ucode_api_max = IWL6000G2_UCODE_API_MAX, \
372 .ucode_api_ok = IWL6000G2_UCODE_API_OK, \
370 .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ 373 .ucode_api_min = IWL6000G2_UCODE_API_MIN, \
371 .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \ 374 .eeprom_ver = EEPROM_6005_EEPROM_VERSION, \
372 .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \ 375 .eeprom_calib_ver = EEPROM_6005_TX_POWER_VERSION, \
@@ -393,8 +396,9 @@ struct iwl_cfg iwl6005_2bg_cfg = {
393}; 396};
394 397
395#define IWL_DEVICE_6030 \ 398#define IWL_DEVICE_6030 \
396 .fw_name_pre = IWL6030_FW_PRE, \ 399 .fw_name_pre = IWL6030_FW_PRE, \
397 .ucode_api_max = IWL6000G2_UCODE_API_MAX, \ 400 .ucode_api_max = IWL6000G2_UCODE_API_MAX, \
401 .ucode_api_ok = IWL6000G2_UCODE_API_OK, \
398 .ucode_api_min = IWL6000G2_UCODE_API_MIN, \ 402 .ucode_api_min = IWL6000G2_UCODE_API_MIN, \
399 .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \ 403 .eeprom_ver = EEPROM_6030_EEPROM_VERSION, \
400 .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \ 404 .eeprom_calib_ver = EEPROM_6030_TX_POWER_VERSION, \
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
index 72d6297602b8..1789e3af8101 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-calib.c
@@ -505,28 +505,53 @@ static int iwl_enhance_sensitivity_write(struct iwl_priv *priv)
505 505
506 iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]); 506 iwl_prepare_legacy_sensitivity_tbl(priv, data, &cmd.enhance_table[0]);
507 507
508 cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] = 508 if (priv->cfg->base_params->hd_v2) {
509 HD_INA_NON_SQUARE_DET_OFDM_DATA; 509 cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
510 cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] = 510 HD_INA_NON_SQUARE_DET_OFDM_DATA_V2;
511 HD_INA_NON_SQUARE_DET_CCK_DATA; 511 cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
512 cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] = 512 HD_INA_NON_SQUARE_DET_CCK_DATA_V2;
513 HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA; 513 cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] =
514 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] = 514 HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V2;
515 HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA; 515 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
516 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] = 516 HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V2;
517 HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA; 517 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
518 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] = 518 HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2;
519 HD_OFDM_NON_SQUARE_DET_SLOPE_DATA; 519 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] =
520 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] = 520 HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V2;
521 HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA; 521 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] =
522 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] = 522 HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V2;
523 HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA; 523 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
524 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] = 524 HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V2;
525 HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA; 525 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
526 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] = 526 HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2;
527 HD_CCK_NON_SQUARE_DET_SLOPE_DATA; 527 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] =
528 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] = 528 HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V2;
529 HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA; 529 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] =
530 HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V2;
531 } else {
532 cmd.enhance_table[HD_INA_NON_SQUARE_DET_OFDM_INDEX] =
533 HD_INA_NON_SQUARE_DET_OFDM_DATA_V1;
534 cmd.enhance_table[HD_INA_NON_SQUARE_DET_CCK_INDEX] =
535 HD_INA_NON_SQUARE_DET_CCK_DATA_V1;
536 cmd.enhance_table[HD_CORR_11_INSTEAD_OF_CORR_9_EN_INDEX] =
537 HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V1;
538 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
539 HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V1;
540 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
541 HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1;
542 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_SLOPE_INDEX] =
543 HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V1;
544 cmd.enhance_table[HD_OFDM_NON_SQUARE_DET_INTERCEPT_INDEX] =
545 HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V1;
546 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_MRC_INDEX] =
547 HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V1;
548 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_INDEX] =
549 HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1;
550 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_SLOPE_INDEX] =
551 HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V1;
552 cmd.enhance_table[HD_CCK_NON_SQUARE_DET_INTERCEPT_INDEX] =
553 HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V1;
554 }
530 555
531 /* Update uCode's "work" table, and copy it to DSP */ 556 /* Update uCode's "work" table, and copy it to DSP */
532 cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE; 557 cmd.control = SENSITIVITY_CMD_CONTROL_WORK_TABLE;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
index 0e5b842529c4..47c43042ba4f 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-hw.h
@@ -92,8 +92,8 @@
92 92
93#define IWLAGN_CMD_FIFO_NUM 7 93#define IWLAGN_CMD_FIFO_NUM 7
94#define IWLAGN_NUM_QUEUES 20 94#define IWLAGN_NUM_QUEUES 20
95#define IWLAGN_NUM_AMPDU_QUEUES 10 95#define IWLAGN_NUM_AMPDU_QUEUES 9
96#define IWLAGN_FIRST_AMPDU_QUEUE 10 96#define IWLAGN_FIRST_AMPDU_QUEUE 11
97 97
98/* Fixed (non-configurable) rx data from phy */ 98/* Fixed (non-configurable) rx data from phy */
99 99
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 3bee0f119bcd..4edb6cfc5488 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -753,18 +753,6 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
753 return added; 753 return added;
754} 754}
755 755
756static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
757{
758 struct sk_buff *skb = priv->offchan_tx_skb;
759
760 if (skb->len < maxlen)
761 maxlen = skb->len;
762
763 memcpy(data, skb->data, maxlen);
764
765 return maxlen;
766}
767
768int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) 756int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
769{ 757{
770 struct iwl_host_cmd cmd = { 758 struct iwl_host_cmd cmd = {
@@ -807,7 +795,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
807 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; 795 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
808 scan->quiet_time = IWL_ACTIVE_QUIET_TIME; 796 scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
809 797
810 if (priv->scan_type != IWL_SCAN_OFFCH_TX && 798 if (priv->scan_type != IWL_SCAN_ROC &&
811 iwl_is_any_associated(priv)) { 799 iwl_is_any_associated(priv)) {
812 u16 interval = 0; 800 u16 interval = 0;
813 u32 extra; 801 u32 extra;
@@ -816,7 +804,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
816 804
817 IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); 805 IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
818 switch (priv->scan_type) { 806 switch (priv->scan_type) {
819 case IWL_SCAN_OFFCH_TX: 807 case IWL_SCAN_ROC:
820 WARN_ON(1); 808 WARN_ON(1);
821 break; 809 break;
822 case IWL_SCAN_RADIO_RESET: 810 case IWL_SCAN_RADIO_RESET:
@@ -838,10 +826,11 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
838 scan->suspend_time = cpu_to_le32(scan_suspend_time); 826 scan->suspend_time = cpu_to_le32(scan_suspend_time);
839 IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", 827 IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
840 scan_suspend_time, interval); 828 scan_suspend_time, interval);
841 } else if (priv->scan_type == IWL_SCAN_OFFCH_TX) { 829 } else if (priv->scan_type == IWL_SCAN_ROC) {
842 scan->suspend_time = 0; 830 scan->suspend_time = 0;
843 scan->max_out_time = 831 scan->max_out_time = 0;
844 cpu_to_le32(1024 * priv->offchan_tx_timeout); 832 scan->quiet_time = 0;
833 scan->quiet_plcp_th = 0;
845 } 834 }
846 835
847 switch (priv->scan_type) { 836 switch (priv->scan_type) {
@@ -869,8 +858,8 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
869 } else 858 } else
870 IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); 859 IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
871 break; 860 break;
872 case IWL_SCAN_OFFCH_TX: 861 case IWL_SCAN_ROC:
873 IWL_DEBUG_SCAN(priv, "Start offchannel TX scan.\n"); 862 IWL_DEBUG_SCAN(priv, "Start ROC scan.\n");
874 break; 863 break;
875 } 864 }
876 865
@@ -988,19 +977,13 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
988 IWL_MAX_SCAN_SIZE - sizeof(*scan)); 977 IWL_MAX_SCAN_SIZE - sizeof(*scan));
989 break; 978 break;
990 case IWL_SCAN_RADIO_RESET: 979 case IWL_SCAN_RADIO_RESET:
980 case IWL_SCAN_ROC:
991 /* use bcast addr, will not be transmitted but must be valid */ 981 /* use bcast addr, will not be transmitted but must be valid */
992 cmd_len = iwl_fill_probe_req(priv, 982 cmd_len = iwl_fill_probe_req(priv,
993 (struct ieee80211_mgmt *)scan->data, 983 (struct ieee80211_mgmt *)scan->data,
994 iwl_bcast_addr, NULL, 0, 984 iwl_bcast_addr, NULL, 0,
995 IWL_MAX_SCAN_SIZE - sizeof(*scan)); 985 IWL_MAX_SCAN_SIZE - sizeof(*scan));
996 break; 986 break;
997 case IWL_SCAN_OFFCH_TX:
998 cmd_len = iwl_fill_offch_tx(priv, scan->data,
999 IWL_MAX_SCAN_SIZE
1000 - sizeof(*scan)
1001 - sizeof(struct iwl_scan_channel));
1002 scan->scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX;
1003 break;
1004 default: 987 default:
1005 BUG(); 988 BUG();
1006 } 989 }
@@ -1021,18 +1004,18 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1021 is_active, n_probes, 1004 is_active, n_probes,
1022 (void *)&scan->data[cmd_len]); 1005 (void *)&scan->data[cmd_len]);
1023 break; 1006 break;
1024 case IWL_SCAN_OFFCH_TX: { 1007 case IWL_SCAN_ROC: {
1025 struct iwl_scan_channel *scan_ch; 1008 struct iwl_scan_channel *scan_ch;
1026 1009
1027 scan->channel_count = 1; 1010 scan->channel_count = 1;
1028 1011
1029 scan_ch = (void *)&scan->data[cmd_len]; 1012 scan_ch = (void *)&scan->data[cmd_len];
1030 scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE; 1013 scan_ch->type = SCAN_CHANNEL_TYPE_PASSIVE;
1031 scan_ch->channel = 1014 scan_ch->channel =
1032 cpu_to_le16(priv->offchan_tx_chan->hw_value); 1015 cpu_to_le16(priv->hw_roc_channel->hw_value);
1033 scan_ch->active_dwell = 1016 scan_ch->active_dwell =
1034 cpu_to_le16(priv->offchan_tx_timeout); 1017 scan_ch->passive_dwell =
1035 scan_ch->passive_dwell = 0; 1018 cpu_to_le16(priv->hw_roc_duration);
1036 1019
1037 /* Set txpower levels to defaults */ 1020 /* Set txpower levels to defaults */
1038 scan_ch->dsp_atten = 110; 1021 scan_ch->dsp_atten = 110;
@@ -1041,7 +1024,7 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1041 * power level: 1024 * power level:
1042 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3; 1025 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
1043 */ 1026 */
1044 if (priv->offchan_tx_chan->band == IEEE80211_BAND_5GHZ) 1027 if (priv->hw_roc_channel->band == IEEE80211_BAND_5GHZ)
1045 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3; 1028 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
1046 else 1029 else
1047 scan_ch->tx_gain = ((1 << 5) | (5 << 3)); 1030 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
index 3789ff4bf53b..1fa438e20f0a 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c
@@ -27,7 +27,6 @@
27#include <linux/init.h> 27#include <linux/init.h>
28#include <linux/skbuff.h> 28#include <linux/skbuff.h>
29#include <linux/slab.h> 29#include <linux/slab.h>
30#include <linux/wireless.h>
31#include <net/mac80211.h> 30#include <net/mac80211.h>
32 31
33#include <linux/netdevice.h> 32#include <linux/netdevice.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
index d42ef1763a71..d562e9359d97 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-rxon.c
@@ -337,10 +337,10 @@ int iwlagn_set_pan_params(struct iwl_priv *priv)
337 cmd.slots[0].type = 0; /* BSS */ 337 cmd.slots[0].type = 0; /* BSS */
338 cmd.slots[1].type = 1; /* PAN */ 338 cmd.slots[1].type = 1; /* PAN */
339 339
340 if (priv->hw_roc_channel) { 340 if (priv->hw_roc_setup) {
341 /* both contexts must be used for this to happen */ 341 /* both contexts must be used for this to happen */
342 slot1 = priv->hw_roc_duration; 342 slot1 = IWL_MIN_SLOT_TIME;
343 slot0 = IWL_MIN_SLOT_TIME; 343 slot0 = 3000;
344 } else if (ctx_bss->vif && ctx_pan->vif) { 344 } else if (ctx_bss->vif && ctx_pan->vif) {
345 int bcnint = ctx_pan->beacon_int; 345 int bcnint = ctx_pan->beacon_int;
346 int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1; 346 int dtim = ctx_pan->vif->bss_conf.dtim_period ?: 1;
@@ -437,23 +437,6 @@ int iwlagn_commit_rxon(struct iwl_priv *priv, struct iwl_rxon_context *ctx)
437 /* always get timestamp with Rx frame */ 437 /* always get timestamp with Rx frame */
438 ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK; 438 ctx->staging.flags |= RXON_FLG_TSF2HOST_MSK;
439 439
440 if (ctx->ctxid == IWL_RXON_CTX_PAN && priv->hw_roc_channel) {
441 struct ieee80211_channel *chan = priv->hw_roc_channel;
442
443 iwl_set_rxon_channel(priv, chan, ctx);
444 iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
445 ctx->staging.filter_flags |=
446 RXON_FILTER_ASSOC_MSK |
447 RXON_FILTER_PROMISC_MSK |
448 RXON_FILTER_CTL2HOST_MSK;
449 ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
450 new_assoc = true;
451
452 if (memcmp(&ctx->staging, &ctx->active,
453 sizeof(ctx->staging)) == 0)
454 return 0;
455 }
456
457 /* 440 /*
458 * force CTS-to-self frames protection if RTS-CTS is not preferred 441 * force CTS-to-self frames protection if RTS-CTS is not preferred
459 * one aggregation protection method 442 * one aggregation protection method
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
index 53bb59ee719d..9bc26da62768 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-tx.c
@@ -128,11 +128,10 @@ static void iwlagn_tx_cmd_protection(struct iwl_priv *priv,
128 * handle build REPLY_TX command notification. 128 * handle build REPLY_TX command notification.
129 */ 129 */
130static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv, 130static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
131 struct sk_buff *skb, 131 struct sk_buff *skb,
132 struct iwl_tx_cmd *tx_cmd, 132 struct iwl_tx_cmd *tx_cmd,
133 struct ieee80211_tx_info *info, 133 struct ieee80211_tx_info *info,
134 struct ieee80211_hdr *hdr, 134 struct ieee80211_hdr *hdr, u8 sta_id)
135 u8 std_id)
136{ 135{
137 __le16 fc = hdr->frame_control; 136 __le16 fc = hdr->frame_control;
138 __le32 tx_flags = tx_cmd->tx_flags; 137 __le32 tx_flags = tx_cmd->tx_flags;
@@ -157,7 +156,7 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
157 tx_flags |= TX_CMD_FLG_IGNORE_BT; 156 tx_flags |= TX_CMD_FLG_IGNORE_BT;
158 157
159 158
160 tx_cmd->sta_id = std_id; 159 tx_cmd->sta_id = sta_id;
161 if (ieee80211_has_morefrags(fc)) 160 if (ieee80211_has_morefrags(fc))
162 tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK; 161 tx_flags |= TX_CMD_FLG_MORE_FRAG_MSK;
163 162
@@ -189,9 +188,9 @@ static void iwlagn_tx_cmd_build_basic(struct iwl_priv *priv,
189#define RTS_DFAULT_RETRY_LIMIT 60 188#define RTS_DFAULT_RETRY_LIMIT 60
190 189
191static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv, 190static void iwlagn_tx_cmd_build_rate(struct iwl_priv *priv,
192 struct iwl_tx_cmd *tx_cmd, 191 struct iwl_tx_cmd *tx_cmd,
193 struct ieee80211_tx_info *info, 192 struct ieee80211_tx_info *info,
194 __le16 fc) 193 __le16 fc)
195{ 194{
196 u32 rate_flags; 195 u32 rate_flags;
197 int rate_idx; 196 int rate_idx;
@@ -334,14 +333,7 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
334 unsigned long flags; 333 unsigned long flags;
335 bool is_agg = false; 334 bool is_agg = false;
336 335
337 /* 336 if (info->control.vif)
338 * If the frame needs to go out off-channel, then
339 * we'll have put the PAN context to that channel,
340 * so make the frame go out there.
341 */
342 if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
343 ctx = &priv->contexts[IWL_RXON_CTX_PAN];
344 else if (info->control.vif)
345 ctx = iwl_rxon_ctx_from_vif(info->control.vif); 337 ctx = iwl_rxon_ctx_from_vif(info->control.vif);
346 338
347 spin_lock_irqsave(&priv->lock, flags); 339 spin_lock_irqsave(&priv->lock, flags);
@@ -407,7 +399,9 @@ int iwlagn_tx_skb(struct iwl_priv *priv, struct sk_buff *skb)
407 */ 399 */
408 hdr->frame_control |= 400 hdr->frame_control |=
409 cpu_to_le16(IEEE80211_FCTL_MOREDATA); 401 cpu_to_le16(IEEE80211_FCTL_MOREDATA);
410 } else 402 } else if (info->flags & IEEE80211_TX_CTL_TX_OFFCHAN)
403 txq_id = IWL_AUX_QUEUE;
404 else
411 txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)]; 405 txq_id = ctx->ac_to_queue[skb_get_queue_mapping(skb)];
412 406
413 /* irqs already disabled/saved above when locking priv->lock */ 407 /* irqs already disabled/saved above when locking priv->lock */
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index b0ae4de7f083..33894dde1ae3 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -35,7 +35,6 @@
35#include <linux/sched.h> 35#include <linux/sched.h>
36#include <linux/skbuff.h> 36#include <linux/skbuff.h>
37#include <linux/netdevice.h> 37#include <linux/netdevice.h>
38#include <linux/wireless.h>
39#include <linux/firmware.h> 38#include <linux/firmware.h>
40#include <linux/etherdevice.h> 39#include <linux/etherdevice.h>
41#include <linux/if_arp.h> 40#include <linux/if_arp.h>
@@ -614,6 +613,87 @@ static int iwl_alloc_fw_desc(struct iwl_priv *priv, struct fw_desc *desc,
614 return 0; 613 return 0;
615} 614}
616 615
616static void iwl_init_context(struct iwl_priv *priv, u32 ucode_flags)
617{
618 static const u8 iwlagn_bss_ac_to_fifo[] = {
619 IWL_TX_FIFO_VO,
620 IWL_TX_FIFO_VI,
621 IWL_TX_FIFO_BE,
622 IWL_TX_FIFO_BK,
623 };
624 static const u8 iwlagn_bss_ac_to_queue[] = {
625 0, 1, 2, 3,
626 };
627 static const u8 iwlagn_pan_ac_to_fifo[] = {
628 IWL_TX_FIFO_VO_IPAN,
629 IWL_TX_FIFO_VI_IPAN,
630 IWL_TX_FIFO_BE_IPAN,
631 IWL_TX_FIFO_BK_IPAN,
632 };
633 static const u8 iwlagn_pan_ac_to_queue[] = {
634 7, 6, 5, 4,
635 };
636 int i;
637
638 /*
639 * The default context is always valid,
640 * the PAN context depends on uCode.
641 */
642 priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
643 if (ucode_flags & IWL_UCODE_TLV_FLAGS_PAN)
644 priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
645
646 for (i = 0; i < NUM_IWL_RXON_CTX; i++)
647 priv->contexts[i].ctxid = i;
648
649 priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
650 priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
651 priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
652 priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
653 priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
654 priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
655 priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
656 priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
657 priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo;
658 priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue;
659 priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
660 BIT(NL80211_IFTYPE_ADHOC);
661 priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
662 BIT(NL80211_IFTYPE_STATION);
663 priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
664 priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
665 priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
666 priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
667
668 priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
669 priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
670 REPLY_WIPAN_RXON_TIMING;
671 priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
672 REPLY_WIPAN_RXON_ASSOC;
673 priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
674 priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
675 priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
676 priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
677 priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
678 priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
679 priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
680 priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
681 priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
682 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
683
684 if (ucode_flags & IWL_UCODE_TLV_FLAGS_P2P)
685 priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
686 BIT(NL80211_IFTYPE_P2P_CLIENT) |
687 BIT(NL80211_IFTYPE_P2P_GO);
688
689 priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
690 priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
691 priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
692
693 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
694}
695
696
617struct iwlagn_ucode_capabilities { 697struct iwlagn_ucode_capabilities {
618 u32 max_probe_length; 698 u32 max_probe_length;
619 u32 standard_phy_calibration_size; 699 u32 standard_phy_calibration_size;
@@ -952,6 +1032,7 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
952 int err; 1032 int err;
953 struct iwlagn_firmware_pieces pieces; 1033 struct iwlagn_firmware_pieces pieces;
954 const unsigned int api_max = priv->cfg->ucode_api_max; 1034 const unsigned int api_max = priv->cfg->ucode_api_max;
1035 unsigned int api_ok = priv->cfg->ucode_api_ok;
955 const unsigned int api_min = priv->cfg->ucode_api_min; 1036 const unsigned int api_min = priv->cfg->ucode_api_min;
956 u32 api_ver; 1037 u32 api_ver;
957 char buildstr[25]; 1038 char buildstr[25];
@@ -962,10 +1043,13 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
962 IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE, 1043 IWL_DEFAULT_STANDARD_PHY_CALIBRATE_TBL_SIZE,
963 }; 1044 };
964 1045
1046 if (!api_ok)
1047 api_ok = api_max;
1048
965 memset(&pieces, 0, sizeof(pieces)); 1049 memset(&pieces, 0, sizeof(pieces));
966 1050
967 if (!ucode_raw) { 1051 if (!ucode_raw) {
968 if (priv->fw_index <= priv->cfg->ucode_api_max) 1052 if (priv->fw_index <= api_ok)
969 IWL_ERR(priv, 1053 IWL_ERR(priv,
970 "request for firmware file '%s' failed.\n", 1054 "request for firmware file '%s' failed.\n",
971 priv->firmware_name); 1055 priv->firmware_name);
@@ -1011,12 +1095,18 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1011 goto try_again; 1095 goto try_again;
1012 } 1096 }
1013 1097
1014 if (api_ver != api_max) 1098 if (api_ver < api_ok) {
1015 IWL_ERR(priv, 1099 if (api_ok != api_max)
1016 "Firmware has old API version. Expected v%u, " 1100 IWL_ERR(priv, "Firmware has old API version, "
1017 "got v%u. New firmware can be obtained " 1101 "expected v%u through v%u, got v%u.\n",
1018 "from http://www.intellinuxwireless.org.\n", 1102 api_ok, api_max, api_ver);
1019 api_max, api_ver); 1103 else
1104 IWL_ERR(priv, "Firmware has old API version, "
1105 "expected v%u, got v%u.\n",
1106 api_max, api_ver);
1107 IWL_ERR(priv, "New firmware can be obtained from "
1108 "http://www.intellinuxwireless.org/.\n");
1109 }
1020 } 1110 }
1021 1111
1022 if (build) 1112 if (build)
@@ -1143,17 +1233,23 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1143 priv->new_scan_threshold_behaviour = 1233 priv->new_scan_threshold_behaviour =
1144 !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN); 1234 !!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_NEWSCAN);
1145 1235
1146 if ((priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE) && 1236 if (!(priv->cfg->sku & EEPROM_SKU_CAP_IPAN_ENABLE))
1147 (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN)) { 1237 ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_PAN;
1148 priv->valid_contexts |= BIT(IWL_RXON_CTX_PAN);
1149 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
1150 } else
1151 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1152 1238
1153 if (priv->valid_contexts != BIT(IWL_RXON_CTX_BSS)) 1239 /*
1240 * if not PAN, then don't support P2P -- might be a uCode
1241 * packaging bug or due to the eeprom check above
1242 */
1243 if (!(ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN))
1244 ucode_capa.flags &= ~IWL_UCODE_TLV_FLAGS_P2P;
1245
1246 if (ucode_capa.flags & IWL_UCODE_TLV_FLAGS_PAN) {
1247 priv->sta_key_max_num = STA_KEY_MAX_NUM_PAN;
1154 priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM; 1248 priv->cmd_queue = IWL_IPAN_CMD_QUEUE_NUM;
1155 else 1249 } else {
1250 priv->sta_key_max_num = STA_KEY_MAX_NUM;
1156 priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM; 1251 priv->cmd_queue = IWL_DEFAULT_CMD_QUEUE_NUM;
1252 }
1157 1253
1158 /* 1254 /*
1159 * figure out the offset of chain noise reset and gain commands 1255 * figure out the offset of chain noise reset and gain commands
@@ -1169,6 +1265,9 @@ static void iwl_ucode_callback(const struct firmware *ucode_raw, void *context)
1169 priv->phy_calib_chain_noise_gain_cmd = 1265 priv->phy_calib_chain_noise_gain_cmd =
1170 ucode_capa.standard_phy_calibration_size + 1; 1266 ucode_capa.standard_phy_calibration_size + 1;
1171 1267
1268 /* initialize all valid contexts */
1269 iwl_init_context(priv, ucode_capa.flags);
1270
1172 /************************************************** 1271 /**************************************************
1173 * This is still part of probe() in a sense... 1272 * This is still part of probe() in a sense...
1174 * 1273 *
@@ -1765,6 +1864,13 @@ static void __iwl_down(struct iwl_priv *priv)
1765 1864
1766 iwl_scan_cancel_timeout(priv, 200); 1865 iwl_scan_cancel_timeout(priv, 200);
1767 1866
1867 /*
1868 * If active, scanning won't cancel it, so say it expired.
1869 * No race since we hold the mutex here and a new one
1870 * can't come in at this time.
1871 */
1872 ieee80211_remain_on_channel_expired(priv->hw);
1873
1768 exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status); 1874 exit_pending = test_and_set_bit(STATUS_EXIT_PENDING, &priv->status);
1769 1875
1770 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set 1876 /* Stop TX queues watchdog. We need to have STATUS_EXIT_PENDING bit set
@@ -1955,94 +2061,6 @@ static void iwl_bg_restart(struct work_struct *data)
1955 } 2061 }
1956} 2062}
1957 2063
1958static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
1959 struct ieee80211_channel *chan,
1960 enum nl80211_channel_type channel_type,
1961 unsigned int wait)
1962{
1963 struct iwl_priv *priv = hw->priv;
1964 int ret;
1965
1966 /* Not supported if we don't have PAN */
1967 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) {
1968 ret = -EOPNOTSUPP;
1969 goto free;
1970 }
1971
1972 /* Not supported on pre-P2P firmware */
1973 if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
1974 BIT(NL80211_IFTYPE_P2P_CLIENT))) {
1975 ret = -EOPNOTSUPP;
1976 goto free;
1977 }
1978
1979 mutex_lock(&priv->mutex);
1980
1981 if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) {
1982 /*
1983 * If the PAN context is free, use the normal
1984 * way of doing remain-on-channel offload + TX.
1985 */
1986 ret = 1;
1987 goto out;
1988 }
1989
1990 /* TODO: queue up if scanning? */
1991 if (test_bit(STATUS_SCANNING, &priv->status) ||
1992 priv->offchan_tx_skb) {
1993 ret = -EBUSY;
1994 goto out;
1995 }
1996
1997 /*
1998 * max_scan_ie_len doesn't include the blank SSID or the header,
1999 * so need to add that again here.
2000 */
2001 if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) {
2002 ret = -ENOBUFS;
2003 goto out;
2004 }
2005
2006 priv->offchan_tx_skb = skb;
2007 priv->offchan_tx_timeout = wait;
2008 priv->offchan_tx_chan = chan;
2009
2010 ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
2011 IWL_SCAN_OFFCH_TX, chan->band);
2012 if (ret)
2013 priv->offchan_tx_skb = NULL;
2014 out:
2015 mutex_unlock(&priv->mutex);
2016 free:
2017 if (ret < 0)
2018 kfree_skb(skb);
2019
2020 return ret;
2021}
2022
2023static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
2024{
2025 struct iwl_priv *priv = hw->priv;
2026 int ret;
2027
2028 mutex_lock(&priv->mutex);
2029
2030 if (!priv->offchan_tx_skb) {
2031 ret = -EINVAL;
2032 goto unlock;
2033 }
2034
2035 priv->offchan_tx_skb = NULL;
2036
2037 ret = iwl_scan_cancel_timeout(priv, 200);
2038 if (ret)
2039 ret = -EIO;
2040unlock:
2041 mutex_unlock(&priv->mutex);
2042
2043 return ret;
2044}
2045
2046/***************************************************************************** 2064/*****************************************************************************
2047 * 2065 *
2048 * mac80211 entry point functions 2066 * mac80211 entry point functions
@@ -3198,35 +3216,34 @@ done:
3198 IWL_DEBUG_MAC80211(priv, "leave\n"); 3216 IWL_DEBUG_MAC80211(priv, "leave\n");
3199} 3217}
3200 3218
3201static void iwlagn_disable_roc(struct iwl_priv *priv) 3219void iwlagn_disable_roc(struct iwl_priv *priv)
3202{ 3220{
3203 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN]; 3221 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
3204 struct ieee80211_channel *chan = ACCESS_ONCE(priv->hw->conf.channel);
3205 3222
3206 lockdep_assert_held(&priv->mutex); 3223 lockdep_assert_held(&priv->mutex);
3207 3224
3208 if (!ctx->is_active) 3225 if (!priv->hw_roc_setup)
3209 return; 3226 return;
3210 3227
3211 ctx->staging.dev_type = RXON_DEV_TYPE_2STA; 3228 ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
3212 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK; 3229 ctx->staging.filter_flags &= ~RXON_FILTER_ASSOC_MSK;
3213 iwl_set_rxon_channel(priv, chan, ctx);
3214 iwl_set_flags_for_band(priv, ctx, chan->band, NULL);
3215 3230
3216 priv->hw_roc_channel = NULL; 3231 priv->hw_roc_channel = NULL;
3217 3232
3233 memset(ctx->staging.node_addr, 0, ETH_ALEN);
3234
3218 iwlagn_commit_rxon(priv, ctx); 3235 iwlagn_commit_rxon(priv, ctx);
3219 3236
3220 ctx->is_active = false; 3237 ctx->is_active = false;
3238 priv->hw_roc_setup = false;
3221} 3239}
3222 3240
3223static void iwlagn_bg_roc_done(struct work_struct *work) 3241static void iwlagn_disable_roc_work(struct work_struct *work)
3224{ 3242{
3225 struct iwl_priv *priv = container_of(work, struct iwl_priv, 3243 struct iwl_priv *priv = container_of(work, struct iwl_priv,
3226 hw_roc_work.work); 3244 hw_roc_disable_work.work);
3227 3245
3228 mutex_lock(&priv->mutex); 3246 mutex_lock(&priv->mutex);
3229 ieee80211_remain_on_channel_expired(priv->hw);
3230 iwlagn_disable_roc(priv); 3247 iwlagn_disable_roc(priv);
3231 mutex_unlock(&priv->mutex); 3248 mutex_unlock(&priv->mutex);
3232} 3249}
@@ -3237,33 +3254,63 @@ static int iwl_mac_remain_on_channel(struct ieee80211_hw *hw,
3237 int duration) 3254 int duration)
3238{ 3255{
3239 struct iwl_priv *priv = hw->priv; 3256 struct iwl_priv *priv = hw->priv;
3257 struct iwl_rxon_context *ctx = &priv->contexts[IWL_RXON_CTX_PAN];
3240 int err = 0; 3258 int err = 0;
3241 3259
3242 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) 3260 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
3243 return -EOPNOTSUPP; 3261 return -EOPNOTSUPP;
3244 3262
3245 if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes & 3263 if (!(ctx->interface_modes & BIT(NL80211_IFTYPE_P2P_CLIENT)))
3246 BIT(NL80211_IFTYPE_P2P_CLIENT)))
3247 return -EOPNOTSUPP; 3264 return -EOPNOTSUPP;
3248 3265
3249 mutex_lock(&priv->mutex); 3266 mutex_lock(&priv->mutex);
3250 3267
3251 if (priv->contexts[IWL_RXON_CTX_PAN].is_active || 3268 /*
3252 test_bit(STATUS_SCAN_HW, &priv->status)) { 3269 * TODO: Remove this hack! Firmware needs to be updated
3270 * to allow longer off-channel periods in scanning for
3271 * this use case, based on a flag (and we'll need an API
3272 * flag in the firmware when it has that).
3273 */
3274 if (iwl_is_associated(priv, IWL_RXON_CTX_BSS) && duration > 80)
3275 duration = 80;
3276
3277 if (test_bit(STATUS_SCAN_HW, &priv->status)) {
3253 err = -EBUSY; 3278 err = -EBUSY;
3254 goto out; 3279 goto out;
3255 } 3280 }
3256 3281
3257 priv->contexts[IWL_RXON_CTX_PAN].is_active = true;
3258 priv->hw_roc_channel = channel; 3282 priv->hw_roc_channel = channel;
3259 priv->hw_roc_chantype = channel_type; 3283 priv->hw_roc_chantype = channel_type;
3260 priv->hw_roc_duration = DIV_ROUND_UP(duration * 1000, 1024); 3284 priv->hw_roc_duration = duration;
3261 iwlagn_commit_rxon(priv, &priv->contexts[IWL_RXON_CTX_PAN]); 3285 cancel_delayed_work(&priv->hw_roc_disable_work);
3262 queue_delayed_work(priv->workqueue, &priv->hw_roc_work, 3286
3263 msecs_to_jiffies(duration + 20)); 3287 if (!ctx->is_active) {
3288 ctx->is_active = true;
3289 ctx->staging.dev_type = RXON_DEV_TYPE_P2P;
3290 memcpy(ctx->staging.node_addr,
3291 priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
3292 ETH_ALEN);
3293 memcpy(ctx->staging.bssid_addr,
3294 priv->contexts[IWL_RXON_CTX_BSS].staging.node_addr,
3295 ETH_ALEN);
3296 err = iwlagn_commit_rxon(priv, ctx);
3297 if (err)
3298 goto out;
3299 ctx->staging.filter_flags |= RXON_FILTER_ASSOC_MSK |
3300 RXON_FILTER_PROMISC_MSK |
3301 RXON_FILTER_CTL2HOST_MSK;
3302
3303 err = iwlagn_commit_rxon(priv, ctx);
3304 if (err) {
3305 iwlagn_disable_roc(priv);
3306 goto out;
3307 }
3308 priv->hw_roc_setup = true;
3309 }
3264 3310
3265 msleep(IWL_MIN_SLOT_TIME); /* TU is almost ms */ 3311 err = iwl_scan_initiate(priv, ctx->vif, IWL_SCAN_ROC, channel->band);
3266 ieee80211_ready_on_channel(priv->hw); 3312 if (err)
3313 iwlagn_disable_roc(priv);
3267 3314
3268 out: 3315 out:
3269 mutex_unlock(&priv->mutex); 3316 mutex_unlock(&priv->mutex);
@@ -3278,9 +3325,8 @@ static int iwl_mac_cancel_remain_on_channel(struct ieee80211_hw *hw)
3278 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) 3325 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN)))
3279 return -EOPNOTSUPP; 3326 return -EOPNOTSUPP;
3280 3327
3281 cancel_delayed_work_sync(&priv->hw_roc_work);
3282
3283 mutex_lock(&priv->mutex); 3328 mutex_lock(&priv->mutex);
3329 iwl_scan_cancel_timeout(priv, priv->hw_roc_duration);
3284 iwlagn_disable_roc(priv); 3330 iwlagn_disable_roc(priv);
3285 mutex_unlock(&priv->mutex); 3331 mutex_unlock(&priv->mutex);
3286 3332
@@ -3305,7 +3351,8 @@ static void iwl_setup_deferred_work(struct iwl_priv *priv)
3305 INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush); 3351 INIT_WORK(&priv->tx_flush, iwl_bg_tx_flush);
3306 INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency); 3352 INIT_WORK(&priv->bt_full_concurrency, iwl_bg_bt_full_concurrency);
3307 INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config); 3353 INIT_WORK(&priv->bt_runtime_config, iwl_bg_bt_runtime_config);
3308 INIT_DELAYED_WORK(&priv->hw_roc_work, iwlagn_bg_roc_done); 3354 INIT_DELAYED_WORK(&priv->hw_roc_disable_work,
3355 iwlagn_disable_roc_work);
3309 3356
3310 iwl_setup_scan_deferred_work(priv); 3357 iwl_setup_scan_deferred_work(priv);
3311 3358
@@ -3337,6 +3384,7 @@ static void iwl_cancel_deferred_work(struct iwl_priv *priv)
3337 3384
3338 cancel_work_sync(&priv->bt_full_concurrency); 3385 cancel_work_sync(&priv->bt_full_concurrency);
3339 cancel_work_sync(&priv->bt_runtime_config); 3386 cancel_work_sync(&priv->bt_runtime_config);
3387 cancel_delayed_work_sync(&priv->hw_roc_disable_work);
3340 3388
3341 del_timer_sync(&priv->statistics_periodic); 3389 del_timer_sync(&priv->statistics_periodic);
3342 del_timer_sync(&priv->ucode_trace); 3390 del_timer_sync(&priv->ucode_trace);
@@ -3489,8 +3537,6 @@ struct ieee80211_ops iwlagn_hw_ops = {
3489 .tx_last_beacon = iwl_mac_tx_last_beacon, 3537 .tx_last_beacon = iwl_mac_tx_last_beacon,
3490 .remain_on_channel = iwl_mac_remain_on_channel, 3538 .remain_on_channel = iwl_mac_remain_on_channel,
3491 .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, 3539 .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
3492 .offchannel_tx = iwl_mac_offchannel_tx,
3493 .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
3494 .rssi_callback = iwl_mac_rssi_callback, 3540 .rssi_callback = iwl_mac_rssi_callback,
3495 CFG80211_TESTMODE_CMD(iwl_testmode_cmd) 3541 CFG80211_TESTMODE_CMD(iwl_testmode_cmd)
3496 CFG80211_TESTMODE_DUMP(iwl_testmode_dump) 3542 CFG80211_TESTMODE_DUMP(iwl_testmode_dump)
@@ -3519,28 +3565,6 @@ static int iwl_set_hw_params(struct iwl_priv *priv)
3519 return priv->cfg->lib->set_hw_params(priv); 3565 return priv->cfg->lib->set_hw_params(priv);
3520} 3566}
3521 3567
3522static const u8 iwlagn_bss_ac_to_fifo[] = {
3523 IWL_TX_FIFO_VO,
3524 IWL_TX_FIFO_VI,
3525 IWL_TX_FIFO_BE,
3526 IWL_TX_FIFO_BK,
3527};
3528
3529static const u8 iwlagn_bss_ac_to_queue[] = {
3530 0, 1, 2, 3,
3531};
3532
3533static const u8 iwlagn_pan_ac_to_fifo[] = {
3534 IWL_TX_FIFO_VO_IPAN,
3535 IWL_TX_FIFO_VI_IPAN,
3536 IWL_TX_FIFO_BE_IPAN,
3537 IWL_TX_FIFO_BK_IPAN,
3538};
3539
3540static const u8 iwlagn_pan_ac_to_queue[] = {
3541 7, 6, 5, 4,
3542};
3543
3544/* This function both allocates and initializes hw and priv. */ 3568/* This function both allocates and initializes hw and priv. */
3545static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg) 3569static struct ieee80211_hw *iwl_alloc_all(struct iwl_cfg *cfg)
3546{ 3570{
@@ -3563,65 +3587,6 @@ out:
3563 return hw; 3587 return hw;
3564} 3588}
3565 3589
3566static void iwl_init_context(struct iwl_priv *priv)
3567{
3568 int i;
3569
3570 /*
3571 * The default context is always valid,
3572 * more may be discovered when firmware
3573 * is loaded.
3574 */
3575 priv->valid_contexts = BIT(IWL_RXON_CTX_BSS);
3576
3577 for (i = 0; i < NUM_IWL_RXON_CTX; i++)
3578 priv->contexts[i].ctxid = i;
3579
3580 priv->contexts[IWL_RXON_CTX_BSS].always_active = true;
3581 priv->contexts[IWL_RXON_CTX_BSS].is_active = true;
3582 priv->contexts[IWL_RXON_CTX_BSS].rxon_cmd = REPLY_RXON;
3583 priv->contexts[IWL_RXON_CTX_BSS].rxon_timing_cmd = REPLY_RXON_TIMING;
3584 priv->contexts[IWL_RXON_CTX_BSS].rxon_assoc_cmd = REPLY_RXON_ASSOC;
3585 priv->contexts[IWL_RXON_CTX_BSS].qos_cmd = REPLY_QOS_PARAM;
3586 priv->contexts[IWL_RXON_CTX_BSS].ap_sta_id = IWL_AP_ID;
3587 priv->contexts[IWL_RXON_CTX_BSS].wep_key_cmd = REPLY_WEPKEY;
3588 priv->contexts[IWL_RXON_CTX_BSS].ac_to_fifo = iwlagn_bss_ac_to_fifo;
3589 priv->contexts[IWL_RXON_CTX_BSS].ac_to_queue = iwlagn_bss_ac_to_queue;
3590 priv->contexts[IWL_RXON_CTX_BSS].exclusive_interface_modes =
3591 BIT(NL80211_IFTYPE_ADHOC);
3592 priv->contexts[IWL_RXON_CTX_BSS].interface_modes =
3593 BIT(NL80211_IFTYPE_STATION);
3594 priv->contexts[IWL_RXON_CTX_BSS].ap_devtype = RXON_DEV_TYPE_AP;
3595 priv->contexts[IWL_RXON_CTX_BSS].ibss_devtype = RXON_DEV_TYPE_IBSS;
3596 priv->contexts[IWL_RXON_CTX_BSS].station_devtype = RXON_DEV_TYPE_ESS;
3597 priv->contexts[IWL_RXON_CTX_BSS].unused_devtype = RXON_DEV_TYPE_ESS;
3598
3599 priv->contexts[IWL_RXON_CTX_PAN].rxon_cmd = REPLY_WIPAN_RXON;
3600 priv->contexts[IWL_RXON_CTX_PAN].rxon_timing_cmd =
3601 REPLY_WIPAN_RXON_TIMING;
3602 priv->contexts[IWL_RXON_CTX_PAN].rxon_assoc_cmd =
3603 REPLY_WIPAN_RXON_ASSOC;
3604 priv->contexts[IWL_RXON_CTX_PAN].qos_cmd = REPLY_WIPAN_QOS_PARAM;
3605 priv->contexts[IWL_RXON_CTX_PAN].ap_sta_id = IWL_AP_ID_PAN;
3606 priv->contexts[IWL_RXON_CTX_PAN].wep_key_cmd = REPLY_WIPAN_WEPKEY;
3607 priv->contexts[IWL_RXON_CTX_PAN].bcast_sta_id = IWLAGN_PAN_BCAST_ID;
3608 priv->contexts[IWL_RXON_CTX_PAN].station_flags = STA_FLG_PAN_STATION;
3609 priv->contexts[IWL_RXON_CTX_PAN].ac_to_fifo = iwlagn_pan_ac_to_fifo;
3610 priv->contexts[IWL_RXON_CTX_PAN].ac_to_queue = iwlagn_pan_ac_to_queue;
3611 priv->contexts[IWL_RXON_CTX_PAN].mcast_queue = IWL_IPAN_MCAST_QUEUE;
3612 priv->contexts[IWL_RXON_CTX_PAN].interface_modes =
3613 BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_AP);
3614#ifdef CONFIG_IWL_P2P
3615 priv->contexts[IWL_RXON_CTX_PAN].interface_modes |=
3616 BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO);
3617#endif
3618 priv->contexts[IWL_RXON_CTX_PAN].ap_devtype = RXON_DEV_TYPE_CP;
3619 priv->contexts[IWL_RXON_CTX_PAN].station_devtype = RXON_DEV_TYPE_2STA;
3620 priv->contexts[IWL_RXON_CTX_PAN].unused_devtype = RXON_DEV_TYPE_P2P;
3621
3622 BUILD_BUG_ON(NUM_IWL_RXON_CTX != 2);
3623}
3624
3625int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg) 3590int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
3626{ 3591{
3627 int err = 0; 3592 int err = 0;
@@ -3724,9 +3689,6 @@ int iwl_probe(struct iwl_bus *bus, struct iwl_cfg *cfg)
3724 priv->hw->wiphy->n_addresses++; 3689 priv->hw->wiphy->n_addresses++;
3725 } 3690 }
3726 3691
3727 /* initialize all valid contexts */
3728 iwl_init_context(priv);
3729
3730 /************************ 3692 /************************
3731 * 5. Setup HW constants 3693 * 5. Setup HW constants
3732 ************************/ 3694 ************************/
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.h b/drivers/net/wireless/iwlwifi/iwl-agn.h
index d941c4c98e4b..df2960ae92aa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.h
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.h
@@ -209,6 +209,7 @@ u8 iwl_toggle_tx_ant(struct iwl_priv *priv, u8 ant_idx, u8 valid);
209/* scan */ 209/* scan */
210int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif); 210int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif);
211void iwlagn_post_scan(struct iwl_priv *priv); 211void iwlagn_post_scan(struct iwl_priv *priv);
212void iwlagn_disable_roc(struct iwl_priv *priv);
212 213
213/* station mgmt */ 214/* station mgmt */
214int iwlagn_manage_ibss_station(struct iwl_priv *priv, 215int iwlagn_manage_ibss_station(struct iwl_priv *priv,
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index e9e9d1d1778d..0016c61b3000 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -3067,17 +3067,29 @@ struct iwl_missed_beacon_notif {
3067/* number of additional entries for enhanced tbl */ 3067/* number of additional entries for enhanced tbl */
3068#define ENHANCE_HD_TABLE_ENTRIES (ENHANCE_HD_TABLE_SIZE - HD_TABLE_SIZE) 3068#define ENHANCE_HD_TABLE_ENTRIES (ENHANCE_HD_TABLE_SIZE - HD_TABLE_SIZE)
3069 3069
3070#define HD_INA_NON_SQUARE_DET_OFDM_DATA cpu_to_le16(0) 3070#define HD_INA_NON_SQUARE_DET_OFDM_DATA_V1 cpu_to_le16(0)
3071#define HD_INA_NON_SQUARE_DET_CCK_DATA cpu_to_le16(0) 3071#define HD_INA_NON_SQUARE_DET_CCK_DATA_V1 cpu_to_le16(0)
3072#define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA cpu_to_le16(0) 3072#define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V1 cpu_to_le16(0)
3073#define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA cpu_to_le16(668) 3073#define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V1 cpu_to_le16(668)
3074#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA cpu_to_le16(4) 3074#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1 cpu_to_le16(4)
3075#define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA cpu_to_le16(486) 3075#define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V1 cpu_to_le16(486)
3076#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA cpu_to_le16(37) 3076#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V1 cpu_to_le16(37)
3077#define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA cpu_to_le16(853) 3077#define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V1 cpu_to_le16(853)
3078#define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA cpu_to_le16(4) 3078#define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V1 cpu_to_le16(4)
3079#define HD_CCK_NON_SQUARE_DET_SLOPE_DATA cpu_to_le16(476) 3079#define HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V1 cpu_to_le16(476)
3080#define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA cpu_to_le16(99) 3080#define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V1 cpu_to_le16(99)
3081
3082#define HD_INA_NON_SQUARE_DET_OFDM_DATA_V2 cpu_to_le16(1)
3083#define HD_INA_NON_SQUARE_DET_CCK_DATA_V2 cpu_to_le16(1)
3084#define HD_CORR_11_INSTEAD_OF_CORR_9_EN_DATA_V2 cpu_to_le16(1)
3085#define HD_OFDM_NON_SQUARE_DET_SLOPE_MRC_DATA_V2 cpu_to_le16(600)
3086#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2 cpu_to_le16(40)
3087#define HD_OFDM_NON_SQUARE_DET_SLOPE_DATA_V2 cpu_to_le16(486)
3088#define HD_OFDM_NON_SQUARE_DET_INTERCEPT_DATA_V2 cpu_to_le16(45)
3089#define HD_CCK_NON_SQUARE_DET_SLOPE_MRC_DATA_V2 cpu_to_le16(853)
3090#define HD_CCK_NON_SQUARE_DET_INTERCEPT_MRC_DATA_V2 cpu_to_le16(60)
3091#define HD_CCK_NON_SQUARE_DET_SLOPE_DATA_V2 cpu_to_le16(476)
3092#define HD_CCK_NON_SQUARE_DET_INTERCEPT_DATA_V2 cpu_to_le16(99)
3081 3093
3082 3094
3083/* Control field in struct iwl_sensitivity_cmd */ 3095/* Control field in struct iwl_sensitivity_cmd */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.c b/drivers/net/wireless/iwlwifi/iwl-core.c
index cf376f62b2f6..e269987cd64c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.c
+++ b/drivers/net/wireless/iwlwifi/iwl-core.c
@@ -40,6 +40,7 @@
40#include "iwl-io.h" 40#include "iwl-io.h"
41#include "iwl-power.h" 41#include "iwl-power.h"
42#include "iwl-sta.h" 42#include "iwl-sta.h"
43#include "iwl-agn.h"
43#include "iwl-helpers.h" 44#include "iwl-helpers.h"
44#include "iwl-agn.h" 45#include "iwl-agn.h"
45#include "iwl-trans.h" 46#include "iwl-trans.h"
@@ -1273,8 +1274,12 @@ int iwl_mac_add_interface(struct ieee80211_hw *hw, struct ieee80211_vif *vif)
1273 IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n", 1274 IWL_DEBUG_MAC80211(priv, "enter: type %d, addr %pM\n",
1274 viftype, vif->addr); 1275 viftype, vif->addr);
1275 1276
1277 cancel_delayed_work_sync(&priv->hw_roc_disable_work);
1278
1276 mutex_lock(&priv->mutex); 1279 mutex_lock(&priv->mutex);
1277 1280
1281 iwlagn_disable_roc(priv);
1282
1278 if (!iwl_is_ready_rf(priv)) { 1283 if (!iwl_is_ready_rf(priv)) {
1279 IWL_WARN(priv, "Try to add interface when device not ready\n"); 1284 IWL_WARN(priv, "Try to add interface when device not ready\n");
1280 err = -EINVAL; 1285 err = -EINVAL;
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index 02817a438550..42bcb469d32c 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -136,6 +136,7 @@ struct iwl_mod_params {
136 * @max_event_log_size: size of event log buffer size for ucode event logging 136 * @max_event_log_size: size of event log buffer size for ucode event logging
137 * @shadow_reg_enable: HW shadhow register bit 137 * @shadow_reg_enable: HW shadhow register bit
138 * @no_idle_support: do not support idle mode 138 * @no_idle_support: do not support idle mode
139 * @hd_v2: v2 of enhanced sensitivity value, used for 2000 series and up
139 */ 140 */
140struct iwl_base_params { 141struct iwl_base_params {
141 int eeprom_size; 142 int eeprom_size;
@@ -158,6 +159,7 @@ struct iwl_base_params {
158 u32 max_event_log_size; 159 u32 max_event_log_size;
159 const bool shadow_reg_enable; 160 const bool shadow_reg_enable;
160 const bool no_idle_support; 161 const bool no_idle_support;
162 const bool hd_v2;
161}; 163};
162/* 164/*
163 * @advanced_bt_coexist: support advanced bt coexist 165 * @advanced_bt_coexist: support advanced bt coexist
@@ -194,6 +196,8 @@ struct iwl_ht_params {
194 * (.ucode) will be added to filename before loading from disk. The 196 * (.ucode) will be added to filename before loading from disk. The
195 * filename is constructed as fw_name_pre<api>.ucode. 197 * filename is constructed as fw_name_pre<api>.ucode.
196 * @ucode_api_max: Highest version of uCode API supported by driver. 198 * @ucode_api_max: Highest version of uCode API supported by driver.
199 * @ucode_api_ok: oldest version of the uCode API that is OK to load
200 * without a warning, for use in transitions
197 * @ucode_api_min: Lowest version of uCode API supported by driver. 201 * @ucode_api_min: Lowest version of uCode API supported by driver.
198 * @valid_tx_ant: valid transmit antenna 202 * @valid_tx_ant: valid transmit antenna
199 * @valid_rx_ant: valid receive antenna 203 * @valid_rx_ant: valid receive antenna
@@ -237,6 +241,7 @@ struct iwl_cfg {
237 const char *name; 241 const char *name;
238 const char *fw_name_pre; 242 const char *fw_name_pre;
239 const unsigned int ucode_api_max; 243 const unsigned int ucode_api_max;
244 const unsigned int ucode_api_ok;
240 const unsigned int ucode_api_min; 245 const unsigned int ucode_api_min;
241 u8 valid_tx_ant; 246 u8 valid_tx_ant;
242 u8 valid_rx_ant; 247 u8 valid_rx_ant;
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6c9790cac8d0..dd34c7c502fa 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -230,12 +230,23 @@ struct iwl_channel_info {
230#define IWL_TX_FIFO_BE_IPAN 4 230#define IWL_TX_FIFO_BE_IPAN 4
231#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI 231#define IWL_TX_FIFO_VI_IPAN IWL_TX_FIFO_VI
232#define IWL_TX_FIFO_VO_IPAN 5 232#define IWL_TX_FIFO_VO_IPAN 5
233/* re-uses the VO FIFO, uCode will properly flush/schedule */
234#define IWL_TX_FIFO_AUX 5
233#define IWL_TX_FIFO_UNUSED -1 235#define IWL_TX_FIFO_UNUSED -1
234 236
235/* Minimum number of queues. MAX_NUM is defined in hw specific files. 237/* AUX (TX during scan dwell) queue */
236 * Set the minimum to accommodate the 4 standard TX queues, 1 command 238#define IWL_AUX_QUEUE 10
237 * queue, 2 (unused) HCCA queues, and 4 HT queues (one for each AC) */ 239
238#define IWL_MIN_NUM_QUEUES 10 240/*
241 * Minimum number of queues. MAX_NUM is defined in hw specific files.
242 * Set the minimum to accommodate
243 * - 4 standard TX queues
244 * - the command queue
245 * - 4 PAN TX queues
246 * - the PAN multicast queue, and
247 * - the AUX (TX during scan dwell) queue.
248 */
249#define IWL_MIN_NUM_QUEUES 11
239 250
240/* 251/*
241 * Command queue depends on iPAN support. 252 * Command queue depends on iPAN support.
@@ -564,11 +575,13 @@ enum iwl_ucode_tlv_type {
564 * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID, 575 * @IWL_UCODE_TLV_FLAGS_NEWSCAN: new uCode scan behaviour on hidden SSID,
565 * treats good CRC threshold as a boolean 576 * treats good CRC threshold as a boolean
566 * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w). 577 * @IWL_UCODE_TLV_FLAGS_MFP: This uCode image supports MFP (802.11w).
578 * @IWL_UCODE_TLV_FLAGS_P2P: This uCode image supports P2P.
567 */ 579 */
568enum iwl_ucode_tlv_flag { 580enum iwl_ucode_tlv_flag {
569 IWL_UCODE_TLV_FLAGS_PAN = BIT(0), 581 IWL_UCODE_TLV_FLAGS_PAN = BIT(0),
570 IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1), 582 IWL_UCODE_TLV_FLAGS_NEWSCAN = BIT(1),
571 IWL_UCODE_TLV_FLAGS_MFP = BIT(2), 583 IWL_UCODE_TLV_FLAGS_MFP = BIT(2),
584 IWL_UCODE_TLV_FLAGS_P2P = BIT(3),
572}; 585};
573 586
574struct iwl_ucode_tlv { 587struct iwl_ucode_tlv {
@@ -1168,7 +1181,7 @@ struct iwl_rxon_context {
1168enum iwl_scan_type { 1181enum iwl_scan_type {
1169 IWL_SCAN_NORMAL, 1182 IWL_SCAN_NORMAL,
1170 IWL_SCAN_RADIO_RESET, 1183 IWL_SCAN_RADIO_RESET,
1171 IWL_SCAN_OFFCH_TX, 1184 IWL_SCAN_ROC,
1172}; 1185};
1173 1186
1174enum iwlagn_ucode_type { 1187enum iwlagn_ucode_type {
@@ -1438,15 +1451,11 @@ struct iwl_priv {
1438 1451
1439 /* remain-on-channel offload support */ 1452 /* remain-on-channel offload support */
1440 struct ieee80211_channel *hw_roc_channel; 1453 struct ieee80211_channel *hw_roc_channel;
1441 struct delayed_work hw_roc_work; 1454 struct delayed_work hw_roc_disable_work;
1442 enum nl80211_channel_type hw_roc_chantype; 1455 enum nl80211_channel_type hw_roc_chantype;
1443 int hw_roc_duration; 1456 int hw_roc_duration;
1444 bool hw_roc_setup; 1457 bool hw_roc_setup;
1445 1458
1446 struct sk_buff *offchan_tx_skb;
1447 int offchan_tx_timeout;
1448 struct ieee80211_channel *offchan_tx_chan;
1449
1450 /* bt coex */ 1459 /* bt coex */
1451 u8 bt_enable_flag; 1460 u8 bt_enable_flag;
1452 u8 bt_status; 1461 u8 bt_status;
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c
index a67ae56d5464..1a5252d8ca73 100644
--- a/drivers/net/wireless/iwlwifi/iwl-led.c
+++ b/drivers/net/wireless/iwlwifi/iwl-led.c
@@ -31,7 +31,6 @@
31#include <linux/delay.h> 31#include <linux/delay.h>
32#include <linux/skbuff.h> 32#include <linux/skbuff.h>
33#include <linux/netdevice.h> 33#include <linux/netdevice.h>
34#include <linux/wireless.h>
35#include <net/mac80211.h> 34#include <net/mac80211.h>
36#include <linux/etherdevice.h> 35#include <linux/etherdevice.h>
37#include <asm/unaligned.h> 36#include <asm/unaligned.h>
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index dd6937e97055..28e59319f581 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -103,6 +103,12 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
103 ieee80211_scan_completed(priv->hw, aborted); 103 ieee80211_scan_completed(priv->hw, aborted);
104 } 104 }
105 105
106 if (priv->scan_type == IWL_SCAN_ROC) {
107 ieee80211_remain_on_channel_expired(priv->hw);
108 priv->hw_roc_channel = NULL;
109 schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
110 }
111
106 priv->scan_type = IWL_SCAN_NORMAL; 112 priv->scan_type = IWL_SCAN_NORMAL;
107 priv->scan_vif = NULL; 113 priv->scan_vif = NULL;
108 priv->scan_request = NULL; 114 priv->scan_request = NULL;
@@ -211,6 +217,9 @@ static void iwl_rx_scan_start_notif(struct iwl_priv *priv,
211 le32_to_cpu(notif->tsf_high), 217 le32_to_cpu(notif->tsf_high),
212 le32_to_cpu(notif->tsf_low), 218 le32_to_cpu(notif->tsf_low),
213 notif->status, notif->beacon_timer); 219 notif->status, notif->beacon_timer);
220
221 if (priv->scan_type == IWL_SCAN_ROC)
222 ieee80211_ready_on_channel(priv->hw);
214} 223}
215 224
216/* Service SCAN_RESULTS_NOTIFICATION (0x83) */ 225/* Service SCAN_RESULTS_NOTIFICATION (0x83) */
@@ -370,7 +379,7 @@ int __must_check iwl_scan_initiate(struct iwl_priv *priv,
370 379
371 IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", 380 IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
372 scan_type == IWL_SCAN_NORMAL ? "" : 381 scan_type == IWL_SCAN_NORMAL ? "" :
373 scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " : 382 scan_type == IWL_SCAN_ROC ? "remain-on-channel " :
374 "internal short "); 383 "internal short ");
375 384
376 set_bit(STATUS_SCANNING, &priv->status); 385 set_bit(STATUS_SCANNING, &priv->status);
@@ -565,10 +574,10 @@ static void iwl_bg_scan_completed(struct work_struct *work)
565 goto out_settings; 574 goto out_settings;
566 } 575 }
567 576
568 if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->offchan_tx_skb) { 577 if (priv->scan_type == IWL_SCAN_ROC) {
569 ieee80211_tx_status_irqsafe(priv->hw, 578 ieee80211_remain_on_channel_expired(priv->hw);
570 priv->offchan_tx_skb); 579 priv->hw_roc_channel = NULL;
571 priv->offchan_tx_skb = NULL; 580 schedule_delayed_work(&priv->hw_roc_disable_work, 10 * HZ);
572 } 581 }
573 582
574 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) { 583 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
diff --git a/drivers/net/wireless/iwlwifi/iwl-trans.c b/drivers/net/wireless/iwlwifi/iwl-trans.c
index 41f0de914008..3001bfb46e25 100644
--- a/drivers/net/wireless/iwlwifi/iwl-trans.c
+++ b/drivers/net/wireless/iwlwifi/iwl-trans.c
@@ -750,6 +750,7 @@ static const struct queue_to_fifo_ac iwlagn_default_queue_to_tx_fifo[] = {
750 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, 750 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
751 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, 751 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
752 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, }, 752 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
753 { IWL_TX_FIFO_UNUSED, IWL_AC_UNSET, },
753}; 754};
754 755
755static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = { 756static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
@@ -763,6 +764,7 @@ static const struct queue_to_fifo_ac iwlagn_ipan_queue_to_tx_fifo[] = {
763 { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, }, 764 { IWL_TX_FIFO_VO_IPAN, IEEE80211_AC_VO, },
764 { IWL_TX_FIFO_BE_IPAN, 2, }, 765 { IWL_TX_FIFO_BE_IPAN, 2, },
765 { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, }, 766 { IWLAGN_CMD_FIFO_NUM, IWL_AC_UNSET, },
767 { IWL_TX_FIFO_AUX, IWL_AC_UNSET, },
766}; 768};
767static void iwl_trans_tx_start(struct iwl_priv *priv) 769static void iwl_trans_tx_start(struct iwl_priv *priv)
768{ 770{
@@ -848,10 +850,12 @@ static void iwl_trans_tx_start(struct iwl_priv *priv)
848 /* reset to 0 to enable all the queue first */ 850 /* reset to 0 to enable all the queue first */
849 priv->txq_ctx_active_msk = 0; 851 priv->txq_ctx_active_msk = 0;
850 852
851 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) != 10); 853 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_default_queue_to_tx_fifo) !=
852 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) != 10); 854 IWLAGN_FIRST_AMPDU_QUEUE);
855 BUILD_BUG_ON(ARRAY_SIZE(iwlagn_ipan_queue_to_tx_fifo) !=
856 IWLAGN_FIRST_AMPDU_QUEUE);
853 857
854 for (i = 0; i < 10; i++) { 858 for (i = 0; i < IWLAGN_FIRST_AMPDU_QUEUE; i++) {
855 int fifo = queue_to_fifo[i].fifo; 859 int fifo = queue_to_fifo[i].fifo;
856 int ac = queue_to_fifo[i].ac; 860 int ac = queue_to_fifo[i].ac;
857 861
diff --git a/drivers/net/wireless/libertas/cfg.c b/drivers/net/wireless/libertas/cfg.c
index b456a53b64b1..85b3169c40d7 100644
--- a/drivers/net/wireless/libertas/cfg.c
+++ b/drivers/net/wireless/libertas/cfg.c
@@ -19,6 +19,7 @@
19#include "decl.h" 19#include "decl.h"
20#include "cfg.h" 20#include "cfg.h"
21#include "cmd.h" 21#include "cmd.h"
22#include "mesh.h"
22 23
23 24
24#define CHAN2G(_channel, _freq, _flags) { \ 25#define CHAN2G(_channel, _freq, _flags) { \
@@ -442,13 +443,16 @@ static int lbs_cfg_set_channel(struct wiphy *wiphy,
442 struct lbs_private *priv = wiphy_priv(wiphy); 443 struct lbs_private *priv = wiphy_priv(wiphy);
443 int ret = -ENOTSUPP; 444 int ret = -ENOTSUPP;
444 445
445 lbs_deb_enter_args(LBS_DEB_CFG80211, "freq %d, type %d", 446 lbs_deb_enter_args(LBS_DEB_CFG80211, "iface %s freq %d, type %d",
446 channel->center_freq, channel_type); 447 netdev_name(netdev), channel->center_freq, channel_type);
447 448
448 if (channel_type != NL80211_CHAN_NO_HT) 449 if (channel_type != NL80211_CHAN_NO_HT)
449 goto out; 450 goto out;
450 451
451 ret = lbs_set_channel(priv, channel->hw_value); 452 if (netdev == priv->mesh_dev)
453 ret = lbs_mesh_set_channel(priv, channel->hw_value);
454 else
455 ret = lbs_set_channel(priv, channel->hw_value);
452 456
453 out: 457 out:
454 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret); 458 lbs_deb_leave_args(LBS_DEB_CFG80211, "ret %d", ret);
@@ -708,7 +712,7 @@ static void lbs_scan_worker(struct work_struct *work)
708 712
709 if (priv->scan_channel < priv->scan_req->n_channels) { 713 if (priv->scan_channel < priv->scan_req->n_channels) {
710 cancel_delayed_work(&priv->scan_work); 714 cancel_delayed_work(&priv->scan_work);
711 if (!priv->stopping) 715 if (netif_running(priv->dev))
712 queue_delayed_work(priv->work_thread, &priv->scan_work, 716 queue_delayed_work(priv->work_thread, &priv->scan_work,
713 msecs_to_jiffies(300)); 717 msecs_to_jiffies(300));
714 } 718 }
@@ -1292,6 +1296,9 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
1292 int ret = 0; 1296 int ret = 0;
1293 u8 preamble = RADIO_PREAMBLE_SHORT; 1297 u8 preamble = RADIO_PREAMBLE_SHORT;
1294 1298
1299 if (dev == priv->mesh_dev)
1300 return -EOPNOTSUPP;
1301
1295 lbs_deb_enter(LBS_DEB_CFG80211); 1302 lbs_deb_enter(LBS_DEB_CFG80211);
1296 1303
1297 if (!sme->bssid) { 1304 if (!sme->bssid) {
@@ -1402,28 +1409,23 @@ static int lbs_cfg_connect(struct wiphy *wiphy, struct net_device *dev,
1402 return ret; 1409 return ret;
1403} 1410}
1404 1411
1405static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev, 1412int lbs_disconnect(struct lbs_private *priv, u16 reason)
1406 u16 reason_code)
1407{ 1413{
1408 struct lbs_private *priv = wiphy_priv(wiphy);
1409 struct cmd_ds_802_11_deauthenticate cmd; 1414 struct cmd_ds_802_11_deauthenticate cmd;
1410 1415 int ret;
1411 lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
1412
1413 /* store for lbs_cfg_ret_disconnect() */
1414 priv->disassoc_reason = reason_code;
1415 1416
1416 memset(&cmd, 0, sizeof(cmd)); 1417 memset(&cmd, 0, sizeof(cmd));
1417 cmd.hdr.size = cpu_to_le16(sizeof(cmd)); 1418 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
1418 /* Mildly ugly to use a locally store my own BSSID ... */ 1419 /* Mildly ugly to use a locally store my own BSSID ... */
1419 memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN); 1420 memcpy(cmd.macaddr, &priv->assoc_bss, ETH_ALEN);
1420 cmd.reasoncode = cpu_to_le16(reason_code); 1421 cmd.reasoncode = cpu_to_le16(reason);
1421 1422
1422 if (lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd)) 1423 ret = lbs_cmd_with_response(priv, CMD_802_11_DEAUTHENTICATE, &cmd);
1423 return -EFAULT; 1424 if (ret)
1425 return ret;
1424 1426
1425 cfg80211_disconnected(priv->dev, 1427 cfg80211_disconnected(priv->dev,
1426 priv->disassoc_reason, 1428 reason,
1427 NULL, 0, 1429 NULL, 0,
1428 GFP_KERNEL); 1430 GFP_KERNEL);
1429 priv->connect_status = LBS_DISCONNECTED; 1431 priv->connect_status = LBS_DISCONNECTED;
@@ -1431,6 +1433,21 @@ static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
1431 return 0; 1433 return 0;
1432} 1434}
1433 1435
1436static int lbs_cfg_disconnect(struct wiphy *wiphy, struct net_device *dev,
1437 u16 reason_code)
1438{
1439 struct lbs_private *priv = wiphy_priv(wiphy);
1440
1441 if (dev == priv->mesh_dev)
1442 return -EOPNOTSUPP;
1443
1444 lbs_deb_enter_args(LBS_DEB_CFG80211, "reason_code %d", reason_code);
1445
1446 /* store for lbs_cfg_ret_disconnect() */
1447 priv->disassoc_reason = reason_code;
1448
1449 return lbs_disconnect(priv, reason_code);
1450}
1434 1451
1435static int lbs_cfg_set_default_key(struct wiphy *wiphy, 1452static int lbs_cfg_set_default_key(struct wiphy *wiphy,
1436 struct net_device *netdev, 1453 struct net_device *netdev,
@@ -1439,6 +1456,9 @@ static int lbs_cfg_set_default_key(struct wiphy *wiphy,
1439{ 1456{
1440 struct lbs_private *priv = wiphy_priv(wiphy); 1457 struct lbs_private *priv = wiphy_priv(wiphy);
1441 1458
1459 if (netdev == priv->mesh_dev)
1460 return -EOPNOTSUPP;
1461
1442 lbs_deb_enter(LBS_DEB_CFG80211); 1462 lbs_deb_enter(LBS_DEB_CFG80211);
1443 1463
1444 if (key_index != priv->wep_tx_key) { 1464 if (key_index != priv->wep_tx_key) {
@@ -1460,6 +1480,9 @@ static int lbs_cfg_add_key(struct wiphy *wiphy, struct net_device *netdev,
1460 u16 key_type; 1480 u16 key_type;
1461 int ret = 0; 1481 int ret = 0;
1462 1482
1483 if (netdev == priv->mesh_dev)
1484 return -EOPNOTSUPP;
1485
1463 lbs_deb_enter(LBS_DEB_CFG80211); 1486 lbs_deb_enter(LBS_DEB_CFG80211);
1464 1487
1465 lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n", 1488 lbs_deb_assoc("add_key: cipher 0x%x, mac_addr %pM\n",
@@ -1603,6 +1626,9 @@ static int lbs_get_survey(struct wiphy *wiphy, struct net_device *dev,
1603 s8 signal, noise; 1626 s8 signal, noise;
1604 int ret; 1627 int ret;
1605 1628
1629 if (dev == priv->mesh_dev)
1630 return -EOPNOTSUPP;
1631
1606 if (idx != 0) 1632 if (idx != 0)
1607 ret = -ENOENT; 1633 ret = -ENOENT;
1608 1634
@@ -1636,6 +1662,9 @@ static int lbs_change_intf(struct wiphy *wiphy, struct net_device *dev,
1636 struct lbs_private *priv = wiphy_priv(wiphy); 1662 struct lbs_private *priv = wiphy_priv(wiphy);
1637 int ret = 0; 1663 int ret = 0;
1638 1664
1665 if (dev == priv->mesh_dev)
1666 return -EOPNOTSUPP;
1667
1639 lbs_deb_enter(LBS_DEB_CFG80211); 1668 lbs_deb_enter(LBS_DEB_CFG80211);
1640 1669
1641 switch (type) { 1670 switch (type) {
@@ -1959,6 +1988,9 @@ static int lbs_join_ibss(struct wiphy *wiphy, struct net_device *dev,
1959 struct cfg80211_bss *bss; 1988 struct cfg80211_bss *bss;
1960 DECLARE_SSID_BUF(ssid_buf); 1989 DECLARE_SSID_BUF(ssid_buf);
1961 1990
1991 if (dev == priv->mesh_dev)
1992 return -EOPNOTSUPP;
1993
1962 lbs_deb_enter(LBS_DEB_CFG80211); 1994 lbs_deb_enter(LBS_DEB_CFG80211);
1963 1995
1964 if (!params->channel) { 1996 if (!params->channel) {
@@ -1995,6 +2027,9 @@ static int lbs_leave_ibss(struct wiphy *wiphy, struct net_device *dev)
1995 struct cmd_ds_802_11_ad_hoc_stop cmd; 2027 struct cmd_ds_802_11_ad_hoc_stop cmd;
1996 int ret = 0; 2028 int ret = 0;
1997 2029
2030 if (dev == priv->mesh_dev)
2031 return -EOPNOTSUPP;
2032
1998 lbs_deb_enter(LBS_DEB_CFG80211); 2033 lbs_deb_enter(LBS_DEB_CFG80211);
1999 2034
2000 memset(&cmd, 0, sizeof(cmd)); 2035 memset(&cmd, 0, sizeof(cmd));
@@ -2117,6 +2152,8 @@ int lbs_cfg_register(struct lbs_private *priv)
2117 BIT(NL80211_IFTYPE_ADHOC); 2152 BIT(NL80211_IFTYPE_ADHOC);
2118 if (lbs_rtap_supported(priv)) 2153 if (lbs_rtap_supported(priv))
2119 wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); 2154 wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
2155 if (lbs_mesh_activated(priv))
2156 wdev->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MESH_POINT);
2120 2157
2121 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz; 2158 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &lbs_band_2ghz;
2122 2159
diff --git a/drivers/net/wireless/libertas/cfg.h b/drivers/net/wireless/libertas/cfg.h
index 4f46bb744bee..a02ee151710e 100644
--- a/drivers/net/wireless/libertas/cfg.h
+++ b/drivers/net/wireless/libertas/cfg.h
@@ -17,5 +17,6 @@ void lbs_send_disconnect_notification(struct lbs_private *priv);
17void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); 17void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
18 18
19void lbs_scan_deinit(struct lbs_private *priv); 19void lbs_scan_deinit(struct lbs_private *priv);
20int lbs_disconnect(struct lbs_private *priv, u16 reason);
20 21
21#endif 22#endif
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index dbd24a4607ec..e08ab1de3d9d 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -1088,7 +1088,7 @@ void __lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
1088 if (!cmd->callback || cmd->callback == lbs_cmd_async_callback) 1088 if (!cmd->callback || cmd->callback == lbs_cmd_async_callback)
1089 __lbs_cleanup_and_insert_cmd(priv, cmd); 1089 __lbs_cleanup_and_insert_cmd(priv, cmd);
1090 priv->cur_cmd = NULL; 1090 priv->cur_cmd = NULL;
1091 wake_up_interruptible(&priv->waitq); 1091 wake_up(&priv->waitq);
1092} 1092}
1093 1093
1094void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd, 1094void lbs_complete_command(struct lbs_private *priv, struct cmd_ctrl_node *cmd,
@@ -1627,7 +1627,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
1627 lbs_deb_host("PREP_CMD: cmdnode is NULL\n"); 1627 lbs_deb_host("PREP_CMD: cmdnode is NULL\n");
1628 1628
1629 /* Wake up main thread to execute next command */ 1629 /* Wake up main thread to execute next command */
1630 wake_up_interruptible(&priv->waitq); 1630 wake_up(&priv->waitq);
1631 cmdnode = ERR_PTR(-ENOBUFS); 1631 cmdnode = ERR_PTR(-ENOBUFS);
1632 goto done; 1632 goto done;
1633 } 1633 }
@@ -1647,7 +1647,7 @@ struct cmd_ctrl_node *__lbs_cmd_async(struct lbs_private *priv,
1647 1647
1648 cmdnode->cmdwaitqwoken = 0; 1648 cmdnode->cmdwaitqwoken = 0;
1649 lbs_queue_cmd(priv, cmdnode); 1649 lbs_queue_cmd(priv, cmdnode);
1650 wake_up_interruptible(&priv->waitq); 1650 wake_up(&priv->waitq);
1651 1651
1652 done: 1652 done:
1653 lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode); 1653 lbs_deb_leave_args(LBS_DEB_HOST, "ret %p", cmdnode);
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index da0b05bb89fe..9304e6fc421f 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -43,10 +43,14 @@ int lbs_start_card(struct lbs_private *priv);
43void lbs_stop_card(struct lbs_private *priv); 43void lbs_stop_card(struct lbs_private *priv);
44void lbs_host_to_card_done(struct lbs_private *priv); 44void lbs_host_to_card_done(struct lbs_private *priv);
45 45
46int lbs_start_iface(struct lbs_private *priv);
47int lbs_stop_iface(struct lbs_private *priv);
48
46int lbs_rtap_supported(struct lbs_private *priv); 49int lbs_rtap_supported(struct lbs_private *priv);
47 50
48int lbs_set_mac_address(struct net_device *dev, void *addr); 51int lbs_set_mac_address(struct net_device *dev, void *addr);
49void lbs_set_multicast_list(struct net_device *dev); 52void lbs_set_multicast_list(struct net_device *dev);
53void lbs_update_mcast(struct lbs_private *priv);
50 54
51int lbs_suspend(struct lbs_private *priv); 55int lbs_suspend(struct lbs_private *priv);
52int lbs_resume(struct lbs_private *priv); 56int lbs_resume(struct lbs_private *priv);
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index adb3490e3cf5..814838916b82 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -6,7 +6,6 @@
6#ifndef _LBS_DEV_H_ 6#ifndef _LBS_DEV_H_
7#define _LBS_DEV_H_ 7#define _LBS_DEV_H_
8 8
9#include "mesh.h"
10#include "defs.h" 9#include "defs.h"
11#include "host.h" 10#include "host.h"
12 11
@@ -22,6 +21,17 @@ struct sleep_params {
22 uint16_t sp_reserved; 21 uint16_t sp_reserved;
23}; 22};
24 23
24/* Mesh statistics */
25struct lbs_mesh_stats {
26 u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
27 u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
28 u32 fwd_drop_ttl; /* Fwd: TTL zero */
29 u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
30 u32 fwd_drop_noroute; /* Fwd: No route to Destination */
31 u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
32 u32 drop_blind; /* Rx: Dropped by blinding table */
33 u32 tx_failed_cnt; /* Tx: Failed transmissions */
34};
25 35
26/* Private structure for the MV device */ 36/* Private structure for the MV device */
27struct lbs_private { 37struct lbs_private {
@@ -36,7 +46,6 @@ struct lbs_private {
36 /* CFG80211 */ 46 /* CFG80211 */
37 struct wireless_dev *wdev; 47 struct wireless_dev *wdev;
38 bool wiphy_registered; 48 bool wiphy_registered;
39 bool stopping;
40 struct cfg80211_scan_request *scan_req; 49 struct cfg80211_scan_request *scan_req;
41 u8 assoc_bss[ETH_ALEN]; 50 u8 assoc_bss[ETH_ALEN];
42 u8 disassoc_reason; 51 u8 disassoc_reason;
@@ -86,11 +95,14 @@ struct lbs_private {
86 95
87 /* Hardware access */ 96 /* Hardware access */
88 void *card; 97 void *card;
98 bool iface_running;
89 u8 fw_ready; 99 u8 fw_ready;
90 u8 surpriseremoved; 100 u8 surpriseremoved;
91 u8 setup_fw_on_resume; 101 u8 setup_fw_on_resume;
92 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb); 102 int (*hw_host_to_card) (struct lbs_private *priv, u8 type, u8 *payload, u16 nb);
93 void (*reset_card) (struct lbs_private *priv); 103 void (*reset_card) (struct lbs_private *priv);
104 int (*power_save) (struct lbs_private *priv);
105 int (*power_restore) (struct lbs_private *priv);
94 int (*enter_deep_sleep) (struct lbs_private *priv); 106 int (*enter_deep_sleep) (struct lbs_private *priv);
95 int (*exit_deep_sleep) (struct lbs_private *priv); 107 int (*exit_deep_sleep) (struct lbs_private *priv);
96 int (*reset_deep_sleep_wakeup) (struct lbs_private *priv); 108 int (*reset_deep_sleep_wakeup) (struct lbs_private *priv);
@@ -172,4 +184,16 @@ struct lbs_private {
172 184
173extern struct cmd_confirm_sleep confirm_sleep; 185extern struct cmd_confirm_sleep confirm_sleep;
174 186
187/* Check if there is an interface active. */
188static inline int lbs_iface_active(struct lbs_private *priv)
189{
190 int r;
191
192 r = netif_running(priv->dev);
193 if (priv->mesh_dev);
194 r |= netif_running(priv->dev);
195
196 return r;
197}
198
175#endif 199#endif
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 4dfb3bfd2cf3..885ddc1c4fed 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -5,6 +5,7 @@
5 5
6#include "decl.h" 6#include "decl.h"
7#include "cmd.h" 7#include "cmd.h"
8#include "mesh.h"
8 9
9 10
10static void lbs_ethtool_get_drvinfo(struct net_device *dev, 11static void lbs_ethtool_get_drvinfo(struct net_device *dev,
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c
index 387786e1b394..c962e21762dc 100644
--- a/drivers/net/wireless/libertas/if_sdio.c
+++ b/drivers/net/wireless/libertas/if_sdio.c
@@ -39,6 +39,7 @@
39#include <linux/mmc/sdio_ids.h> 39#include <linux/mmc/sdio_ids.h>
40#include <linux/mmc/sdio.h> 40#include <linux/mmc/sdio.h>
41#include <linux/mmc/host.h> 41#include <linux/mmc/host.h>
42#include <linux/pm_runtime.h>
42 43
43#include "host.h" 44#include "host.h"
44#include "decl.h" 45#include "decl.h"
@@ -47,6 +48,8 @@
47#include "cmd.h" 48#include "cmd.h"
48#include "if_sdio.h" 49#include "if_sdio.h"
49 50
51static void if_sdio_interrupt(struct sdio_func *func);
52
50/* The if_sdio_remove() callback function is called when 53/* The if_sdio_remove() callback function is called when
51 * user removes this module from kernel space or ejects 54 * user removes this module from kernel space or ejects
52 * the card from the slot. The driver handles these 2 cases 55 * the card from the slot. The driver handles these 2 cases
@@ -757,6 +760,136 @@ out:
757 return ret; 760 return ret;
758} 761}
759 762
763/********************************************************************/
764/* Power management */
765/********************************************************************/
766
767static int if_sdio_power_on(struct if_sdio_card *card)
768{
769 struct sdio_func *func = card->func;
770 struct lbs_private *priv = card->priv;
771 struct mmc_host *host = func->card->host;
772 int ret;
773
774 sdio_claim_host(func);
775
776 ret = sdio_enable_func(func);
777 if (ret)
778 goto release;
779
780 /* For 1-bit transfers to the 8686 model, we need to enable the
781 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
782 * bit to allow access to non-vendor registers. */
783 if ((card->model == MODEL_8686) &&
784 (host->caps & MMC_CAP_SDIO_IRQ) &&
785 (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
786 u8 reg;
787
788 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
789 reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
790 if (ret)
791 goto disable;
792
793 reg |= SDIO_BUS_ECSI;
794 sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
795 if (ret)
796 goto disable;
797 }
798
799 card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
800 if (ret)
801 goto disable;
802
803 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
804 if (ret)
805 goto disable;
806
807 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
808 if (ret)
809 goto disable;
810
811 sdio_release_host(func);
812 ret = if_sdio_prog_firmware(card);
813 sdio_claim_host(func);
814 if (ret)
815 goto disable;
816
817 /*
818 * Get rx_unit if the chip is SD8688 or newer.
819 * SD8385 & SD8686 do not have rx_unit.
820 */
821 if ((card->model != MODEL_8385)
822 && (card->model != MODEL_8686))
823 card->rx_unit = if_sdio_read_rx_unit(card);
824 else
825 card->rx_unit = 0;
826
827 /*
828 * Set up the interrupt handler late.
829 *
830 * If we set it up earlier, the (buggy) hardware generates a spurious
831 * interrupt, even before the interrupt has been enabled, with
832 * CCCR_INTx = 0.
833 *
834 * We register the interrupt handler late so that we can handle any
835 * spurious interrupts, and also to avoid generation of that known
836 * spurious interrupt in the first place.
837 */
838 ret = sdio_claim_irq(func, if_sdio_interrupt);
839 if (ret)
840 goto disable;
841
842 /*
843 * Enable interrupts now that everything is set up
844 */
845 sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
846 if (ret)
847 goto release_irq;
848
849 sdio_release_host(func);
850
851 /*
852 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
853 */
854 if (card->model == MODEL_8688) {
855 struct cmd_header cmd;
856
857 memset(&cmd, 0, sizeof(cmd));
858
859 lbs_deb_sdio("send function INIT command\n");
860 if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
861 lbs_cmd_copyback, (unsigned long) &cmd))
862 netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
863 }
864
865 priv->fw_ready = 1;
866
867 return 0;
868
869release_irq:
870 sdio_release_irq(func);
871disable:
872 sdio_disable_func(func);
873release:
874 sdio_release_host(func);
875 return ret;
876}
877
878static int if_sdio_power_off(struct if_sdio_card *card)
879{
880 struct sdio_func *func = card->func;
881 struct lbs_private *priv = card->priv;
882
883 priv->fw_ready = 0;
884
885 sdio_claim_host(func);
886 sdio_release_irq(func);
887 sdio_disable_func(func);
888 sdio_release_host(func);
889 return 0;
890}
891
892
760/*******************************************************************/ 893/*******************************************************************/
761/* Libertas callbacks */ 894/* Libertas callbacks */
762/*******************************************************************/ 895/*******************************************************************/
@@ -923,6 +1056,32 @@ static void if_sdio_reset_card(struct lbs_private *priv)
923 schedule_work(&card_reset_work); 1056 schedule_work(&card_reset_work);
924} 1057}
925 1058
1059static int if_sdio_power_save(struct lbs_private *priv)
1060{
1061 struct if_sdio_card *card = priv->card;
1062 int ret;
1063
1064 flush_workqueue(card->workqueue);
1065
1066 ret = if_sdio_power_off(card);
1067
1068 /* Let runtime PM know the card is powered off */
1069 pm_runtime_put_sync(&card->func->dev);
1070
1071 return ret;
1072}
1073
1074static int if_sdio_power_restore(struct lbs_private *priv)
1075{
1076 struct if_sdio_card *card = priv->card;
1077
1078 /* Make sure the card will not be powered off by runtime PM */
1079 pm_runtime_get_sync(&card->func->dev);
1080
1081 return if_sdio_power_on(card);
1082}
1083
1084
926/*******************************************************************/ 1085/*******************************************************************/
927/* SDIO callbacks */ 1086/* SDIO callbacks */
928/*******************************************************************/ 1087/*******************************************************************/
@@ -976,7 +1135,6 @@ static int if_sdio_probe(struct sdio_func *func,
976 int ret, i; 1135 int ret, i;
977 unsigned int model; 1136 unsigned int model;
978 struct if_sdio_packet *packet; 1137 struct if_sdio_packet *packet;
979 struct mmc_host *host = func->card->host;
980 1138
981 lbs_deb_enter(LBS_DEB_SDIO); 1139 lbs_deb_enter(LBS_DEB_SDIO);
982 1140
@@ -1033,45 +1191,6 @@ static int if_sdio_probe(struct sdio_func *func,
1033 goto free; 1191 goto free;
1034 } 1192 }
1035 1193
1036 sdio_claim_host(func);
1037
1038 ret = sdio_enable_func(func);
1039 if (ret)
1040 goto release;
1041
1042 /* For 1-bit transfers to the 8686 model, we need to enable the
1043 * interrupt flag in the CCCR register. Set the MMC_QUIRK_LENIENT_FN0
1044 * bit to allow access to non-vendor registers. */
1045 if ((card->model == MODEL_8686) &&
1046 (host->caps & MMC_CAP_SDIO_IRQ) &&
1047 (host->ios.bus_width == MMC_BUS_WIDTH_1)) {
1048 u8 reg;
1049
1050 func->card->quirks |= MMC_QUIRK_LENIENT_FN0;
1051 reg = sdio_f0_readb(func, SDIO_CCCR_IF, &ret);
1052 if (ret)
1053 goto release_int;
1054
1055 reg |= SDIO_BUS_ECSI;
1056 sdio_f0_writeb(func, reg, SDIO_CCCR_IF, &ret);
1057 if (ret)
1058 goto release_int;
1059 }
1060
1061 card->ioport = sdio_readb(func, IF_SDIO_IOPORT, &ret);
1062 if (ret)
1063 goto release_int;
1064
1065 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 1, &ret) << 8;
1066 if (ret)
1067 goto release_int;
1068
1069 card->ioport |= sdio_readb(func, IF_SDIO_IOPORT + 2, &ret) << 16;
1070 if (ret)
1071 goto release_int;
1072
1073 sdio_release_host(func);
1074
1075 sdio_set_drvdata(func, card); 1194 sdio_set_drvdata(func, card);
1076 1195
1077 lbs_deb_sdio("class = 0x%X, vendor = 0x%X, " 1196 lbs_deb_sdio("class = 0x%X, vendor = 0x%X, "
@@ -1079,14 +1198,11 @@ static int if_sdio_probe(struct sdio_func *func,
1079 func->class, func->vendor, func->device, 1198 func->class, func->vendor, func->device,
1080 model, (unsigned)card->ioport); 1199 model, (unsigned)card->ioport);
1081 1200
1082 ret = if_sdio_prog_firmware(card);
1083 if (ret)
1084 goto reclaim;
1085 1201
1086 priv = lbs_add_card(card, &func->dev); 1202 priv = lbs_add_card(card, &func->dev);
1087 if (!priv) { 1203 if (!priv) {
1088 ret = -ENOMEM; 1204 ret = -ENOMEM;
1089 goto reclaim; 1205 goto free;
1090 } 1206 }
1091 1207
1092 card->priv = priv; 1208 card->priv = priv;
@@ -1097,62 +1213,21 @@ static int if_sdio_probe(struct sdio_func *func,
1097 priv->exit_deep_sleep = if_sdio_exit_deep_sleep; 1213 priv->exit_deep_sleep = if_sdio_exit_deep_sleep;
1098 priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup; 1214 priv->reset_deep_sleep_wakeup = if_sdio_reset_deep_sleep_wakeup;
1099 priv->reset_card = if_sdio_reset_card; 1215 priv->reset_card = if_sdio_reset_card;
1216 priv->power_save = if_sdio_power_save;
1217 priv->power_restore = if_sdio_power_restore;
1100 1218
1101 sdio_claim_host(func); 1219 ret = if_sdio_power_on(card);
1102
1103 /*
1104 * Get rx_unit if the chip is SD8688 or newer.
1105 * SD8385 & SD8686 do not have rx_unit.
1106 */
1107 if ((card->model != MODEL_8385)
1108 && (card->model != MODEL_8686))
1109 card->rx_unit = if_sdio_read_rx_unit(card);
1110 else
1111 card->rx_unit = 0;
1112
1113 /*
1114 * Set up the interrupt handler late.
1115 *
1116 * If we set it up earlier, the (buggy) hardware generates a spurious
1117 * interrupt, even before the interrupt has been enabled, with
1118 * CCCR_INTx = 0.
1119 *
1120 * We register the interrupt handler late so that we can handle any
1121 * spurious interrupts, and also to avoid generation of that known
1122 * spurious interrupt in the first place.
1123 */
1124 ret = sdio_claim_irq(func, if_sdio_interrupt);
1125 if (ret)
1126 goto disable;
1127
1128 /*
1129 * Enable interrupts now that everything is set up
1130 */
1131 sdio_writeb(func, 0x0f, IF_SDIO_H_INT_MASK, &ret);
1132 sdio_release_host(func);
1133 if (ret) 1220 if (ret)
1134 goto reclaim; 1221 goto err_activate_card;
1135
1136 priv->fw_ready = 1;
1137
1138 /*
1139 * FUNC_INIT is required for SD8688 WLAN/BT multiple functions
1140 */
1141 if (card->model == MODEL_8688) {
1142 struct cmd_header cmd;
1143
1144 memset(&cmd, 0, sizeof(cmd));
1145
1146 lbs_deb_sdio("send function INIT command\n");
1147 if (__lbs_cmd(priv, CMD_FUNC_INIT, &cmd, sizeof(cmd),
1148 lbs_cmd_copyback, (unsigned long) &cmd))
1149 netdev_alert(priv->dev, "CMD_FUNC_INIT cmd failed\n");
1150 }
1151 1222
1152 ret = lbs_start_card(priv); 1223 ret = lbs_start_card(priv);
1224 if_sdio_power_off(card);
1153 if (ret) 1225 if (ret)
1154 goto err_activate_card; 1226 goto err_activate_card;
1155 1227
1228 /* Tell PM core that we don't need the card to be powered now */
1229 pm_runtime_put_noidle(&func->dev);
1230
1156out: 1231out:
1157 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret); 1232 lbs_deb_leave_args(LBS_DEB_SDIO, "ret %d", ret);
1158 1233
@@ -1161,14 +1236,6 @@ out:
1161err_activate_card: 1236err_activate_card:
1162 flush_workqueue(card->workqueue); 1237 flush_workqueue(card->workqueue);
1163 lbs_remove_card(priv); 1238 lbs_remove_card(priv);
1164reclaim:
1165 sdio_claim_host(func);
1166release_int:
1167 sdio_release_irq(func);
1168disable:
1169 sdio_disable_func(func);
1170release:
1171 sdio_release_host(func);
1172free: 1239free:
1173 destroy_workqueue(card->workqueue); 1240 destroy_workqueue(card->workqueue);
1174 while (card->packets) { 1241 while (card->packets) {
@@ -1195,6 +1262,9 @@ static void if_sdio_remove(struct sdio_func *func)
1195 1262
1196 card = sdio_get_drvdata(func); 1263 card = sdio_get_drvdata(func);
1197 1264
1265 /* Undo decrement done above in if_sdio_probe */
1266 pm_runtime_get_noresume(&func->dev);
1267
1198 if (user_rmmod && (card->model == MODEL_8688)) { 1268 if (user_rmmod && (card->model == MODEL_8688)) {
1199 /* 1269 /*
1200 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT 1270 * FUNC_SHUTDOWN is required for SD8688 WLAN/BT
@@ -1219,11 +1289,6 @@ static void if_sdio_remove(struct sdio_func *func)
1219 flush_workqueue(card->workqueue); 1289 flush_workqueue(card->workqueue);
1220 destroy_workqueue(card->workqueue); 1290 destroy_workqueue(card->workqueue);
1221 1291
1222 sdio_claim_host(func);
1223 sdio_release_irq(func);
1224 sdio_disable_func(func);
1225 sdio_release_host(func);
1226
1227 while (card->packets) { 1292 while (card->packets) {
1228 packet = card->packets; 1293 packet = card->packets;
1229 card->packets = card->packets->next; 1294 card->packets = card->packets->next;
diff --git a/drivers/net/wireless/libertas/if_spi.c b/drivers/net/wireless/libertas/if_spi.c
index e0286cfbc91d..622ae6de0d8b 100644
--- a/drivers/net/wireless/libertas/if_spi.c
+++ b/drivers/net/wireless/libertas/if_spi.c
@@ -531,10 +531,6 @@ static int if_spi_prog_helper_firmware(struct if_spi_card *card,
531 goto out; 531 goto out;
532 err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG, 532 err = spu_write_u16(card, IF_SPI_CARD_INT_CAUSE_REG,
533 IF_SPI_CIC_CMD_DOWNLOAD_OVER); 533 IF_SPI_CIC_CMD_DOWNLOAD_OVER);
534 goto out;
535
536 lbs_deb_spi("waiting for helper to boot...\n");
537
538out: 534out:
539 if (err) 535 if (err)
540 pr_err("failed to load helper firmware (err=%d)\n", err); 536 pr_err("failed to load helper firmware (err=%d)\n", err);
diff --git a/drivers/net/wireless/libertas/if_usb.c b/drivers/net/wireless/libertas/if_usb.c
index b5acc393a65a..0c846f5a646a 100644
--- a/drivers/net/wireless/libertas/if_usb.c
+++ b/drivers/net/wireless/libertas/if_usb.c
@@ -324,7 +324,7 @@ static int if_usb_probe(struct usb_interface *intf,
324 } 324 }
325 kparam_unblock_sysfs_write(fw_name); 325 kparam_unblock_sysfs_write(fw_name);
326 326
327 if (!(priv = lbs_add_card(cardp, &udev->dev))) 327 if (!(priv = lbs_add_card(cardp, &intf->dev)))
328 goto err_prog_firmware; 328 goto err_prog_firmware;
329 329
330 cardp->priv = priv; 330 cardp->priv = priv;
@@ -956,7 +956,7 @@ static int if_usb_prog_firmware(struct if_usb_card *cardp,
956 priv->dnld_sent = DNLD_RES_RECEIVED; 956 priv->dnld_sent = DNLD_RES_RECEIVED;
957 spin_unlock_irqrestore(&priv->driver_lock, flags); 957 spin_unlock_irqrestore(&priv->driver_lock, flags);
958 958
959 wake_up_interruptible(&priv->waitq); 959 wake_up(&priv->waitq);
960 960
961 return ret; 961 return ret;
962} 962}
@@ -1112,6 +1112,15 @@ static int if_usb_suspend(struct usb_interface *intf, pm_message_t message)
1112 if (priv->psstate != PS_STATE_FULL_POWER) 1112 if (priv->psstate != PS_STATE_FULL_POWER)
1113 return -1; 1113 return -1;
1114 1114
1115#ifdef CONFIG_OLPC
1116 if (machine_is_olpc()) {
1117 if (priv->wol_criteria == EHS_REMOVE_WAKEUP)
1118 olpc_ec_wakeup_clear(EC_SCI_SRC_WLAN);
1119 else
1120 olpc_ec_wakeup_set(EC_SCI_SRC_WLAN);
1121 }
1122#endif
1123
1115 ret = lbs_suspend(priv); 1124 ret = lbs_suspend(priv);
1116 if (ret) 1125 if (ret)
1117 goto out; 1126 goto out;
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 2fdeb81ce5b2..d1c1d52931f1 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -23,6 +23,7 @@
23#include "cfg.h" 23#include "cfg.h"
24#include "debugfs.h" 24#include "debugfs.h"
25#include "cmd.h" 25#include "cmd.h"
26#include "mesh.h"
26 27
27#define DRIVER_RELEASE_VERSION "323.p0" 28#define DRIVER_RELEASE_VERSION "323.p0"
28const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION 29const char lbs_driver_version[] = "COMM-USB8388-" DRIVER_RELEASE_VERSION
@@ -98,6 +99,37 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
98 return 0; 99 return 0;
99} 100}
100 101
102int lbs_start_iface(struct lbs_private *priv)
103{
104 struct cmd_ds_802_11_mac_address cmd;
105 int ret;
106
107 if (priv->power_restore) {
108 ret = priv->power_restore(priv);
109 if (ret)
110 return ret;
111 }
112
113 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
114 cmd.action = cpu_to_le16(CMD_ACT_SET);
115 memcpy(cmd.macadd, priv->current_addr, ETH_ALEN);
116
117 ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
118 if (ret) {
119 lbs_deb_net("set MAC address failed\n");
120 goto err;
121 }
122
123 lbs_update_channel(priv);
124
125 priv->iface_running = true;
126 return 0;
127
128err:
129 if (priv->power_save)
130 priv->power_save(priv);
131 return ret;
132}
101 133
102/** 134/**
103 * lbs_dev_open - open the ethX interface 135 * lbs_dev_open - open the ethX interface
@@ -111,23 +143,64 @@ static int lbs_dev_open(struct net_device *dev)
111 int ret = 0; 143 int ret = 0;
112 144
113 lbs_deb_enter(LBS_DEB_NET); 145 lbs_deb_enter(LBS_DEB_NET);
146 if (!priv->iface_running) {
147 ret = lbs_start_iface(priv);
148 if (ret)
149 goto out;
150 }
114 151
115 spin_lock_irq(&priv->driver_lock); 152 spin_lock_irq(&priv->driver_lock);
116 priv->stopping = false;
117 153
118 if (priv->connect_status == LBS_CONNECTED) 154 netif_carrier_off(dev);
119 netif_carrier_on(dev);
120 else
121 netif_carrier_off(dev);
122 155
123 if (!priv->tx_pending_len) 156 if (!priv->tx_pending_len)
124 netif_wake_queue(dev); 157 netif_wake_queue(dev);
125 158
126 spin_unlock_irq(&priv->driver_lock); 159 spin_unlock_irq(&priv->driver_lock);
160
161out:
127 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); 162 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
128 return ret; 163 return ret;
129} 164}
130 165
166static bool lbs_command_queue_empty(struct lbs_private *priv)
167{
168 unsigned long flags;
169 bool ret;
170 spin_lock_irqsave(&priv->driver_lock, flags);
171 ret = priv->cur_cmd == NULL && list_empty(&priv->cmdpendingq);
172 spin_unlock_irqrestore(&priv->driver_lock, flags);
173 return ret;
174}
175
176int lbs_stop_iface(struct lbs_private *priv)
177{
178 unsigned long flags;
179 int ret = 0;
180
181 lbs_deb_enter(LBS_DEB_MAIN);
182
183 spin_lock_irqsave(&priv->driver_lock, flags);
184 priv->iface_running = false;
185 kfree_skb(priv->currenttxskb);
186 priv->currenttxskb = NULL;
187 priv->tx_pending_len = 0;
188 spin_unlock_irqrestore(&priv->driver_lock, flags);
189
190 cancel_work_sync(&priv->mcast_work);
191
192 /* Disable command processing, and wait for all commands to complete */
193 lbs_deb_main("waiting for commands to complete\n");
194 wait_event(priv->waitq, lbs_command_queue_empty(priv));
195 lbs_deb_main("all commands completed\n");
196
197 if (priv->power_save)
198 ret = priv->power_save(priv);
199
200 lbs_deb_leave(LBS_DEB_MAIN);
201 return ret;
202}
203
131/** 204/**
132 * lbs_eth_stop - close the ethX interface 205 * lbs_eth_stop - close the ethX interface
133 * 206 *
@@ -140,18 +213,25 @@ static int lbs_eth_stop(struct net_device *dev)
140 213
141 lbs_deb_enter(LBS_DEB_NET); 214 lbs_deb_enter(LBS_DEB_NET);
142 215
216 if (priv->connect_status == LBS_CONNECTED)
217 lbs_disconnect(priv, WLAN_REASON_DEAUTH_LEAVING);
218
143 spin_lock_irq(&priv->driver_lock); 219 spin_lock_irq(&priv->driver_lock);
144 priv->stopping = true;
145 netif_stop_queue(dev); 220 netif_stop_queue(dev);
146 spin_unlock_irq(&priv->driver_lock); 221 spin_unlock_irq(&priv->driver_lock);
147 222
148 schedule_work(&priv->mcast_work); 223 lbs_update_mcast(priv);
149 cancel_delayed_work_sync(&priv->scan_work); 224 cancel_delayed_work_sync(&priv->scan_work);
150 if (priv->scan_req) { 225 if (priv->scan_req) {
151 cfg80211_scan_done(priv->scan_req, false); 226 cfg80211_scan_done(priv->scan_req, false);
152 priv->scan_req = NULL; 227 priv->scan_req = NULL;
153 } 228 }
154 229
230 netif_carrier_off(priv->dev);
231
232 if (!lbs_iface_active(priv))
233 lbs_stop_iface(priv);
234
155 lbs_deb_leave(LBS_DEB_NET); 235 lbs_deb_leave(LBS_DEB_NET);
156 return 0; 236 return 0;
157} 237}
@@ -169,7 +249,7 @@ void lbs_host_to_card_done(struct lbs_private *priv)
169 /* Wake main thread if commands are pending */ 249 /* Wake main thread if commands are pending */
170 if (!priv->cur_cmd || priv->tx_pending_len > 0) { 250 if (!priv->cur_cmd || priv->tx_pending_len > 0) {
171 if (!priv->wakeup_dev_required) 251 if (!priv->wakeup_dev_required)
172 wake_up_interruptible(&priv->waitq); 252 wake_up(&priv->waitq);
173 } 253 }
174 254
175 spin_unlock_irqrestore(&priv->driver_lock, flags); 255 spin_unlock_irqrestore(&priv->driver_lock, flags);
@@ -182,29 +262,24 @@ int lbs_set_mac_address(struct net_device *dev, void *addr)
182 int ret = 0; 262 int ret = 0;
183 struct lbs_private *priv = dev->ml_priv; 263 struct lbs_private *priv = dev->ml_priv;
184 struct sockaddr *phwaddr = addr; 264 struct sockaddr *phwaddr = addr;
185 struct cmd_ds_802_11_mac_address cmd;
186 265
187 lbs_deb_enter(LBS_DEB_NET); 266 lbs_deb_enter(LBS_DEB_NET);
188 267
268 /*
269 * Can only set MAC address when all interfaces are down, to be written
270 * to the hardware when one of them is brought up.
271 */
272 if (lbs_iface_active(priv))
273 return -EBUSY;
274
189 /* In case it was called from the mesh device */ 275 /* In case it was called from the mesh device */
190 dev = priv->dev; 276 dev = priv->dev;
191 277
192 cmd.hdr.size = cpu_to_le16(sizeof(cmd));
193 cmd.action = cpu_to_le16(CMD_ACT_SET);
194 memcpy(cmd.macadd, phwaddr->sa_data, ETH_ALEN);
195
196 ret = lbs_cmd_with_response(priv, CMD_802_11_MAC_ADDRESS, &cmd);
197 if (ret) {
198 lbs_deb_net("set MAC address failed\n");
199 goto done;
200 }
201
202 memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN); 278 memcpy(priv->current_addr, phwaddr->sa_data, ETH_ALEN);
203 memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN); 279 memcpy(dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
204 if (priv->mesh_dev) 280 if (priv->mesh_dev)
205 memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN); 281 memcpy(priv->mesh_dev->dev_addr, phwaddr->sa_data, ETH_ALEN);
206 282
207done:
208 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); 283 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
209 return ret; 284 return ret;
210} 285}
@@ -258,18 +333,18 @@ static int lbs_add_mcast_addrs(struct cmd_ds_mac_multicast_adr *cmd,
258 return i; 333 return i;
259} 334}
260 335
261static void lbs_set_mcast_worker(struct work_struct *work) 336void lbs_update_mcast(struct lbs_private *priv)
262{ 337{
263 struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
264 struct cmd_ds_mac_multicast_adr mcast_cmd; 338 struct cmd_ds_mac_multicast_adr mcast_cmd;
265 int dev_flags; 339 int dev_flags = 0;
266 int nr_addrs; 340 int nr_addrs;
267 int old_mac_control = priv->mac_control; 341 int old_mac_control = priv->mac_control;
268 342
269 lbs_deb_enter(LBS_DEB_NET); 343 lbs_deb_enter(LBS_DEB_NET);
270 344
271 dev_flags = priv->dev->flags; 345 if (netif_running(priv->dev))
272 if (priv->mesh_dev) 346 dev_flags |= priv->dev->flags;
347 if (priv->mesh_dev && netif_running(priv->mesh_dev))
273 dev_flags |= priv->mesh_dev->flags; 348 dev_flags |= priv->mesh_dev->flags;
274 349
275 if (dev_flags & IFF_PROMISC) { 350 if (dev_flags & IFF_PROMISC) {
@@ -315,6 +390,12 @@ static void lbs_set_mcast_worker(struct work_struct *work)
315 lbs_deb_leave(LBS_DEB_NET); 390 lbs_deb_leave(LBS_DEB_NET);
316} 391}
317 392
393static void lbs_set_mcast_worker(struct work_struct *work)
394{
395 struct lbs_private *priv = container_of(work, struct lbs_private, mcast_work);
396 lbs_update_mcast(priv);
397}
398
318void lbs_set_multicast_list(struct net_device *dev) 399void lbs_set_multicast_list(struct net_device *dev)
319{ 400{
320 struct lbs_private *priv = dev->ml_priv; 401 struct lbs_private *priv = dev->ml_priv;
@@ -647,7 +728,7 @@ static void lbs_cmd_timeout_handler(unsigned long data)
647 if (priv->dnld_sent == DNLD_CMD_SENT) 728 if (priv->dnld_sent == DNLD_CMD_SENT)
648 priv->dnld_sent = DNLD_RES_RECEIVED; 729 priv->dnld_sent = DNLD_RES_RECEIVED;
649 730
650 wake_up_interruptible(&priv->waitq); 731 wake_up(&priv->waitq);
651out: 732out:
652 spin_unlock_irqrestore(&priv->driver_lock, flags); 733 spin_unlock_irqrestore(&priv->driver_lock, flags);
653 lbs_deb_leave(LBS_DEB_CMD); 734 lbs_deb_leave(LBS_DEB_CMD);
@@ -889,10 +970,6 @@ void lbs_remove_card(struct lbs_private *priv)
889 lbs_remove_mesh(priv); 970 lbs_remove_mesh(priv);
890 lbs_scan_deinit(priv); 971 lbs_scan_deinit(priv);
891 972
892 dev = priv->dev;
893
894 cancel_work_sync(&priv->mcast_work);
895
896 /* worker thread destruction blocks on the in-flight command which 973 /* worker thread destruction blocks on the in-flight command which
897 * should have been cleared already in lbs_stop_card(). 974 * should have been cleared already in lbs_stop_card().
898 */ 975 */
@@ -950,17 +1027,18 @@ int lbs_start_card(struct lbs_private *priv)
950 if (ret) 1027 if (ret)
951 goto done; 1028 goto done;
952 1029
1030 if (!lbs_disablemesh)
1031 lbs_init_mesh(priv);
1032 else
1033 pr_info("%s: mesh disabled\n", dev->name);
1034
953 if (lbs_cfg_register(priv)) { 1035 if (lbs_cfg_register(priv)) {
954 pr_err("cannot register device\n"); 1036 pr_err("cannot register device\n");
955 goto done; 1037 goto done;
956 } 1038 }
957 1039
958 lbs_update_channel(priv); 1040 if (lbs_mesh_activated(priv))
959 1041 lbs_start_mesh(priv);
960 if (!lbs_disablemesh)
961 lbs_init_mesh(priv);
962 else
963 pr_info("%s: mesh disabled\n", dev->name);
964 1042
965 lbs_debugfs_init_one(priv, dev); 1043 lbs_debugfs_init_one(priv, dev);
966 1044
@@ -978,8 +1056,6 @@ EXPORT_SYMBOL_GPL(lbs_start_card);
978void lbs_stop_card(struct lbs_private *priv) 1056void lbs_stop_card(struct lbs_private *priv)
979{ 1057{
980 struct net_device *dev; 1058 struct net_device *dev;
981 struct cmd_ctrl_node *cmdnode;
982 unsigned long flags;
983 1059
984 lbs_deb_enter(LBS_DEB_MAIN); 1060 lbs_deb_enter(LBS_DEB_MAIN);
985 1061
@@ -992,30 +1068,6 @@ void lbs_stop_card(struct lbs_private *priv)
992 1068
993 lbs_debugfs_remove_one(priv); 1069 lbs_debugfs_remove_one(priv);
994 lbs_deinit_mesh(priv); 1070 lbs_deinit_mesh(priv);
995
996 /* Delete the timeout of the currently processing command */
997 del_timer_sync(&priv->command_timer);
998 del_timer_sync(&priv->auto_deepsleep_timer);
999
1000 /* Flush pending command nodes */
1001 spin_lock_irqsave(&priv->driver_lock, flags);
1002 lbs_deb_main("clearing pending commands\n");
1003 list_for_each_entry(cmdnode, &priv->cmdpendingq, list) {
1004 cmdnode->result = -ENOENT;
1005 cmdnode->cmdwaitqwoken = 1;
1006 wake_up(&cmdnode->cmdwait_q);
1007 }
1008
1009 /* Flush the command the card is currently processing */
1010 if (priv->cur_cmd) {
1011 lbs_deb_main("clearing current command\n");
1012 priv->cur_cmd->result = -ENOENT;
1013 priv->cur_cmd->cmdwaitqwoken = 1;
1014 wake_up(&priv->cur_cmd->cmdwait_q);
1015 }
1016 lbs_deb_main("done clearing commands\n");
1017 spin_unlock_irqrestore(&priv->driver_lock, flags);
1018
1019 unregister_netdev(dev); 1071 unregister_netdev(dev);
1020 1072
1021out: 1073out:
@@ -1036,7 +1088,7 @@ void lbs_queue_event(struct lbs_private *priv, u32 event)
1036 1088
1037 kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32)); 1089 kfifo_in(&priv->event_fifo, (unsigned char *) &event, sizeof(u32));
1038 1090
1039 wake_up_interruptible(&priv->waitq); 1091 wake_up(&priv->waitq);
1040 1092
1041 spin_unlock_irqrestore(&priv->driver_lock, flags); 1093 spin_unlock_irqrestore(&priv->driver_lock, flags);
1042 lbs_deb_leave(LBS_DEB_THREAD); 1094 lbs_deb_leave(LBS_DEB_THREAD);
@@ -1054,7 +1106,7 @@ void lbs_notify_command_response(struct lbs_private *priv, u8 resp_idx)
1054 BUG_ON(resp_idx > 1); 1106 BUG_ON(resp_idx > 1);
1055 priv->resp_idx = resp_idx; 1107 priv->resp_idx = resp_idx;
1056 1108
1057 wake_up_interruptible(&priv->waitq); 1109 wake_up(&priv->waitq);
1058 1110
1059 lbs_deb_leave(LBS_DEB_THREAD); 1111 lbs_deb_leave(LBS_DEB_THREAD);
1060} 1112}
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index 8e3104d990fb..e87c031b298f 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -129,6 +129,19 @@ static int lbs_mesh_config(struct lbs_private *priv, uint16_t action,
129 return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv); 129 return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
130} 130}
131 131
132int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel)
133{
134 return lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, channel);
135}
136
137static uint16_t lbs_mesh_get_channel(struct lbs_private *priv)
138{
139 struct wireless_dev *mesh_wdev = priv->mesh_dev->ieee80211_ptr;
140 if (mesh_wdev->channel)
141 return mesh_wdev->channel->hw_value;
142 else
143 return 1;
144}
132 145
133/*************************************************************************** 146/***************************************************************************
134 * Mesh sysfs support 147 * Mesh sysfs support
@@ -812,7 +825,6 @@ static void lbs_persist_config_remove(struct net_device *dev)
812 */ 825 */
813int lbs_init_mesh(struct lbs_private *priv) 826int lbs_init_mesh(struct lbs_private *priv)
814{ 827{
815 struct net_device *dev = priv->dev;
816 int ret = 0; 828 int ret = 0;
817 829
818 lbs_deb_enter(LBS_DEB_MESH); 830 lbs_deb_enter(LBS_DEB_MESH);
@@ -837,11 +849,9 @@ int lbs_init_mesh(struct lbs_private *priv)
837 useful */ 849 useful */
838 850
839 priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID; 851 priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
840 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 852 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1)) {
841 priv->channel)) {
842 priv->mesh_tlv = TLV_TYPE_MESH_ID; 853 priv->mesh_tlv = TLV_TYPE_MESH_ID;
843 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 854 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
844 priv->channel))
845 priv->mesh_tlv = 0; 855 priv->mesh_tlv = 0;
846 } 856 }
847 } else 857 } else
@@ -851,23 +861,16 @@ int lbs_init_mesh(struct lbs_private *priv)
851 * 0x100+37; Do not invoke command with old TLV. 861 * 0x100+37; Do not invoke command with old TLV.
852 */ 862 */
853 priv->mesh_tlv = TLV_TYPE_MESH_ID; 863 priv->mesh_tlv = TLV_TYPE_MESH_ID;
854 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 864 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, 1))
855 priv->channel))
856 priv->mesh_tlv = 0; 865 priv->mesh_tlv = 0;
857 } 866 }
858 867
859 /* Stop meshing until interface is brought up */ 868 /* Stop meshing until interface is brought up */
860 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel); 869 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, 1);
861 870
862 if (priv->mesh_tlv) { 871 if (priv->mesh_tlv) {
863 sprintf(priv->mesh_ssid, "mesh"); 872 sprintf(priv->mesh_ssid, "mesh");
864 priv->mesh_ssid_len = 4; 873 priv->mesh_ssid_len = 4;
865
866 lbs_add_mesh(priv);
867
868 if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
869 netdev_err(dev, "cannot register lbs_mesh attribute\n");
870
871 ret = 1; 874 ret = 1;
872 } 875 }
873 876
@@ -875,6 +878,13 @@ int lbs_init_mesh(struct lbs_private *priv)
875 return ret; 878 return ret;
876} 879}
877 880
881void lbs_start_mesh(struct lbs_private *priv)
882{
883 lbs_add_mesh(priv);
884
885 if (device_create_file(&priv->dev->dev, &dev_attr_lbs_mesh))
886 netdev_err(priv->dev, "cannot register lbs_mesh attribute\n");
887}
878 888
879int lbs_deinit_mesh(struct lbs_private *priv) 889int lbs_deinit_mesh(struct lbs_private *priv)
880{ 890{
@@ -904,7 +914,8 @@ static int lbs_mesh_stop(struct net_device *dev)
904 struct lbs_private *priv = dev->ml_priv; 914 struct lbs_private *priv = dev->ml_priv;
905 915
906 lbs_deb_enter(LBS_DEB_MESH); 916 lbs_deb_enter(LBS_DEB_MESH);
907 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP, priv->channel); 917 lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_STOP,
918 lbs_mesh_get_channel(priv));
908 919
909 spin_lock_irq(&priv->driver_lock); 920 spin_lock_irq(&priv->driver_lock);
910 921
@@ -913,7 +924,9 @@ static int lbs_mesh_stop(struct net_device *dev)
913 924
914 spin_unlock_irq(&priv->driver_lock); 925 spin_unlock_irq(&priv->driver_lock);
915 926
916 schedule_work(&priv->mcast_work); 927 lbs_update_mcast(priv);
928 if (!lbs_iface_active(priv))
929 lbs_stop_iface(priv);
917 930
918 lbs_deb_leave(LBS_DEB_MESH); 931 lbs_deb_leave(LBS_DEB_MESH);
919 return 0; 932 return 0;
@@ -931,6 +944,11 @@ static int lbs_mesh_dev_open(struct net_device *dev)
931 int ret = 0; 944 int ret = 0;
932 945
933 lbs_deb_enter(LBS_DEB_NET); 946 lbs_deb_enter(LBS_DEB_NET);
947 if (!priv->iface_running) {
948 ret = lbs_start_iface(priv);
949 if (ret)
950 goto out;
951 }
934 952
935 spin_lock_irq(&priv->driver_lock); 953 spin_lock_irq(&priv->driver_lock);
936 954
@@ -947,7 +965,8 @@ static int lbs_mesh_dev_open(struct net_device *dev)
947 965
948 spin_unlock_irq(&priv->driver_lock); 966 spin_unlock_irq(&priv->driver_lock);
949 967
950 ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START, priv->channel); 968 ret = lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
969 lbs_mesh_get_channel(priv));
951 970
952out: 971out:
953 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret); 972 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
@@ -971,18 +990,32 @@ static const struct net_device_ops mesh_netdev_ops = {
971static int lbs_add_mesh(struct lbs_private *priv) 990static int lbs_add_mesh(struct lbs_private *priv)
972{ 991{
973 struct net_device *mesh_dev = NULL; 992 struct net_device *mesh_dev = NULL;
993 struct wireless_dev *mesh_wdev;
974 int ret = 0; 994 int ret = 0;
975 995
976 lbs_deb_enter(LBS_DEB_MESH); 996 lbs_deb_enter(LBS_DEB_MESH);
977 997
978 /* Allocate a virtual mesh device */ 998 /* Allocate a virtual mesh device */
999 mesh_wdev = kzalloc(sizeof(struct wireless_dev), GFP_KERNEL);
1000 if (!mesh_wdev) {
1001 lbs_deb_mesh("init mshX wireless device failed\n");
1002 ret = -ENOMEM;
1003 goto done;
1004 }
1005
979 mesh_dev = alloc_netdev(0, "msh%d", ether_setup); 1006 mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
980 if (!mesh_dev) { 1007 if (!mesh_dev) {
981 lbs_deb_mesh("init mshX device failed\n"); 1008 lbs_deb_mesh("init mshX device failed\n");
982 ret = -ENOMEM; 1009 ret = -ENOMEM;
983 goto done; 1010 goto err_free_wdev;
984 } 1011 }
1012
1013 mesh_wdev->iftype = NL80211_IFTYPE_MESH_POINT;
1014 mesh_wdev->wiphy = priv->wdev->wiphy;
1015 mesh_wdev->netdev = mesh_dev;
1016
985 mesh_dev->ml_priv = priv; 1017 mesh_dev->ml_priv = priv;
1018 mesh_dev->ieee80211_ptr = mesh_wdev;
986 priv->mesh_dev = mesh_dev; 1019 priv->mesh_dev = mesh_dev;
987 1020
988 mesh_dev->netdev_ops = &mesh_netdev_ops; 1021 mesh_dev->netdev_ops = &mesh_netdev_ops;
@@ -996,7 +1029,7 @@ static int lbs_add_mesh(struct lbs_private *priv)
996 ret = register_netdev(mesh_dev); 1029 ret = register_netdev(mesh_dev);
997 if (ret) { 1030 if (ret) {
998 pr_err("cannot register mshX virtual interface\n"); 1031 pr_err("cannot register mshX virtual interface\n");
999 goto err_free; 1032 goto err_free_netdev;
1000 } 1033 }
1001 1034
1002 ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group); 1035 ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
@@ -1012,9 +1045,12 @@ static int lbs_add_mesh(struct lbs_private *priv)
1012err_unregister: 1045err_unregister:
1013 unregister_netdev(mesh_dev); 1046 unregister_netdev(mesh_dev);
1014 1047
1015err_free: 1048err_free_netdev:
1016 free_netdev(mesh_dev); 1049 free_netdev(mesh_dev);
1017 1050
1051err_free_wdev:
1052 kfree(mesh_wdev);
1053
1018done: 1054done:
1019 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret); 1055 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
1020 return ret; 1056 return ret;
@@ -1035,6 +1071,7 @@ void lbs_remove_mesh(struct lbs_private *priv)
1035 lbs_persist_config_remove(mesh_dev); 1071 lbs_persist_config_remove(mesh_dev);
1036 unregister_netdev(mesh_dev); 1072 unregister_netdev(mesh_dev);
1037 priv->mesh_dev = NULL; 1073 priv->mesh_dev = NULL;
1074 kfree(mesh_dev->ieee80211_ptr);
1038 free_netdev(mesh_dev); 1075 free_netdev(mesh_dev);
1039 lbs_deb_leave(LBS_DEB_MESH); 1076 lbs_deb_leave(LBS_DEB_MESH);
1040} 1077}
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
index 50144913f2ab..6603f341c874 100644
--- a/drivers/net/wireless/libertas/mesh.h
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -9,30 +9,25 @@
9#include <net/lib80211.h> 9#include <net/lib80211.h>
10 10
11#include "host.h" 11#include "host.h"
12#include "dev.h"
12 13
13#ifdef CONFIG_LIBERTAS_MESH 14#ifdef CONFIG_LIBERTAS_MESH
14 15
15/* Mesh statistics */
16struct lbs_mesh_stats {
17 u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
18 u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
19 u32 fwd_drop_ttl; /* Fwd: TTL zero */
20 u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
21 u32 fwd_drop_noroute; /* Fwd: No route to Destination */
22 u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
23 u32 drop_blind; /* Rx: Dropped by blinding table */
24 u32 tx_failed_cnt; /* Tx: Failed transmissions */
25};
26
27
28struct net_device; 16struct net_device;
29struct lbs_private;
30 17
31int lbs_init_mesh(struct lbs_private *priv); 18int lbs_init_mesh(struct lbs_private *priv);
19void lbs_start_mesh(struct lbs_private *priv);
32int lbs_deinit_mesh(struct lbs_private *priv); 20int lbs_deinit_mesh(struct lbs_private *priv);
33 21
34void lbs_remove_mesh(struct lbs_private *priv); 22void lbs_remove_mesh(struct lbs_private *priv);
35 23
24static inline bool lbs_mesh_activated(struct lbs_private *priv)
25{
26 /* Mesh SSID is only programmed after successful init */
27 return priv->mesh_ssid_len != 0;
28}
29
30int lbs_mesh_set_channel(struct lbs_private *priv, u8 channel);
36 31
37/* Sending / Receiving */ 32/* Sending / Receiving */
38 33
@@ -67,11 +62,13 @@ void lbs_mesh_ethtool_get_strings(struct net_device *dev,
67 62
68#define lbs_init_mesh(priv) 63#define lbs_init_mesh(priv)
69#define lbs_deinit_mesh(priv) 64#define lbs_deinit_mesh(priv)
65#define lbs_start_mesh(priv)
70#define lbs_add_mesh(priv) 66#define lbs_add_mesh(priv)
71#define lbs_remove_mesh(priv) 67#define lbs_remove_mesh(priv)
72#define lbs_mesh_set_dev(priv, dev, rxpd) (dev) 68#define lbs_mesh_set_dev(priv, dev, rxpd) (dev)
73#define lbs_mesh_set_txpd(priv, dev, txpd) 69#define lbs_mesh_set_txpd(priv, dev, txpd)
74#define lbs_mesh_config(priv, enable, chan) 70#define lbs_mesh_set_channel(priv, channel) (0)
71#define lbs_mesh_activated(priv) (false)
75 72
76#endif 73#endif
77 74
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index bfb8898ae518..62e10eeadd7e 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -15,6 +15,7 @@
15#include "radiotap.h" 15#include "radiotap.h"
16#include "decl.h" 16#include "decl.h"
17#include "dev.h" 17#include "dev.h"
18#include "mesh.h"
18 19
19struct eth803hdr { 20struct eth803hdr {
20 u8 dest_addr[6]; 21 u8 dest_addr[6];
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index a6e85134cfe1..8f127520d786 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -12,6 +12,7 @@
12#include "decl.h" 12#include "decl.h"
13#include "defs.h" 13#include "defs.h"
14#include "dev.h" 14#include "dev.h"
15#include "mesh.h"
15 16
16/** 17/**
17 * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE 18 * convert_radiotap_rate_to_mv - converts Tx/Rx rates from IEEE80211_RADIOTAP_RATE
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c
index 031cd89b1768..34b79fc91e39 100644
--- a/drivers/net/wireless/mac80211_hwsim.c
+++ b/drivers/net/wireless/mac80211_hwsim.c
@@ -612,6 +612,12 @@ static bool mac80211_hwsim_tx_frame_no_nl(struct ieee80211_hw *hw,
612 rx_status.freq = data->channel->center_freq; 612 rx_status.freq = data->channel->center_freq;
613 rx_status.band = data->channel->band; 613 rx_status.band = data->channel->band;
614 rx_status.rate_idx = info->control.rates[0].idx; 614 rx_status.rate_idx = info->control.rates[0].idx;
615 if (info->control.rates[0].flags & IEEE80211_TX_RC_MCS)
616 rx_status.flag |= RX_FLAG_HT;
617 if (info->control.rates[0].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
618 rx_status.flag |= RX_FLAG_40MHZ;
619 if (info->control.rates[0].flags & IEEE80211_TX_RC_SHORT_GI)
620 rx_status.flag |= RX_FLAG_SHORT_GI;
615 /* TODO: simulate real signal strength (and optional packet loss) */ 621 /* TODO: simulate real signal strength (and optional packet loss) */
616 rx_status.signal = data->power_level - 50; 622 rx_status.signal = data->power_level - 50;
617 623
diff --git a/drivers/net/wireless/mwifiex/cfg80211.c b/drivers/net/wireless/mwifiex/cfg80211.c
index 352d2c5da1fc..6fd53e4e3fe6 100644
--- a/drivers/net/wireless/mwifiex/cfg80211.c
+++ b/drivers/net/wireless/mwifiex/cfg80211.c
@@ -547,7 +547,7 @@ mwifiex_dump_station_info(struct mwifiex_private *priv,
547 sinfo->tx_bytes = priv->stats.tx_bytes; 547 sinfo->tx_bytes = priv->stats.tx_bytes;
548 sinfo->rx_packets = priv->stats.rx_packets; 548 sinfo->rx_packets = priv->stats.rx_packets;
549 sinfo->tx_packets = priv->stats.tx_packets; 549 sinfo->tx_packets = priv->stats.tx_packets;
550 sinfo->signal = priv->w_stats.qual.level; 550 sinfo->signal = priv->qual_level;
551 sinfo->txrate.legacy = rate.rate; 551 sinfo->txrate.legacy = rate.rate;
552 552
553 return ret; 553 return ret;
@@ -793,139 +793,6 @@ static int mwifiex_cfg80211_inform_ibss_bss(struct mwifiex_private *priv)
793} 793}
794 794
795/* 795/*
796 * This function informs the CFG802.11 subsystem of a new BSS connection.
797 *
798 * The following information are sent to the CFG802.11 subsystem
799 * to register the new BSS connection. If we do not register the new BSS,
800 * a kernel panic will result.
801 * - MAC address
802 * - Capabilities
803 * - Beacon period
804 * - RSSI value
805 * - Channel
806 * - Supported rates IE
807 * - Extended capabilities IE
808 * - DS parameter set IE
809 * - HT Capability IE
810 * - Vendor Specific IE (221)
811 * - WPA IE
812 * - RSN IE
813 */
814static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
815 struct mwifiex_802_11_ssid *ssid)
816{
817 struct mwifiex_bssdescriptor *scan_table;
818 int i, j;
819 struct ieee80211_channel *chan;
820 u8 *ie, *ie_buf;
821 u32 ie_len;
822 u8 *beacon;
823 int beacon_size;
824 u8 element_id, element_len;
825
826#define MAX_IE_BUF 2048
827 ie_buf = kzalloc(MAX_IE_BUF, GFP_KERNEL);
828 if (!ie_buf) {
829 dev_err(priv->adapter->dev, "%s: failed to alloc ie_buf\n",
830 __func__);
831 return -ENOMEM;
832 }
833
834 scan_table = priv->adapter->scan_table;
835 for (i = 0; i < priv->adapter->num_in_scan_table; i++) {
836 if (ssid) {
837 /* Inform specific BSS only */
838 if (memcmp(ssid->ssid, scan_table[i].ssid.ssid,
839 ssid->ssid_len))
840 continue;
841 }
842 memset(ie_buf, 0, MAX_IE_BUF);
843 ie_buf[0] = WLAN_EID_SSID;
844 ie_buf[1] = scan_table[i].ssid.ssid_len;
845 memcpy(&ie_buf[sizeof(struct ieee_types_header)],
846 scan_table[i].ssid.ssid, ie_buf[1]);
847
848 ie = ie_buf + ie_buf[1] + sizeof(struct ieee_types_header);
849 ie_len = ie_buf[1] + sizeof(struct ieee_types_header);
850
851 ie[0] = WLAN_EID_SUPP_RATES;
852
853 for (j = 0; j < sizeof(scan_table[i].supported_rates); j++) {
854 if (!scan_table[i].supported_rates[j])
855 break;
856 else
857 ie[j + sizeof(struct ieee_types_header)] =
858 scan_table[i].supported_rates[j];
859 }
860
861 ie[1] = j;
862 ie_len += ie[1] + sizeof(struct ieee_types_header);
863
864 beacon = scan_table[i].beacon_buf;
865 beacon_size = scan_table[i].beacon_buf_size;
866
867 /* Skip time stamp, beacon interval and capability */
868
869 if (beacon) {
870 beacon += sizeof(scan_table[i].beacon_period)
871 + sizeof(scan_table[i].time_stamp) +
872 +sizeof(scan_table[i].cap_info_bitmap);
873
874 beacon_size -= sizeof(scan_table[i].beacon_period)
875 + sizeof(scan_table[i].time_stamp)
876 + sizeof(scan_table[i].cap_info_bitmap);
877 }
878
879 while (beacon_size >= sizeof(struct ieee_types_header)) {
880 ie = ie_buf + ie_len;
881 element_id = *beacon;
882 element_len = *(beacon + 1);
883 if (beacon_size < (int) element_len +
884 sizeof(struct ieee_types_header)) {
885 dev_err(priv->adapter->dev, "%s: in processing"
886 " IE, bytes left < IE length\n",
887 __func__);
888 break;
889 }
890 switch (element_id) {
891 case WLAN_EID_EXT_CAPABILITY:
892 case WLAN_EID_DS_PARAMS:
893 case WLAN_EID_HT_CAPABILITY:
894 case WLAN_EID_VENDOR_SPECIFIC:
895 case WLAN_EID_RSN:
896 case WLAN_EID_BSS_AC_ACCESS_DELAY:
897 ie[0] = element_id;
898 ie[1] = element_len;
899 memcpy(&ie[sizeof(struct ieee_types_header)],
900 (u8 *) beacon
901 + sizeof(struct ieee_types_header),
902 element_len);
903 ie_len += ie[1] +
904 sizeof(struct ieee_types_header);
905 break;
906 default:
907 break;
908 }
909 beacon += element_len +
910 sizeof(struct ieee_types_header);
911 beacon_size -= element_len +
912 sizeof(struct ieee_types_header);
913 }
914 chan = ieee80211_get_channel(priv->wdev->wiphy,
915 scan_table[i].freq);
916 cfg80211_inform_bss(priv->wdev->wiphy, chan,
917 scan_table[i].mac_address,
918 0, scan_table[i].cap_info_bitmap,
919 scan_table[i].beacon_period,
920 ie_buf, ie_len,
921 scan_table[i].rssi, GFP_KERNEL);
922 }
923
924 kfree(ie_buf);
925 return 0;
926}
927
928/*
929 * This function connects with a BSS. 796 * This function connects with a BSS.
930 * 797 *
931 * This function handles both Infra and Ad-Hoc modes. It also performs 798 * This function handles both Infra and Ad-Hoc modes. It also performs
@@ -937,8 +804,7 @@ static int mwifiex_inform_bss_from_scan_result(struct mwifiex_private *priv,
937 * For Infra mode, the function returns failure if the specified SSID 804 * For Infra mode, the function returns failure if the specified SSID
938 * is not found in scan table. However, for Ad-Hoc mode, it can create 805 * is not found in scan table. However, for Ad-Hoc mode, it can create
939 * the IBSS if it does not exist. On successful completion in either case, 806 * the IBSS if it does not exist. On successful completion in either case,
940 * the function notifies the CFG802.11 subsystem of the new BSS connection, 807 * the function notifies the CFG802.11 subsystem of the new BSS connection.
941 * otherwise the kernel will panic.
942 */ 808 */
943static int 809static int
944mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid, 810mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
@@ -946,11 +812,11 @@ mwifiex_cfg80211_assoc(struct mwifiex_private *priv, size_t ssid_len, u8 *ssid,
946 struct cfg80211_connect_params *sme, bool privacy) 812 struct cfg80211_connect_params *sme, bool privacy)
947{ 813{
948 struct mwifiex_802_11_ssid req_ssid; 814 struct mwifiex_802_11_ssid req_ssid;
949 struct mwifiex_ssid_bssid ssid_bssid;
950 int ret, auth_type = 0; 815 int ret, auth_type = 0;
816 struct cfg80211_bss *bss = NULL;
817 u8 is_scanning_required = 0;
951 818
952 memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid)); 819 memset(&req_ssid, 0, sizeof(struct mwifiex_802_11_ssid));
953 memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
954 820
955 req_ssid.ssid_len = ssid_len; 821 req_ssid.ssid_len = ssid_len;
956 if (ssid_len > IEEE80211_MAX_SSID_LEN) { 822 if (ssid_len > IEEE80211_MAX_SSID_LEN) {
@@ -1028,30 +894,48 @@ done:
1028 return -EFAULT; 894 return -EFAULT;
1029 } 895 }
1030 896
897 /*
898 * Scan entries are valid for some time (15 sec). So we can save one
899 * active scan time if we just try cfg80211_get_bss first. If it fails
900 * then request scan and cfg80211_get_bss() again for final output.
901 */
902 while (1) {
903 if (is_scanning_required) {
904 /* Do specific SSID scanning */
905 if (mwifiex_request_scan(priv, &req_ssid)) {
906 dev_err(priv->adapter->dev, "scan error\n");
907 return -EFAULT;
908 }
909 }
1031 910
1032 memcpy(&ssid_bssid.ssid, &req_ssid, sizeof(struct mwifiex_802_11_ssid)); 911 /* Find the BSS we want using available scan results */
1033 912 if (mode == NL80211_IFTYPE_ADHOC)
1034 if (mode != NL80211_IFTYPE_ADHOC) { 913 bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1035 if (mwifiex_find_best_bss(priv, &ssid_bssid)) 914 bssid, ssid, ssid_len,
1036 return -EFAULT; 915 WLAN_CAPABILITY_IBSS,
1037 /* Inform the BSS information to kernel, otherwise 916 WLAN_CAPABILITY_IBSS);
1038 * kernel will give a panic after successful assoc */ 917 else
1039 if (mwifiex_inform_bss_from_scan_result(priv, &req_ssid)) 918 bss = cfg80211_get_bss(priv->wdev->wiphy, channel,
1040 return -EFAULT; 919 bssid, ssid, ssid_len,
920 WLAN_CAPABILITY_ESS,
921 WLAN_CAPABILITY_ESS);
922
923 if (!bss) {
924 if (is_scanning_required) {
925 dev_warn(priv->adapter->dev, "assoc: requested "
926 "bss not found in scan results\n");
927 break;
928 }
929 is_scanning_required = 1;
930 } else {
931 dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n",
932 (char *) req_ssid.ssid, bss->bssid);
933 memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
934 break;
935 }
1041 } 936 }
1042 937
1043 dev_dbg(priv->adapter->dev, "info: trying to associate to %s and bssid %pM\n", 938 if (mwifiex_bss_start(priv, bss, &req_ssid))
1044 (char *) req_ssid.ssid, ssid_bssid.bssid);
1045
1046 memcpy(&priv->cfg_bssid, ssid_bssid.bssid, 6);
1047
1048 /* Connect to BSS by ESSID */
1049 memset(&ssid_bssid.bssid, 0, ETH_ALEN);
1050
1051 if (!netif_queue_stopped(priv->netdev))
1052 netif_stop_queue(priv->netdev);
1053
1054 if (mwifiex_bss_start(priv, &ssid_bssid))
1055 return -EFAULT; 939 return -EFAULT;
1056 940
1057 if (mode == NL80211_IFTYPE_ADHOC) { 941 if (mode == NL80211_IFTYPE_ADHOC) {
@@ -1416,13 +1300,8 @@ mwifiex_cfg80211_results(struct work_struct *work)
1416 MWIFIEX_SCAN_TYPE_ACTIVE; 1300 MWIFIEX_SCAN_TYPE_ACTIVE;
1417 scan_req->chan_list[i].scan_time = 0; 1301 scan_req->chan_list[i].scan_time = 0;
1418 } 1302 }
1419 if (mwifiex_set_user_scan_ioctl(priv, scan_req)) { 1303 if (mwifiex_set_user_scan_ioctl(priv, scan_req))
1420 ret = -EFAULT; 1304 ret = -EFAULT;
1421 goto done;
1422 }
1423 if (mwifiex_inform_bss_from_scan_result(priv, NULL))
1424 ret = -EFAULT;
1425done:
1426 priv->scan_result_status = ret; 1305 priv->scan_result_status = ret;
1427 dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n", 1306 dev_dbg(priv->adapter->dev, "info: %s: sending scan results\n",
1428 __func__); 1307 __func__);
diff --git a/drivers/net/wireless/mwifiex/fw.h b/drivers/net/wireless/mwifiex/fw.h
index 4fee0993b186..f23ec72ed4fe 100644
--- a/drivers/net/wireless/mwifiex/fw.h
+++ b/drivers/net/wireless/mwifiex/fw.h
@@ -821,6 +821,14 @@ struct host_cmd_ds_txpwr_cfg {
821 __le32 mode; 821 __le32 mode;
822} __packed; 822} __packed;
823 823
824struct mwifiex_bcn_param {
825 u8 bssid[ETH_ALEN];
826 u8 rssi;
827 __le32 timestamp[2];
828 __le16 beacon_period;
829 __le16 cap_info_bitmap;
830} __packed;
831
824#define MWIFIEX_USER_SCAN_CHAN_MAX 50 832#define MWIFIEX_USER_SCAN_CHAN_MAX 50
825 833
826#define MWIFIEX_MAX_SSID_LIST_LENGTH 10 834#define MWIFIEX_MAX_SSID_LIST_LENGTH 10
@@ -862,13 +870,6 @@ struct mwifiex_user_scan_ssid {
862 870
863struct mwifiex_user_scan_cfg { 871struct mwifiex_user_scan_cfg {
864 /* 872 /*
865 * Flag set to keep the previous scan table intact
866 *
867 * If set, the scan results will accumulate, replacing any previous
868 * matched entries for a BSS with the new scan data
869 */
870 u8 keep_previous_scan;
871 /*
872 * BSS mode to be sent in the firmware command 873 * BSS mode to be sent in the firmware command
873 */ 874 */
874 u8 bss_mode; 875 u8 bss_mode;
diff --git a/drivers/net/wireless/mwifiex/init.c b/drivers/net/wireless/mwifiex/init.c
index 3f1559e61320..26e685a31bc0 100644
--- a/drivers/net/wireless/mwifiex/init.c
+++ b/drivers/net/wireless/mwifiex/init.c
@@ -152,19 +152,6 @@ static int mwifiex_init_priv(struct mwifiex_private *priv)
152static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter) 152static int mwifiex_allocate_adapter(struct mwifiex_adapter *adapter)
153{ 153{
154 int ret; 154 int ret;
155 u32 buf_size;
156 struct mwifiex_bssdescriptor *temp_scan_table;
157
158 /* Allocate buffer to store the BSSID list */
159 buf_size = sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP;
160 temp_scan_table = kzalloc(buf_size, GFP_KERNEL);
161 if (!temp_scan_table) {
162 dev_err(adapter->dev, "%s: failed to alloc temp_scan_table\n",
163 __func__);
164 return -ENOMEM;
165 }
166
167 adapter->scan_table = temp_scan_table;
168 155
169 /* Allocate command buffer */ 156 /* Allocate command buffer */
170 ret = mwifiex_alloc_cmd_buffer(adapter); 157 ret = mwifiex_alloc_cmd_buffer(adapter);
@@ -222,14 +209,8 @@ static void mwifiex_init_adapter(struct mwifiex_adapter *adapter)
222 adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME; 209 adapter->active_scan_time = MWIFIEX_ACTIVE_SCAN_CHAN_TIME;
223 adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME; 210 adapter->passive_scan_time = MWIFIEX_PASSIVE_SCAN_CHAN_TIME;
224 211
225 adapter->num_in_scan_table = 0;
226 memset(adapter->scan_table, 0,
227 (sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP));
228 adapter->scan_probes = 1; 212 adapter->scan_probes = 1;
229 213
230 memset(adapter->bcn_buf, 0, sizeof(adapter->bcn_buf));
231 adapter->bcn_buf_end = adapter->bcn_buf;
232
233 adapter->multiple_dtim = 1; 214 adapter->multiple_dtim = 1;
234 215
235 adapter->local_listen_interval = 0; /* default value in firmware 216 adapter->local_listen_interval = 0; /* default value in firmware
@@ -326,8 +307,6 @@ mwifiex_free_adapter(struct mwifiex_adapter *adapter)
326 del_timer(&adapter->cmd_timer); 307 del_timer(&adapter->cmd_timer);
327 308
328 dev_dbg(adapter->dev, "info: free scan table\n"); 309 dev_dbg(adapter->dev, "info: free scan table\n");
329 kfree(adapter->scan_table);
330 adapter->scan_table = NULL;
331 310
332 adapter->if_ops.cleanup_if(adapter); 311 adapter->if_ops.cleanup_if(adapter);
333 312
diff --git a/drivers/net/wireless/mwifiex/ioctl.h b/drivers/net/wireless/mwifiex/ioctl.h
index f6bcc868562f..e0b68e7c8ca2 100644
--- a/drivers/net/wireless/mwifiex/ioctl.h
+++ b/drivers/net/wireless/mwifiex/ioctl.h
@@ -134,7 +134,6 @@ struct mwifiex_ver_ext {
134struct mwifiex_bss_info { 134struct mwifiex_bss_info {
135 u32 bss_mode; 135 u32 bss_mode;
136 struct mwifiex_802_11_ssid ssid; 136 struct mwifiex_802_11_ssid ssid;
137 u32 scan_table_idx;
138 u32 bss_chan; 137 u32 bss_chan;
139 u32 region_code; 138 u32 region_code;
140 u32 media_connected; 139 u32 media_connected;
@@ -307,10 +306,12 @@ struct mwifiex_ds_read_eeprom {
307 u8 value[MAX_EEPROM_DATA]; 306 u8 value[MAX_EEPROM_DATA];
308}; 307};
309 308
309#define IEEE_MAX_IE_SIZE 256
310
310struct mwifiex_ds_misc_gen_ie { 311struct mwifiex_ds_misc_gen_ie {
311 u32 type; 312 u32 type;
312 u32 len; 313 u32 len;
313 u8 ie_data[IW_CUSTOM_MAX]; 314 u8 ie_data[IEEE_MAX_IE_SIZE];
314}; 315};
315 316
316struct mwifiex_ds_misc_cmd { 317struct mwifiex_ds_misc_cmd {
diff --git a/drivers/net/wireless/mwifiex/join.c b/drivers/net/wireless/mwifiex/join.c
index 644e2e405cb5..5cdad92277fa 100644
--- a/drivers/net/wireless/mwifiex/join.c
+++ b/drivers/net/wireless/mwifiex/join.c
@@ -224,32 +224,6 @@ mwifiex_setup_rates_from_bssdesc(struct mwifiex_private *priv,
224} 224}
225 225
226/* 226/*
227 * This function updates the scan entry TSF timestamps to reflect
228 * a new association.
229 */
230static void
231mwifiex_update_tsf_timestamps(struct mwifiex_private *priv,
232 struct mwifiex_bssdescriptor *new_bss_desc)
233{
234 struct mwifiex_adapter *adapter = priv->adapter;
235 u32 table_idx;
236 long long new_tsf_base;
237 signed long long tsf_delta;
238
239 memcpy(&new_tsf_base, new_bss_desc->time_stamp, sizeof(new_tsf_base));
240
241 tsf_delta = new_tsf_base - new_bss_desc->network_tsf;
242
243 dev_dbg(adapter->dev, "info: TSF: update TSF timestamps, "
244 "0x%016llx -> 0x%016llx\n",
245 new_bss_desc->network_tsf, new_tsf_base);
246
247 for (table_idx = 0; table_idx < adapter->num_in_scan_table;
248 table_idx++)
249 adapter->scan_table[table_idx].network_tsf += tsf_delta;
250}
251
252/*
253 * This function appends a WAPI IE. 227 * This function appends a WAPI IE.
254 * 228 *
255 * This function is called from the network join command preparation routine. 229 * This function is called from the network join command preparation routine.
@@ -639,12 +613,6 @@ int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
639 613
640 priv->curr_bss_params.band = (u8) bss_desc->bss_band; 614 priv->curr_bss_params.band = (u8) bss_desc->bss_band;
641 615
642 /*
643 * Adjust the timestamps in the scan table to be relative to the newly
644 * associated AP's TSF
645 */
646 mwifiex_update_tsf_timestamps(priv, bss_desc);
647
648 if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC) 616 if (bss_desc->wmm_ie.vend_hdr.element_id == WLAN_EID_VENDOR_SPECIFIC)
649 priv->curr_bss_params.wmm_enabled = true; 617 priv->curr_bss_params.wmm_enabled = true;
650 else 618 else
diff --git a/drivers/net/wireless/mwifiex/main.c b/drivers/net/wireless/mwifiex/main.c
index 0415e3d1c317..48b4d95219fb 100644
--- a/drivers/net/wireless/mwifiex/main.c
+++ b/drivers/net/wireless/mwifiex/main.c
@@ -849,6 +849,7 @@ mwifiex_add_card(void *card, struct semaphore *sem,
849{ 849{
850 int i; 850 int i;
851 struct mwifiex_adapter *adapter; 851 struct mwifiex_adapter *adapter;
852 char fmt[64];
852 853
853 if (down_interruptible(sem)) 854 if (down_interruptible(sem))
854 goto exit_sem_err; 855 goto exit_sem_err;
@@ -897,6 +898,9 @@ mwifiex_add_card(void *card, struct semaphore *sem,
897 898
898 up(sem); 899 up(sem);
899 900
901 mwifiex_drv_get_driver_version(adapter, fmt, sizeof(fmt) - 1);
902 dev_notice(adapter->dev, "driver_version = %s\n", fmt);
903
900 return 0; 904 return 0;
901 905
902err_add_intf: 906err_add_intf:
diff --git a/drivers/net/wireless/mwifiex/main.h b/drivers/net/wireless/mwifiex/main.h
index 2215c3c97354..e6b6c0cfb63e 100644
--- a/drivers/net/wireless/mwifiex/main.h
+++ b/drivers/net/wireless/mwifiex/main.h
@@ -54,6 +54,8 @@ struct mwifiex_drv_mode {
54}; 54};
55 55
56 56
57#define MWIFIEX_MAX_AP 64
58
57#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ) 59#define MWIFIEX_DEFAULT_WATCHDOG_TIMEOUT (5 * HZ)
58 60
59#define MWIFIEX_TIMER_10S 10000 61#define MWIFIEX_TIMER_10S 10000
@@ -227,27 +229,10 @@ struct ieee_types_header {
227 u8 len; 229 u8 len;
228} __packed; 230} __packed;
229 231
230struct ieee_obss_scan_param {
231 u16 obss_scan_passive_dwell;
232 u16 obss_scan_active_dwell;
233 u16 bss_chan_width_trigger_scan_int;
234 u16 obss_scan_passive_total;
235 u16 obss_scan_active_total;
236 u16 bss_width_chan_trans_delay;
237 u16 obss_scan_active_threshold;
238} __packed;
239
240struct ieee_types_obss_scan_param {
241 struct ieee_types_header ieee_hdr;
242 struct ieee_obss_scan_param obss_scan;
243} __packed;
244
245#define MWIFIEX_SUPPORTED_RATES 14 232#define MWIFIEX_SUPPORTED_RATES 14
246 233
247#define MWIFIEX_SUPPORTED_RATES_EXT 32 234#define MWIFIEX_SUPPORTED_RATES_EXT 32
248 235
249#define IEEE_MAX_IE_SIZE 256
250
251struct ieee_types_vendor_specific { 236struct ieee_types_vendor_specific {
252 struct ieee_types_vendor_header vend_hdr; 237 struct ieee_types_vendor_header vend_hdr;
253 u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)]; 238 u8 data[IEEE_MAX_IE_SIZE - sizeof(struct ieee_types_vendor_header)];
@@ -291,8 +276,6 @@ struct mwifiex_bssdescriptor {
291 u16 bss_co_2040_offset; 276 u16 bss_co_2040_offset;
292 u8 *bcn_ext_cap; 277 u8 *bcn_ext_cap;
293 u16 ext_cap_offset; 278 u16 ext_cap_offset;
294 struct ieee_types_obss_scan_param *bcn_obss_scan;
295 u16 overlap_bss_offset;
296 struct ieee_types_vendor_specific *bcn_wpa_ie; 279 struct ieee_types_vendor_specific *bcn_wpa_ie;
297 u16 wpa_offset; 280 u16 wpa_offset;
298 struct ieee_types_generic *bcn_rsn_ie; 281 struct ieee_types_generic *bcn_rsn_ie;
@@ -301,8 +284,6 @@ struct mwifiex_bssdescriptor {
301 u16 wapi_offset; 284 u16 wapi_offset;
302 u8 *beacon_buf; 285 u8 *beacon_buf;
303 u32 beacon_buf_size; 286 u32 beacon_buf_size;
304 u32 beacon_buf_size_max;
305
306}; 287};
307 288
308struct mwifiex_current_bss_params { 289struct mwifiex_current_bss_params {
@@ -468,7 +449,7 @@ struct mwifiex_private {
468 struct dentry *dfs_dev_dir; 449 struct dentry *dfs_dev_dir;
469#endif 450#endif
470 u8 nick_name[16]; 451 u8 nick_name[16];
471 struct iw_statistics w_stats; 452 u8 qual_level, qual_noise;
472 u16 current_key_index; 453 u16 current_key_index;
473 struct semaphore async_sem; 454 struct semaphore async_sem;
474 u8 scan_pending_on_block; 455 u8 scan_pending_on_block;
@@ -624,15 +605,11 @@ struct mwifiex_adapter {
624 u32 scan_processing; 605 u32 scan_processing;
625 u16 region_code; 606 u16 region_code;
626 struct mwifiex_802_11d_domain_reg domain_reg; 607 struct mwifiex_802_11d_domain_reg domain_reg;
627 struct mwifiex_bssdescriptor *scan_table;
628 u32 num_in_scan_table;
629 u16 scan_probes; 608 u16 scan_probes;
630 u32 scan_mode; 609 u32 scan_mode;
631 u16 specific_scan_time; 610 u16 specific_scan_time;
632 u16 active_scan_time; 611 u16 active_scan_time;
633 u16 passive_scan_time; 612 u16 passive_scan_time;
634 u8 bcn_buf[MAX_SCAN_BEACON_BUFFER];
635 u8 *bcn_buf_end;
636 u8 fw_bands; 613 u8 fw_bands;
637 u8 adhoc_start_band; 614 u8 adhoc_start_band;
638 u8 config_bands; 615 u8 config_bands;
@@ -765,13 +742,6 @@ void mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
765 struct cmd_ctrl_node *cmd_node); 742 struct cmd_ctrl_node *cmd_node);
766int mwifiex_ret_802_11_scan(struct mwifiex_private *priv, 743int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
767 struct host_cmd_ds_command *resp); 744 struct host_cmd_ds_command *resp);
768s32 mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
769 struct mwifiex_802_11_ssid *ssid, u8 *bssid,
770 u32 mode);
771s32 mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
772 u32 mode);
773int mwifiex_find_best_network(struct mwifiex_private *priv,
774 struct mwifiex_ssid_bssid *req_ssid_bssid);
775s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1, 745s32 mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
776 struct mwifiex_802_11_ssid *ssid2); 746 struct mwifiex_802_11_ssid *ssid2);
777int mwifiex_associate(struct mwifiex_private *priv, 747int mwifiex_associate(struct mwifiex_private *priv,
@@ -782,7 +752,6 @@ int mwifiex_cmd_802_11_associate(struct mwifiex_private *priv,
782int mwifiex_ret_802_11_associate(struct mwifiex_private *priv, 752int mwifiex_ret_802_11_associate(struct mwifiex_private *priv,
783 struct host_cmd_ds_command *resp); 753 struct host_cmd_ds_command *resp);
784void mwifiex_reset_connect_state(struct mwifiex_private *priv); 754void mwifiex_reset_connect_state(struct mwifiex_private *priv);
785void mwifiex_2040_coex_event(struct mwifiex_private *priv);
786u8 mwifiex_band_to_radio_type(u8 band); 755u8 mwifiex_band_to_radio_type(u8 band);
787int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac); 756int mwifiex_deauthenticate(struct mwifiex_private *priv, u8 *mac);
788int mwifiex_adhoc_start(struct mwifiex_private *priv, 757int mwifiex_adhoc_start(struct mwifiex_private *priv,
@@ -922,8 +891,8 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
922int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist, 891int mwifiex_copy_mcast_addr(struct mwifiex_multicast_list *mlist,
923 struct net_device *dev); 892 struct net_device *dev);
924int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter); 893int mwifiex_wait_queue_complete(struct mwifiex_adapter *adapter);
925int mwifiex_bss_start(struct mwifiex_private *priv, 894int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
926 struct mwifiex_ssid_bssid *ssid_bssid); 895 struct mwifiex_802_11_ssid *req_ssid);
927int mwifiex_set_hs_params(struct mwifiex_private *priv, 896int mwifiex_set_hs_params(struct mwifiex_private *priv,
928 u16 action, int cmd_type, 897 u16 action, int cmd_type,
929 struct mwifiex_ds_hs_cfg *hscfg); 898 struct mwifiex_ds_hs_cfg *hscfg);
@@ -934,8 +903,6 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
934 struct mwifiex_ds_get_signal *signal); 903 struct mwifiex_ds_get_signal *signal);
935int mwifiex_drv_get_data_rate(struct mwifiex_private *priv, 904int mwifiex_drv_get_data_rate(struct mwifiex_private *priv,
936 struct mwifiex_rate_cfg *rate); 905 struct mwifiex_rate_cfg *rate);
937int mwifiex_find_best_bss(struct mwifiex_private *priv,
938 struct mwifiex_ssid_bssid *ssid_bssid);
939int mwifiex_request_scan(struct mwifiex_private *priv, 906int mwifiex_request_scan(struct mwifiex_private *priv,
940 struct mwifiex_802_11_ssid *req_ssid); 907 struct mwifiex_802_11_ssid *req_ssid);
941int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv, 908int mwifiex_set_user_scan_ioctl(struct mwifiex_private *priv,
@@ -984,12 +951,20 @@ int mwifiex_main_process(struct mwifiex_adapter *);
984 951
985int mwifiex_bss_set_channel(struct mwifiex_private *, 952int mwifiex_bss_set_channel(struct mwifiex_private *,
986 struct mwifiex_chan_freq_power *cfp); 953 struct mwifiex_chan_freq_power *cfp);
987int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *,
988 struct mwifiex_ssid_bssid *);
989int mwifiex_set_radio_band_cfg(struct mwifiex_private *, 954int mwifiex_set_radio_band_cfg(struct mwifiex_private *,
990 struct mwifiex_ds_band_cfg *); 955 struct mwifiex_ds_band_cfg *);
991int mwifiex_get_bss_info(struct mwifiex_private *, 956int mwifiex_get_bss_info(struct mwifiex_private *,
992 struct mwifiex_bss_info *); 957 struct mwifiex_bss_info *);
958int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
959 u8 *bssid, s32 rssi, u8 *ie_buf,
960 size_t ie_len, u16 beacon_period,
961 u16 cap_info_bitmap,
962 struct mwifiex_bssdescriptor *bss_desc);
963int mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
964 struct mwifiex_bssdescriptor *bss_entry,
965 u8 *ie_buf, u32 ie_len);
966int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
967 struct mwifiex_bssdescriptor *bss_desc);
993 968
994#ifdef CONFIG_DEBUG_FS 969#ifdef CONFIG_DEBUG_FS
995void mwifiex_debugfs_init(void); 970void mwifiex_debugfs_init(void);
diff --git a/drivers/net/wireless/mwifiex/scan.c b/drivers/net/wireless/mwifiex/scan.c
index 6f88c8ab5de5..b28241c6e737 100644
--- a/drivers/net/wireless/mwifiex/scan.c
+++ b/drivers/net/wireless/mwifiex/scan.c
@@ -172,36 +172,6 @@ mwifiex_ssid_cmp(struct mwifiex_802_11_ssid *ssid1,
172} 172}
173 173
174/* 174/*
175 * Sends IOCTL request to get the best BSS.
176 *
177 * This function allocates the IOCTL request buffer, fills it
178 * with requisite parameters and calls the IOCTL handler.
179 */
180int mwifiex_find_best_bss(struct mwifiex_private *priv,
181 struct mwifiex_ssid_bssid *ssid_bssid)
182{
183 struct mwifiex_ssid_bssid tmp_ssid_bssid;
184 u8 *mac;
185
186 if (!ssid_bssid)
187 return -1;
188
189 memcpy(&tmp_ssid_bssid, ssid_bssid,
190 sizeof(struct mwifiex_ssid_bssid));
191
192 if (!mwifiex_bss_ioctl_find_bss(priv, &tmp_ssid_bssid)) {
193 memcpy(ssid_bssid, &tmp_ssid_bssid,
194 sizeof(struct mwifiex_ssid_bssid));
195 mac = (u8 *) &ssid_bssid->bssid;
196 dev_dbg(priv->adapter->dev, "cmd: found network: ssid=%s,"
197 " %pM\n", ssid_bssid->ssid.ssid, mac);
198 return 0;
199 }
200
201 return -1;
202}
203
204/*
205 * Sends IOCTL request to start a scan with user configurations. 175 * Sends IOCTL request to start a scan with user configurations.
206 * 176 *
207 * This function allocates the IOCTL request buffer, fills it 177 * This function allocates the IOCTL request buffer, fills it
@@ -286,8 +256,7 @@ mwifiex_is_network_compatible_for_static_wep(struct mwifiex_private *priv,
286 */ 256 */
287static bool 257static bool
288mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv, 258mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
289 struct mwifiex_bssdescriptor *bss_desc, 259 struct mwifiex_bssdescriptor *bss_desc)
290 int index)
291{ 260{
292 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED 261 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
293 && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled 262 && priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -298,9 +267,9 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
298 * LinkSys WRT54G && bss_desc->privacy 267 * LinkSys WRT54G && bss_desc->privacy
299 */ 268 */
300 ) { 269 ) {
301 dev_dbg(priv->adapter->dev, "info: %s: WPA: index=%d" 270 dev_dbg(priv->adapter->dev, "info: %s: WPA:"
302 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " 271 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
303 "EncMode=%#x privacy=%#x\n", __func__, index, 272 "EncMode=%#x privacy=%#x\n", __func__,
304 (bss_desc->bcn_wpa_ie) ? 273 (bss_desc->bcn_wpa_ie) ?
305 (*(bss_desc->bcn_wpa_ie)). 274 (*(bss_desc->bcn_wpa_ie)).
306 vend_hdr.element_id : 0, 275 vend_hdr.element_id : 0,
@@ -324,8 +293,7 @@ mwifiex_is_network_compatible_for_wpa(struct mwifiex_private *priv,
324 */ 293 */
325static bool 294static bool
326mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv, 295mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
327 struct mwifiex_bssdescriptor *bss_desc, 296 struct mwifiex_bssdescriptor *bss_desc)
328 int index)
329{ 297{
330 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED 298 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
331 && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled 299 && !priv->sec_info.wpa_enabled && priv->sec_info.wpa2_enabled
@@ -336,9 +304,9 @@ mwifiex_is_network_compatible_for_wpa2(struct mwifiex_private *priv,
336 * LinkSys WRT54G && bss_desc->privacy 304 * LinkSys WRT54G && bss_desc->privacy
337 */ 305 */
338 ) { 306 ) {
339 dev_dbg(priv->adapter->dev, "info: %s: WPA2: index=%d" 307 dev_dbg(priv->adapter->dev, "info: %s: WPA2: "
340 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s " 308 " wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s "
341 "EncMode=%#x privacy=%#x\n", __func__, index, 309 "EncMode=%#x privacy=%#x\n", __func__,
342 (bss_desc->bcn_wpa_ie) ? 310 (bss_desc->bcn_wpa_ie) ?
343 (*(bss_desc->bcn_wpa_ie)). 311 (*(bss_desc->bcn_wpa_ie)).
344 vend_hdr.element_id : 0, 312 vend_hdr.element_id : 0,
@@ -383,8 +351,7 @@ mwifiex_is_network_compatible_for_adhoc_aes(struct mwifiex_private *priv,
383 */ 351 */
384static bool 352static bool
385mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv, 353mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
386 struct mwifiex_bssdescriptor *bss_desc, 354 struct mwifiex_bssdescriptor *bss_desc)
387 int index)
388{ 355{
389 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED 356 if (priv->sec_info.wep_status == MWIFIEX_802_11_WEP_DISABLED
390 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled 357 && !priv->sec_info.wpa_enabled && !priv->sec_info.wpa2_enabled
@@ -395,9 +362,9 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
395 && priv->sec_info.encryption_mode 362 && priv->sec_info.encryption_mode
396 && bss_desc->privacy) { 363 && bss_desc->privacy) {
397 dev_dbg(priv->adapter->dev, "info: %s: dynamic " 364 dev_dbg(priv->adapter->dev, "info: %s: dynamic "
398 "WEP: index=%d wpa_ie=%#x wpa2_ie=%#x " 365 "WEP: wpa_ie=%#x wpa2_ie=%#x "
399 "EncMode=%#x privacy=%#x\n", 366 "EncMode=%#x privacy=%#x\n",
400 __func__, index, 367 __func__,
401 (bss_desc->bcn_wpa_ie) ? 368 (bss_desc->bcn_wpa_ie) ?
402 (*(bss_desc->bcn_wpa_ie)). 369 (*(bss_desc->bcn_wpa_ie)).
403 vend_hdr.element_id : 0, 370 vend_hdr.element_id : 0,
@@ -430,42 +397,41 @@ mwifiex_is_network_compatible_for_dynamic_wep(struct mwifiex_private *priv,
430 * Compatibility is not matched while roaming, except for mode. 397 * Compatibility is not matched while roaming, except for mode.
431 */ 398 */
432static s32 399static s32
433mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode) 400mwifiex_is_network_compatible(struct mwifiex_private *priv,
401 struct mwifiex_bssdescriptor *bss_desc, u32 mode)
434{ 402{
435 struct mwifiex_adapter *adapter = priv->adapter; 403 struct mwifiex_adapter *adapter = priv->adapter;
436 struct mwifiex_bssdescriptor *bss_desc;
437 404
438 bss_desc = &adapter->scan_table[index];
439 bss_desc->disable_11n = false; 405 bss_desc->disable_11n = false;
440 406
441 /* Don't check for compatibility if roaming */ 407 /* Don't check for compatibility if roaming */
442 if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION) 408 if (priv->media_connected && (priv->bss_mode == NL80211_IFTYPE_STATION)
443 && (bss_desc->bss_mode == NL80211_IFTYPE_STATION)) 409 && (bss_desc->bss_mode == NL80211_IFTYPE_STATION))
444 return index; 410 return 0;
445 411
446 if (priv->wps.session_enable) { 412 if (priv->wps.session_enable) {
447 dev_dbg(adapter->dev, 413 dev_dbg(adapter->dev,
448 "info: return success directly in WPS period\n"); 414 "info: return success directly in WPS period\n");
449 return index; 415 return 0;
450 } 416 }
451 417
452 if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) { 418 if (mwifiex_is_network_compatible_for_wapi(priv, bss_desc)) {
453 dev_dbg(adapter->dev, "info: return success for WAPI AP\n"); 419 dev_dbg(adapter->dev, "info: return success for WAPI AP\n");
454 return index; 420 return 0;
455 } 421 }
456 422
457 if (bss_desc->bss_mode == mode) { 423 if (bss_desc->bss_mode == mode) {
458 if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) { 424 if (mwifiex_is_network_compatible_for_no_sec(priv, bss_desc)) {
459 /* No security */ 425 /* No security */
460 return index; 426 return 0;
461 } else if (mwifiex_is_network_compatible_for_static_wep(priv, 427 } else if (mwifiex_is_network_compatible_for_static_wep(priv,
462 bss_desc)) { 428 bss_desc)) {
463 /* Static WEP enabled */ 429 /* Static WEP enabled */
464 dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n"); 430 dev_dbg(adapter->dev, "info: Disable 11n in WEP mode.\n");
465 bss_desc->disable_11n = true; 431 bss_desc->disable_11n = true;
466 return index; 432 return 0;
467 } else if (mwifiex_is_network_compatible_for_wpa(priv, bss_desc, 433 } else if (mwifiex_is_network_compatible_for_wpa(priv,
468 index)) { 434 bss_desc)) {
469 /* WPA enabled */ 435 /* WPA enabled */
470 if (((priv->adapter->config_bands & BAND_GN 436 if (((priv->adapter->config_bands & BAND_GN
471 || priv->adapter->config_bands & BAND_AN) 437 || priv->adapter->config_bands & BAND_AN)
@@ -483,9 +449,9 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
483 return -1; 449 return -1;
484 } 450 }
485 } 451 }
486 return index; 452 return 0;
487 } else if (mwifiex_is_network_compatible_for_wpa2(priv, 453 } else if (mwifiex_is_network_compatible_for_wpa2(priv,
488 bss_desc, index)) { 454 bss_desc)) {
489 /* WPA2 enabled */ 455 /* WPA2 enabled */
490 if (((priv->adapter->config_bands & BAND_GN 456 if (((priv->adapter->config_bands & BAND_GN
491 || priv->adapter->config_bands & BAND_AN) 457 || priv->adapter->config_bands & BAND_AN)
@@ -503,22 +469,22 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
503 return -1; 469 return -1;
504 } 470 }
505 } 471 }
506 return index; 472 return 0;
507 } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv, 473 } else if (mwifiex_is_network_compatible_for_adhoc_aes(priv,
508 bss_desc)) { 474 bss_desc)) {
509 /* Ad-hoc AES enabled */ 475 /* Ad-hoc AES enabled */
510 return index; 476 return 0;
511 } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv, 477 } else if (mwifiex_is_network_compatible_for_dynamic_wep(priv,
512 bss_desc, index)) { 478 bss_desc)) {
513 /* Dynamic WEP enabled */ 479 /* Dynamic WEP enabled */
514 return index; 480 return 0;
515 } 481 }
516 482
517 /* Security doesn't match */ 483 /* Security doesn't match */
518 dev_dbg(adapter->dev, "info: %s: failed: index=%d " 484 dev_dbg(adapter->dev, "info: %s: failed: "
519 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode" 485 "wpa_ie=%#x wpa2_ie=%#x WEP=%s WPA=%s WPA2=%s EncMode"
520 "=%#x privacy=%#x\n", 486 "=%#x privacy=%#x\n",
521 __func__, index, 487 __func__,
522 (bss_desc->bcn_wpa_ie) ? 488 (bss_desc->bcn_wpa_ie) ?
523 (*(bss_desc->bcn_wpa_ie)).vend_hdr. 489 (*(bss_desc->bcn_wpa_ie)).vend_hdr.
524 element_id : 0, 490 element_id : 0,
@@ -538,52 +504,6 @@ mwifiex_is_network_compatible(struct mwifiex_private *priv, u32 index, u32 mode)
538} 504}
539 505
540/* 506/*
541 * This function finds the best SSID in the scan list.
542 *
543 * It searches the scan table for the best SSID that also matches the current
544 * adapter network preference (mode, security etc.).
545 */
546static s32
547mwifiex_find_best_network_in_list(struct mwifiex_private *priv)
548{
549 struct mwifiex_adapter *adapter = priv->adapter;
550 u32 mode = priv->bss_mode;
551 s32 best_net = -1;
552 s32 best_rssi = 0;
553 u32 i;
554
555 dev_dbg(adapter->dev, "info: num of BSSIDs = %d\n",
556 adapter->num_in_scan_table);
557
558 for (i = 0; i < adapter->num_in_scan_table; i++) {
559 switch (mode) {
560 case NL80211_IFTYPE_STATION:
561 case NL80211_IFTYPE_ADHOC:
562 if (mwifiex_is_network_compatible(priv, i, mode) >= 0) {
563 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
564 best_rssi) {
565 best_rssi = SCAN_RSSI(adapter->
566 scan_table[i].rssi);
567 best_net = i;
568 }
569 }
570 break;
571 case NL80211_IFTYPE_UNSPECIFIED:
572 default:
573 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
574 best_rssi) {
575 best_rssi = SCAN_RSSI(adapter->scan_table[i].
576 rssi);
577 best_net = i;
578 }
579 break;
580 }
581 }
582
583 return best_net;
584}
585
586/*
587 * This function creates a channel list for the driver to scan, based 507 * This function creates a channel list for the driver to scan, based
588 * on region/band information. 508 * on region/band information.
589 * 509 *
@@ -1161,34 +1081,13 @@ mwifiex_ret_802_11_scan_get_tlv_ptrs(struct mwifiex_adapter *adapter,
1161} 1081}
1162 1082
1163/* 1083/*
1164 * This function interprets a BSS scan response returned from the firmware. 1084 * This function parses provided beacon buffer and updates
1165 * 1085 * respective fields in bss descriptor structure.
1166 * The various fixed fields and IEs are parsed and passed back for a BSS
1167 * probe response or beacon from scan command. Information is recorded as
1168 * needed in the scan table for that entry.
1169 *
1170 * The following IE types are recognized and parsed -
1171 * - SSID
1172 * - Supported rates
1173 * - FH parameters set
1174 * - DS parameters set
1175 * - CF parameters set
1176 * - IBSS parameters set
1177 * - ERP information
1178 * - Extended supported rates
1179 * - Vendor specific (221)
1180 * - RSN IE
1181 * - WAPI IE
1182 * - HT capability
1183 * - HT operation
1184 * - BSS Coexistence 20/40
1185 * - Extended capability
1186 * - Overlapping BSS scan parameters
1187 */ 1086 */
1188static int 1087int
1189mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter, 1088mwifiex_update_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1190 struct mwifiex_bssdescriptor *bss_entry, 1089 struct mwifiex_bssdescriptor *bss_entry,
1191 u8 **beacon_info, u32 *bytes_left) 1090 u8 *ie_buf, u32 ie_len)
1192{ 1091{
1193 int ret = 0; 1092 int ret = 0;
1194 u8 element_id; 1093 u8 element_id;
@@ -1196,135 +1095,43 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1196 struct ieee_types_ds_param_set *ds_param_set; 1095 struct ieee_types_ds_param_set *ds_param_set;
1197 struct ieee_types_cf_param_set *cf_param_set; 1096 struct ieee_types_cf_param_set *cf_param_set;
1198 struct ieee_types_ibss_param_set *ibss_param_set; 1097 struct ieee_types_ibss_param_set *ibss_param_set;
1199 __le16 beacon_interval;
1200 __le16 capabilities;
1201 u8 *current_ptr; 1098 u8 *current_ptr;
1202 u8 *rate; 1099 u8 *rate;
1203 u8 element_len; 1100 u8 element_len;
1204 u16 total_ie_len; 1101 u16 total_ie_len;
1205 u8 bytes_to_copy; 1102 u8 bytes_to_copy;
1206 u8 rate_size; 1103 u8 rate_size;
1207 u16 beacon_size;
1208 u8 found_data_rate_ie; 1104 u8 found_data_rate_ie;
1209 u32 bytes_left_for_current_beacon; 1105 u32 bytes_left;
1210 struct ieee_types_vendor_specific *vendor_ie; 1106 struct ieee_types_vendor_specific *vendor_ie;
1211 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 }; 1107 const u8 wpa_oui[4] = { 0x00, 0x50, 0xf2, 0x01 };
1212 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 }; 1108 const u8 wmm_oui[4] = { 0x00, 0x50, 0xf2, 0x02 };
1213 1109
1214 found_data_rate_ie = false; 1110 found_data_rate_ie = false;
1215 rate_size = 0; 1111 rate_size = 0;
1216 beacon_size = 0; 1112 current_ptr = ie_buf;
1217 1113 bytes_left = ie_len;
1218 if (*bytes_left >= sizeof(beacon_size)) { 1114 bss_entry->beacon_buf = ie_buf;
1219 /* Extract & convert beacon size from the command buffer */ 1115 bss_entry->beacon_buf_size = ie_len;
1220 memcpy(&beacon_size, *beacon_info, sizeof(beacon_size));
1221 *bytes_left -= sizeof(beacon_size);
1222 *beacon_info += sizeof(beacon_size);
1223 }
1224
1225 if (!beacon_size || beacon_size > *bytes_left) {
1226 *beacon_info += *bytes_left;
1227 *bytes_left = 0;
1228 return -1;
1229 }
1230
1231 /* Initialize the current working beacon pointer for this BSS
1232 iteration */
1233 current_ptr = *beacon_info;
1234
1235 /* Advance the return beacon pointer past the current beacon */
1236 *beacon_info += beacon_size;
1237 *bytes_left -= beacon_size;
1238
1239 bytes_left_for_current_beacon = beacon_size;
1240
1241 memcpy(bss_entry->mac_address, current_ptr, ETH_ALEN);
1242 dev_dbg(adapter->dev, "info: InterpretIE: AP MAC Addr: %pM\n",
1243 bss_entry->mac_address);
1244
1245 current_ptr += ETH_ALEN;
1246 bytes_left_for_current_beacon -= ETH_ALEN;
1247
1248 if (bytes_left_for_current_beacon < 12) {
1249 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1250 return -1;
1251 }
1252
1253 /*
1254 * Next 4 fields are RSSI, time stamp, beacon interval,
1255 * and capability information
1256 */
1257
1258 /* RSSI is 1 byte long */
1259 bss_entry->rssi = (s32) (*current_ptr);
1260 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n", *current_ptr);
1261 current_ptr += 1;
1262 bytes_left_for_current_beacon -= 1;
1263
1264 /*
1265 * The RSSI is not part of the beacon/probe response. After we have
1266 * advanced current_ptr past the RSSI field, save the remaining
1267 * data for use at the application layer
1268 */
1269 bss_entry->beacon_buf = current_ptr;
1270 bss_entry->beacon_buf_size = bytes_left_for_current_beacon;
1271
1272 /* Time stamp is 8 bytes long */
1273 memcpy(bss_entry->time_stamp, current_ptr, 8);
1274 current_ptr += 8;
1275 bytes_left_for_current_beacon -= 8;
1276
1277 /* Beacon interval is 2 bytes long */
1278 memcpy(&beacon_interval, current_ptr, 2);
1279 bss_entry->beacon_period = le16_to_cpu(beacon_interval);
1280 current_ptr += 2;
1281 bytes_left_for_current_beacon -= 2;
1282
1283 /* Capability information is 2 bytes long */
1284 memcpy(&capabilities, current_ptr, 2);
1285 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1286 capabilities);
1287 bss_entry->cap_info_bitmap = le16_to_cpu(capabilities);
1288 current_ptr += 2;
1289 bytes_left_for_current_beacon -= 2;
1290
1291 /* Rest of the current buffer are IE's */
1292 dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP = %d\n",
1293 bytes_left_for_current_beacon);
1294
1295 if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
1296 dev_dbg(adapter->dev, "info: InterpretIE: AP WEP enabled\n");
1297 bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
1298 } else {
1299 bss_entry->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
1300 }
1301
1302 if (bss_entry->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
1303 bss_entry->bss_mode = NL80211_IFTYPE_ADHOC;
1304 else
1305 bss_entry->bss_mode = NL80211_IFTYPE_STATION;
1306
1307 1116
1308 /* Process variable IE */ 1117 /* Process variable IE */
1309 while (bytes_left_for_current_beacon >= 2) { 1118 while (bytes_left >= 2) {
1310 element_id = *current_ptr; 1119 element_id = *current_ptr;
1311 element_len = *(current_ptr + 1); 1120 element_len = *(current_ptr + 1);
1312 total_ie_len = element_len + sizeof(struct ieee_types_header); 1121 total_ie_len = element_len + sizeof(struct ieee_types_header);
1313 1122
1314 if (bytes_left_for_current_beacon < total_ie_len) { 1123 if (bytes_left < total_ie_len) {
1315 dev_err(adapter->dev, "err: InterpretIE: in processing" 1124 dev_err(adapter->dev, "err: InterpretIE: in processing"
1316 " IE, bytes left < IE length\n"); 1125 " IE, bytes left < IE length\n");
1317 bytes_left_for_current_beacon = 0; 1126 return -1;
1318 ret = -1;
1319 continue;
1320 } 1127 }
1321 switch (element_id) { 1128 switch (element_id) {
1322 case WLAN_EID_SSID: 1129 case WLAN_EID_SSID:
1323 bss_entry->ssid.ssid_len = element_len; 1130 bss_entry->ssid.ssid_len = element_len;
1324 memcpy(bss_entry->ssid.ssid, (current_ptr + 2), 1131 memcpy(bss_entry->ssid.ssid, (current_ptr + 2),
1325 element_len); 1132 element_len);
1326 dev_dbg(adapter->dev, "info: InterpretIE: ssid: %-32s\n", 1133 dev_dbg(adapter->dev, "info: InterpretIE: ssid: "
1327 bss_entry->ssid.ssid); 1134 "%-32s\n", bss_entry->ssid.ssid);
1328 break; 1135 break;
1329 1136
1330 case WLAN_EID_SUPP_RATES: 1137 case WLAN_EID_SUPP_RATES:
@@ -1471,13 +1278,6 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1471 sizeof(struct ieee_types_header) - 1278 sizeof(struct ieee_types_header) -
1472 bss_entry->beacon_buf); 1279 bss_entry->beacon_buf);
1473 break; 1280 break;
1474 case WLAN_EID_OVERLAP_BSS_SCAN_PARAM:
1475 bss_entry->bcn_obss_scan =
1476 (struct ieee_types_obss_scan_param *)
1477 current_ptr;
1478 bss_entry->overlap_bss_offset = (u16) (current_ptr -
1479 bss_entry->beacon_buf);
1480 break;
1481 default: 1281 default:
1482 break; 1282 break;
1483 } 1283 }
@@ -1485,577 +1285,13 @@ mwifiex_interpret_bss_desc_with_ie(struct mwifiex_adapter *adapter,
1485 current_ptr += element_len + 2; 1285 current_ptr += element_len + 2;
1486 1286
1487 /* Need to account for IE ID and IE Len */ 1287 /* Need to account for IE ID and IE Len */
1488 bytes_left_for_current_beacon -= (element_len + 2); 1288 bytes_left -= (element_len + 2);
1489 1289
1490 } /* while (bytes_left_for_current_beacon > 2) */ 1290 } /* while (bytes_left > 2) */
1491 return ret; 1291 return ret;
1492} 1292}
1493 1293
1494/* 1294/*
1495 * This function adjusts the pointers used in beacon buffers to reflect
1496 * shifts.
1497 *
1498 * The memory allocated for beacon buffers is of fixed sizes where all the
1499 * saved beacons must be stored. New beacons are added in the free portion
1500 * of this memory, space permitting; while duplicate beacon buffers are
1501 * placed at the same start location. However, since duplicate beacon
1502 * buffers may not match the size of the old one, all the following buffers
1503 * in the memory must be shifted to either make space, or to fill up freed
1504 * up space.
1505 *
1506 * This function is used to update the beacon buffer pointers that are past
1507 * an existing beacon buffer that is updated with a new one of different
1508 * size. The pointers are shifted by a fixed amount, either forward or
1509 * backward.
1510 *
1511 * the following pointers in every affected beacon buffers are changed, if
1512 * present -
1513 * - WPA IE pointer
1514 * - RSN IE pointer
1515 * - WAPI IE pointer
1516 * - HT capability IE pointer
1517 * - HT information IE pointer
1518 * - BSS coexistence 20/40 IE pointer
1519 * - Extended capability IE pointer
1520 * - Overlapping BSS scan parameter IE pointer
1521 */
1522static void
1523mwifiex_adjust_beacon_buffer_ptrs(struct mwifiex_private *priv, u8 advance,
1524 u8 *bcn_store, u32 rem_bcn_size,
1525 u32 num_of_ent)
1526{
1527 struct mwifiex_adapter *adapter = priv->adapter;
1528 u32 adj_idx;
1529 for (adj_idx = 0; adj_idx < num_of_ent; adj_idx++) {
1530 if (adapter->scan_table[adj_idx].beacon_buf > bcn_store) {
1531
1532 if (advance)
1533 adapter->scan_table[adj_idx].beacon_buf +=
1534 rem_bcn_size;
1535 else
1536 adapter->scan_table[adj_idx].beacon_buf -=
1537 rem_bcn_size;
1538
1539 if (adapter->scan_table[adj_idx].bcn_wpa_ie)
1540 adapter->scan_table[adj_idx].bcn_wpa_ie =
1541 (struct ieee_types_vendor_specific *)
1542 (adapter->scan_table[adj_idx].beacon_buf +
1543 adapter->scan_table[adj_idx].wpa_offset);
1544 if (adapter->scan_table[adj_idx].bcn_rsn_ie)
1545 adapter->scan_table[adj_idx].bcn_rsn_ie =
1546 (struct ieee_types_generic *)
1547 (adapter->scan_table[adj_idx].beacon_buf +
1548 adapter->scan_table[adj_idx].rsn_offset);
1549 if (adapter->scan_table[adj_idx].bcn_wapi_ie)
1550 adapter->scan_table[adj_idx].bcn_wapi_ie =
1551 (struct ieee_types_generic *)
1552 (adapter->scan_table[adj_idx].beacon_buf +
1553 adapter->scan_table[adj_idx].wapi_offset);
1554 if (adapter->scan_table[adj_idx].bcn_ht_cap)
1555 adapter->scan_table[adj_idx].bcn_ht_cap =
1556 (struct ieee80211_ht_cap *)
1557 (adapter->scan_table[adj_idx].beacon_buf +
1558 adapter->scan_table[adj_idx].ht_cap_offset);
1559
1560 if (adapter->scan_table[adj_idx].bcn_ht_info)
1561 adapter->scan_table[adj_idx].bcn_ht_info =
1562 (struct ieee80211_ht_info *)
1563 (adapter->scan_table[adj_idx].beacon_buf +
1564 adapter->scan_table[adj_idx].ht_info_offset);
1565 if (adapter->scan_table[adj_idx].bcn_bss_co_2040)
1566 adapter->scan_table[adj_idx].bcn_bss_co_2040 =
1567 (u8 *)
1568 (adapter->scan_table[adj_idx].beacon_buf +
1569 adapter->scan_table[adj_idx].bss_co_2040_offset);
1570 if (adapter->scan_table[adj_idx].bcn_ext_cap)
1571 adapter->scan_table[adj_idx].bcn_ext_cap =
1572 (u8 *)
1573 (adapter->scan_table[adj_idx].beacon_buf +
1574 adapter->scan_table[adj_idx].ext_cap_offset);
1575 if (adapter->scan_table[adj_idx].bcn_obss_scan)
1576 adapter->scan_table[adj_idx].bcn_obss_scan =
1577 (struct ieee_types_obss_scan_param *)
1578 (adapter->scan_table[adj_idx].beacon_buf +
1579 adapter->scan_table[adj_idx].overlap_bss_offset);
1580 }
1581 }
1582}
1583
1584/*
1585 * This function updates the pointers used in beacon buffer for given bss
1586 * descriptor to reflect shifts
1587 *
1588 * Following pointers are updated
1589 * - WPA IE pointer
1590 * - RSN IE pointer
1591 * - WAPI IE pointer
1592 * - HT capability IE pointer
1593 * - HT information IE pointer
1594 * - BSS coexistence 20/40 IE pointer
1595 * - Extended capability IE pointer
1596 * - Overlapping BSS scan parameter IE pointer
1597 */
1598static void
1599mwifiex_update_beacon_buffer_ptrs(struct mwifiex_bssdescriptor *beacon)
1600{
1601 if (beacon->bcn_wpa_ie)
1602 beacon->bcn_wpa_ie = (struct ieee_types_vendor_specific *)
1603 (beacon->beacon_buf + beacon->wpa_offset);
1604 if (beacon->bcn_rsn_ie)
1605 beacon->bcn_rsn_ie = (struct ieee_types_generic *)
1606 (beacon->beacon_buf + beacon->rsn_offset);
1607 if (beacon->bcn_wapi_ie)
1608 beacon->bcn_wapi_ie = (struct ieee_types_generic *)
1609 (beacon->beacon_buf + beacon->wapi_offset);
1610 if (beacon->bcn_ht_cap)
1611 beacon->bcn_ht_cap = (struct ieee80211_ht_cap *)
1612 (beacon->beacon_buf + beacon->ht_cap_offset);
1613 if (beacon->bcn_ht_info)
1614 beacon->bcn_ht_info = (struct ieee80211_ht_info *)
1615 (beacon->beacon_buf + beacon->ht_info_offset);
1616 if (beacon->bcn_bss_co_2040)
1617 beacon->bcn_bss_co_2040 = (u8 *) (beacon->beacon_buf +
1618 beacon->bss_co_2040_offset);
1619 if (beacon->bcn_ext_cap)
1620 beacon->bcn_ext_cap = (u8 *) (beacon->beacon_buf +
1621 beacon->ext_cap_offset);
1622 if (beacon->bcn_obss_scan)
1623 beacon->bcn_obss_scan = (struct ieee_types_obss_scan_param *)
1624 (beacon->beacon_buf + beacon->overlap_bss_offset);
1625}
1626
1627/*
1628 * This function stores a beacon or probe response for a BSS returned
1629 * in the scan.
1630 *
1631 * This stores a new scan response or an update for a previous scan response.
1632 * New entries need to verify that they do not exceed the total amount of
1633 * memory allocated for the table.
1634 *
1635 * Replacement entries need to take into consideration the amount of space
1636 * currently allocated for the beacon/probe response and adjust the entry
1637 * as needed.
1638 *
1639 * A small amount of extra pad (SCAN_BEACON_ENTRY_PAD) is generally reserved
1640 * for an entry in case it is a beacon since a probe response for the
1641 * network will by larger per the standard. This helps to reduce the
1642 * amount of memory copying to fit a new probe response into an entry
1643 * already occupied by a network's previously stored beacon.
1644 */
1645static void
1646mwifiex_ret_802_11_scan_store_beacon(struct mwifiex_private *priv,
1647 u32 beacon_idx, u32 num_of_ent,
1648 struct mwifiex_bssdescriptor *new_beacon)
1649{
1650 struct mwifiex_adapter *adapter = priv->adapter;
1651 u8 *bcn_store;
1652 u32 new_bcn_size;
1653 u32 old_bcn_size;
1654 u32 bcn_space;
1655
1656 if (adapter->scan_table[beacon_idx].beacon_buf) {
1657
1658 new_bcn_size = new_beacon->beacon_buf_size;
1659 old_bcn_size = adapter->scan_table[beacon_idx].beacon_buf_size;
1660 bcn_space = adapter->scan_table[beacon_idx].beacon_buf_size_max;
1661 bcn_store = adapter->scan_table[beacon_idx].beacon_buf;
1662
1663 /* Set the max to be the same as current entry unless changed
1664 below */
1665 new_beacon->beacon_buf_size_max = bcn_space;
1666 if (new_bcn_size == old_bcn_size) {
1667 /*
1668 * Beacon is the same size as the previous entry.
1669 * Replace the previous contents with the scan result
1670 */
1671 memcpy(bcn_store, new_beacon->beacon_buf,
1672 new_beacon->beacon_buf_size);
1673
1674 } else if (new_bcn_size <= bcn_space) {
1675 /*
1676 * New beacon size will fit in the amount of space
1677 * we have previously allocated for it
1678 */
1679
1680 /* Copy the new beacon buffer entry over the old one */
1681 memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
1682
1683 /*
1684 * If the old beacon size was less than the maximum
1685 * we had alloted for the entry, and the new entry
1686 * is even smaller, reset the max size to the old
1687 * beacon entry and compress the storage space
1688 * (leaving a new pad space of (old_bcn_size -
1689 * new_bcn_size).
1690 */
1691 if (old_bcn_size < bcn_space
1692 && new_bcn_size <= old_bcn_size) {
1693 /*
1694 * Old Beacon size is smaller than the alloted
1695 * storage size. Shrink the alloted storage
1696 * space.
1697 */
1698 dev_dbg(adapter->dev, "info: AppControl:"
1699 " smaller duplicate beacon "
1700 "(%d), old = %d, new = %d, space = %d,"
1701 "left = %d\n",
1702 beacon_idx, old_bcn_size, new_bcn_size,
1703 bcn_space,
1704 (int)(sizeof(adapter->bcn_buf) -
1705 (adapter->bcn_buf_end -
1706 adapter->bcn_buf)));
1707
1708 /*
1709 * memmove (since the memory overlaps) the
1710 * data after the beacon we just stored to the
1711 * end of the current beacon. This cleans up
1712 * any unused space the old larger beacon was
1713 * using in the buffer
1714 */
1715 memmove(bcn_store + old_bcn_size,
1716 bcn_store + bcn_space,
1717 adapter->bcn_buf_end - (bcn_store +
1718 bcn_space));
1719
1720 /*
1721 * Decrement the end pointer by the difference
1722 * between the old larger size and the new
1723 * smaller size since we are using less space
1724 * due to the new beacon being smaller
1725 */
1726 adapter->bcn_buf_end -=
1727 (bcn_space - old_bcn_size);
1728
1729 /* Set the maximum storage size to the old
1730 beacon size */
1731 new_beacon->beacon_buf_size_max = old_bcn_size;
1732
1733 /* Adjust beacon buffer pointers that are past
1734 the current */
1735 mwifiex_adjust_beacon_buffer_ptrs(priv, 0,
1736 bcn_store, (bcn_space - old_bcn_size),
1737 num_of_ent);
1738 }
1739 } else if (adapter->bcn_buf_end + (new_bcn_size - bcn_space)
1740 < (adapter->bcn_buf + sizeof(adapter->bcn_buf))) {
1741 /*
1742 * Beacon is larger than space previously allocated
1743 * (bcn_space) and there is enough space left in the
1744 * beaconBuffer to store the additional data
1745 */
1746 dev_dbg(adapter->dev, "info: AppControl:"
1747 " larger duplicate beacon (%d), "
1748 "old = %d, new = %d, space = %d, left = %d\n",
1749 beacon_idx, old_bcn_size, new_bcn_size,
1750 bcn_space,
1751 (int)(sizeof(adapter->bcn_buf) -
1752 (adapter->bcn_buf_end -
1753 adapter->bcn_buf)));
1754
1755 /*
1756 * memmove (since the memory overlaps) the data
1757 * after the beacon we just stored to the end of
1758 * the current beacon. This moves the data for
1759 * the beacons after this further in memory to
1760 * make space for the new larger beacon we are
1761 * about to copy in.
1762 */
1763 memmove(bcn_store + new_bcn_size,
1764 bcn_store + bcn_space,
1765 adapter->bcn_buf_end - (bcn_store + bcn_space));
1766
1767 /* Copy the new beacon buffer entry over the old one */
1768 memcpy(bcn_store, new_beacon->beacon_buf, new_bcn_size);
1769
1770 /* Move the beacon end pointer by the amount of new
1771 beacon data we are adding */
1772 adapter->bcn_buf_end += (new_bcn_size - bcn_space);
1773
1774 /*
1775 * This entry is bigger than the alloted max space
1776 * previously reserved. Increase the max space to
1777 * be equal to the new beacon size
1778 */
1779 new_beacon->beacon_buf_size_max = new_bcn_size;
1780
1781 /* Adjust beacon buffer pointers that are past the
1782 current */
1783 mwifiex_adjust_beacon_buffer_ptrs(priv, 1, bcn_store,
1784 (new_bcn_size - bcn_space),
1785 num_of_ent);
1786 } else {
1787 /*
1788 * Beacon is larger than the previously allocated space,
1789 * but there is not enough free space to store the
1790 * additional data.
1791 */
1792 dev_err(adapter->dev, "AppControl: larger duplicate "
1793 " beacon (%d), old = %d new = %d, space = %d,"
1794 " left = %d\n", beacon_idx, old_bcn_size,
1795 new_bcn_size, bcn_space,
1796 (int)(sizeof(adapter->bcn_buf) -
1797 (adapter->bcn_buf_end - adapter->bcn_buf)));
1798
1799 /* Storage failure, keep old beacon intact */
1800 new_beacon->beacon_buf_size = old_bcn_size;
1801 if (new_beacon->bcn_wpa_ie)
1802 new_beacon->wpa_offset =
1803 adapter->scan_table[beacon_idx].
1804 wpa_offset;
1805 if (new_beacon->bcn_rsn_ie)
1806 new_beacon->rsn_offset =
1807 adapter->scan_table[beacon_idx].
1808 rsn_offset;
1809 if (new_beacon->bcn_wapi_ie)
1810 new_beacon->wapi_offset =
1811 adapter->scan_table[beacon_idx].
1812 wapi_offset;
1813 if (new_beacon->bcn_ht_cap)
1814 new_beacon->ht_cap_offset =
1815 adapter->scan_table[beacon_idx].
1816 ht_cap_offset;
1817 if (new_beacon->bcn_ht_info)
1818 new_beacon->ht_info_offset =
1819 adapter->scan_table[beacon_idx].
1820 ht_info_offset;
1821 if (new_beacon->bcn_bss_co_2040)
1822 new_beacon->bss_co_2040_offset =
1823 adapter->scan_table[beacon_idx].
1824 bss_co_2040_offset;
1825 if (new_beacon->bcn_ext_cap)
1826 new_beacon->ext_cap_offset =
1827 adapter->scan_table[beacon_idx].
1828 ext_cap_offset;
1829 if (new_beacon->bcn_obss_scan)
1830 new_beacon->overlap_bss_offset =
1831 adapter->scan_table[beacon_idx].
1832 overlap_bss_offset;
1833 }
1834 /* Point the new entry to its permanent storage space */
1835 new_beacon->beacon_buf = bcn_store;
1836 mwifiex_update_beacon_buffer_ptrs(new_beacon);
1837 } else {
1838 /*
1839 * No existing beacon data exists for this entry, check to see
1840 * if we can fit it in the remaining space
1841 */
1842 if (adapter->bcn_buf_end + new_beacon->beacon_buf_size +
1843 SCAN_BEACON_ENTRY_PAD < (adapter->bcn_buf +
1844 sizeof(adapter->bcn_buf))) {
1845
1846 /*
1847 * Copy the beacon buffer data from the local entry to
1848 * the adapter dev struct buffer space used to store
1849 * the raw beacon data for each entry in the scan table
1850 */
1851 memcpy(adapter->bcn_buf_end, new_beacon->beacon_buf,
1852 new_beacon->beacon_buf_size);
1853
1854 /* Update the beacon ptr to point to the table save
1855 area */
1856 new_beacon->beacon_buf = adapter->bcn_buf_end;
1857 new_beacon->beacon_buf_size_max =
1858 (new_beacon->beacon_buf_size +
1859 SCAN_BEACON_ENTRY_PAD);
1860
1861 mwifiex_update_beacon_buffer_ptrs(new_beacon);
1862
1863 /* Increment the end pointer by the size reserved */
1864 adapter->bcn_buf_end += new_beacon->beacon_buf_size_max;
1865
1866 dev_dbg(adapter->dev, "info: AppControl: beacon[%02d]"
1867 " sz=%03d, used = %04d, left = %04d\n",
1868 beacon_idx,
1869 new_beacon->beacon_buf_size,
1870 (int)(adapter->bcn_buf_end - adapter->bcn_buf),
1871 (int)(sizeof(adapter->bcn_buf) -
1872 (adapter->bcn_buf_end -
1873 adapter->bcn_buf)));
1874 } else {
1875 /* No space for new beacon */
1876 dev_dbg(adapter->dev, "info: AppControl: no space for"
1877 " beacon (%d): %pM sz=%03d, left=%03d\n",
1878 beacon_idx, new_beacon->mac_address,
1879 new_beacon->beacon_buf_size,
1880 (int)(sizeof(adapter->bcn_buf) -
1881 (adapter->bcn_buf_end -
1882 adapter->bcn_buf)));
1883
1884 /* Storage failure; clear storage records for this
1885 bcn */
1886 new_beacon->beacon_buf = NULL;
1887 new_beacon->beacon_buf_size = 0;
1888 new_beacon->beacon_buf_size_max = 0;
1889 new_beacon->bcn_wpa_ie = NULL;
1890 new_beacon->wpa_offset = 0;
1891 new_beacon->bcn_rsn_ie = NULL;
1892 new_beacon->rsn_offset = 0;
1893 new_beacon->bcn_wapi_ie = NULL;
1894 new_beacon->wapi_offset = 0;
1895 new_beacon->bcn_ht_cap = NULL;
1896 new_beacon->ht_cap_offset = 0;
1897 new_beacon->bcn_ht_info = NULL;
1898 new_beacon->ht_info_offset = 0;
1899 new_beacon->bcn_bss_co_2040 = NULL;
1900 new_beacon->bss_co_2040_offset = 0;
1901 new_beacon->bcn_ext_cap = NULL;
1902 new_beacon->ext_cap_offset = 0;
1903 new_beacon->bcn_obss_scan = NULL;
1904 new_beacon->overlap_bss_offset = 0;
1905 }
1906 }
1907}
1908
1909/*
1910 * This function restores a beacon buffer of the current BSS descriptor.
1911 */
1912static void mwifiex_restore_curr_bcn(struct mwifiex_private *priv)
1913{
1914 struct mwifiex_adapter *adapter = priv->adapter;
1915 struct mwifiex_bssdescriptor *curr_bss =
1916 &priv->curr_bss_params.bss_descriptor;
1917 unsigned long flags;
1918
1919 if (priv->curr_bcn_buf &&
1920 ((adapter->bcn_buf_end + priv->curr_bcn_size) <
1921 (adapter->bcn_buf + sizeof(adapter->bcn_buf)))) {
1922 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1923
1924 /* restore the current beacon buffer */
1925 memcpy(adapter->bcn_buf_end, priv->curr_bcn_buf,
1926 priv->curr_bcn_size);
1927 curr_bss->beacon_buf = adapter->bcn_buf_end;
1928 curr_bss->beacon_buf_size = priv->curr_bcn_size;
1929 adapter->bcn_buf_end += priv->curr_bcn_size;
1930
1931 /* adjust the pointers in the current BSS descriptor */
1932 if (curr_bss->bcn_wpa_ie)
1933 curr_bss->bcn_wpa_ie =
1934 (struct ieee_types_vendor_specific *)
1935 (curr_bss->beacon_buf +
1936 curr_bss->wpa_offset);
1937
1938 if (curr_bss->bcn_rsn_ie)
1939 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
1940 (curr_bss->beacon_buf +
1941 curr_bss->rsn_offset);
1942
1943 if (curr_bss->bcn_ht_cap)
1944 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
1945 (curr_bss->beacon_buf +
1946 curr_bss->ht_cap_offset);
1947
1948 if (curr_bss->bcn_ht_info)
1949 curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
1950 (curr_bss->beacon_buf +
1951 curr_bss->ht_info_offset);
1952
1953 if (curr_bss->bcn_bss_co_2040)
1954 curr_bss->bcn_bss_co_2040 =
1955 (u8 *) (curr_bss->beacon_buf +
1956 curr_bss->bss_co_2040_offset);
1957
1958 if (curr_bss->bcn_ext_cap)
1959 curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
1960 curr_bss->ext_cap_offset);
1961
1962 if (curr_bss->bcn_obss_scan)
1963 curr_bss->bcn_obss_scan =
1964 (struct ieee_types_obss_scan_param *)
1965 (curr_bss->beacon_buf +
1966 curr_bss->overlap_bss_offset);
1967
1968 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1969
1970 dev_dbg(adapter->dev, "info: current beacon restored %d\n",
1971 priv->curr_bcn_size);
1972 } else {
1973 dev_warn(adapter->dev,
1974 "curr_bcn_buf not saved or bcn_buf has no space\n");
1975 }
1976}
1977
1978/*
1979 * This function post processes the scan table after a new scan command has
1980 * completed.
1981 *
1982 * It inspects each entry of the scan table and tries to find an entry that
1983 * matches with our current associated/joined network from the scan. If
1984 * one is found, the stored copy of the BSS descriptor of our current network
1985 * is updated.
1986 *
1987 * It also debug dumps the current scan table contents after processing is over.
1988 */
1989static void
1990mwifiex_process_scan_results(struct mwifiex_private *priv)
1991{
1992 struct mwifiex_adapter *adapter = priv->adapter;
1993 s32 j;
1994 u32 i;
1995 unsigned long flags;
1996
1997 if (priv->media_connected) {
1998
1999 j = mwifiex_find_ssid_in_list(priv, &priv->curr_bss_params.
2000 bss_descriptor.ssid,
2001 priv->curr_bss_params.
2002 bss_descriptor.mac_address,
2003 priv->bss_mode);
2004
2005 if (j >= 0) {
2006 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
2007 priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
2008 priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
2009 priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
2010 priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
2011 priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
2012 priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
2013 priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
2014 priv->curr_bss_params.bss_descriptor.ht_cap_offset =
2015 0;
2016 priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
2017 priv->curr_bss_params.bss_descriptor.ht_info_offset =
2018 0;
2019 priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
2020 NULL;
2021 priv->curr_bss_params.bss_descriptor.
2022 bss_co_2040_offset = 0;
2023 priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
2024 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
2025 priv->curr_bss_params.bss_descriptor.
2026 bcn_obss_scan = NULL;
2027 priv->curr_bss_params.bss_descriptor.
2028 overlap_bss_offset = 0;
2029 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
2030 priv->curr_bss_params.bss_descriptor.beacon_buf_size =
2031 0;
2032 priv->curr_bss_params.bss_descriptor.
2033 beacon_buf_size_max = 0;
2034
2035 dev_dbg(adapter->dev, "info: Found current ssid/bssid"
2036 " in list @ index #%d\n", j);
2037 /* Make a copy of current BSSID descriptor */
2038 memcpy(&priv->curr_bss_params.bss_descriptor,
2039 &adapter->scan_table[j],
2040 sizeof(priv->curr_bss_params.bss_descriptor));
2041
2042 mwifiex_save_curr_bcn(priv);
2043 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
2044
2045 } else {
2046 mwifiex_restore_curr_bcn(priv);
2047 }
2048 }
2049
2050 for (i = 0; i < adapter->num_in_scan_table; i++)
2051 dev_dbg(adapter->dev, "info: scan:(%02d) %pM "
2052 "RSSI[%03d], SSID[%s]\n",
2053 i, adapter->scan_table[i].mac_address,
2054 (s32) adapter->scan_table[i].rssi,
2055 adapter->scan_table[i].ssid.ssid);
2056}
2057
2058/*
2059 * This function converts radio type scan parameter to a band configuration 1295 * This function converts radio type scan parameter to a band configuration
2060 * to be used in join command. 1296 * to be used in join command.
2061 */ 1297 */
@@ -2072,175 +1308,6 @@ mwifiex_radio_type_to_band(u8 radio_type)
2072} 1308}
2073 1309
2074/* 1310/*
2075 * This function deletes a specific indexed entry from the scan table.
2076 *
2077 * This also compacts the remaining entries and adjusts any buffering
2078 * of beacon/probe response data if needed.
2079 */
2080static void
2081mwifiex_scan_delete_table_entry(struct mwifiex_private *priv, s32 table_idx)
2082{
2083 struct mwifiex_adapter *adapter = priv->adapter;
2084 u32 del_idx;
2085 u32 beacon_buf_adj;
2086 u8 *beacon_buf;
2087
2088 /*
2089 * Shift the saved beacon buffer data for the scan table back over the
2090 * entry being removed. Update the end of buffer pointer. Save the
2091 * deleted buffer allocation size for pointer adjustments for entries
2092 * compacted after the deleted index.
2093 */
2094 beacon_buf_adj = adapter->scan_table[table_idx].beacon_buf_size_max;
2095
2096 dev_dbg(adapter->dev, "info: Scan: Delete Entry %d, beacon buffer "
2097 "removal = %d bytes\n", table_idx, beacon_buf_adj);
2098
2099 /* Check if the table entry had storage allocated for its beacon */
2100 if (beacon_buf_adj) {
2101 beacon_buf = adapter->scan_table[table_idx].beacon_buf;
2102
2103 /*
2104 * Remove the entry's buffer space, decrement the table end
2105 * pointer by the amount we are removing
2106 */
2107 adapter->bcn_buf_end -= beacon_buf_adj;
2108
2109 dev_dbg(adapter->dev, "info: scan: delete entry %d,"
2110 " compact data: %p <- %p (sz = %d)\n",
2111 table_idx, beacon_buf,
2112 beacon_buf + beacon_buf_adj,
2113 (int)(adapter->bcn_buf_end - beacon_buf));
2114
2115 /*
2116 * Compact data storage. Copy all data after the deleted
2117 * entry's end address (beacon_buf + beacon_buf_adj) back
2118 * to the original start address (beacon_buf).
2119 *
2120 * Scan table entries affected by the move will have their
2121 * entry pointer adjusted below.
2122 *
2123 * Use memmove since the dest/src memory regions overlap.
2124 */
2125 memmove(beacon_buf, beacon_buf + beacon_buf_adj,
2126 adapter->bcn_buf_end - beacon_buf);
2127 }
2128
2129 dev_dbg(adapter->dev,
2130 "info: Scan: Delete Entry %d, num_in_scan_table = %d\n",
2131 table_idx, adapter->num_in_scan_table);
2132
2133 /* Shift all of the entries after the table_idx back by one, compacting
2134 the table and removing the requested entry */
2135 for (del_idx = table_idx; (del_idx + 1) < adapter->num_in_scan_table;
2136 del_idx++) {
2137 /* Copy the next entry over this one */
2138 memcpy(adapter->scan_table + del_idx,
2139 adapter->scan_table + del_idx + 1,
2140 sizeof(struct mwifiex_bssdescriptor));
2141
2142 /*
2143 * Adjust this entry's pointer to its beacon buffer based on
2144 * the removed/compacted entry from the deleted index. Don't
2145 * decrement if the buffer pointer is NULL (no data stored for
2146 * this entry).
2147 */
2148 if (adapter->scan_table[del_idx].beacon_buf) {
2149 adapter->scan_table[del_idx].beacon_buf -=
2150 beacon_buf_adj;
2151 if (adapter->scan_table[del_idx].bcn_wpa_ie)
2152 adapter->scan_table[del_idx].bcn_wpa_ie =
2153 (struct ieee_types_vendor_specific *)
2154 (adapter->scan_table[del_idx].
2155 beacon_buf +
2156 adapter->scan_table[del_idx].
2157 wpa_offset);
2158 if (adapter->scan_table[del_idx].bcn_rsn_ie)
2159 adapter->scan_table[del_idx].bcn_rsn_ie =
2160 (struct ieee_types_generic *)
2161 (adapter->scan_table[del_idx].
2162 beacon_buf +
2163 adapter->scan_table[del_idx].
2164 rsn_offset);
2165 if (adapter->scan_table[del_idx].bcn_wapi_ie)
2166 adapter->scan_table[del_idx].bcn_wapi_ie =
2167 (struct ieee_types_generic *)
2168 (adapter->scan_table[del_idx].beacon_buf
2169 + adapter->scan_table[del_idx].
2170 wapi_offset);
2171 if (adapter->scan_table[del_idx].bcn_ht_cap)
2172 adapter->scan_table[del_idx].bcn_ht_cap =
2173 (struct ieee80211_ht_cap *)
2174 (adapter->scan_table[del_idx].beacon_buf
2175 + adapter->scan_table[del_idx].
2176 ht_cap_offset);
2177
2178 if (adapter->scan_table[del_idx].bcn_ht_info)
2179 adapter->scan_table[del_idx].bcn_ht_info =
2180 (struct ieee80211_ht_info *)
2181 (adapter->scan_table[del_idx].beacon_buf
2182 + adapter->scan_table[del_idx].
2183 ht_info_offset);
2184 if (adapter->scan_table[del_idx].bcn_bss_co_2040)
2185 adapter->scan_table[del_idx].bcn_bss_co_2040 =
2186 (u8 *)
2187 (adapter->scan_table[del_idx].beacon_buf
2188 + adapter->scan_table[del_idx].
2189 bss_co_2040_offset);
2190 if (adapter->scan_table[del_idx].bcn_ext_cap)
2191 adapter->scan_table[del_idx].bcn_ext_cap =
2192 (u8 *)
2193 (adapter->scan_table[del_idx].beacon_buf
2194 + adapter->scan_table[del_idx].
2195 ext_cap_offset);
2196 if (adapter->scan_table[del_idx].bcn_obss_scan)
2197 adapter->scan_table[del_idx].
2198 bcn_obss_scan =
2199 (struct ieee_types_obss_scan_param *)
2200 (adapter->scan_table[del_idx].beacon_buf
2201 + adapter->scan_table[del_idx].
2202 overlap_bss_offset);
2203 }
2204 }
2205
2206 /* The last entry is invalid now that it has been deleted or moved
2207 back */
2208 memset(adapter->scan_table + adapter->num_in_scan_table - 1,
2209 0x00, sizeof(struct mwifiex_bssdescriptor));
2210
2211 adapter->num_in_scan_table--;
2212}
2213
2214/*
2215 * This function deletes all occurrences of a given SSID from the scan table.
2216 *
2217 * This iterates through the scan table and deletes all entries that match
2218 * the given SSID. It also compacts the remaining scan table entries.
2219 */
2220static int
2221mwifiex_scan_delete_ssid_table_entry(struct mwifiex_private *priv,
2222 struct mwifiex_802_11_ssid *del_ssid)
2223{
2224 s32 table_idx = -1;
2225
2226 dev_dbg(priv->adapter->dev, "info: scan: delete ssid entry: %-32s\n",
2227 del_ssid->ssid);
2228
2229 /* If the requested SSID is found in the table, delete it. Then keep
2230 searching the table for multiple entires for the SSID until no
2231 more are found */
2232 while ((table_idx = mwifiex_find_ssid_in_list(priv, del_ssid, NULL,
2233 NL80211_IFTYPE_UNSPECIFIED)) >= 0) {
2234 dev_dbg(priv->adapter->dev,
2235 "info: Scan: Delete SSID Entry: Found Idx = %d\n",
2236 table_idx);
2237 mwifiex_scan_delete_table_entry(priv, table_idx);
2238 }
2239
2240 return table_idx == -1 ? -1 : 0;
2241}
2242
2243/*
2244 * This is an internal function used to start a scan based on an input 1311 * This is an internal function used to start a scan based on an input
2245 * configuration. 1312 * configuration.
2246 * 1313 *
@@ -2258,7 +1325,6 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
2258 struct mwifiex_ie_types_chan_list_param_set *chan_list_out; 1325 struct mwifiex_ie_types_chan_list_param_set *chan_list_out;
2259 u32 buf_size; 1326 u32 buf_size;
2260 struct mwifiex_chan_scan_param_set *scan_chan_list; 1327 struct mwifiex_chan_scan_param_set *scan_chan_list;
2261 u8 keep_previous_scan;
2262 u8 filtered_scan; 1328 u8 filtered_scan;
2263 u8 scan_current_chan_only; 1329 u8 scan_current_chan_only;
2264 u8 max_chan_per_scan; 1330 u8 max_chan_per_scan;
@@ -2295,24 +1361,11 @@ int mwifiex_scan_networks(struct mwifiex_private *priv,
2295 return -ENOMEM; 1361 return -ENOMEM;
2296 } 1362 }
2297 1363
2298 keep_previous_scan = false;
2299
2300 mwifiex_scan_setup_scan_config(priv, user_scan_in, 1364 mwifiex_scan_setup_scan_config(priv, user_scan_in,
2301 &scan_cfg_out->config, &chan_list_out, 1365 &scan_cfg_out->config, &chan_list_out,
2302 scan_chan_list, &max_chan_per_scan, 1366 scan_chan_list, &max_chan_per_scan,
2303 &filtered_scan, &scan_current_chan_only); 1367 &filtered_scan, &scan_current_chan_only);
2304 1368
2305 if (user_scan_in)
2306 keep_previous_scan = user_scan_in->keep_previous_scan;
2307
2308
2309 if (!keep_previous_scan) {
2310 memset(adapter->scan_table, 0x00,
2311 sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
2312 adapter->num_in_scan_table = 0;
2313 adapter->bcn_buf_end = adapter->bcn_buf;
2314 }
2315
2316 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan, 1369 ret = mwifiex_scan_channel_list(priv, max_chan_per_scan, filtered_scan,
2317 &scan_cfg_out->config, chan_list_out, 1370 &scan_cfg_out->config, chan_list_out,
2318 scan_chan_list); 1371 scan_chan_list);
@@ -2379,6 +1432,107 @@ int mwifiex_cmd_802_11_scan(struct host_cmd_ds_command *cmd,
2379} 1432}
2380 1433
2381/* 1434/*
1435 * This function checks compatibility of requested network with current
1436 * driver settings.
1437 */
1438int mwifiex_check_network_compatibility(struct mwifiex_private *priv,
1439 struct mwifiex_bssdescriptor *bss_desc)
1440{
1441 int ret = -1;
1442
1443 if (!bss_desc)
1444 return -1;
1445
1446 if ((mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv,
1447 (u8) bss_desc->bss_band, (u16) bss_desc->channel))) {
1448 switch (priv->bss_mode) {
1449 case NL80211_IFTYPE_STATION:
1450 case NL80211_IFTYPE_ADHOC:
1451 ret = mwifiex_is_network_compatible(priv, bss_desc,
1452 priv->bss_mode);
1453 if (ret)
1454 dev_err(priv->adapter->dev, "cannot find ssid "
1455 "%s\n", bss_desc->ssid.ssid);
1456 break;
1457 default:
1458 ret = 0;
1459 }
1460 }
1461
1462 return ret;
1463}
1464
1465static int
1466mwifiex_update_curr_bss_params(struct mwifiex_private *priv,
1467 u8 *bssid, s32 rssi, const u8 *ie_buf,
1468 size_t ie_len, u16 beacon_period, u16 cap_info_bitmap)
1469{
1470 struct mwifiex_bssdescriptor *bss_desc = NULL;
1471 int ret;
1472 unsigned long flags;
1473 u8 *beacon_ie;
1474
1475 /* Allocate and fill new bss descriptor */
1476 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
1477 GFP_KERNEL);
1478 if (!bss_desc) {
1479 dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
1480 return -ENOMEM;
1481 }
1482 beacon_ie = kzalloc(ie_len, GFP_KERNEL);
1483 if (!bss_desc) {
1484 dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
1485 return -ENOMEM;
1486 }
1487 memcpy(beacon_ie, ie_buf, ie_len);
1488
1489 ret = mwifiex_fill_new_bss_desc(priv, bssid, rssi, beacon_ie,
1490 ie_len, beacon_period,
1491 cap_info_bitmap, bss_desc);
1492 if (ret)
1493 goto done;
1494
1495 ret = mwifiex_check_network_compatibility(priv, bss_desc);
1496 if (ret)
1497 goto done;
1498
1499 /* Update current bss descriptor parameters */
1500 spin_lock_irqsave(&priv->curr_bcn_buf_lock, flags);
1501 priv->curr_bss_params.bss_descriptor.bcn_wpa_ie = NULL;
1502 priv->curr_bss_params.bss_descriptor.wpa_offset = 0;
1503 priv->curr_bss_params.bss_descriptor.bcn_rsn_ie = NULL;
1504 priv->curr_bss_params.bss_descriptor.rsn_offset = 0;
1505 priv->curr_bss_params.bss_descriptor.bcn_wapi_ie = NULL;
1506 priv->curr_bss_params.bss_descriptor.wapi_offset = 0;
1507 priv->curr_bss_params.bss_descriptor.bcn_ht_cap = NULL;
1508 priv->curr_bss_params.bss_descriptor.ht_cap_offset =
1509 0;
1510 priv->curr_bss_params.bss_descriptor.bcn_ht_info = NULL;
1511 priv->curr_bss_params.bss_descriptor.ht_info_offset =
1512 0;
1513 priv->curr_bss_params.bss_descriptor.bcn_bss_co_2040 =
1514 NULL;
1515 priv->curr_bss_params.bss_descriptor.
1516 bss_co_2040_offset = 0;
1517 priv->curr_bss_params.bss_descriptor.bcn_ext_cap = NULL;
1518 priv->curr_bss_params.bss_descriptor.ext_cap_offset = 0;
1519 priv->curr_bss_params.bss_descriptor.beacon_buf = NULL;
1520 priv->curr_bss_params.bss_descriptor.beacon_buf_size =
1521 0;
1522
1523 /* Make a copy of current BSSID descriptor */
1524 memcpy(&priv->curr_bss_params.bss_descriptor, bss_desc,
1525 sizeof(priv->curr_bss_params.bss_descriptor));
1526 mwifiex_save_curr_bcn(priv);
1527 spin_unlock_irqrestore(&priv->curr_bcn_buf_lock, flags);
1528
1529done:
1530 kfree(bss_desc);
1531 kfree(beacon_ie);
1532 return 0;
1533}
1534
1535/*
2382 * This function handles the command response of scan. 1536 * This function handles the command response of scan.
2383 * 1537 *
2384 * The response buffer for the scan command has the following 1538 * The response buffer for the scan command has the following
@@ -2404,21 +1558,16 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2404 struct mwifiex_adapter *adapter = priv->adapter; 1558 struct mwifiex_adapter *adapter = priv->adapter;
2405 struct cmd_ctrl_node *cmd_node; 1559 struct cmd_ctrl_node *cmd_node;
2406 struct host_cmd_ds_802_11_scan_rsp *scan_rsp; 1560 struct host_cmd_ds_802_11_scan_rsp *scan_rsp;
2407 struct mwifiex_bssdescriptor *bss_new_entry = NULL;
2408 struct mwifiex_ie_types_data *tlv_data; 1561 struct mwifiex_ie_types_data *tlv_data;
2409 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv; 1562 struct mwifiex_ie_types_tsf_timestamp *tsf_tlv;
2410 u8 *bss_info; 1563 u8 *bss_info;
2411 u32 scan_resp_size; 1564 u32 scan_resp_size;
2412 u32 bytes_left; 1565 u32 bytes_left;
2413 u32 num_in_table;
2414 u32 bss_idx;
2415 u32 idx; 1566 u32 idx;
2416 u32 tlv_buf_size; 1567 u32 tlv_buf_size;
2417 long long tsf_val;
2418 struct mwifiex_chan_freq_power *cfp; 1568 struct mwifiex_chan_freq_power *cfp;
2419 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv; 1569 struct mwifiex_ie_types_chan_band_list_param_set *chan_band_tlv;
2420 struct chan_band_param_set *chan_band; 1570 struct chan_band_param_set *chan_band;
2421 u8 band;
2422 u8 is_bgscan_resp; 1571 u8 is_bgscan_resp;
2423 unsigned long flags; 1572 unsigned long flags;
2424 1573
@@ -2430,7 +1579,7 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2430 scan_rsp = &resp->params.scan_resp; 1579 scan_rsp = &resp->params.scan_resp;
2431 1580
2432 1581
2433 if (scan_rsp->number_of_sets > IW_MAX_AP) { 1582 if (scan_rsp->number_of_sets > MWIFIEX_MAX_AP) {
2434 dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n", 1583 dev_err(adapter->dev, "SCAN_RESP: too many AP returned (%d)\n",
2435 scan_rsp->number_of_sets); 1584 scan_rsp->number_of_sets);
2436 ret = -1; 1585 ret = -1;
@@ -2447,7 +1596,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2447 "info: SCAN_RESP: returned %d APs before parsing\n", 1596 "info: SCAN_RESP: returned %d APs before parsing\n",
2448 scan_rsp->number_of_sets); 1597 scan_rsp->number_of_sets);
2449 1598
2450 num_in_table = adapter->num_in_scan_table;
2451 bss_info = scan_rsp->bss_desc_and_tlv_buffer; 1599 bss_info = scan_rsp->bss_desc_and_tlv_buffer;
2452 1600
2453 /* 1601 /*
@@ -2479,125 +1627,147 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2479 (struct mwifiex_ie_types_data **) 1627 (struct mwifiex_ie_types_data **)
2480 &chan_band_tlv); 1628 &chan_band_tlv);
2481 1629
2482 /*
2483 * Process each scan response returned (scan_rsp->number_of_sets).
2484 * Save the information in the bss_new_entry and then insert into the
2485 * driver scan table either as an update to an existing entry
2486 * or as an addition at the end of the table
2487 */
2488 bss_new_entry = kzalloc(sizeof(struct mwifiex_bssdescriptor),
2489 GFP_KERNEL);
2490 if (!bss_new_entry) {
2491 dev_err(adapter->dev, " failed to alloc bss_new_entry\n");
2492 return -ENOMEM;
2493 }
2494
2495 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) { 1630 for (idx = 0; idx < scan_rsp->number_of_sets && bytes_left; idx++) {
2496 /* Zero out the bss_new_entry we are about to store info in */ 1631 u8 bssid[ETH_ALEN];
2497 memset(bss_new_entry, 0x00, 1632 s32 rssi;
2498 sizeof(struct mwifiex_bssdescriptor)); 1633 const u8 *ie_buf;
2499 1634 size_t ie_len;
2500 if (mwifiex_interpret_bss_desc_with_ie(adapter, bss_new_entry, 1635 int channel = -1;
2501 &bss_info, 1636 u64 network_tsf = 0;
2502 &bytes_left)) { 1637 u16 beacon_size = 0;
2503 /* Error parsing/interpreting scan response, skipped */ 1638 u32 curr_bcn_bytes;
2504 dev_err(adapter->dev, "SCAN_RESP: " 1639 u32 freq;
2505 "mwifiex_interpret_bss_desc_with_ie " 1640 u16 beacon_period;
2506 "returned ERROR\n"); 1641 u16 cap_info_bitmap;
2507 continue; 1642 u8 *current_ptr;
1643 struct mwifiex_bcn_param *bcn_param;
1644
1645 if (bytes_left >= sizeof(beacon_size)) {
1646 /* Extract & convert beacon size from command buffer */
1647 memcpy(&beacon_size, bss_info, sizeof(beacon_size));
1648 bytes_left -= sizeof(beacon_size);
1649 bss_info += sizeof(beacon_size);
2508 } 1650 }
2509 1651
2510 /* Process the data fields and IEs returned for this BSS */ 1652 if (!beacon_size || beacon_size > bytes_left) {
2511 dev_dbg(adapter->dev, "info: SCAN_RESP: BSSID = %pM\n", 1653 bss_info += bytes_left;
2512 bss_new_entry->mac_address); 1654 bytes_left = 0;
1655 return -1;
1656 }
2513 1657
2514 /* Search the scan table for the same bssid */ 1658 /* Initialize the current working beacon pointer for this BSS
2515 for (bss_idx = 0; bss_idx < num_in_table; bss_idx++) { 1659 * iteration */
2516 if (memcmp(bss_new_entry->mac_address, 1660 current_ptr = bss_info;
2517 adapter->scan_table[bss_idx].mac_address, 1661
2518 sizeof(bss_new_entry->mac_address))) { 1662 /* Advance the return beacon pointer past the current beacon */
2519 continue; 1663 bss_info += beacon_size;
1664 bytes_left -= beacon_size;
1665
1666 curr_bcn_bytes = beacon_size;
1667
1668 /*
1669 * First 5 fields are bssid, RSSI, time stamp, beacon interval,
1670 * and capability information
1671 */
1672 if (curr_bcn_bytes < sizeof(struct mwifiex_bcn_param)) {
1673 dev_err(adapter->dev, "InterpretIE: not enough bytes left\n");
1674 continue;
1675 }
1676 bcn_param = (struct mwifiex_bcn_param *)current_ptr;
1677 current_ptr += sizeof(*bcn_param);
1678 curr_bcn_bytes -= sizeof(*bcn_param);
1679
1680 memcpy(bssid, bcn_param->bssid, ETH_ALEN);
1681
1682 rssi = (s32) (bcn_param->rssi);
1683 dev_dbg(adapter->dev, "info: InterpretIE: RSSI=%02X\n",
1684 rssi);
1685
1686 beacon_period = le16_to_cpu(bcn_param->beacon_period);
1687
1688 cap_info_bitmap = le16_to_cpu(bcn_param->cap_info_bitmap);
1689 dev_dbg(adapter->dev, "info: InterpretIE: capabilities=0x%X\n",
1690 cap_info_bitmap);
1691
1692 /* Rest of the current buffer are IE's */
1693 ie_buf = current_ptr;
1694 ie_len = curr_bcn_bytes;
1695 dev_dbg(adapter->dev, "info: InterpretIE: IELength for this AP"
1696 " = %d\n", curr_bcn_bytes);
1697
1698 while (curr_bcn_bytes >= sizeof(struct ieee_types_header)) {
1699 u8 element_id, element_len;
1700
1701 element_id = *current_ptr;
1702 element_len = *(current_ptr + 1);
1703 if (curr_bcn_bytes < element_len +
1704 sizeof(struct ieee_types_header)) {
1705 dev_err(priv->adapter->dev, "%s: in processing"
1706 " IE, bytes left < IE length\n",
1707 __func__);
1708 goto done;
2520 } 1709 }
2521 /* 1710 if (element_id == WLAN_EID_DS_PARAMS) {
2522 * If the SSID matches as well, it is a 1711 channel = *(u8 *) (current_ptr +
2523 * duplicate of this entry. Keep the bss_idx 1712 sizeof(struct ieee_types_header));
2524 * set to this entry so we replace the old
2525 * contents in the table
2526 */
2527 if ((bss_new_entry->ssid.ssid_len
2528 == adapter->scan_table[bss_idx]. ssid.ssid_len)
2529 && (!memcmp(bss_new_entry->ssid.ssid,
2530 adapter->scan_table[bss_idx].ssid.ssid,
2531 bss_new_entry->ssid.ssid_len))) {
2532 dev_dbg(adapter->dev, "info: SCAN_RESP:"
2533 " duplicate of index: %d\n", bss_idx);
2534 break; 1713 break;
2535 } 1714 }
2536 } 1715
2537 /* 1716 current_ptr += element_len +
2538 * If the bss_idx is equal to the number of entries in 1717 sizeof(struct ieee_types_header);
2539 * the table, the new entry was not a duplicate; append 1718 curr_bcn_bytes -= element_len +
2540 * it to the scan table 1719 sizeof(struct ieee_types_header);
2541 */
2542 if (bss_idx == num_in_table) {
2543 /* Range check the bss_idx, keep it limited to
2544 the last entry */
2545 if (bss_idx == IW_MAX_AP)
2546 bss_idx--;
2547 else
2548 num_in_table++;
2549 } 1720 }
2550 1721
2551 /* 1722 /*
2552 * Save the beacon/probe response returned for later application
2553 * retrieval. Duplicate beacon/probe responses are updated if
2554 * possible
2555 */
2556 mwifiex_ret_802_11_scan_store_beacon(priv, bss_idx,
2557 num_in_table, bss_new_entry);
2558 /*
2559 * If the TSF TLV was appended to the scan results, save this 1723 * If the TSF TLV was appended to the scan results, save this
2560 * entry's TSF value in the networkTSF field.The networkTSF is 1724 * entry's TSF value in the networkTSF field.The networkTSF is
2561 * the firmware's TSF value at the time the beacon or probe 1725 * the firmware's TSF value at the time the beacon or probe
2562 * response was received. 1726 * response was received.
2563 */ 1727 */
2564 if (tsf_tlv) { 1728 if (tsf_tlv)
2565 memcpy(&tsf_val, &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE] 1729 memcpy(&network_tsf,
2566 , sizeof(tsf_val)); 1730 &tsf_tlv->tsf_data[idx * TSF_DATA_SIZE],
2567 memcpy(&bss_new_entry->network_tsf, &tsf_val, 1731 sizeof(network_tsf));
2568 sizeof(bss_new_entry->network_tsf)); 1732
2569 } 1733 if (channel != -1) {
2570 band = BAND_G; 1734 struct ieee80211_channel *chan;
2571 if (chan_band_tlv) { 1735 u8 band;
2572 chan_band = &chan_band_tlv->chan_band_param[idx]; 1736
2573 band = mwifiex_radio_type_to_band(chan_band->radio_type 1737 band = BAND_G;
2574 & (BIT(0) | BIT(1))); 1738 if (chan_band_tlv) {
2575 } 1739 chan_band =
2576 1740 &chan_band_tlv->chan_band_param[idx];
2577 /* Save the band designation for this entry for use in join */ 1741 band = mwifiex_radio_type_to_band(
2578 bss_new_entry->bss_band = band; 1742 chan_band->radio_type
2579 cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(priv, 1743 & (BIT(0) | BIT(1)));
2580 (u8) bss_new_entry->bss_band, 1744 }
2581 (u16)bss_new_entry->channel);
2582 1745
2583 if (cfp) 1746 cfp = mwifiex_get_cfp_by_band_and_channel_from_cfg80211(
2584 bss_new_entry->freq = cfp->freq; 1747 priv, (u8)band, (u16)channel);
2585 else
2586 bss_new_entry->freq = 0;
2587 1748
2588 /* Copy the locally created bss_new_entry to the scan table */ 1749 freq = cfp ? cfp->freq : 0;
2589 memcpy(&adapter->scan_table[bss_idx], bss_new_entry,
2590 sizeof(adapter->scan_table[bss_idx]));
2591 1750
2592 } 1751 chan = ieee80211_get_channel(priv->wdev->wiphy, freq);
2593 1752
2594 dev_dbg(adapter->dev, 1753 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
2595 "info: SCAN_RESP: Scanned %2d APs, %d valid, %d total\n", 1754 cfg80211_inform_bss(priv->wdev->wiphy, chan,
2596 scan_rsp->number_of_sets, 1755 bssid, network_tsf, cap_info_bitmap,
2597 num_in_table - adapter->num_in_scan_table, num_in_table); 1756 beacon_period, ie_buf, ie_len, rssi,
1757 GFP_KERNEL);
2598 1758
2599 /* Update the total number of BSSIDs in the scan table */ 1759 if (priv->media_connected && !memcmp(bssid,
2600 adapter->num_in_scan_table = num_in_table; 1760 priv->curr_bss_params.bss_descriptor
1761 .mac_address, ETH_ALEN))
1762 mwifiex_update_curr_bss_params(priv,
1763 bssid, rssi, ie_buf,
1764 ie_len, beacon_period,
1765 cap_info_bitmap);
1766 }
1767 } else {
1768 dev_dbg(adapter->dev, "missing BSS channel IE\n");
1769 }
1770 }
2601 1771
2602 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags); 1772 spin_lock_irqsave(&adapter->scan_pending_q_lock, flags);
2603 if (list_empty(&adapter->scan_pending_q)) { 1773 if (list_empty(&adapter->scan_pending_q)) {
@@ -2605,12 +1775,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2605 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags); 1775 spin_lock_irqsave(&adapter->mwifiex_cmd_lock, flags);
2606 adapter->scan_processing = false; 1776 adapter->scan_processing = false;
2607 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags); 1777 spin_unlock_irqrestore(&adapter->mwifiex_cmd_lock, flags);
2608 /*
2609 * Process the resulting scan table:
2610 * - Remove any bad ssids
2611 * - Update our current BSS information from scan data
2612 */
2613 mwifiex_process_scan_results(priv);
2614 1778
2615 /* Need to indicate IOCTL complete */ 1779 /* Need to indicate IOCTL complete */
2616 if (adapter->curr_cmd->wait_q_enabled) { 1780 if (adapter->curr_cmd->wait_q_enabled) {
@@ -2636,7 +1800,6 @@ int mwifiex_ret_802_11_scan(struct mwifiex_private *priv,
2636 } 1800 }
2637 1801
2638done: 1802done:
2639 kfree((u8 *) bss_new_entry);
2640 return ret; 1803 return ret;
2641} 1804}
2642 1805
@@ -2663,141 +1826,6 @@ int mwifiex_cmd_802_11_bg_scan_query(struct host_cmd_ds_command *cmd)
2663} 1826}
2664 1827
2665/* 1828/*
2666 * This function finds a SSID in the scan table.
2667 *
2668 * A BSSID may optionally be provided to qualify the SSID.
2669 * For non-Auto mode, further check is made to make sure the
2670 * BSS found in the scan table is compatible with the current
2671 * settings of the driver.
2672 */
2673s32
2674mwifiex_find_ssid_in_list(struct mwifiex_private *priv,
2675 struct mwifiex_802_11_ssid *ssid, u8 *bssid,
2676 u32 mode)
2677{
2678 struct mwifiex_adapter *adapter = priv->adapter;
2679 s32 net = -1, j;
2680 u8 best_rssi = 0;
2681 u32 i;
2682
2683 dev_dbg(adapter->dev, "info: num of entries in table = %d\n",
2684 adapter->num_in_scan_table);
2685
2686 /*
2687 * Loop through the table until the maximum is reached or until a match
2688 * is found based on the bssid field comparison
2689 */
2690 for (i = 0;
2691 i < adapter->num_in_scan_table && (!bssid || (bssid && net < 0));
2692 i++) {
2693 if (!mwifiex_ssid_cmp(&adapter->scan_table[i].ssid, ssid) &&
2694 (!bssid
2695 || !memcmp(adapter->scan_table[i].mac_address, bssid,
2696 ETH_ALEN))
2697 &&
2698 (mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2699 (priv, (u8) adapter->scan_table[i].bss_band,
2700 (u16) adapter->scan_table[i].channel))) {
2701 switch (mode) {
2702 case NL80211_IFTYPE_STATION:
2703 case NL80211_IFTYPE_ADHOC:
2704 j = mwifiex_is_network_compatible(priv, i,
2705 mode);
2706
2707 if (j >= 0) {
2708 if (SCAN_RSSI
2709 (adapter->scan_table[i].rssi) >
2710 best_rssi) {
2711 best_rssi = SCAN_RSSI(adapter->
2712 scan_table
2713 [i].rssi);
2714 net = i;
2715 }
2716 } else {
2717 if (net == -1)
2718 net = j;
2719 }
2720 break;
2721 case NL80211_IFTYPE_UNSPECIFIED:
2722 default:
2723 /*
2724 * Do not check compatibility if the mode
2725 * requested is Auto/Unknown. Allows generic
2726 * find to work without verifying against the
2727 * Adapter security settings
2728 */
2729 if (SCAN_RSSI(adapter->scan_table[i].rssi) >
2730 best_rssi) {
2731 best_rssi = SCAN_RSSI(adapter->
2732 scan_table[i].rssi);
2733 net = i;
2734 }
2735 break;
2736 }
2737 }
2738 }
2739
2740 return net;
2741}
2742
2743/*
2744 * This function finds a specific compatible BSSID in the scan list.
2745 *
2746 * This function loops through the scan table looking for a compatible
2747 * match. If a BSSID matches, but the BSS is found to be not compatible
2748 * the function ignores it and continues to search through the rest of
2749 * the entries in case there is an AP with multiple SSIDs assigned to
2750 * the same BSSID.
2751 */
2752s32
2753mwifiex_find_bssid_in_list(struct mwifiex_private *priv, u8 *bssid,
2754 u32 mode)
2755{
2756 struct mwifiex_adapter *adapter = priv->adapter;
2757 s32 net = -1;
2758 u32 i;
2759
2760 if (!bssid)
2761 return -1;
2762
2763 dev_dbg(adapter->dev, "info: FindBSSID: Num of BSSIDs = %d\n",
2764 adapter->num_in_scan_table);
2765
2766 /*
2767 * Look through the scan table for a compatible match. The ret return
2768 * variable will be equal to the index in the scan table (greater
2769 * than zero) if the network is compatible. The loop will continue
2770 * past a matched bssid that is not compatible in case there is an
2771 * AP with multiple SSIDs assigned to the same BSSID
2772 */
2773 for (i = 0; net < 0 && i < adapter->num_in_scan_table; i++) {
2774 if (!memcmp
2775 (adapter->scan_table[i].mac_address, bssid, ETH_ALEN)
2776 && mwifiex_get_cfp_by_band_and_channel_from_cfg80211
2777 (priv,
2778 (u8) adapter->
2779 scan_table[i].
2780 bss_band,
2781 (u16) adapter->
2782 scan_table[i].
2783 channel)) {
2784 switch (mode) {
2785 case NL80211_IFTYPE_STATION:
2786 case NL80211_IFTYPE_ADHOC:
2787 net = mwifiex_is_network_compatible(priv, i,
2788 mode);
2789 break;
2790 default:
2791 net = i;
2792 break;
2793 }
2794 }
2795 }
2796
2797 return net;
2798}
2799
2800/*
2801 * This function inserts scan command node to the scan pending queue. 1829 * This function inserts scan command node to the scan pending queue.
2802 */ 1830 */
2803void 1831void
@@ -2814,42 +1842,6 @@ mwifiex_queue_scan_cmd(struct mwifiex_private *priv,
2814} 1842}
2815 1843
2816/* 1844/*
2817 * This function finds an AP with specific ssid in the scan list.
2818 */
2819int mwifiex_find_best_network(struct mwifiex_private *priv,
2820 struct mwifiex_ssid_bssid *req_ssid_bssid)
2821{
2822 struct mwifiex_adapter *adapter = priv->adapter;
2823 struct mwifiex_bssdescriptor *req_bss;
2824 s32 i;
2825
2826 memset(req_ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
2827
2828 i = mwifiex_find_best_network_in_list(priv);
2829
2830 if (i >= 0) {
2831 req_bss = &adapter->scan_table[i];
2832 memcpy(&req_ssid_bssid->ssid, &req_bss->ssid,
2833 sizeof(struct mwifiex_802_11_ssid));
2834 memcpy((u8 *) &req_ssid_bssid->bssid,
2835 (u8 *) &req_bss->mac_address, ETH_ALEN);
2836
2837 /* Make sure we are in the right mode */
2838 if (priv->bss_mode == NL80211_IFTYPE_UNSPECIFIED)
2839 priv->bss_mode = req_bss->bss_mode;
2840 }
2841
2842 if (!req_ssid_bssid->ssid.ssid_len)
2843 return -1;
2844
2845 dev_dbg(adapter->dev, "info: Best network found = [%s], "
2846 "[%pM]\n", req_ssid_bssid->ssid.ssid,
2847 req_ssid_bssid->bssid);
2848
2849 return 0;
2850}
2851
2852/*
2853 * This function sends a scan command for all available channels to the 1845 * This function sends a scan command for all available channels to the
2854 * firmware, filtered on a specific SSID. 1846 * firmware, filtered on a specific SSID.
2855 */ 1847 */
@@ -2874,8 +1866,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2874 return ret; 1866 return ret;
2875 } 1867 }
2876 1868
2877 mwifiex_scan_delete_ssid_table_entry(priv, req_ssid);
2878
2879 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL); 1869 scan_cfg = kzalloc(sizeof(struct mwifiex_user_scan_cfg), GFP_KERNEL);
2880 if (!scan_cfg) { 1870 if (!scan_cfg) {
2881 dev_err(adapter->dev, "failed to alloc scan_cfg\n"); 1871 dev_err(adapter->dev, "failed to alloc scan_cfg\n");
@@ -2884,7 +1874,6 @@ static int mwifiex_scan_specific_ssid(struct mwifiex_private *priv,
2884 1874
2885 memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid, 1875 memcpy(scan_cfg->ssid_list[0].ssid, req_ssid->ssid,
2886 req_ssid->ssid_len); 1876 req_ssid->ssid_len);
2887 scan_cfg->keep_previous_scan = true;
2888 1877
2889 ret = mwifiex_scan_networks(priv, scan_cfg); 1878 ret = mwifiex_scan_networks(priv, scan_cfg);
2890 1879
@@ -3010,6 +1999,39 @@ mwifiex_save_curr_bcn(struct mwifiex_private *priv)
3010 curr_bss->beacon_buf_size); 1999 curr_bss->beacon_buf_size);
3011 dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n", 2000 dev_dbg(priv->adapter->dev, "info: current beacon saved %d\n",
3012 priv->curr_bcn_size); 2001 priv->curr_bcn_size);
2002
2003 curr_bss->beacon_buf = priv->curr_bcn_buf;
2004
2005 /* adjust the pointers in the current BSS descriptor */
2006 if (curr_bss->bcn_wpa_ie)
2007 curr_bss->bcn_wpa_ie =
2008 (struct ieee_types_vendor_specific *)
2009 (curr_bss->beacon_buf +
2010 curr_bss->wpa_offset);
2011
2012 if (curr_bss->bcn_rsn_ie)
2013 curr_bss->bcn_rsn_ie = (struct ieee_types_generic *)
2014 (curr_bss->beacon_buf +
2015 curr_bss->rsn_offset);
2016
2017 if (curr_bss->bcn_ht_cap)
2018 curr_bss->bcn_ht_cap = (struct ieee80211_ht_cap *)
2019 (curr_bss->beacon_buf +
2020 curr_bss->ht_cap_offset);
2021
2022 if (curr_bss->bcn_ht_info)
2023 curr_bss->bcn_ht_info = (struct ieee80211_ht_info *)
2024 (curr_bss->beacon_buf +
2025 curr_bss->ht_info_offset);
2026
2027 if (curr_bss->bcn_bss_co_2040)
2028 curr_bss->bcn_bss_co_2040 =
2029 (u8 *) (curr_bss->beacon_buf +
2030 curr_bss->bss_co_2040_offset);
2031
2032 if (curr_bss->bcn_ext_cap)
2033 curr_bss->bcn_ext_cap = (u8 *) (curr_bss->beacon_buf +
2034 curr_bss->ext_cap_offset);
3013} 2035}
3014 2036
3015/* 2037/*
diff --git a/drivers/net/wireless/mwifiex/sta_event.c b/drivers/net/wireless/mwifiex/sta_event.c
index fc265cab0907..f204810e8338 100644
--- a/drivers/net/wireless/mwifiex/sta_event.c
+++ b/drivers/net/wireless/mwifiex/sta_event.c
@@ -130,8 +130,8 @@ mwifiex_reset_connect_state(struct mwifiex_private *priv)
130 if (netif_carrier_ok(priv->netdev)) 130 if (netif_carrier_ok(priv->netdev))
131 netif_carrier_off(priv->netdev); 131 netif_carrier_off(priv->netdev);
132 /* Reset wireless stats signal info */ 132 /* Reset wireless stats signal info */
133 priv->w_stats.qual.level = 0; 133 priv->qual_level = 0;
134 priv->w_stats.qual.noise = 0; 134 priv->qual_noise = 0;
135} 135}
136 136
137/* 137/*
@@ -299,11 +299,6 @@ int mwifiex_process_sta_event(struct mwifiex_private *priv)
299 299
300 case EVENT_BG_SCAN_REPORT: 300 case EVENT_BG_SCAN_REPORT:
301 dev_dbg(adapter->dev, "event: BGS_REPORT\n"); 301 dev_dbg(adapter->dev, "event: BGS_REPORT\n");
302 /* Clear the previous scan result */
303 memset(adapter->scan_table, 0x00,
304 sizeof(struct mwifiex_bssdescriptor) * IW_MAX_AP);
305 adapter->num_in_scan_table = 0;
306 adapter->bcn_buf_end = adapter->bcn_buf;
307 ret = mwifiex_send_cmd_async(priv, 302 ret = mwifiex_send_cmd_async(priv,
308 HostCmd_CMD_802_11_BG_SCAN_QUERY, 303 HostCmd_CMD_802_11_BG_SCAN_QUERY,
309 HostCmd_ACT_GEN_GET, 0, NULL); 304 HostCmd_ACT_GEN_GET, 0, NULL);
diff --git a/drivers/net/wireless/mwifiex/sta_ioctl.c b/drivers/net/wireless/mwifiex/sta_ioctl.c
index c34ff8c4f4f8..3fca219bcfb6 100644
--- a/drivers/net/wireless/mwifiex/sta_ioctl.c
+++ b/drivers/net/wireless/mwifiex/sta_ioctl.c
@@ -142,90 +142,142 @@ int mwifiex_request_set_multicast_list(struct mwifiex_private *priv,
142} 142}
143 143
144/* 144/*
145 * This function fills bss descriptor structure using provided
146 * information.
147 */
148int mwifiex_fill_new_bss_desc(struct mwifiex_private *priv,
149 u8 *bssid, s32 rssi, u8 *ie_buf,
150 size_t ie_len, u16 beacon_period,
151 u16 cap_info_bitmap,
152 struct mwifiex_bssdescriptor *bss_desc)
153{
154 int ret;
155
156 memcpy(bss_desc->mac_address, bssid, ETH_ALEN);
157 bss_desc->rssi = rssi;
158 bss_desc->beacon_buf = ie_buf;
159 bss_desc->beacon_buf_size = ie_len;
160 bss_desc->beacon_period = beacon_period;
161 bss_desc->cap_info_bitmap = cap_info_bitmap;
162 if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_PRIVACY) {
163 dev_dbg(priv->adapter->dev, "info: InterpretIE: AP WEP enabled\n");
164 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_8021X_WEP;
165 } else {
166 bss_desc->privacy = MWIFIEX_802_11_PRIV_FILTER_ACCEPT_ALL;
167 }
168 if (bss_desc->cap_info_bitmap & WLAN_CAPABILITY_IBSS)
169 bss_desc->bss_mode = NL80211_IFTYPE_ADHOC;
170 else
171 bss_desc->bss_mode = NL80211_IFTYPE_STATION;
172
173 ret = mwifiex_update_bss_desc_with_ie(priv->adapter, bss_desc,
174 ie_buf, ie_len);
175
176 return ret;
177}
178
179/*
145 * In Ad-Hoc mode, the IBSS is created if not found in scan list. 180 * In Ad-Hoc mode, the IBSS is created if not found in scan list.
146 * In both Ad-Hoc and infra mode, an deauthentication is performed 181 * In both Ad-Hoc and infra mode, an deauthentication is performed
147 * first. 182 * first.
148 */ 183 */
149int mwifiex_bss_start(struct mwifiex_private *priv, 184int mwifiex_bss_start(struct mwifiex_private *priv, struct cfg80211_bss *bss,
150 struct mwifiex_ssid_bssid *ssid_bssid) 185 struct mwifiex_802_11_ssid *req_ssid)
151{ 186{
152 int ret; 187 int ret;
153 struct mwifiex_adapter *adapter = priv->adapter; 188 struct mwifiex_adapter *adapter = priv->adapter;
154 s32 i = -1; 189 struct mwifiex_bssdescriptor *bss_desc = NULL;
190 u8 *beacon_ie = NULL;
155 191
156 priv->scan_block = false; 192 priv->scan_block = false;
157 if (!ssid_bssid) 193
158 return -1; 194 if (bss) {
195 /* Allocate and fill new bss descriptor */
196 bss_desc = kzalloc(sizeof(struct mwifiex_bssdescriptor),
197 GFP_KERNEL);
198 if (!bss_desc) {
199 dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
200 return -ENOMEM;
201 }
202 beacon_ie = kzalloc(bss->len_beacon_ies, GFP_KERNEL);
203 if (!beacon_ie) {
204 dev_err(priv->adapter->dev, " failed to alloc bss_desc\n");
205 return -ENOMEM;
206 }
207 memcpy(beacon_ie, bss->information_elements,
208 bss->len_beacon_ies);
209 ret = mwifiex_fill_new_bss_desc(priv, bss->bssid, bss->signal,
210 beacon_ie, bss->len_beacon_ies,
211 bss->beacon_interval,
212 bss->capability, bss_desc);
213 if (ret)
214 goto done;
215 }
159 216
160 if (priv->bss_mode == NL80211_IFTYPE_STATION) { 217 if (priv->bss_mode == NL80211_IFTYPE_STATION) {
161 /* Infra mode */ 218 /* Infra mode */
162 ret = mwifiex_deauthenticate(priv, NULL); 219 ret = mwifiex_deauthenticate(priv, NULL);
163 if (ret) 220 if (ret)
164 return ret; 221 goto done;
165 222
166 /* Search for the requested SSID in the scan table */ 223 ret = mwifiex_check_network_compatibility(priv, bss_desc);
167 if (ssid_bssid->ssid.ssid_len) 224 if (ret)
168 i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, 225 goto done;
169 NULL, NL80211_IFTYPE_STATION); 226
170 else 227 dev_dbg(adapter->dev, "info: SSID found in scan list ... "
171 i = mwifiex_find_bssid_in_list(priv, 228 "associating...\n");
172 (u8 *) &ssid_bssid->bssid,
173 NL80211_IFTYPE_STATION);
174 if (i < 0)
175 return -1;
176 229
177 dev_dbg(adapter->dev, 230 if (!netif_queue_stopped(priv->netdev))
178 "info: SSID found in scan list ... associating...\n"); 231 netif_stop_queue(priv->netdev);
179 232
180 /* Clear any past association response stored for 233 /* Clear any past association response stored for
181 * application retrieval */ 234 * application retrieval */
182 priv->assoc_rsp_size = 0; 235 priv->assoc_rsp_size = 0;
183 ret = mwifiex_associate(priv, &adapter->scan_table[i]); 236 ret = mwifiex_associate(priv, bss_desc);
184 if (ret) 237 if (bss)
185 return ret; 238 cfg80211_put_bss(bss);
186 } else { 239 } else {
187 /* Adhoc mode */ 240 /* Adhoc mode */
188 /* If the requested SSID matches current SSID, return */ 241 /* If the requested SSID matches current SSID, return */
189 if (ssid_bssid->ssid.ssid_len && 242 if (bss_desc && bss_desc->ssid.ssid_len &&
190 (!mwifiex_ssid_cmp 243 (!mwifiex_ssid_cmp
191 (&priv->curr_bss_params.bss_descriptor.ssid, 244 (&priv->curr_bss_params.bss_descriptor.ssid,
192 &ssid_bssid->ssid))) 245 &bss_desc->ssid))) {
246 kfree(bss_desc);
247 kfree(beacon_ie);
193 return 0; 248 return 0;
249 }
194 250
195 /* Exit Adhoc mode first */ 251 /* Exit Adhoc mode first */
196 dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n"); 252 dev_dbg(adapter->dev, "info: Sending Adhoc Stop\n");
197 ret = mwifiex_deauthenticate(priv, NULL); 253 ret = mwifiex_deauthenticate(priv, NULL);
198 if (ret) 254 if (ret)
199 return ret; 255 goto done;
200 256
201 priv->adhoc_is_link_sensed = false; 257 priv->adhoc_is_link_sensed = false;
202 258
203 /* Search for the requested network in the scan table */ 259 ret = mwifiex_check_network_compatibility(priv, bss_desc);
204 if (ssid_bssid->ssid.ssid_len) 260
205 i = mwifiex_find_ssid_in_list(priv, 261 if (!netif_queue_stopped(priv->netdev))
206 &ssid_bssid->ssid, NULL, 262 netif_stop_queue(priv->netdev);
207 NL80211_IFTYPE_ADHOC); 263
208 else 264 if (!ret) {
209 i = mwifiex_find_bssid_in_list(priv,
210 (u8 *)&ssid_bssid->bssid,
211 NL80211_IFTYPE_ADHOC);
212
213 if (i >= 0) {
214 dev_dbg(adapter->dev, "info: network found in scan" 265 dev_dbg(adapter->dev, "info: network found in scan"
215 " list. Joining...\n"); 266 " list. Joining...\n");
216 ret = mwifiex_adhoc_join(priv, &adapter->scan_table[i]); 267 ret = mwifiex_adhoc_join(priv, bss_desc);
217 if (ret) 268 if (bss)
218 return ret; 269 cfg80211_put_bss(bss);
219 } else { 270 } else {
220 dev_dbg(adapter->dev, "info: Network not found in " 271 dev_dbg(adapter->dev, "info: Network not found in "
221 "the list, creating adhoc with ssid = %s\n", 272 "the list, creating adhoc with ssid = %s\n",
222 ssid_bssid->ssid.ssid); 273 req_ssid->ssid);
223 ret = mwifiex_adhoc_start(priv, &ssid_bssid->ssid); 274 ret = mwifiex_adhoc_start(priv, req_ssid);
224 if (ret)
225 return ret;
226 } 275 }
227 } 276 }
228 277
278done:
279 kfree(bss_desc);
280 kfree(beacon_ie);
229 return ret; 281 return ret;
230} 282}
231 283
@@ -376,7 +428,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
376{ 428{
377 struct mwifiex_adapter *adapter = priv->adapter; 429 struct mwifiex_adapter *adapter = priv->adapter;
378 struct mwifiex_bssdescriptor *bss_desc; 430 struct mwifiex_bssdescriptor *bss_desc;
379 s32 tbl_idx;
380 431
381 if (!info) 432 if (!info)
382 return -1; 433 return -1;
@@ -394,17 +445,6 @@ int mwifiex_get_bss_info(struct mwifiex_private *priv,
394 445
395 info->region_code = adapter->region_code; 446 info->region_code = adapter->region_code;
396 447
397 /* Scan table index if connected */
398 info->scan_table_idx = 0;
399 if (priv->media_connected) {
400 tbl_idx =
401 mwifiex_find_ssid_in_list(priv, &bss_desc->ssid,
402 bss_desc->mac_address,
403 priv->bss_mode);
404 if (tbl_idx >= 0)
405 info->scan_table_idx = tbl_idx;
406 }
407
408 info->media_connected = priv->media_connected; 448 info->media_connected = priv->media_connected;
409 449
410 info->max_power_level = priv->max_tx_power_level; 450 info->max_power_level = priv->max_tx_power_level;
@@ -586,50 +626,6 @@ static int mwifiex_bss_ioctl_ibss_channel(struct mwifiex_private *priv,
586} 626}
587 627
588/* 628/*
589 * IOCTL request handler to find a particular BSS.
590 *
591 * The BSS can be searched with either a BSSID or a SSID. If none of
592 * these are provided, just the best BSS (best RSSI) is returned.
593 */
594int mwifiex_bss_ioctl_find_bss(struct mwifiex_private *priv,
595 struct mwifiex_ssid_bssid *ssid_bssid)
596{
597 struct mwifiex_adapter *adapter = priv->adapter;
598 struct mwifiex_bssdescriptor *bss_desc;
599 u8 zero_mac[ETH_ALEN] = { 0, 0, 0, 0, 0, 0 };
600 u8 mac[ETH_ALEN];
601 int i = 0;
602
603 if (memcmp(ssid_bssid->bssid, zero_mac, sizeof(zero_mac))) {
604 i = mwifiex_find_bssid_in_list(priv,
605 (u8 *) ssid_bssid->bssid,
606 priv->bss_mode);
607 if (i < 0) {
608 memcpy(mac, ssid_bssid->bssid, sizeof(mac));
609 dev_err(adapter->dev, "cannot find bssid %pM\n", mac);
610 return -1;
611 }
612 bss_desc = &adapter->scan_table[i];
613 memcpy(&ssid_bssid->ssid, &bss_desc->ssid,
614 sizeof(struct mwifiex_802_11_ssid));
615 } else if (ssid_bssid->ssid.ssid_len) {
616 i = mwifiex_find_ssid_in_list(priv, &ssid_bssid->ssid, NULL,
617 priv->bss_mode);
618 if (i < 0) {
619 dev_err(adapter->dev, "cannot find ssid %s\n",
620 ssid_bssid->ssid.ssid);
621 return -1;
622 }
623 bss_desc = &adapter->scan_table[i];
624 memcpy(ssid_bssid->bssid, bss_desc->mac_address, ETH_ALEN);
625 } else {
626 return mwifiex_find_best_network(priv, ssid_bssid);
627 }
628
629 return 0;
630}
631
632/*
633 * IOCTL request handler to change Ad-Hoc channel. 629 * IOCTL request handler to change Ad-Hoc channel.
634 * 630 *
635 * This function allocates the IOCTL request buffer, fills it 631 * This function allocates the IOCTL request buffer, fills it
@@ -653,6 +649,8 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
653 struct mwifiex_bss_info bss_info; 649 struct mwifiex_bss_info bss_info;
654 struct mwifiex_ssid_bssid ssid_bssid; 650 struct mwifiex_ssid_bssid ssid_bssid;
655 u16 curr_chan = 0; 651 u16 curr_chan = 0;
652 struct cfg80211_bss *bss = NULL;
653 struct ieee80211_channel *chan;
656 654
657 memset(&bss_info, 0, sizeof(bss_info)); 655 memset(&bss_info, 0, sizeof(bss_info));
658 656
@@ -688,12 +686,20 @@ mwifiex_drv_change_adhoc_chan(struct mwifiex_private *priv, int channel)
688 ret = -1; 686 ret = -1;
689 goto done; 687 goto done;
690 } 688 }
691 /* Start/Join Adhoc network */
692 memset(&ssid_bssid, 0, sizeof(struct mwifiex_ssid_bssid));
693 memcpy(&ssid_bssid.ssid, &bss_info.ssid,
694 sizeof(struct mwifiex_802_11_ssid));
695 689
696 ret = mwifiex_bss_start(priv, &ssid_bssid); 690 chan = __ieee80211_get_channel(priv->wdev->wiphy,
691 ieee80211_channel_to_frequency(channel,
692 priv->curr_bss_params.band));
693
694 /* Find the BSS we want using available scan results */
695 bss = cfg80211_get_bss(priv->wdev->wiphy, chan, bss_info.bssid,
696 bss_info.ssid.ssid, bss_info.ssid.ssid_len,
697 WLAN_CAPABILITY_ESS, WLAN_CAPABILITY_ESS);
698 if (!bss)
699 wiphy_warn(priv->wdev->wiphy, "assoc: bss %pM not in scan results\n",
700 bss_info.bssid);
701
702 ret = mwifiex_bss_start(priv, bss, &bss_info.ssid);
697done: 703done:
698 return ret; 704 return ret;
699} 705}
@@ -1280,9 +1286,9 @@ int mwifiex_get_signal_info(struct mwifiex_private *priv,
1280 1286
1281 if (!status) { 1287 if (!status) {
1282 if (signal->selector & BCN_RSSI_AVG_MASK) 1288 if (signal->selector & BCN_RSSI_AVG_MASK)
1283 priv->w_stats.qual.level = signal->bcn_rssi_avg; 1289 priv->qual_level = signal->bcn_rssi_avg;
1284 if (signal->selector & BCN_NF_AVG_MASK) 1290 if (signal->selector & BCN_NF_AVG_MASK)
1285 priv->w_stats.qual.noise = signal->bcn_nf_avg; 1291 priv->qual_noise = signal->bcn_nf_avg;
1286 } 1292 }
1287 1293
1288 return status; 1294 return status;
@@ -1341,18 +1347,8 @@ int
1341mwifiex_get_stats_info(struct mwifiex_private *priv, 1347mwifiex_get_stats_info(struct mwifiex_private *priv,
1342 struct mwifiex_ds_get_stats *log) 1348 struct mwifiex_ds_get_stats *log)
1343{ 1349{
1344 int ret; 1350 return mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
1345
1346 ret = mwifiex_send_cmd_sync(priv, HostCmd_CMD_802_11_GET_LOG,
1347 HostCmd_ACT_GEN_GET, 0, log); 1351 HostCmd_ACT_GEN_GET, 0, log);
1348
1349 if (!ret) {
1350 priv->w_stats.discard.fragment = log->fcs_error;
1351 priv->w_stats.discard.retries = log->retry;
1352 priv->w_stats.discard.misc = log->ack_failure;
1353 }
1354
1355 return ret;
1356} 1352}
1357 1353
1358/* 1354/*
@@ -1594,7 +1590,7 @@ mwifiex_set_gen_ie(struct mwifiex_private *priv, u8 *ie, int ie_len)
1594{ 1590{
1595 struct mwifiex_ds_misc_gen_ie gen_ie; 1591 struct mwifiex_ds_misc_gen_ie gen_ie;
1596 1592
1597 if (ie_len > IW_CUSTOM_MAX) 1593 if (ie_len > IEEE_MAX_IE_SIZE)
1598 return -EFAULT; 1594 return -EFAULT;
1599 1595
1600 gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE; 1596 gen_ie.type = MWIFIEX_IE_TYPE_GEN_IE;
diff --git a/drivers/net/wireless/orinoco/wext.c b/drivers/net/wireless/orinoco/wext.c
index bbb9beb206b1..33747e131a96 100644
--- a/drivers/net/wireless/orinoco/wext.c
+++ b/drivers/net/wireless/orinoco/wext.c
@@ -9,6 +9,7 @@
9#include <linux/ieee80211.h> 9#include <linux/ieee80211.h>
10#include <net/iw_handler.h> 10#include <net/iw_handler.h>
11#include <net/cfg80211.h> 11#include <net/cfg80211.h>
12#include <net/cfg80211-wext.h>
12 13
13#include "hermes.h" 14#include "hermes.h"
14#include "hermes_rid.h" 15#include "hermes_rid.h"
diff --git a/drivers/net/wireless/rndis_wlan.c b/drivers/net/wireless/rndis_wlan.c
index 6e0c61145b18..0c13840a7de5 100644
--- a/drivers/net/wireless/rndis_wlan.c
+++ b/drivers/net/wireless/rndis_wlan.c
@@ -36,13 +36,11 @@
36#include <linux/mii.h> 36#include <linux/mii.h>
37#include <linux/usb.h> 37#include <linux/usb.h>
38#include <linux/usb/cdc.h> 38#include <linux/usb/cdc.h>
39#include <linux/wireless.h>
40#include <linux/ieee80211.h> 39#include <linux/ieee80211.h>
41#include <linux/if_arp.h> 40#include <linux/if_arp.h>
42#include <linux/ctype.h> 41#include <linux/ctype.h>
43#include <linux/spinlock.h> 42#include <linux/spinlock.h>
44#include <linux/slab.h> 43#include <linux/slab.h>
45#include <net/iw_handler.h>
46#include <net/cfg80211.h> 44#include <net/cfg80211.h>
47#include <linux/usb/usbnet.h> 45#include <linux/usb/usbnet.h>
48#include <linux/usb/rndis_host.h> 46#include <linux/usb/rndis_host.h>
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 76bcc3547976..daa32fc9398b 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -645,11 +645,6 @@ static void rt2400pci_start_queue(struct data_queue *queue)
645 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); 645 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
646 break; 646 break;
647 case QID_BEACON: 647 case QID_BEACON:
648 /*
649 * Allow the tbtt tasklet to be scheduled.
650 */
651 tasklet_enable(&rt2x00dev->tbtt_tasklet);
652
653 rt2x00pci_register_read(rt2x00dev, CSR14, &reg); 648 rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
654 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1); 649 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
655 rt2x00_set_field32(&reg, CSR14_TBCN, 1); 650 rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -715,7 +710,7 @@ static void rt2400pci_stop_queue(struct data_queue *queue)
715 /* 710 /*
716 * Wait for possibly running tbtt tasklets. 711 * Wait for possibly running tbtt tasklets.
717 */ 712 */
718 tasklet_disable(&rt2x00dev->tbtt_tasklet); 713 tasklet_kill(&rt2x00dev->tbtt_tasklet);
719 break; 714 break;
720 default: 715 default:
721 break; 716 break;
@@ -982,12 +977,6 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
982 if (state == STATE_RADIO_IRQ_ON) { 977 if (state == STATE_RADIO_IRQ_ON) {
983 rt2x00pci_register_read(rt2x00dev, CSR7, &reg); 978 rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
984 rt2x00pci_register_write(rt2x00dev, CSR7, reg); 979 rt2x00pci_register_write(rt2x00dev, CSR7, reg);
985
986 /*
987 * Enable tasklets.
988 */
989 tasklet_enable(&rt2x00dev->txstatus_tasklet);
990 tasklet_enable(&rt2x00dev->rxdone_tasklet);
991 } 980 }
992 981
993 /* 982 /*
@@ -1011,8 +1000,9 @@ static void rt2400pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1011 * Ensure that all tasklets are finished before 1000 * Ensure that all tasklets are finished before
1012 * disabling the interrupts. 1001 * disabling the interrupts.
1013 */ 1002 */
1014 tasklet_disable(&rt2x00dev->txstatus_tasklet); 1003 tasklet_kill(&rt2x00dev->txstatus_tasklet);
1015 tasklet_disable(&rt2x00dev->rxdone_tasklet); 1004 tasklet_kill(&rt2x00dev->rxdone_tasklet);
1005 tasklet_kill(&rt2x00dev->tbtt_tasklet);
1016 } 1006 }
1017} 1007}
1018 1008
@@ -1347,22 +1337,25 @@ static void rt2400pci_txstatus_tasklet(unsigned long data)
1347 /* 1337 /*
1348 * Enable all TXDONE interrupts again. 1338 * Enable all TXDONE interrupts again.
1349 */ 1339 */
1350 spin_lock_irq(&rt2x00dev->irqmask_lock); 1340 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
1341 spin_lock_irq(&rt2x00dev->irqmask_lock);
1351 1342
1352 rt2x00pci_register_read(rt2x00dev, CSR8, &reg); 1343 rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
1353 rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0); 1344 rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
1354 rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0); 1345 rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
1355 rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0); 1346 rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
1356 rt2x00pci_register_write(rt2x00dev, CSR8, reg); 1347 rt2x00pci_register_write(rt2x00dev, CSR8, reg);
1357 1348
1358 spin_unlock_irq(&rt2x00dev->irqmask_lock); 1349 spin_unlock_irq(&rt2x00dev->irqmask_lock);
1350 }
1359} 1351}
1360 1352
1361static void rt2400pci_tbtt_tasklet(unsigned long data) 1353static void rt2400pci_tbtt_tasklet(unsigned long data)
1362{ 1354{
1363 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 1355 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1364 rt2x00lib_beacondone(rt2x00dev); 1356 rt2x00lib_beacondone(rt2x00dev);
1365 rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); 1357 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1358 rt2400pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
1366} 1359}
1367 1360
1368static void rt2400pci_rxdone_tasklet(unsigned long data) 1361static void rt2400pci_rxdone_tasklet(unsigned long data)
@@ -1370,7 +1363,7 @@ static void rt2400pci_rxdone_tasklet(unsigned long data)
1370 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 1363 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1371 if (rt2x00pci_rxdone(rt2x00dev)) 1364 if (rt2x00pci_rxdone(rt2x00dev))
1372 tasklet_schedule(&rt2x00dev->rxdone_tasklet); 1365 tasklet_schedule(&rt2x00dev->rxdone_tasklet);
1373 else 1366 else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1374 rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); 1367 rt2400pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
1375} 1368}
1376 1369
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index c288d951c034..b46c3b8866fa 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -735,11 +735,6 @@ static void rt2500pci_start_queue(struct data_queue *queue)
735 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg); 735 rt2x00pci_register_write(rt2x00dev, RXCSR0, reg);
736 break; 736 break;
737 case QID_BEACON: 737 case QID_BEACON:
738 /*
739 * Allow the tbtt tasklet to be scheduled.
740 */
741 tasklet_enable(&rt2x00dev->tbtt_tasklet);
742
743 rt2x00pci_register_read(rt2x00dev, CSR14, &reg); 738 rt2x00pci_register_read(rt2x00dev, CSR14, &reg);
744 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1); 739 rt2x00_set_field32(&reg, CSR14_TSF_COUNT, 1);
745 rt2x00_set_field32(&reg, CSR14_TBCN, 1); 740 rt2x00_set_field32(&reg, CSR14_TBCN, 1);
@@ -805,7 +800,7 @@ static void rt2500pci_stop_queue(struct data_queue *queue)
805 /* 800 /*
806 * Wait for possibly running tbtt tasklets. 801 * Wait for possibly running tbtt tasklets.
807 */ 802 */
808 tasklet_disable(&rt2x00dev->tbtt_tasklet); 803 tasklet_kill(&rt2x00dev->tbtt_tasklet);
809 break; 804 break;
810 default: 805 default:
811 break; 806 break;
@@ -1137,12 +1132,6 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1137 if (state == STATE_RADIO_IRQ_ON) { 1132 if (state == STATE_RADIO_IRQ_ON) {
1138 rt2x00pci_register_read(rt2x00dev, CSR7, &reg); 1133 rt2x00pci_register_read(rt2x00dev, CSR7, &reg);
1139 rt2x00pci_register_write(rt2x00dev, CSR7, reg); 1134 rt2x00pci_register_write(rt2x00dev, CSR7, reg);
1140
1141 /*
1142 * Enable tasklets.
1143 */
1144 tasklet_enable(&rt2x00dev->txstatus_tasklet);
1145 tasklet_enable(&rt2x00dev->rxdone_tasklet);
1146 } 1135 }
1147 1136
1148 /* 1137 /*
@@ -1165,8 +1154,9 @@ static void rt2500pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1165 /* 1154 /*
1166 * Ensure that all tasklets are finished. 1155 * Ensure that all tasklets are finished.
1167 */ 1156 */
1168 tasklet_disable(&rt2x00dev->txstatus_tasklet); 1157 tasklet_kill(&rt2x00dev->txstatus_tasklet);
1169 tasklet_disable(&rt2x00dev->rxdone_tasklet); 1158 tasklet_kill(&rt2x00dev->rxdone_tasklet);
1159 tasklet_kill(&rt2x00dev->tbtt_tasklet);
1170 } 1160 }
1171} 1161}
1172 1162
@@ -1479,22 +1469,25 @@ static void rt2500pci_txstatus_tasklet(unsigned long data)
1479 /* 1469 /*
1480 * Enable all TXDONE interrupts again. 1470 * Enable all TXDONE interrupts again.
1481 */ 1471 */
1482 spin_lock_irq(&rt2x00dev->irqmask_lock); 1472 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags)) {
1473 spin_lock_irq(&rt2x00dev->irqmask_lock);
1483 1474
1484 rt2x00pci_register_read(rt2x00dev, CSR8, &reg); 1475 rt2x00pci_register_read(rt2x00dev, CSR8, &reg);
1485 rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0); 1476 rt2x00_set_field32(&reg, CSR8_TXDONE_TXRING, 0);
1486 rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0); 1477 rt2x00_set_field32(&reg, CSR8_TXDONE_ATIMRING, 0);
1487 rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0); 1478 rt2x00_set_field32(&reg, CSR8_TXDONE_PRIORING, 0);
1488 rt2x00pci_register_write(rt2x00dev, CSR8, reg); 1479 rt2x00pci_register_write(rt2x00dev, CSR8, reg);
1489 1480
1490 spin_unlock_irq(&rt2x00dev->irqmask_lock); 1481 spin_unlock_irq(&rt2x00dev->irqmask_lock);
1482 }
1491} 1483}
1492 1484
1493static void rt2500pci_tbtt_tasklet(unsigned long data) 1485static void rt2500pci_tbtt_tasklet(unsigned long data)
1494{ 1486{
1495 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 1487 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1496 rt2x00lib_beacondone(rt2x00dev); 1488 rt2x00lib_beacondone(rt2x00dev);
1497 rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE); 1489 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1490 rt2500pci_enable_interrupt(rt2x00dev, CSR8_TBCN_EXPIRE);
1498} 1491}
1499 1492
1500static void rt2500pci_rxdone_tasklet(unsigned long data) 1493static void rt2500pci_rxdone_tasklet(unsigned long data)
@@ -1502,7 +1495,7 @@ static void rt2500pci_rxdone_tasklet(unsigned long data)
1502 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 1495 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
1503 if (rt2x00pci_rxdone(rt2x00dev)) 1496 if (rt2x00pci_rxdone(rt2x00dev))
1504 tasklet_schedule(&rt2x00dev->rxdone_tasklet); 1497 tasklet_schedule(&rt2x00dev->rxdone_tasklet);
1505 else 1498 else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
1506 rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE); 1499 rt2500pci_enable_interrupt(rt2x00dev, CSR8_RXDONE);
1507} 1500}
1508 1501
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index ebc17ad61dec..cabf249aa55b 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -200,13 +200,6 @@ static void rt2800pci_start_queue(struct data_queue *queue)
200 rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg); 200 rt2x00pci_register_write(rt2x00dev, MAC_SYS_CTRL, reg);
201 break; 201 break;
202 case QID_BEACON: 202 case QID_BEACON:
203 /*
204 * Allow beacon tasklets to be scheduled for periodic
205 * beacon updates.
206 */
207 tasklet_enable(&rt2x00dev->tbtt_tasklet);
208 tasklet_enable(&rt2x00dev->pretbtt_tasklet);
209
210 rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg); 203 rt2x00pci_register_read(rt2x00dev, BCN_TIME_CFG, &reg);
211 rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1); 204 rt2x00_set_field32(&reg, BCN_TIME_CFG_TSF_TICKING, 1);
212 rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1); 205 rt2x00_set_field32(&reg, BCN_TIME_CFG_TBTT_ENABLE, 1);
@@ -269,10 +262,13 @@ static void rt2800pci_stop_queue(struct data_queue *queue)
269 rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg); 262 rt2x00pci_register_write(rt2x00dev, INT_TIMER_EN, reg);
270 263
271 /* 264 /*
272 * Wait for tbtt tasklets to finish. 265 * Wait for current invocation to finish. The tasklet
266 * won't be scheduled anymore afterwards since we disabled
267 * the TBTT and PRE TBTT timer.
273 */ 268 */
274 tasklet_disable(&rt2x00dev->tbtt_tasklet); 269 tasklet_kill(&rt2x00dev->tbtt_tasklet);
275 tasklet_disable(&rt2x00dev->pretbtt_tasklet); 270 tasklet_kill(&rt2x00dev->pretbtt_tasklet);
271
276 break; 272 break;
277 default: 273 default:
278 break; 274 break;
@@ -437,14 +433,6 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
437 if (state == STATE_RADIO_IRQ_ON) { 433 if (state == STATE_RADIO_IRQ_ON) {
438 rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg); 434 rt2x00pci_register_read(rt2x00dev, INT_SOURCE_CSR, &reg);
439 rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg); 435 rt2x00pci_register_write(rt2x00dev, INT_SOURCE_CSR, reg);
440
441 /*
442 * Enable tasklets. The beacon related tasklets are
443 * enabled when the beacon queue is started.
444 */
445 tasklet_enable(&rt2x00dev->txstatus_tasklet);
446 tasklet_enable(&rt2x00dev->rxdone_tasklet);
447 tasklet_enable(&rt2x00dev->autowake_tasklet);
448 } 436 }
449 437
450 spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags); 438 spin_lock_irqsave(&rt2x00dev->irqmask_lock, flags);
@@ -472,12 +460,13 @@ static void rt2800pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
472 460
473 if (state == STATE_RADIO_IRQ_OFF) { 461 if (state == STATE_RADIO_IRQ_OFF) {
474 /* 462 /*
475 * Ensure that all tasklets are finished before 463 * Wait for possibly running tasklets to finish.
476 * disabling the interrupts.
477 */ 464 */
478 tasklet_disable(&rt2x00dev->txstatus_tasklet); 465 tasklet_kill(&rt2x00dev->txstatus_tasklet);
479 tasklet_disable(&rt2x00dev->rxdone_tasklet); 466 tasklet_kill(&rt2x00dev->rxdone_tasklet);
480 tasklet_disable(&rt2x00dev->autowake_tasklet); 467 tasklet_kill(&rt2x00dev->autowake_tasklet);
468 tasklet_kill(&rt2x00dev->tbtt_tasklet);
469 tasklet_kill(&rt2x00dev->pretbtt_tasklet);
481 } 470 }
482} 471}
483 472
@@ -813,14 +802,16 @@ static void rt2800pci_pretbtt_tasklet(unsigned long data)
813{ 802{
814 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 803 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
815 rt2x00lib_pretbtt(rt2x00dev); 804 rt2x00lib_pretbtt(rt2x00dev);
816 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT); 805 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
806 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_PRE_TBTT);
817} 807}
818 808
819static void rt2800pci_tbtt_tasklet(unsigned long data) 809static void rt2800pci_tbtt_tasklet(unsigned long data)
820{ 810{
821 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 811 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
822 rt2x00lib_beacondone(rt2x00dev); 812 rt2x00lib_beacondone(rt2x00dev);
823 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT); 813 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
814 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TBTT);
824} 815}
825 816
826static void rt2800pci_rxdone_tasklet(unsigned long data) 817static void rt2800pci_rxdone_tasklet(unsigned long data)
@@ -828,7 +819,7 @@ static void rt2800pci_rxdone_tasklet(unsigned long data)
828 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 819 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
829 if (rt2x00pci_rxdone(rt2x00dev)) 820 if (rt2x00pci_rxdone(rt2x00dev))
830 tasklet_schedule(&rt2x00dev->rxdone_tasklet); 821 tasklet_schedule(&rt2x00dev->rxdone_tasklet);
831 else 822 else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
832 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE); 823 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RX_DONE);
833} 824}
834 825
@@ -836,7 +827,8 @@ static void rt2800pci_autowake_tasklet(unsigned long data)
836{ 827{
837 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 828 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
838 rt2800pci_wakeup(rt2x00dev); 829 rt2800pci_wakeup(rt2x00dev);
839 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP); 830 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
831 rt2800pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_AUTO_WAKEUP);
840} 832}
841 833
842static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev) 834static void rt2800pci_txstatus_interrupt(struct rt2x00_dev *rt2x00dev)
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 0955c941317f..92ff6a72a2bb 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -946,7 +946,6 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
946 tasklet_init(&rt2x00dev->taskletname, \ 946 tasklet_init(&rt2x00dev->taskletname, \
947 rt2x00dev->ops->lib->taskletname, \ 947 rt2x00dev->ops->lib->taskletname, \
948 (unsigned long)rt2x00dev); \ 948 (unsigned long)rt2x00dev); \
949 tasklet_disable(&rt2x00dev->taskletname); \
950 } 949 }
951 950
952 RT2X00_TASKLET_INIT(txstatus_tasklet); 951 RT2X00_TASKLET_INIT(txstatus_tasklet);
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index 53110b83bf6e..058ef4b19d1d 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -1142,11 +1142,6 @@ static void rt61pci_start_queue(struct data_queue *queue)
1142 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg); 1142 rt2x00pci_register_write(rt2x00dev, TXRX_CSR0, reg);
1143 break; 1143 break;
1144 case QID_BEACON: 1144 case QID_BEACON:
1145 /*
1146 * Allow the tbtt tasklet to be scheduled.
1147 */
1148 tasklet_enable(&rt2x00dev->tbtt_tasklet);
1149
1150 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg); 1145 rt2x00pci_register_read(rt2x00dev, TXRX_CSR9, &reg);
1151 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1); 1146 rt2x00_set_field32(&reg, TXRX_CSR9_TSF_TICKING, 1);
1152 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1); 1147 rt2x00_set_field32(&reg, TXRX_CSR9_TBTT_ENABLE, 1);
@@ -1230,7 +1225,7 @@ static void rt61pci_stop_queue(struct data_queue *queue)
1230 /* 1225 /*
1231 * Wait for possibly running tbtt tasklets. 1226 * Wait for possibly running tbtt tasklets.
1232 */ 1227 */
1233 tasklet_disable(&rt2x00dev->tbtt_tasklet); 1228 tasklet_kill(&rt2x00dev->tbtt_tasklet);
1234 break; 1229 break;
1235 default: 1230 default:
1236 break; 1231 break;
@@ -1731,13 +1726,6 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1731 1726
1732 rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg); 1727 rt2x00pci_register_read(rt2x00dev, MCU_INT_SOURCE_CSR, &reg);
1733 rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg); 1728 rt2x00pci_register_write(rt2x00dev, MCU_INT_SOURCE_CSR, reg);
1734
1735 /*
1736 * Enable tasklets.
1737 */
1738 tasklet_enable(&rt2x00dev->txstatus_tasklet);
1739 tasklet_enable(&rt2x00dev->rxdone_tasklet);
1740 tasklet_enable(&rt2x00dev->autowake_tasklet);
1741 } 1729 }
1742 1730
1743 /* 1731 /*
@@ -1772,9 +1760,10 @@ static void rt61pci_toggle_irq(struct rt2x00_dev *rt2x00dev,
1772 /* 1760 /*
1773 * Ensure that all tasklets are finished. 1761 * Ensure that all tasklets are finished.
1774 */ 1762 */
1775 tasklet_disable(&rt2x00dev->txstatus_tasklet); 1763 tasklet_kill(&rt2x00dev->txstatus_tasklet);
1776 tasklet_disable(&rt2x00dev->rxdone_tasklet); 1764 tasklet_kill(&rt2x00dev->rxdone_tasklet);
1777 tasklet_disable(&rt2x00dev->autowake_tasklet); 1765 tasklet_kill(&rt2x00dev->autowake_tasklet);
1766 tasklet_kill(&rt2x00dev->tbtt_tasklet);
1778 } 1767 }
1779} 1768}
1780 1769
@@ -2300,22 +2289,24 @@ static void rt61pci_txstatus_tasklet(unsigned long data)
2300{ 2289{
2301 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 2290 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
2302 rt61pci_txdone(rt2x00dev); 2291 rt61pci_txdone(rt2x00dev);
2303 rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE); 2292 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
2293 rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_TXDONE);
2304} 2294}
2305 2295
2306static void rt61pci_tbtt_tasklet(unsigned long data) 2296static void rt61pci_tbtt_tasklet(unsigned long data)
2307{ 2297{
2308 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 2298 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
2309 rt2x00lib_beacondone(rt2x00dev); 2299 rt2x00lib_beacondone(rt2x00dev);
2310 rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE); 2300 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
2301 rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_BEACON_DONE);
2311} 2302}
2312 2303
2313static void rt61pci_rxdone_tasklet(unsigned long data) 2304static void rt61pci_rxdone_tasklet(unsigned long data)
2314{ 2305{
2315 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data; 2306 struct rt2x00_dev *rt2x00dev = (struct rt2x00_dev *)data;
2316 if (rt2x00pci_rxdone(rt2x00dev)) 2307 if (rt2x00pci_rxdone(rt2x00dev))
2317 rt2x00pci_rxdone(rt2x00dev); 2308 tasklet_schedule(&rt2x00dev->rxdone_tasklet);
2318 else 2309 else if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
2319 rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE); 2310 rt61pci_enable_interrupt(rt2x00dev, INT_MASK_CSR_RXDONE);
2320} 2311}
2321 2312
@@ -2325,7 +2316,8 @@ static void rt61pci_autowake_tasklet(unsigned long data)
2325 rt61pci_wakeup(rt2x00dev); 2316 rt61pci_wakeup(rt2x00dev);
2326 rt2x00pci_register_write(rt2x00dev, 2317 rt2x00pci_register_write(rt2x00dev,
2327 M2H_CMD_DONE_CSR, 0xffffffff); 2318 M2H_CMD_DONE_CSR, 0xffffffff);
2328 rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP); 2319 if (test_bit(DEVICE_STATE_ENABLED_RADIO, &rt2x00dev->flags))
2320 rt61pci_enable_mcu_interrupt(rt2x00dev, MCU_INT_MASK_CSR_TWAKEUP);
2329} 2321}
2330 2322
2331static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance) 2323static irqreturn_t rt61pci_interrupt(int irq, void *dev_instance)
diff --git a/drivers/net/wireless/rtlwifi/pci.c b/drivers/net/wireless/rtlwifi/pci.c
index 56f12358389d..9983fa18065a 100644
--- a/drivers/net/wireless/rtlwifi/pci.c
+++ b/drivers/net/wireless/rtlwifi/pci.c
@@ -218,7 +218,6 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
218 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw)); 218 struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
219 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 219 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
220 u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; 220 u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
221 u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
222 u8 num4bytes = pcipriv->ndis_adapter.num4bytes; 221 u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
223 /*Retrieve original configuration settings. */ 222 /*Retrieve original configuration settings. */
224 u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg; 223 u8 linkctrl_reg = pcipriv->ndis_adapter.linkctrl_reg;
@@ -254,9 +253,8 @@ static void rtl_pci_disable_aspm(struct ieee80211_hw *hw)
254 udelay(50); 253 udelay(50);
255 254
256 /*4 Disable Pci Bridge ASPM */ 255 /*4 Disable Pci Bridge ASPM */
257 rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, 256 pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
258 pcicfg_addrport + (num4bytes << 2)); 257 pcibridge_linkctrlreg);
259 rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, pcibridge_linkctrlreg);
260 258
261 udelay(50); 259 udelay(50);
262} 260}
@@ -277,7 +275,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
277 u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum; 275 u8 pcibridge_devnum = pcipriv->ndis_adapter.pcibridge_devnum;
278 u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum; 276 u8 pcibridge_funcnum = pcipriv->ndis_adapter.pcibridge_funcnum;
279 u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor; 277 u8 pcibridge_vendor = pcipriv->ndis_adapter.pcibridge_vendor;
280 u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
281 u8 num4bytes = pcipriv->ndis_adapter.num4bytes; 278 u8 num4bytes = pcipriv->ndis_adapter.num4bytes;
282 u16 aspmlevel; 279 u16 aspmlevel;
283 u8 u_pcibridge_aspmsetting; 280 u8 u_pcibridge_aspmsetting;
@@ -293,8 +290,6 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
293 } 290 }
294 291
295 /*4 Enable Pci Bridge ASPM */ 292 /*4 Enable Pci Bridge ASPM */
296 rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS,
297 pcicfg_addrport + (num4bytes << 2));
298 293
299 u_pcibridge_aspmsetting = 294 u_pcibridge_aspmsetting =
300 pcipriv->ndis_adapter.pcibridge_linkctrlreg | 295 pcipriv->ndis_adapter.pcibridge_linkctrlreg |
@@ -303,7 +298,8 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
303 if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL) 298 if (pcibridge_vendor == PCI_BRIDGE_VENDOR_INTEL)
304 u_pcibridge_aspmsetting &= ~BIT(0); 299 u_pcibridge_aspmsetting &= ~BIT(0);
305 300
306 rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, u_pcibridge_aspmsetting); 301 pci_write_config_byte(rtlpci->pdev, (num4bytes << 2),
302 u_pcibridge_aspmsetting);
307 303
308 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 304 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD,
309 ("PlatformEnableASPM():PciBridge busnumber[%x], " 305 ("PlatformEnableASPM():PciBridge busnumber[%x], "
@@ -335,25 +331,18 @@ static void rtl_pci_enable_aspm(struct ieee80211_hw *hw)
335 331
336static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw) 332static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
337{ 333{
338 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); 334 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
339 u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
340 335
341 bool status = false; 336 bool status = false;
342 u8 offset_e0; 337 u8 offset_e0;
343 unsigned offset_e4; 338 unsigned offset_e4;
344 339
345 rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, 340 pci_write_config_byte(rtlpci->pdev, 0xe0, 0xa0);
346 pcicfg_addrport + 0xE0);
347 rtl_pci_raw_write_port_uchar(PCI_CONF_DATA, 0xA0);
348 341
349 rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, 342 pci_read_config_byte(rtlpci->pdev, 0xe0, &offset_e0);
350 pcicfg_addrport + 0xE0);
351 rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &offset_e0);
352 343
353 if (offset_e0 == 0xA0) { 344 if (offset_e0 == 0xA0) {
354 rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, 345 pci_read_config_dword(rtlpci->pdev, 0xe4, &offset_e4);
355 pcicfg_addrport + 0xE4);
356 rtl_pci_raw_read_port_ulong(PCI_CONF_DATA, &offset_e4);
357 if (offset_e4 & BIT(23)) 346 if (offset_e4 & BIT(23))
358 status = true; 347 status = true;
359 } 348 }
@@ -364,17 +353,15 @@ static bool rtl_pci_get_amd_l1_patch(struct ieee80211_hw *hw)
364static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw) 353static void rtl_pci_get_linkcontrol_field(struct ieee80211_hw *hw)
365{ 354{
366 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw); 355 struct rtl_pci_priv *pcipriv = rtl_pcipriv(hw);
356 struct rtl_pci *rtlpci = rtl_pcidev(pcipriv);
367 u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset; 357 u8 capabilityoffset = pcipriv->ndis_adapter.pcibridge_pciehdr_offset;
368 u32 pcicfg_addrport = pcipriv->ndis_adapter.pcicfg_addrport;
369 u8 linkctrl_reg; 358 u8 linkctrl_reg;
370 u8 num4bbytes; 359 u8 num4bbytes;
371 360
372 num4bbytes = (capabilityoffset + 0x10) / 4; 361 num4bbytes = (capabilityoffset + 0x10) / 4;
373 362
374 /*Read Link Control Register */ 363 /*Read Link Control Register */
375 rtl_pci_raw_write_port_ulong(PCI_CONF_ADDRESS, 364 pci_read_config_byte(rtlpci->pdev, (num4bbytes << 2), &linkctrl_reg);
376 pcicfg_addrport + (num4bbytes << 2));
377 rtl_pci_raw_read_port_uchar(PCI_CONF_DATA, &linkctrl_reg);
378 365
379 pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg; 366 pcipriv->ndis_adapter.pcibridge_linkctrlreg = linkctrl_reg;
380} 367}
@@ -1718,10 +1705,6 @@ static bool _rtl_pci_find_adapter(struct pci_dev *pdev,
1718 PCI_SLOT(bridge_pdev->devfn); 1705 PCI_SLOT(bridge_pdev->devfn);
1719 pcipriv->ndis_adapter.pcibridge_funcnum = 1706 pcipriv->ndis_adapter.pcibridge_funcnum =
1720 PCI_FUNC(bridge_pdev->devfn); 1707 PCI_FUNC(bridge_pdev->devfn);
1721 pcipriv->ndis_adapter.pcicfg_addrport =
1722 (pcipriv->ndis_adapter.pcibridge_busnum << 16) |
1723 (pcipriv->ndis_adapter.pcibridge_devnum << 11) |
1724 (pcipriv->ndis_adapter.pcibridge_funcnum << 8) | (1 << 31);
1725 pcipriv->ndis_adapter.pcibridge_pciehdr_offset = 1708 pcipriv->ndis_adapter.pcibridge_pciehdr_offset =
1726 pci_pcie_cap(bridge_pdev); 1709 pci_pcie_cap(bridge_pdev);
1727 pcipriv->ndis_adapter.num4bytes = 1710 pcipriv->ndis_adapter.num4bytes =
diff --git a/drivers/net/wireless/rtlwifi/pci.h b/drivers/net/wireless/rtlwifi/pci.h
index c53c62046747..a24e505b202b 100644
--- a/drivers/net/wireless/rtlwifi/pci.h
+++ b/drivers/net/wireless/rtlwifi/pci.h
@@ -212,7 +212,6 @@ struct mp_adapter {
212 u16 pcibridge_vendorid; 212 u16 pcibridge_vendorid;
213 u16 pcibridge_deviceid; 213 u16 pcibridge_deviceid;
214 214
215 u32 pcicfg_addrport;
216 u8 num4bytes; 215 u8 num4bytes;
217 216
218 u8 pcibridge_pciehdr_offset; 217 u8 pcibridge_pciehdr_offset;
@@ -273,29 +272,4 @@ static inline void pci_write32_async(struct rtl_priv *rtlpriv,
273 writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr); 272 writel(val, (u8 __iomem *) rtlpriv->io.pci_mem_start + addr);
274} 273}
275 274
276static inline void rtl_pci_raw_write_port_ulong(u32 port, u32 val)
277{
278 outl(val, port);
279}
280
281static inline void rtl_pci_raw_write_port_uchar(u32 port, u8 val)
282{
283 outb(val, port);
284}
285
286static inline void rtl_pci_raw_read_port_uchar(u32 port, u8 *pval)
287{
288 *pval = inb(port);
289}
290
291static inline void rtl_pci_raw_read_port_ushort(u32 port, u16 *pval)
292{
293 *pval = inw(port);
294}
295
296static inline void rtl_pci_raw_read_port_ulong(u32 port, u32 *pval)
297{
298 *pval = inl(port);
299}
300
301#endif 275#endif
diff --git a/drivers/net/wireless/wl1251/cmd.h b/drivers/net/wireless/wl1251/cmd.h
index 79ca5273c9e9..ee4f2b391822 100644
--- a/drivers/net/wireless/wl1251/cmd.h
+++ b/drivers/net/wireless/wl1251/cmd.h
@@ -269,7 +269,7 @@ struct cmd_join {
269 u8 bss_type; 269 u8 bss_type;
270 u8 channel; 270 u8 channel;
271 u8 ssid_len; 271 u8 ssid_len;
272 u8 ssid[IW_ESSID_MAX_SIZE]; 272 u8 ssid[IEEE80211_MAX_SSID_LEN];
273 u8 ctrl; /* JOIN_CMD_CTRL_* */ 273 u8 ctrl; /* JOIN_CMD_CTRL_* */
274 u8 tx_mgt_frame_rate; /* OBSOLETE */ 274 u8 tx_mgt_frame_rate; /* OBSOLETE */
275 u8 tx_mgt_frame_mod; /* OBSOLETE */ 275 u8 tx_mgt_frame_mod; /* OBSOLETE */
diff --git a/drivers/net/wireless/wl1251/wl12xx_80211.h b/drivers/net/wireless/wl1251/wl12xx_80211.h
index 1417b1445c3d..04ed51495772 100644
--- a/drivers/net/wireless/wl1251/wl12xx_80211.h
+++ b/drivers/net/wireless/wl1251/wl12xx_80211.h
@@ -76,7 +76,7 @@ struct wl12xx_ie_header {
76 76
77struct wl12xx_ie_ssid { 77struct wl12xx_ie_ssid {
78 struct wl12xx_ie_header header; 78 struct wl12xx_ie_header header;
79 char ssid[IW_ESSID_MAX_SIZE]; 79 char ssid[IEEE80211_MAX_SSID_LEN];
80} __packed; 80} __packed;
81 81
82struct wl12xx_ie_rates { 82struct wl12xx_ie_rates {
diff --git a/drivers/net/wireless/wl12xx/cmd.h b/drivers/net/wireless/wl12xx/cmd.h
index 1f7037292c15..bba077ecd945 100644
--- a/drivers/net/wireless/wl12xx/cmd.h
+++ b/drivers/net/wireless/wl12xx/cmd.h
@@ -239,7 +239,7 @@ struct wl1271_cmd_join {
239 u8 bss_type; 239 u8 bss_type;
240 u8 channel; 240 u8 channel;
241 u8 ssid_len; 241 u8 ssid_len;
242 u8 ssid[IW_ESSID_MAX_SIZE]; 242 u8 ssid[IEEE80211_MAX_SSID_LEN];
243 u8 ctrl; /* JOIN_CMD_CTRL_* */ 243 u8 ctrl; /* JOIN_CMD_CTRL_* */
244 u8 reserved[3]; 244 u8 reserved[3];
245} __packed; 245} __packed;
@@ -528,7 +528,7 @@ struct wl1271_cmd_bss_start {
528 /* wl1271_ssid_type */ 528 /* wl1271_ssid_type */
529 u8 ssid_type; 529 u8 ssid_type;
530 u8 ssid_len; 530 u8 ssid_len;
531 u8 ssid[IW_ESSID_MAX_SIZE]; 531 u8 ssid[IEEE80211_MAX_SSID_LEN];
532 u8 padding_1[2]; 532 u8 padding_1[2];
533 533
534 /* Basic rate set */ 534 /* Basic rate set */
diff --git a/drivers/net/wireless/wl12xx/main.c b/drivers/net/wireless/wl12xx/main.c
index e58c22d21e39..3418299e17c8 100644
--- a/drivers/net/wireless/wl12xx/main.c
+++ b/drivers/net/wireless/wl12xx/main.c
@@ -1997,7 +1997,7 @@ static void __wl1271_op_remove_interface(struct wl1271 *wl,
1997 wl1271_power_off(wl); 1997 wl1271_power_off(wl);
1998 1998
1999 memset(wl->bssid, 0, ETH_ALEN); 1999 memset(wl->bssid, 0, ETH_ALEN);
2000 memset(wl->ssid, 0, IW_ESSID_MAX_SIZE + 1); 2000 memset(wl->ssid, 0, IEEE80211_MAX_SSID_LEN + 1);
2001 wl->ssid_len = 0; 2001 wl->ssid_len = 0;
2002 wl->bss_type = MAX_BSS_TYPE; 2002 wl->bss_type = MAX_BSS_TYPE;
2003 wl->set_bss_type = MAX_BSS_TYPE; 2003 wl->set_bss_type = MAX_BSS_TYPE;
diff --git a/drivers/net/wireless/wl12xx/scan.h b/drivers/net/wireless/wl12xx/scan.h
index d882e4da71b7..0b2a2987439d 100644
--- a/drivers/net/wireless/wl12xx/scan.h
+++ b/drivers/net/wireless/wl12xx/scan.h
@@ -77,7 +77,7 @@ struct basic_scan_params {
77 u8 ssid_len; 77 u8 ssid_len;
78 /* in order to align */ 78 /* in order to align */
79 u8 padding1[2]; 79 u8 padding1[2];
80 u8 ssid[IW_ESSID_MAX_SIZE]; 80 u8 ssid[IEEE80211_MAX_SSID_LEN];
81 /* Band to scan */ 81 /* Band to scan */
82 u8 band; 82 u8 band;
83 u8 use_ssid_list; 83 u8 use_ssid_list;
@@ -167,7 +167,7 @@ struct wl1271_cmd_sched_scan_config {
167 u8 filter_type; 167 u8 filter_type;
168 168
169 u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */ 169 u8 ssid_len; /* For SCAN_SSID_FILTER_SPECIFIC */
170 u8 ssid[IW_ESSID_MAX_SIZE]; 170 u8 ssid[IEEE80211_MAX_SSID_LEN];
171 171
172 u8 n_probe_reqs; /* Number of probes requests per channel */ 172 u8 n_probe_reqs; /* Number of probes requests per channel */
173 173
@@ -194,7 +194,7 @@ enum {
194struct wl1271_ssid { 194struct wl1271_ssid {
195 u8 type; 195 u8 type;
196 u8 len; 196 u8 len;
197 u8 ssid[IW_ESSID_MAX_SIZE]; 197 u8 ssid[IEEE80211_MAX_SSID_LEN];
198 /* u8 padding[2]; */ 198 /* u8 padding[2]; */
199} __packed; 199} __packed;
200 200
diff --git a/drivers/net/wireless/wl12xx/wl12xx.h b/drivers/net/wireless/wl12xx/wl12xx.h
index 1a8751eb8140..0bc29356ebe4 100644
--- a/drivers/net/wireless/wl12xx/wl12xx.h
+++ b/drivers/net/wireless/wl12xx/wl12xx.h
@@ -309,7 +309,7 @@ struct wl1271_scan {
309 unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)]; 309 unsigned long scanned_ch[BITS_TO_LONGS(WL1271_MAX_CHANNELS)];
310 bool failed; 310 bool failed;
311 u8 state; 311 u8 state;
312 u8 ssid[IW_ESSID_MAX_SIZE+1]; 312 u8 ssid[IEEE80211_MAX_SSID_LEN+1];
313 size_t ssid_len; 313 size_t ssid_len;
314}; 314};
315 315
@@ -415,7 +415,7 @@ struct wl1271 {
415 u8 mac_addr[ETH_ALEN]; 415 u8 mac_addr[ETH_ALEN];
416 u8 bss_type; 416 u8 bss_type;
417 u8 set_bss_type; 417 u8 set_bss_type;
418 u8 ssid[IW_ESSID_MAX_SIZE + 1]; 418 u8 ssid[IEEE80211_MAX_SSID_LEN + 1];
419 u8 ssid_len; 419 u8 ssid_len;
420 int channel; 420 int channel;
421 421
diff --git a/drivers/net/wireless/wl12xx/wl12xx_80211.h b/drivers/net/wireless/wl12xx/wl12xx_80211.h
index 18fe542360f2..f334ea081722 100644
--- a/drivers/net/wireless/wl12xx/wl12xx_80211.h
+++ b/drivers/net/wireless/wl12xx/wl12xx_80211.h
@@ -77,7 +77,7 @@ struct wl12xx_ie_header {
77 77
78struct wl12xx_ie_ssid { 78struct wl12xx_ie_ssid {
79 struct wl12xx_ie_header header; 79 struct wl12xx_ie_header header;
80 char ssid[IW_ESSID_MAX_SIZE]; 80 char ssid[IEEE80211_MAX_SSID_LEN];
81} __packed; 81} __packed;
82 82
83struct wl12xx_ie_rates { 83struct wl12xx_ie_rates {