aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDavid S. Miller <davem@davemloft.net>2009-12-04 16:25:15 -0500
committerDavid S. Miller <davem@davemloft.net>2009-12-04 16:25:15 -0500
commit8f56874bd7e8bee73ed6a1cf80dcec2753616262 (patch)
treeaebd15dea662ef5efd89402b8fd92fec540a98eb
parent47e1c323069bcef0acb8a2b48921688573f5ca63 (diff)
parent159bcfeb9123c91f0dc885a42b6387a98192f896 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
-rw-r--r--MAINTAINERS9
-rw-r--r--drivers/net/wireless/airo.c2
-rw-r--r--drivers/net/wireless/ath/ath9k/Kconfig13
-rw-r--r--drivers/net/wireless/ath/ath9k/Makefile2
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h10
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c24
-rw-r--r--drivers/net/wireless/ath/ath9k/common.c26
-rw-r--r--drivers/net/wireless/ath/ath9k/common.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.c20
-rw-r--r--drivers/net/wireless/ath/ath9k/debug.h11
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c38
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h7
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c38
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h15
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c172
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.c433
-rw-r--r--drivers/net/wireless/ath/ath9k/rc.h5
-rw-r--r--drivers/net/wireless/ath/ath9k/reg.h15
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c140
-rw-r--r--drivers/net/wireless/b43/leds.c1
-rw-r--r--drivers/net/wireless/b43/rfkill.c10
-rw-r--r--drivers/net/wireless/b43legacy/rfkill.c7
-rw-r--r--drivers/net/wireless/ipw2x00/ipw2100.c11
-rw-r--r--drivers/net/wireless/ipw2x00/libipw_module.c33
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h4
-rw-r--r--drivers/net/wireless/iwlwifi/iwl3945-base.c13
-rw-r--r--drivers/net/wireless/iwmc3200wifi/cfg80211.c35
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.c77
-rw-r--r--drivers/net/wireless/iwmc3200wifi/commands.h23
-rw-r--r--drivers/net/wireless/iwmc3200wifi/debugfs.c23
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.c50
-rw-r--r--drivers/net/wireless/iwmc3200wifi/eeprom.h29
-rw-r--r--drivers/net/wireless/iwmc3200wifi/iwm.h11
-rw-r--r--drivers/net/wireless/iwmc3200wifi/main.c44
-rw-r--r--drivers/net/wireless/iwmc3200wifi/netdev.c8
-rw-r--r--drivers/net/wireless/iwmc3200wifi/rx.c66
-rw-r--r--drivers/net/wireless/iwmc3200wifi/tx.c66
-rw-r--r--drivers/net/wireless/iwmc3200wifi/umac.h36
-rw-r--r--drivers/net/wireless/libertas/Makefile2
-rw-r--r--drivers/net/wireless/libertas/cmd.c168
-rw-r--r--drivers/net/wireless/libertas/decl.h8
-rw-r--r--drivers/net/wireless/libertas/dev.h12
-rw-r--r--drivers/net/wireless/libertas/ethtool.c84
-rw-r--r--drivers/net/wireless/libertas/main.c357
-rw-r--r--drivers/net/wireless/libertas/mesh.c1141
-rw-r--r--drivers/net/wireless/libertas/mesh.h78
-rw-r--r--drivers/net/wireless/libertas/persistcfg.c453
-rw-r--r--drivers/net/wireless/libertas/rx.c11
-rw-r--r--drivers/net/wireless/libertas/tx.c7
-rw-r--r--drivers/net/wireless/libertas/wext.h5
-rw-r--r--drivers/net/wireless/ray_cs.c36
-rw-r--r--drivers/net/wireless/rt2x00/rt2400pci.c28
-rw-r--r--drivers/net/wireless/rt2x00/rt2500pci.c29
-rw-r--r--drivers/net/wireless/rt2x00/rt2500usb.c29
-rw-r--r--drivers/net/wireless/rt2x00/rt2800lib.c29
-rw-r--r--drivers/net/wireless/rt2x00/rt2800pci.c31
-rw-r--r--drivers/net/wireless/rt2x00/rt2800usb.c25
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00.h1
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00dev.c5
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00mac.c3
-rw-r--r--drivers/net/wireless/rt2x00/rt2x00queue.c6
-rw-r--r--drivers/net/wireless/rt2x00/rt61pci.c26
-rw-r--r--drivers/net/wireless/rt2x00/rt73usb.c26
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.c107
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_cmd.h72
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_event.c8
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.c117
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_init.h70
-rw-r--r--drivers/net/wireless/wl12xx/wl1271_main.c32
-rw-r--r--include/linux/ieee80211.h2
-rw-r--r--include/linux/nl80211.h11
-rw-r--r--include/net/cfg80211.h28
-rw-r--r--include/net/mac80211.h4
-rw-r--r--net/mac80211/driver-trace.h26
-rw-r--r--net/mac80211/ieee80211_i.h4
-rw-r--r--net/mac80211/iface.c14
-rw-r--r--net/mac80211/rx.c589
-rw-r--r--net/mac80211/status.c6
-rw-r--r--net/wireless/core.c12
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/ibss.c2
-rw-r--r--net/wireless/nl80211.c120
-rw-r--r--net/wireless/reg.c6
-rw-r--r--net/wireless/scan.c2
-rw-r--r--net/wireless/sme.c6
-rw-r--r--net/wireless/wext-compat.c42
-rw-r--r--net/wireless/wext-core.c3
88 files changed, 3161 insertions, 2262 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index cdf5ce46b38b..1186b1978b2e 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2816,6 +2816,15 @@ T: git git://git.kernel.org/pub/scm/linux/kernel/git/iwlwifi/iwlwifi-2.6.git
2816S: Supported 2816S: Supported
2817F: drivers/net/wireless/iwlwifi/ 2817F: drivers/net/wireless/iwlwifi/
2818 2818
2819INTEL WIRELESS MULTICOMM 3200 WIFI (iwmc3200wifi)
2820M: Samuel Ortiz <samuel.ortiz@intel.com>
2821M: Zhu Yi <yi.zhu@intel.com>
2822M: Intel Linux Wireless <ilw@linux.intel.com>
2823L: linux-wireless@vger.kernel.org
2824S: Supported
2825W: http://wireless.kernel.org/en/users/Drivers/iwmc3200wifi
2826F: drivers/net/wireless/iwmc3200wifi/
2827
2819IOC3 ETHERNET DRIVER 2828IOC3 ETHERNET DRIVER
2820M: Ralf Baechle <ralf@linux-mips.org> 2829M: Ralf Baechle <ralf@linux-mips.org>
2821L: linux-mips@linux-mips.org 2830L: linux-mips@linux-mips.org
diff --git a/drivers/net/wireless/airo.c b/drivers/net/wireless/airo.c
index 4eec87c3be2b..4331d675fcc6 100644
--- a/drivers/net/wireless/airo.c
+++ b/drivers/net/wireless/airo.c
@@ -4806,7 +4806,7 @@ static int airo_config_commit(struct net_device *dev,
4806 4806
4807static inline int sniffing_mode(struct airo_info *ai) 4807static inline int sniffing_mode(struct airo_info *ai)
4808{ 4808{
4809 return le16_to_cpu(ai->config.rmode & RXMODE_MASK) >= 4809 return (le16_to_cpu(ai->config.rmode) & le16_to_cpu(RXMODE_MASK)) >=
4810 le16_to_cpu(RXMODE_RFMON); 4810 le16_to_cpu(RXMODE_RFMON);
4811} 4811}
4812 4812
diff --git a/drivers/net/wireless/ath/ath9k/Kconfig b/drivers/net/wireless/ath/ath9k/Kconfig
index 006364f76bb4..03a1106ad725 100644
--- a/drivers/net/wireless/ath/ath9k/Kconfig
+++ b/drivers/net/wireless/ath/ath9k/Kconfig
@@ -23,17 +23,12 @@ config ATH9K
23 23
24 If you choose to build a module, it'll be called ath9k. 24 If you choose to build a module, it'll be called ath9k.
25 25
26if ATH_DEBUG 26config ATH9K_DEBUGFS
27
28config ATH9K_DEBUG
29 bool "Atheros ath9k debugging" 27 bool "Atheros ath9k debugging"
30 depends on ATH9K 28 depends on ATH9K
31 ---help--- 29 ---help---
32 Say Y, if you need ath9k to display debug messages. 30 Say Y, if you need access to ath9k's statistics for
33 Pass the debug mask as a module parameter: 31 interrupts, rate control, etc.
34
35 modprobe ath9k debug=0x00000200
36 32
37 Look in ath9k/debug.h for possible debug masks 33 Also required for changing debug message flags at run time.
38 34
39endif # ATH_DEBUG
diff --git a/drivers/net/wireless/ath/ath9k/Makefile b/drivers/net/wireless/ath/ath9k/Makefile
index e53f9680a385..4985b2b1b0a9 100644
--- a/drivers/net/wireless/ath/ath9k/Makefile
+++ b/drivers/net/wireless/ath/ath9k/Makefile
@@ -7,7 +7,7 @@ ath9k-y += beacon.o \
7 7
8ath9k-$(CONFIG_PCI) += pci.o 8ath9k-$(CONFIG_PCI) += pci.o
9ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o 9ath9k-$(CONFIG_ATHEROS_AR71XX) += ahb.o
10ath9k-$(CONFIG_ATH9K_DEBUG) += debug.o 10ath9k-$(CONFIG_ATH9K_DEBUGFS) += debug.o
11 11
12obj-$(CONFIG_ATH9K) += ath9k.o 12obj-$(CONFIG_ATH9K) += ath9k.o
13 13
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 2a40fa2cd914..e2cef2ff5d8f 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -21,7 +21,6 @@
21#include <linux/device.h> 21#include <linux/device.h>
22#include <linux/leds.h> 22#include <linux/leds.h>
23 23
24#include "rc.h"
25#include "debug.h" 24#include "debug.h"
26#include "common.h" 25#include "common.h"
27 26
@@ -330,6 +329,7 @@ void ath_beacon_tasklet(unsigned long data);
330void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif); 329void ath_beacon_config(struct ath_softc *sc, struct ieee80211_vif *vif);
331int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif); 330int ath_beacon_alloc(struct ath_wiphy *aphy, struct ieee80211_vif *vif);
332void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp); 331void ath_beacon_return(struct ath_softc *sc, struct ath_vif *avp);
332int ath_beaconq_config(struct ath_softc *sc);
333 333
334/*******/ 334/*******/
335/* ANI */ 335/* ANI */
@@ -421,8 +421,11 @@ struct ath_led {
421#define SC_OP_WAIT_FOR_TX_ACK BIT(18) 421#define SC_OP_WAIT_FOR_TX_ACK BIT(18)
422#define SC_OP_BEACON_SYNC BIT(19) 422#define SC_OP_BEACON_SYNC BIT(19)
423#define SC_OP_BT_PRIORITY_DETECTED BIT(21) 423#define SC_OP_BT_PRIORITY_DETECTED BIT(21)
424#define SC_OP_NULLFUNC_COMPLETED BIT(22)
425#define SC_OP_PS_ENABLED BIT(23)
424 426
425struct ath_wiphy; 427struct ath_wiphy;
428struct ath_rate_table;
426 429
427struct ath_softc { 430struct ath_softc {
428 struct ieee80211_hw *hw; 431 struct ieee80211_hw *hw;
@@ -467,9 +470,8 @@ struct ath_softc {
467 struct ath_rx rx; 470 struct ath_rx rx;
468 struct ath_tx tx; 471 struct ath_tx tx;
469 struct ath_beacon beacon; 472 struct ath_beacon beacon;
470 struct ieee80211_rate rates[IEEE80211_NUM_BANDS][ATH_RATE_MAX];
471 const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX];
472 const struct ath_rate_table *cur_rate_table; 473 const struct ath_rate_table *cur_rate_table;
474 enum wireless_mode cur_rate_mode;
473 struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; 475 struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
474 476
475 struct ath_led radio_led; 477 struct ath_led radio_led;
@@ -484,7 +486,7 @@ struct ath_softc {
484 486
485 int beacon_interval; 487 int beacon_interval;
486 488
487#ifdef CONFIG_ATH9K_DEBUG 489#ifdef CONFIG_ATH9K_DEBUGFS
488 struct ath9k_debug debug; 490 struct ath9k_debug debug;
489#endif 491#endif
490 struct ath_beacon_config cur_beacon_conf; 492 struct ath_beacon_config cur_beacon_conf;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index b10c884f2933..1660ef17aaf5 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -23,11 +23,12 @@
23 * the operating mode of the station (AP or AdHoc). Parameters are AIFS 23 * the operating mode of the station (AP or AdHoc). Parameters are AIFS
24 * settings and channel width min/max 24 * settings and channel width min/max
25*/ 25*/
26static int ath_beaconq_config(struct ath_softc *sc) 26int ath_beaconq_config(struct ath_softc *sc)
27{ 27{
28 struct ath_hw *ah = sc->sc_ah; 28 struct ath_hw *ah = sc->sc_ah;
29 struct ath_common *common = ath9k_hw_common(ah); 29 struct ath_common *common = ath9k_hw_common(ah);
30 struct ath9k_tx_queue_info qi; 30 struct ath9k_tx_queue_info qi, qi_be;
31 int qnum;
31 32
32 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi); 33 ath9k_hw_get_txq_props(ah, sc->beacon.beaconq, &qi);
33 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 34 if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) {
@@ -37,9 +38,12 @@ static int ath_beaconq_config(struct ath_softc *sc)
37 qi.tqi_cwmax = 0; 38 qi.tqi_cwmax = 0;
38 } else { 39 } else {
39 /* Adhoc mode; important thing is to use 2x cwmin. */ 40 /* Adhoc mode; important thing is to use 2x cwmin. */
40 qi.tqi_aifs = sc->beacon.beacon_qi.tqi_aifs; 41 qnum = ath_tx_get_qnum(sc, ATH9K_TX_QUEUE_DATA,
41 qi.tqi_cwmin = 2*sc->beacon.beacon_qi.tqi_cwmin; 42 ATH9K_WME_AC_BE);
42 qi.tqi_cwmax = sc->beacon.beacon_qi.tqi_cwmax; 43 ath9k_hw_get_txq_props(ah, qnum, &qi_be);
44 qi.tqi_aifs = qi_be.tqi_aifs;
45 qi.tqi_cwmin = 4*qi_be.tqi_cwmin;
46 qi.tqi_cwmax = qi_be.tqi_cwmax;
43 } 47 }
44 48
45 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) { 49 if (!ath9k_hw_set_txq_props(ah, sc->beacon.beaconq, &qi)) {
@@ -65,9 +69,9 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
65 struct ath_common *common = ath9k_hw_common(ah); 69 struct ath_common *common = ath9k_hw_common(ah);
66 struct ath_desc *ds; 70 struct ath_desc *ds;
67 struct ath9k_11n_rate_series series[4]; 71 struct ath9k_11n_rate_series series[4];
68 const struct ath_rate_table *rt;
69 int flags, antenna, ctsrate = 0, ctsduration = 0; 72 int flags, antenna, ctsrate = 0, ctsduration = 0;
70 u8 rate; 73 struct ieee80211_supported_band *sband;
74 u8 rate = 0;
71 75
72 ds = bf->bf_desc; 76 ds = bf->bf_desc;
73 flags = ATH9K_TXDESC_NOACK; 77 flags = ATH9K_TXDESC_NOACK;
@@ -91,10 +95,10 @@ static void ath_beacon_setup(struct ath_softc *sc, struct ath_vif *avp,
91 95
92 ds->ds_data = bf->bf_buf_addr; 96 ds->ds_data = bf->bf_buf_addr;
93 97
94 rt = sc->cur_rate_table; 98 sband = &sc->sbands[common->hw->conf.channel->band];
95 rate = rt->info[0].ratecode; 99 rate = sband->bitrates[0].hw_value;
96 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) 100 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
97 rate |= rt->info[0].short_preamble; 101 rate |= sband->bitrates[0].hw_value_short;
98 102
99 ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN, 103 ath9k_hw_set11n_txdesc(ah, ds, skb->len + FCS_LEN,
100 ATH9K_PKT_TYPE_BEACON, 104 ATH9K_PKT_TYPE_BEACON,
diff --git a/drivers/net/wireless/ath/ath9k/common.c b/drivers/net/wireless/ath/ath9k/common.c
index 4a13632e3e4d..4d775ae141db 100644
--- a/drivers/net/wireless/ath/ath9k/common.c
+++ b/drivers/net/wireless/ath/ath9k/common.c
@@ -181,8 +181,6 @@ static void ath9k_process_rssi(struct ath_common *common,
181 ATH_RSSI_EP_MULTIPLIER); 181 ATH_RSSI_EP_MULTIPLIER);
182 if (rx_stats->rs_rssi < 0) 182 if (rx_stats->rs_rssi < 0)
183 rx_stats->rs_rssi = 0; 183 rx_stats->rs_rssi = 0;
184 else if (rx_stats->rs_rssi > 127)
185 rx_stats->rs_rssi = 127;
186 184
187 /* Update Beacon RSSI, this is used by ANI. */ 185 /* Update Beacon RSSI, this is used by ANI. */
188 if (ieee80211_is_beacon(fc)) 186 if (ieee80211_is_beacon(fc))
@@ -238,16 +236,8 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
238 /* see if any padding is done by the hw and remove it */ 236 /* see if any padding is done by the hw and remove it */
239 hdr = (struct ieee80211_hdr *) skb->data; 237 hdr = (struct ieee80211_hdr *) skb->data;
240 hdrlen = ieee80211_get_hdrlen_from_skb(skb); 238 hdrlen = ieee80211_get_hdrlen_from_skb(skb);
241 padpos = 24;
242 fc = hdr->frame_control; 239 fc = hdr->frame_control;
243 if ((fc & cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) == 240 padpos = ath9k_cmn_padpos(hdr->frame_control);
244 cpu_to_le16(IEEE80211_FCTL_FROMDS|IEEE80211_FCTL_TODS)) {
245 padpos += 6; /* ETH_ALEN */
246 }
247 if ((fc & cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FCTL_FTYPE)) ==
248 cpu_to_le16(IEEE80211_STYPE_QOS_DATA|IEEE80211_FTYPE_DATA)) {
249 padpos += 2;
250 }
251 241
252 /* The MAC header is padded to have 32-bit boundary if the 242 /* The MAC header is padded to have 32-bit boundary if the
253 * packet payload is non-zero. The general calculation for 243 * packet payload is non-zero. The general calculation for
@@ -282,6 +272,20 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
282} 272}
283EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess); 273EXPORT_SYMBOL(ath9k_cmn_rx_skb_postprocess);
284 274
275int ath9k_cmn_padpos(__le16 frame_control)
276{
277 int padpos = 24;
278 if (ieee80211_has_a4(frame_control)) {
279 padpos += ETH_ALEN;
280 }
281 if (ieee80211_is_data_qos(frame_control)) {
282 padpos += IEEE80211_QOS_CTL_LEN;
283 }
284
285 return padpos;
286}
287EXPORT_SYMBOL(ath9k_cmn_padpos);
288
285static int __init ath9k_cmn_init(void) 289static int __init ath9k_cmn_init(void)
286{ 290{
287 return 0; 291 return 0;
diff --git a/drivers/net/wireless/ath/ath9k/common.h b/drivers/net/wireless/ath/ath9k/common.h
index 4e1176029356..042999c2fe9c 100644
--- a/drivers/net/wireless/ath/ath9k/common.h
+++ b/drivers/net/wireless/ath/ath9k/common.h
@@ -78,6 +78,7 @@ struct ath_buf {
78 dma_addr_t bf_daddr; /* physical addr of desc */ 78 dma_addr_t bf_daddr; /* physical addr of desc */
79 dma_addr_t bf_buf_addr; /* physical addr of data buffer */ 79 dma_addr_t bf_buf_addr; /* physical addr of data buffer */
80 bool bf_stale; 80 bool bf_stale;
81 bool bf_isnullfunc;
81 u16 bf_flags; 82 u16 bf_flags;
82 struct ath_buf_state bf_state; 83 struct ath_buf_state bf_state;
83 dma_addr_t bf_dmacontext; 84 dma_addr_t bf_dmacontext;
@@ -122,3 +123,5 @@ void ath9k_cmn_rx_skb_postprocess(struct ath_common *common,
122 struct ath_rx_status *rx_stats, 123 struct ath_rx_status *rx_stats,
123 struct ieee80211_rx_status *rxs, 124 struct ieee80211_rx_status *rxs,
124 bool decrypt_error); 125 bool decrypt_error);
126
127int ath9k_cmn_padpos(__le16 frame_control);
diff --git a/drivers/net/wireless/ath/ath9k/debug.c b/drivers/net/wireless/ath/ath9k/debug.c
index 06f1fcfb03e9..b66f72dbf7b9 100644
--- a/drivers/net/wireless/ath/ath9k/debug.c
+++ b/drivers/net/wireless/ath/ath9k/debug.c
@@ -31,6 +31,8 @@ static int ath9k_debugfs_open(struct inode *inode, struct file *file)
31 return 0; 31 return 0;
32} 32}
33 33
34#ifdef CONFIG_ATH_DEBUG
35
34static ssize_t read_file_debug(struct file *file, char __user *user_buf, 36static ssize_t read_file_debug(struct file *file, char __user *user_buf,
35 size_t count, loff_t *ppos) 37 size_t count, loff_t *ppos)
36{ 38{
@@ -71,6 +73,8 @@ static const struct file_operations fops_debug = {
71 .owner = THIS_MODULE 73 .owner = THIS_MODULE
72}; 74};
73 75
76#endif
77
74static ssize_t read_file_dma(struct file *file, char __user *user_buf, 78static ssize_t read_file_dma(struct file *file, char __user *user_buf,
75 size_t count, loff_t *ppos) 79 size_t count, loff_t *ppos)
76{ 80{
@@ -255,21 +259,11 @@ static const struct file_operations fops_interrupt = {
255 .owner = THIS_MODULE 259 .owner = THIS_MODULE
256}; 260};
257 261
258void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb) 262void ath_debug_stat_rc(struct ath_softc *sc, int final_rate)
259{ 263{
260 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
261 struct ieee80211_tx_rate *rates = tx_info->status.rates;
262 int final_ts_idx = 0, idx, i;
263 struct ath_rc_stats *stats; 264 struct ath_rc_stats *stats;
264 265
265 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 266 stats = &sc->debug.stats.rcstats[final_rate];
266 if (!rates[i].count)
267 break;
268
269 final_ts_idx = i;
270 }
271 idx = rates[final_ts_idx].idx;
272 stats = &sc->debug.stats.rcstats[idx];
273 stats->success++; 267 stats->success++;
274} 268}
275 269
@@ -573,10 +567,12 @@ int ath9k_init_debug(struct ath_hw *ah)
573 if (!sc->debug.debugfs_phy) 567 if (!sc->debug.debugfs_phy)
574 goto err; 568 goto err;
575 569
570#ifdef CONFIG_ATH_DEBUG
576 sc->debug.debugfs_debug = debugfs_create_file("debug", 571 sc->debug.debugfs_debug = debugfs_create_file("debug",
577 S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug); 572 S_IRUSR | S_IWUSR, sc->debug.debugfs_phy, sc, &fops_debug);
578 if (!sc->debug.debugfs_debug) 573 if (!sc->debug.debugfs_debug)
579 goto err; 574 goto err;
575#endif
580 576
581 sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR, 577 sc->debug.debugfs_dma = debugfs_create_file("dma", S_IRUSR,
582 sc->debug.debugfs_phy, sc, &fops_dma); 578 sc->debug.debugfs_phy, sc, &fops_dma);
diff --git a/drivers/net/wireless/ath/ath9k/debug.h b/drivers/net/wireless/ath/ath9k/debug.h
index 749e85d57551..536663e3ee11 100644
--- a/drivers/net/wireless/ath/ath9k/debug.h
+++ b/drivers/net/wireless/ath/ath9k/debug.h
@@ -18,17 +18,18 @@
18#define DEBUG_H 18#define DEBUG_H
19 19
20#include "hw.h" 20#include "hw.h"
21#include "rc.h"
21 22
22struct ath_txq; 23struct ath_txq;
23struct ath_buf; 24struct ath_buf;
24 25
25#ifdef CONFIG_ATH9K_DEBUG 26#ifdef CONFIG_ATH9K_DEBUGFS
26#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++ 27#define TX_STAT_INC(q, c) sc->debug.stats.txstats[q].c++
27#else 28#else
28#define TX_STAT_INC(q, c) do { } while (0) 29#define TX_STAT_INC(q, c) do { } while (0)
29#endif 30#endif
30 31
31#ifdef CONFIG_ATH9K_DEBUG 32#ifdef CONFIG_ATH9K_DEBUGFS
32 33
33/** 34/**
34 * struct ath_interrupt_stats - Contains statistics about interrupts 35 * struct ath_interrupt_stats - Contains statistics about interrupts
@@ -138,7 +139,7 @@ void ath9k_exit_debug(struct ath_hw *ah);
138int ath9k_debug_create_root(void); 139int ath9k_debug_create_root(void);
139void ath9k_debug_remove_root(void); 140void ath9k_debug_remove_root(void);
140void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status); 141void ath_debug_stat_interrupt(struct ath_softc *sc, enum ath9k_int status);
141void ath_debug_stat_rc(struct ath_softc *sc, struct sk_buff *skb); 142void ath_debug_stat_rc(struct ath_softc *sc, int final_rate);
142void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq, 143void ath_debug_stat_tx(struct ath_softc *sc, struct ath_txq *txq,
143 struct ath_buf *bf); 144 struct ath_buf *bf);
144void ath_debug_stat_retries(struct ath_softc *sc, int rix, 145void ath_debug_stat_retries(struct ath_softc *sc, int rix,
@@ -170,7 +171,7 @@ static inline void ath_debug_stat_interrupt(struct ath_softc *sc,
170} 171}
171 172
172static inline void ath_debug_stat_rc(struct ath_softc *sc, 173static inline void ath_debug_stat_rc(struct ath_softc *sc,
173 struct sk_buff *skb) 174 int final_rate)
174{ 175{
175} 176}
176 177
@@ -185,6 +186,6 @@ static inline void ath_debug_stat_retries(struct ath_softc *sc, int rix,
185{ 186{
186} 187}
187 188
188#endif /* CONFIG_ATH9K_DEBUG */ 189#endif /* CONFIG_ATH9K_DEBUGFS */
189 190
190#endif /* DEBUG_H */ 191#endif /* DEBUG_H */
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 53a7b980d8f6..2ec61f08cfdb 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -148,22 +148,19 @@ bool ath9k_get_channel_edges(struct ath_hw *ah,
148} 148}
149 149
150u16 ath9k_hw_computetxtime(struct ath_hw *ah, 150u16 ath9k_hw_computetxtime(struct ath_hw *ah,
151 const struct ath_rate_table *rates, 151 u8 phy, int kbps,
152 u32 frameLen, u16 rateix, 152 u32 frameLen, u16 rateix,
153 bool shortPreamble) 153 bool shortPreamble)
154{ 154{
155 u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime; 155 u32 bitsPerSymbol, numBits, numSymbols, phyTime, txTime;
156 u32 kbps;
157
158 kbps = rates->info[rateix].ratekbps;
159 156
160 if (kbps == 0) 157 if (kbps == 0)
161 return 0; 158 return 0;
162 159
163 switch (rates->info[rateix].phy) { 160 switch (phy) {
164 case WLAN_RC_PHY_CCK: 161 case WLAN_RC_PHY_CCK:
165 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS; 162 phyTime = CCK_PREAMBLE_BITS + CCK_PLCP_BITS;
166 if (shortPreamble && rates->info[rateix].short_preamble) 163 if (shortPreamble)
167 phyTime >>= 1; 164 phyTime >>= 1;
168 numBits = frameLen << 3; 165 numBits = frameLen << 3;
169 txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps); 166 txTime = CCK_SIFS_TIME + phyTime + ((numBits * 1000) / kbps);
@@ -194,8 +191,7 @@ u16 ath9k_hw_computetxtime(struct ath_hw *ah,
194 break; 191 break;
195 default: 192 default:
196 ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL, 193 ath_print(ath9k_hw_common(ah), ATH_DBG_FATAL,
197 "Unknown phy %u (rate ix %u)\n", 194 "Unknown phy %u (rate ix %u)\n", phy, rateix);
198 rates->info[rateix].phy, rateix);
199 txTime = 0; 195 txTime = 0;
200 break; 196 break;
201 } 197 }
@@ -922,6 +918,11 @@ int ath9k_hw_init(struct ath_hw *ah)
922 ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n", 918 ath_print(common, ATH_DBG_RESET, "serialize_regmode is %d\n",
923 ah->config.serialize_regmode); 919 ah->config.serialize_regmode);
924 920
921 if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
922 ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD >> 1;
923 else
924 ah->config.max_txtrig_level = MAX_TX_FIFO_THRESHOLD;
925
925 if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) { 926 if (!ath9k_hw_macversion_supported(ah->hw_version.macVersion)) {
926 ath_print(common, ATH_DBG_FATAL, 927 ath_print(common, ATH_DBG_FATAL,
927 "Mac Chip Rev 0x%02x.%x is not supported by " 928 "Mac Chip Rev 0x%02x.%x is not supported by "
@@ -975,7 +976,10 @@ int ath9k_hw_init(struct ath_hw *ah)
975 return r; 976 return r;
976 977
977 ath9k_hw_init_mode_gain_regs(ah); 978 ath9k_hw_init_mode_gain_regs(ah);
978 ath9k_hw_fill_cap_info(ah); 979 r = ath9k_hw_fill_cap_info(ah);
980 if (r)
981 return r;
982
979 ath9k_hw_init_11a_eeprom_fix(ah); 983 ath9k_hw_init_11a_eeprom_fix(ah);
980 984
981 r = ath9k_hw_init_macaddr(ah); 985 r = ath9k_hw_init_macaddr(ah);
@@ -3111,7 +3115,7 @@ EXPORT_SYMBOL(ath9k_hw_set_sta_beacon_timers);
3111/* HW Capabilities */ 3115/* HW Capabilities */
3112/*******************/ 3116/*******************/
3113 3117
3114void ath9k_hw_fill_cap_info(struct ath_hw *ah) 3118int ath9k_hw_fill_cap_info(struct ath_hw *ah)
3115{ 3119{
3116 struct ath9k_hw_capabilities *pCap = &ah->caps; 3120 struct ath9k_hw_capabilities *pCap = &ah->caps;
3117 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah); 3121 struct ath_regulatory *regulatory = ath9k_hw_regulatory(ah);
@@ -3142,6 +3146,12 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
3142 } 3146 }
3143 3147
3144 eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE); 3148 eeval = ah->eep_ops->get_eeprom(ah, EEP_OP_MODE);
3149 if ((eeval & (AR5416_OPFLAGS_11G | AR5416_OPFLAGS_11A)) == 0) {
3150 ath_print(common, ATH_DBG_FATAL,
3151 "no band has been marked as supported in EEPROM.\n");
3152 return -EINVAL;
3153 }
3154
3145 bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX); 3155 bitmap_zero(pCap->wireless_modes, ATH9K_MODE_MAX);
3146 3156
3147 if (eeval & AR5416_OPFLAGS_11A) { 3157 if (eeval & AR5416_OPFLAGS_11A) {
@@ -3228,7 +3238,11 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
3228 pCap->keycache_size = AR_KEYTABLE_SIZE; 3238 pCap->keycache_size = AR_KEYTABLE_SIZE;
3229 3239
3230 pCap->hw_caps |= ATH9K_HW_CAP_FASTCC; 3240 pCap->hw_caps |= ATH9K_HW_CAP_FASTCC;
3231 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD; 3241
3242 if (AR_SREV_9285(ah) || AR_SREV_9271(ah))
3243 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD >> 1;
3244 else
3245 pCap->tx_triglevel_max = MAX_TX_FIFO_THRESHOLD;
3232 3246
3233 if (AR_SREV_9285_10_OR_LATER(ah)) 3247 if (AR_SREV_9285_10_OR_LATER(ah))
3234 pCap->num_gpio_pins = AR9285_NUM_GPIO; 3248 pCap->num_gpio_pins = AR9285_NUM_GPIO;
@@ -3301,6 +3315,8 @@ void ath9k_hw_fill_cap_info(struct ath_hw *ah)
3301 } else { 3315 } else {
3302 btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE; 3316 btcoex_hw->scheme = ATH_BTCOEX_CFG_NONE;
3303 } 3317 }
3318
3319 return 0;
3304} 3320}
3305 3321
3306bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, 3322bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index f8f5e997162c..e2b0c73a616f 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -60,7 +60,7 @@
60 60
61#define ATH_DEFAULT_NOISE_FLOOR -95 61#define ATH_DEFAULT_NOISE_FLOOR -95
62 62
63#define ATH9K_RSSI_BAD 0x80 63#define ATH9K_RSSI_BAD -128
64 64
65/* Register read/write primitives */ 65/* Register read/write primitives */
66#define REG_WRITE(_ah, _reg, _val) \ 66#define REG_WRITE(_ah, _reg, _val) \
@@ -226,6 +226,7 @@ struct ath9k_ops_config {
226#define AR_SPUR_FEEQ_BOUND_HT20 10 226#define AR_SPUR_FEEQ_BOUND_HT20 10
227 int spurmode; 227 int spurmode;
228 u16 spurchans[AR_EEPROM_MODAL_SPURS][2]; 228 u16 spurchans[AR_EEPROM_MODAL_SPURS][2];
229 u8 max_txtrig_level;
229}; 230};
230 231
231enum ath9k_int { 232enum ath9k_int {
@@ -619,7 +620,7 @@ void ath9k_hw_detach(struct ath_hw *ah);
619int ath9k_hw_init(struct ath_hw *ah); 620int ath9k_hw_init(struct ath_hw *ah);
620int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan, 621int ath9k_hw_reset(struct ath_hw *ah, struct ath9k_channel *chan,
621 bool bChannelChange); 622 bool bChannelChange);
622void ath9k_hw_fill_cap_info(struct ath_hw *ah); 623int ath9k_hw_fill_cap_info(struct ath_hw *ah);
623bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type, 624bool ath9k_hw_getcapability(struct ath_hw *ah, enum ath9k_capability_type type,
624 u32 capability, u32 *result); 625 u32 capability, u32 *result);
625bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type, 626bool ath9k_hw_setcapability(struct ath_hw *ah, enum ath9k_capability_type type,
@@ -647,7 +648,7 @@ bool ath9k_hw_wait(struct ath_hw *ah, u32 reg, u32 mask, u32 val, u32 timeout);
647u32 ath9k_hw_reverse_bits(u32 val, u32 n); 648u32 ath9k_hw_reverse_bits(u32 val, u32 n);
648bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high); 649bool ath9k_get_channel_edges(struct ath_hw *ah, u16 flags, u16 *low, u16 *high);
649u16 ath9k_hw_computetxtime(struct ath_hw *ah, 650u16 ath9k_hw_computetxtime(struct ath_hw *ah,
650 const struct ath_rate_table *rates, 651 u8 phy, int kbps,
651 u32 frameLen, u16 rateix, bool shortPreamble); 652 u32 frameLen, u16 rateix, bool shortPreamble);
652void ath9k_hw_get_channel_centers(struct ath_hw *ah, 653void ath9k_hw_get_channel_centers(struct ath_hw *ah,
653 struct ath9k_channel *chan, 654 struct ath9k_channel *chan,
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 46466ffebcb0..71b84d91dcff 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -70,12 +70,37 @@ u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q)
70} 70}
71EXPORT_SYMBOL(ath9k_hw_numtxpending); 71EXPORT_SYMBOL(ath9k_hw_numtxpending);
72 72
73/**
74 * ath9k_hw_updatetxtriglevel - adjusts the frame trigger level
75 *
76 * @ah: atheros hardware struct
77 * @bIncTrigLevel: whether or not the frame trigger level should be updated
78 *
79 * The frame trigger level specifies the minimum number of bytes,
80 * in units of 64 bytes, that must be DMA'ed into the PCU TX FIFO
81 * before the PCU will initiate sending the frame on the air. This can
82 * mean we initiate transmit before a full frame is on the PCU TX FIFO.
83 * Resets to 0x1 (meaning 64 bytes or a full frame, whichever occurs
84 * first)
85 *
86 * Caution must be taken to ensure to set the frame trigger level based
87 * on the DMA request size. For example if the DMA request size is set to
88 * 128 bytes the trigger level cannot exceed 6 * 64 = 384. This is because
89 * there need to be enough space in the tx FIFO for the requested transfer
90 * size. Hence the tx FIFO will stop with 512 - 128 = 384 bytes. If we set
91 * the threshold to a value beyond 6, then the transmit will hang.
92 *
93 * Current dual stream devices have a PCU TX FIFO size of 8 KB.
94 * Current single stream devices have a PCU TX FIFO size of 4 KB, however,
95 * there is a hardware issue which forces us to use 2 KB instead so the
96 * frame trigger level must not exceed 2 KB for these chipsets.
97 */
73bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel) 98bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
74{ 99{
75 u32 txcfg, curLevel, newLevel; 100 u32 txcfg, curLevel, newLevel;
76 enum ath9k_int omask; 101 enum ath9k_int omask;
77 102
78 if (ah->tx_trig_level >= MAX_TX_FIFO_THRESHOLD) 103 if (ah->tx_trig_level >= ah->config.max_txtrig_level)
79 return false; 104 return false;
80 105
81 omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL); 106 omask = ath9k_hw_set_interrupts(ah, ah->mask_reg & ~ATH9K_INT_GLOBAL);
@@ -84,7 +109,7 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
84 curLevel = MS(txcfg, AR_FTRIG); 109 curLevel = MS(txcfg, AR_FTRIG);
85 newLevel = curLevel; 110 newLevel = curLevel;
86 if (bIncTrigLevel) { 111 if (bIncTrigLevel) {
87 if (curLevel < MAX_TX_FIFO_THRESHOLD) 112 if (curLevel < ah->config.max_txtrig_level)
88 newLevel++; 113 newLevel++;
89 } else if (curLevel > MIN_TX_FIFO_THRESHOLD) 114 } else if (curLevel > MIN_TX_FIFO_THRESHOLD)
90 newLevel--; 115 newLevel--;
@@ -231,6 +256,8 @@ int ath9k_hw_txprocdesc(struct ath_hw *ah, struct ath_desc *ds)
231 ds->ds_txstat.ts_status = 0; 256 ds->ds_txstat.ts_status = 0;
232 ds->ds_txstat.ts_flags = 0; 257 ds->ds_txstat.ts_flags = 0;
233 258
259 if (ads->ds_txstatus1 & AR_FrmXmitOK)
260 ds->ds_txstat.ts_status |= ATH9K_TX_ACKED;
234 if (ads->ds_txstatus1 & AR_ExcessiveRetries) 261 if (ads->ds_txstatus1 & AR_ExcessiveRetries)
235 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY; 262 ds->ds_txstat.ts_status |= ATH9K_TXERR_XRETRY;
236 if (ads->ds_txstatus1 & AR_Filtered) 263 if (ads->ds_txstatus1 & AR_Filtered)
@@ -926,6 +953,13 @@ void ath9k_hw_setuprxdesc(struct ath_hw *ah, struct ath_desc *ds,
926} 953}
927EXPORT_SYMBOL(ath9k_hw_setuprxdesc); 954EXPORT_SYMBOL(ath9k_hw_setuprxdesc);
928 955
956/*
957 * This can stop or re-enables RX.
958 *
959 * If bool is set this will kill any frame which is currently being
960 * transferred between the MAC and baseband and also prevent any new
961 * frames from getting started.
962 */
929bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set) 963bool ath9k_hw_setrxabort(struct ath_hw *ah, bool set)
930{ 964{
931 u32 reg; 965 u32 reg;
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index fefb65dafb1c..0c87771383f0 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -76,6 +76,7 @@
76#define ATH9K_TXERR_FIFO 0x04 76#define ATH9K_TXERR_FIFO 0x04
77#define ATH9K_TXERR_XTXOP 0x08 77#define ATH9K_TXERR_XTXOP 0x08
78#define ATH9K_TXERR_TIMER_EXPIRED 0x10 78#define ATH9K_TXERR_TIMER_EXPIRED 0x10
79#define ATH9K_TX_ACKED 0x20
79 80
80#define ATH9K_TX_BA 0x01 81#define ATH9K_TX_BA 0x01
81#define ATH9K_TX_PWRMGMT 0x02 82#define ATH9K_TX_PWRMGMT 0x02
@@ -85,9 +86,15 @@
85#define ATH9K_TX_SW_ABORTED 0x40 86#define ATH9K_TX_SW_ABORTED 0x40
86#define ATH9K_TX_SW_FILTERED 0x80 87#define ATH9K_TX_SW_FILTERED 0x80
87 88
89/* 64 bytes */
88#define MIN_TX_FIFO_THRESHOLD 0x1 90#define MIN_TX_FIFO_THRESHOLD 0x1
91
92/*
93 * Single stream device AR9285 and AR9271 require 2 KB
94 * to work around a hardware issue, all other devices
95 * have can use the max 4 KB limit.
96 */
89#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1) 97#define MAX_TX_FIFO_THRESHOLD ((4096 / 64) - 1)
90#define INIT_TX_FIFO_THRESHOLD MIN_TX_FIFO_THRESHOLD
91 98
92struct ath_tx_status { 99struct ath_tx_status {
93 u32 ts_tstamp; 100 u32 ts_tstamp;
@@ -380,6 +387,11 @@ struct ar5416_desc {
380#define AR_TxBaStatus 0x40000000 387#define AR_TxBaStatus 0x40000000
381#define AR_TxStatusRsvd01 0x80000000 388#define AR_TxStatusRsvd01 0x80000000
382 389
390/*
391 * AR_FrmXmitOK - Frame transmission success flag. If set, the frame was
392 * transmitted successfully. If clear, no ACK or BA was received to indicate
393 * successful transmission when we were expecting an ACK or BA.
394 */
383#define AR_FrmXmitOK 0x00000001 395#define AR_FrmXmitOK 0x00000001
384#define AR_ExcessiveRetries 0x00000002 396#define AR_ExcessiveRetries 0x00000002
385#define AR_FIFOUnderrun 0x00000004 397#define AR_FIFOUnderrun 0x00000004
@@ -616,7 +628,6 @@ enum ath9k_cipher {
616 628
617struct ath_hw; 629struct ath_hw;
618struct ath9k_channel; 630struct ath9k_channel;
619struct ath_rate_table;
620 631
621u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q); 632u32 ath9k_hw_gettxbuf(struct ath_hw *ah, u32 q);
622void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp); 633void ath9k_hw_puttxbuf(struct ath_hw *ah, u32 q, u32 txdp);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index cbf5d2a1bb26..c48743452515 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -104,37 +104,55 @@ static struct ieee80211_channel ath9k_5ghz_chantable[] = {
104 CHAN5G(5825, 37), /* Channel 165 */ 104 CHAN5G(5825, 37), /* Channel 165 */
105}; 105};
106 106
107/* Atheros hardware rate code addition for short premble */
108#define SHPCHECK(__hw_rate, __flags) \
109 ((__flags & IEEE80211_RATE_SHORT_PREAMBLE) ? (__hw_rate | 0x04 ) : 0)
110
111#define RATE(_bitrate, _hw_rate, _flags) { \
112 .bitrate = (_bitrate), \
113 .flags = (_flags), \
114 .hw_value = (_hw_rate), \
115 .hw_value_short = (SHPCHECK(_hw_rate, _flags)) \
116}
117
118static struct ieee80211_rate ath9k_legacy_rates[] = {
119 RATE(10, 0x1b, 0),
120 RATE(20, 0x1a, IEEE80211_RATE_SHORT_PREAMBLE),
121 RATE(55, 0x19, IEEE80211_RATE_SHORT_PREAMBLE),
122 RATE(110, 0x18, IEEE80211_RATE_SHORT_PREAMBLE),
123 RATE(60, 0x0b, 0),
124 RATE(90, 0x0f, 0),
125 RATE(120, 0x0a, 0),
126 RATE(180, 0x0e, 0),
127 RATE(240, 0x09, 0),
128 RATE(360, 0x0d, 0),
129 RATE(480, 0x08, 0),
130 RATE(540, 0x0c, 0),
131};
132
107static void ath_cache_conf_rate(struct ath_softc *sc, 133static void ath_cache_conf_rate(struct ath_softc *sc,
108 struct ieee80211_conf *conf) 134 struct ieee80211_conf *conf)
109{ 135{
110 switch (conf->channel->band) { 136 switch (conf->channel->band) {
111 case IEEE80211_BAND_2GHZ: 137 case IEEE80211_BAND_2GHZ:
112 if (conf_is_ht20(conf)) 138 if (conf_is_ht20(conf))
113 sc->cur_rate_table = 139 sc->cur_rate_mode = ATH9K_MODE_11NG_HT20;
114 sc->hw_rate_table[ATH9K_MODE_11NG_HT20];
115 else if (conf_is_ht40_minus(conf)) 140 else if (conf_is_ht40_minus(conf))
116 sc->cur_rate_table = 141 sc->cur_rate_mode = ATH9K_MODE_11NG_HT40MINUS;
117 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS];
118 else if (conf_is_ht40_plus(conf)) 142 else if (conf_is_ht40_plus(conf))
119 sc->cur_rate_table = 143 sc->cur_rate_mode = ATH9K_MODE_11NG_HT40PLUS;
120 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS];
121 else 144 else
122 sc->cur_rate_table = 145 sc->cur_rate_mode = ATH9K_MODE_11G;
123 sc->hw_rate_table[ATH9K_MODE_11G];
124 break; 146 break;
125 case IEEE80211_BAND_5GHZ: 147 case IEEE80211_BAND_5GHZ:
126 if (conf_is_ht20(conf)) 148 if (conf_is_ht20(conf))
127 sc->cur_rate_table = 149 sc->cur_rate_mode = ATH9K_MODE_11NA_HT20;
128 sc->hw_rate_table[ATH9K_MODE_11NA_HT20];
129 else if (conf_is_ht40_minus(conf)) 150 else if (conf_is_ht40_minus(conf))
130 sc->cur_rate_table = 151 sc->cur_rate_mode = ATH9K_MODE_11NA_HT40MINUS;
131 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS];
132 else if (conf_is_ht40_plus(conf)) 152 else if (conf_is_ht40_plus(conf))
133 sc->cur_rate_table = 153 sc->cur_rate_mode = ATH9K_MODE_11NA_HT40PLUS;
134 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS];
135 else 154 else
136 sc->cur_rate_table = 155 sc->cur_rate_mode = ATH9K_MODE_11A;
137 sc->hw_rate_table[ATH9K_MODE_11A];
138 break; 156 break;
139 default: 157 default:
140 BUG_ON(1); 158 BUG_ON(1);
@@ -190,51 +208,6 @@ static u8 parse_mpdudensity(u8 mpdudensity)
190 } 208 }
191} 209}
192 210
193static void ath_setup_rates(struct ath_softc *sc, enum ieee80211_band band)
194{
195 const struct ath_rate_table *rate_table = NULL;
196 struct ieee80211_supported_band *sband;
197 struct ieee80211_rate *rate;
198 int i, maxrates;
199
200 switch (band) {
201 case IEEE80211_BAND_2GHZ:
202 rate_table = sc->hw_rate_table[ATH9K_MODE_11G];
203 break;
204 case IEEE80211_BAND_5GHZ:
205 rate_table = sc->hw_rate_table[ATH9K_MODE_11A];
206 break;
207 default:
208 break;
209 }
210
211 if (rate_table == NULL)
212 return;
213
214 sband = &sc->sbands[band];
215 rate = sc->rates[band];
216
217 if (rate_table->rate_cnt > ATH_RATE_MAX)
218 maxrates = ATH_RATE_MAX;
219 else
220 maxrates = rate_table->rate_cnt;
221
222 for (i = 0; i < maxrates; i++) {
223 rate[i].bitrate = rate_table->info[i].ratekbps / 100;
224 rate[i].hw_value = rate_table->info[i].ratecode;
225 if (rate_table->info[i].short_preamble) {
226 rate[i].hw_value_short = rate_table->info[i].ratecode |
227 rate_table->info[i].short_preamble;
228 rate[i].flags = IEEE80211_RATE_SHORT_PREAMBLE;
229 }
230 sband->n_bitrates++;
231
232 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
233 "Rate: %2dMbps, ratecode: %2d\n",
234 rate[i].bitrate / 10, rate[i].hw_value);
235 }
236}
237
238static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc, 211static struct ath9k_channel *ath_get_curchannel(struct ath_softc *sc,
239 struct ieee80211_hw *hw) 212 struct ieee80211_hw *hw)
240{ 213{
@@ -1701,12 +1674,6 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
1701 /* default to MONITOR mode */ 1674 /* default to MONITOR mode */
1702 sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR; 1675 sc->sc_ah->opmode = NL80211_IFTYPE_MONITOR;
1703 1676
1704 /* Setup rate tables */
1705
1706 ath_rate_attach(sc);
1707 ath_setup_rates(sc, IEEE80211_BAND_2GHZ);
1708 ath_setup_rates(sc, IEEE80211_BAND_5GHZ);
1709
1710 /* 1677 /*
1711 * Allocate hardware transmit queues: one queue for 1678 * Allocate hardware transmit queues: one queue for
1712 * beacon frames and one data queue for each QoS 1679 * beacon frames and one data queue for each QoS
@@ -1826,20 +1793,25 @@ static int ath_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
1826 1793
1827 /* setup channels and rates */ 1794 /* setup channels and rates */
1828 1795
1829 sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable; 1796 if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes)) {
1830 sc->sbands[IEEE80211_BAND_2GHZ].bitrates = 1797 sc->sbands[IEEE80211_BAND_2GHZ].channels = ath9k_2ghz_chantable;
1831 sc->rates[IEEE80211_BAND_2GHZ]; 1798 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ;
1832 sc->sbands[IEEE80211_BAND_2GHZ].band = IEEE80211_BAND_2GHZ; 1799 sc->sbands[IEEE80211_BAND_2GHZ].n_channels =
1833 sc->sbands[IEEE80211_BAND_2GHZ].n_channels = 1800 ARRAY_SIZE(ath9k_2ghz_chantable);
1834 ARRAY_SIZE(ath9k_2ghz_chantable); 1801 sc->sbands[IEEE80211_BAND_2GHZ].bitrates = ath9k_legacy_rates;
1802 sc->sbands[IEEE80211_BAND_2GHZ].n_bitrates =
1803 ARRAY_SIZE(ath9k_legacy_rates);
1804 }
1835 1805
1836 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) { 1806 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) {
1837 sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable; 1807 sc->sbands[IEEE80211_BAND_5GHZ].channels = ath9k_5ghz_chantable;
1838 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
1839 sc->rates[IEEE80211_BAND_5GHZ];
1840 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ; 1808 sc->sbands[IEEE80211_BAND_5GHZ].band = IEEE80211_BAND_5GHZ;
1841 sc->sbands[IEEE80211_BAND_5GHZ].n_channels = 1809 sc->sbands[IEEE80211_BAND_5GHZ].n_channels =
1842 ARRAY_SIZE(ath9k_5ghz_chantable); 1810 ARRAY_SIZE(ath9k_5ghz_chantable);
1811 sc->sbands[IEEE80211_BAND_5GHZ].bitrates =
1812 ath9k_legacy_rates + 4;
1813 sc->sbands[IEEE80211_BAND_5GHZ].n_bitrates =
1814 ARRAY_SIZE(ath9k_legacy_rates) - 4;
1843 } 1815 }
1844 1816
1845 switch (ah->btcoex_hw.scheme) { 1817 switch (ah->btcoex_hw.scheme) {
@@ -1906,8 +1878,9 @@ void ath_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw)
1906 1878
1907 hw->rate_control_algorithm = "ath9k_rate_control"; 1879 hw->rate_control_algorithm = "ath9k_rate_control";
1908 1880
1909 hw->wiphy->bands[IEEE80211_BAND_2GHZ] = 1881 if (test_bit(ATH9K_MODE_11G, sc->sc_ah->caps.wireless_modes))
1910 &sc->sbands[IEEE80211_BAND_2GHZ]; 1882 hw->wiphy->bands[IEEE80211_BAND_2GHZ] =
1883 &sc->sbands[IEEE80211_BAND_2GHZ];
1911 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes)) 1884 if (test_bit(ATH9K_MODE_11A, sc->sc_ah->caps.wireless_modes))
1912 hw->wiphy->bands[IEEE80211_BAND_5GHZ] = 1885 hw->wiphy->bands[IEEE80211_BAND_5GHZ] =
1913 &sc->sbands[IEEE80211_BAND_5GHZ]; 1886 &sc->sbands[IEEE80211_BAND_5GHZ];
@@ -1946,9 +1919,12 @@ int ath_init_device(u16 devid, struct ath_softc *sc, u16 subsysid,
1946 reg = &common->regulatory; 1919 reg = &common->regulatory;
1947 1920
1948 if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) { 1921 if (ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
1949 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); 1922 if (test_bit(ATH9K_MODE_11G, ah->caps.wireless_modes))
1923 setup_ht_cap(sc,
1924 &sc->sbands[IEEE80211_BAND_2GHZ].ht_cap);
1950 if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes)) 1925 if (test_bit(ATH9K_MODE_11A, ah->caps.wireless_modes))
1951 setup_ht_cap(sc, &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap); 1926 setup_ht_cap(sc,
1927 &sc->sbands[IEEE80211_BAND_5GHZ].ht_cap);
1952 } 1928 }
1953 1929
1954 /* initialize tx/rx engine */ 1930 /* initialize tx/rx engine */
@@ -2394,7 +2370,8 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2394 struct ath_softc *sc = aphy->sc; 2370 struct ath_softc *sc = aphy->sc;
2395 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 2371 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
2396 struct ath_tx_control txctl; 2372 struct ath_tx_control txctl;
2397 int hdrlen, padsize; 2373 int padpos, padsize;
2374 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2398 2375
2399 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) { 2376 if (aphy->state != ATH_WIPHY_ACTIVE && aphy->state != ATH_WIPHY_SCAN) {
2400 ath_print(common, ATH_DBG_XMIT, 2377 ath_print(common, ATH_DBG_XMIT,
@@ -2404,7 +2381,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2404 } 2381 }
2405 2382
2406 if (sc->ps_enabled) { 2383 if (sc->ps_enabled) {
2407 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2408 /* 2384 /*
2409 * mac80211 does not set PM field for normal data frames, so we 2385 * mac80211 does not set PM field for normal data frames, so we
2410 * need to update that based on the current PS mode. 2386 * need to update that based on the current PS mode.
@@ -2424,7 +2400,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2424 * power save mode. Need to wake up hardware for the TX to be 2400 * power save mode. Need to wake up hardware for the TX to be
2425 * completed and if needed, also for RX of buffered frames. 2401 * completed and if needed, also for RX of buffered frames.
2426 */ 2402 */
2427 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2428 ath9k_ps_wakeup(sc); 2403 ath9k_ps_wakeup(sc);
2429 ath9k_hw_setrxabort(sc->sc_ah, 0); 2404 ath9k_hw_setrxabort(sc->sc_ah, 0);
2430 if (ieee80211_is_pspoll(hdr->frame_control)) { 2405 if (ieee80211_is_pspoll(hdr->frame_control)) {
@@ -2452,7 +2427,6 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2452 * BSSes. 2427 * BSSes.
2453 */ 2428 */
2454 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) { 2429 if (info->flags & IEEE80211_TX_CTL_ASSIGN_SEQ) {
2455 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2456 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT) 2430 if (info->flags & IEEE80211_TX_CTL_FIRST_FRAGMENT)
2457 sc->tx.seq_no += 0x10; 2431 sc->tx.seq_no += 0x10;
2458 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG); 2432 hdr->seq_ctrl &= cpu_to_le16(IEEE80211_SCTL_FRAG);
@@ -2460,13 +2434,13 @@ static int ath9k_tx(struct ieee80211_hw *hw,
2460 } 2434 }
2461 2435
2462 /* Add the padding after the header if this is not already done */ 2436 /* Add the padding after the header if this is not already done */
2463 hdrlen = ieee80211_get_hdrlen_from_skb(skb); 2437 padpos = ath9k_cmn_padpos(hdr->frame_control);
2464 if (hdrlen & 3) { 2438 padsize = padpos & 3;
2465 padsize = hdrlen % 4; 2439 if (padsize && skb->len>padpos) {
2466 if (skb_headroom(skb) < padsize) 2440 if (skb_headroom(skb) < padsize)
2467 return -1; 2441 return -1;
2468 skb_push(skb, padsize); 2442 skb_push(skb, padsize);
2469 memmove(skb->data, skb->data + padsize, hdrlen); 2443 memmove(skb->data, skb->data + padsize, padpos);
2470 } 2444 }
2471 2445
2472 /* Check if a tx queue is available */ 2446 /* Check if a tx queue is available */
@@ -2731,8 +2705,15 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
2731 } 2705 }
2732 } 2706 }
2733 2707
2708 /*
2709 * We just prepare to enable PS. We have to wait until our AP has
2710 * ACK'd our null data frame to disable RX otherwise we'll ignore
2711 * those ACKs and end up retransmitting the same null data frames.
2712 * IEEE80211_CONF_CHANGE_PS is only passed by mac80211 for STA mode.
2713 */
2734 if (changed & IEEE80211_CONF_CHANGE_PS) { 2714 if (changed & IEEE80211_CONF_CHANGE_PS) {
2735 if (conf->flags & IEEE80211_CONF_PS) { 2715 if (conf->flags & IEEE80211_CONF_PS) {
2716 sc->sc_flags |= SC_OP_PS_ENABLED;
2736 if (!(ah->caps.hw_caps & 2717 if (!(ah->caps.hw_caps &
2737 ATH9K_HW_CAP_AUTOSLEEP)) { 2718 ATH9K_HW_CAP_AUTOSLEEP)) {
2738 if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) { 2719 if ((sc->imask & ATH9K_INT_TIM_TIMER) == 0) {
@@ -2740,11 +2721,20 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed)
2740 ath9k_hw_set_interrupts(sc->sc_ah, 2721 ath9k_hw_set_interrupts(sc->sc_ah,
2741 sc->imask); 2722 sc->imask);
2742 } 2723 }
2743 ath9k_hw_setrxabort(sc->sc_ah, 1);
2744 } 2724 }
2745 sc->ps_enabled = true; 2725 /*
2726 * At this point we know hardware has received an ACK
2727 * of a previously sent null data frame.
2728 */
2729 if ((sc->sc_flags & SC_OP_NULLFUNC_COMPLETED)) {
2730 sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED;
2731 sc->ps_enabled = true;
2732 ath9k_hw_setrxabort(sc->sc_ah, 1);
2733 }
2746 } else { 2734 } else {
2747 sc->ps_enabled = false; 2735 sc->ps_enabled = false;
2736 sc->sc_flags &= ~(SC_OP_PS_ENABLED |
2737 SC_OP_NULLFUNC_COMPLETED);
2748 ath9k_setpower(sc, ATH9K_PM_AWAKE); 2738 ath9k_setpower(sc, ATH9K_PM_AWAKE);
2749 if (!(ah->caps.hw_caps & 2739 if (!(ah->caps.hw_caps &
2750 ATH9K_HW_CAP_AUTOSLEEP)) { 2740 ATH9K_HW_CAP_AUTOSLEEP)) {
@@ -2898,6 +2888,10 @@ static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
2898 if (ret) 2888 if (ret)
2899 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n"); 2889 ath_print(common, ATH_DBG_FATAL, "TXQ Update failed\n");
2900 2890
2891 if (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)
2892 if ((qnum == sc->tx.hwq_map[ATH9K_WME_AC_BE]) && !ret)
2893 ath_beaconq_config(sc);
2894
2901 mutex_unlock(&sc->mutex); 2895 mutex_unlock(&sc->mutex);
2902 2896
2903 return ret; 2897 return ret;
diff --git a/drivers/net/wireless/ath/ath9k/rc.c b/drivers/net/wireless/ath/ath9k/rc.c
index 1d96777b4cd2..c915954d4d5b 100644
--- a/drivers/net/wireless/ath/ath9k/rc.c
+++ b/drivers/net/wireless/ath/ath9k/rc.c
@@ -19,133 +19,92 @@
19 19
20static const struct ath_rate_table ar5416_11na_ratetable = { 20static const struct ath_rate_table ar5416_11na_ratetable = {
21 42, 21 42,
22 8, /* MCS start */
22 { 23 {
23 { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 24 { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
24 5400, 0x0b, 0x00, 12, 25 5400, 0, 12, 0, 0, 0, 0, 0 },
25 0, 0, 0, 0, 0, 0 },
26 { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 26 { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
27 7800, 0x0f, 0x00, 18, 27 7800, 1, 18, 0, 1, 1, 1, 1 },
28 0, 1, 1, 1, 1, 0 },
29 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 28 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
30 10000, 0x0a, 0x00, 24, 29 10000, 2, 24, 2, 2, 2, 2, 2 },
31 2, 2, 2, 2, 2, 0 },
32 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 30 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
33 13900, 0x0e, 0x00, 36, 31 13900, 3, 36, 2, 3, 3, 3, 3 },
34 2, 3, 3, 3, 3, 0 },
35 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 32 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
36 17300, 0x09, 0x00, 48, 33 17300, 4, 48, 4, 4, 4, 4, 4 },
37 4, 4, 4, 4, 4, 0 },
38 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 34 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
39 23000, 0x0d, 0x00, 72, 35 23000, 5, 72, 4, 5, 5, 5, 5 },
40 4, 5, 5, 5, 5, 0 },
41 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 36 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
42 27400, 0x08, 0x00, 96, 37 27400, 6, 96, 4, 6, 6, 6, 6 },
43 4, 6, 6, 6, 6, 0 },
44 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 38 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
45 29300, 0x0c, 0x00, 108, 39 29300, 7, 108, 4, 7, 7, 7, 7 },
46 4, 7, 7, 7, 7, 0 },
47 { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ 40 { VALID_2040, VALID_2040, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
48 6400, 0x80, 0x00, 0, 41 6400, 0, 0, 0, 8, 24, 8, 24 },
49 0, 8, 24, 8, 24, 3216 },
50 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ 42 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
51 12700, 0x81, 0x00, 1, 43 12700, 1, 1, 2, 9, 25, 9, 25 },
52 2, 9, 25, 9, 25, 6434 },
53 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ 44 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
54 18800, 0x82, 0x00, 2, 45 18800, 2, 2, 2, 10, 26, 10, 26 },
55 2, 10, 26, 10, 26, 9650 },
56 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ 46 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
57 25000, 0x83, 0x00, 3, 47 25000, 3, 3, 4, 11, 27, 11, 27 },
58 4, 11, 27, 11, 27, 12868 },
59 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ 48 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
60 36700, 0x84, 0x00, 4, 49 36700, 4, 4, 4, 12, 28, 12, 28 },
61 4, 12, 28, 12, 28, 19304 },
62 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ 50 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
63 48100, 0x85, 0x00, 5, 51 48100, 5, 5, 4, 13, 29, 13, 29 },
64 4, 13, 29, 13, 29, 25740 },
65 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ 52 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
66 53500, 0x86, 0x00, 6, 53 53500, 6, 6, 4, 14, 30, 14, 30 },
67 4, 14, 30, 14, 30, 28956 },
68 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ 54 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
69 59000, 0x87, 0x00, 7, 55 59000, 7, 7, 4, 15, 31, 15, 32 },
70 4, 15, 31, 15, 32, 32180 },
71 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ 56 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
72 12700, 0x88, 0x00, 57 12700, 8, 8, 3, 16, 33, 16, 33 },
73 8, 3, 16, 33, 16, 33, 6430 },
74 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ 58 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
75 24800, 0x89, 0x00, 9, 59 24800, 9, 9, 2, 17, 34, 17, 34 },
76 2, 17, 34, 17, 34, 12860 },
77 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ 60 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
78 36600, 0x8a, 0x00, 10, 61 36600, 10, 10, 2, 18, 35, 18, 35 },
79 2, 18, 35, 18, 35, 19300 },
80 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ 62 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
81 48100, 0x8b, 0x00, 11, 63 48100, 11, 11, 4, 19, 36, 19, 36 },
82 4, 19, 36, 19, 36, 25736 },
83 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ 64 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
84 69500, 0x8c, 0x00, 12, 65 69500, 12, 12, 4, 20, 37, 20, 37 },
85 4, 20, 37, 20, 37, 38600 },
86 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ 66 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
87 89500, 0x8d, 0x00, 13, 67 89500, 13, 13, 4, 21, 38, 21, 38 },
88 4, 21, 38, 21, 38, 51472 },
89 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ 68 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
90 98900, 0x8e, 0x00, 14, 69 98900, 14, 14, 4, 22, 39, 22, 39 },
91 4, 22, 39, 22, 39, 57890 },
92 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ 70 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
93 108300, 0x8f, 0x00, 15, 71 108300, 15, 15, 4, 23, 40, 23, 41 },
94 4, 23, 40, 23, 41, 64320 },
95 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ 72 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
96 13200, 0x80, 0x00, 0, 73 13200, 0, 0, 0, 8, 24, 24, 24 },
97 0, 8, 24, 24, 24, 6684 },
98 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ 74 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
99 25900, 0x81, 0x00, 1, 75 25900, 1, 1, 2, 9, 25, 25, 25 },
100 2, 9, 25, 25, 25, 13368 },
101 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ 76 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
102 38600, 0x82, 0x00, 2, 77 38600, 2, 2, 2, 10, 26, 26, 26 },
103 2, 10, 26, 26, 26, 20052 },
104 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ 78 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
105 49800, 0x83, 0x00, 3, 79 49800, 3, 3, 4, 11, 27, 27, 27 },
106 4, 11, 27, 27, 27, 26738 },
107 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ 80 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
108 72200, 0x84, 0x00, 4, 81 72200, 4, 4, 4, 12, 28, 28, 28 },
109 4, 12, 28, 28, 28, 40104 },
110 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ 82 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
111 92900, 0x85, 0x00, 5, 83 92900, 5, 5, 4, 13, 29, 29, 29 },
112 4, 13, 29, 29, 29, 53476 },
113 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ 84 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
114 102700, 0x86, 0x00, 6, 85 102700, 6, 6, 4, 14, 30, 30, 30 },
115 4, 14, 30, 30, 30, 60156 },
116 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ 86 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
117 112000, 0x87, 0x00, 7, 87 112000, 7, 7, 4, 15, 31, 32, 32 },
118 4, 15, 31, 32, 32, 66840 },
119 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ 88 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
120 122000, 0x87, 0x00, 7, 89 122000, 7, 7, 4, 15, 31, 32, 32 },
121 4, 15, 31, 32, 32, 74200 },
122 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ 90 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
123 25800, 0x88, 0x00, 8, 91 25800, 8, 8, 0, 16, 33, 33, 33 },
124 0, 16, 33, 33, 33, 13360 },
125 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ 92 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
126 49800, 0x89, 0x00, 9, 93 49800, 9, 9, 2, 17, 34, 34, 34 },
127 2, 17, 34, 34, 34, 26720 },
128 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ 94 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
129 71900, 0x8a, 0x00, 10, 95 71900, 10, 10, 2, 18, 35, 35, 35 },
130 2, 18, 35, 35, 35, 40080 },
131 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ 96 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
132 92500, 0x8b, 0x00, 11, 97 92500, 11, 11, 4, 19, 36, 36, 36 },
133 4, 19, 36, 36, 36, 53440 },
134 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ 98 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
135 130300, 0x8c, 0x00, 12, 99 130300, 12, 12, 4, 20, 37, 37, 37 },
136 4, 20, 37, 37, 37, 80160 },
137 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ 100 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
138 162800, 0x8d, 0x00, 13, 101 162800, 13, 13, 4, 21, 38, 38, 38 },
139 4, 21, 38, 38, 38, 106880 },
140 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ 102 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
141 178200, 0x8e, 0x00, 14, 103 178200, 14, 14, 4, 22, 39, 39, 39 },
142 4, 22, 39, 39, 39, 120240 },
143 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ 104 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
144 192100, 0x8f, 0x00, 15, 105 192100, 15, 15, 4, 23, 40, 41, 41 },
145 4, 23, 40, 41, 41, 133600 },
146 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ 106 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
147 207000, 0x8f, 0x00, 15, 107 207000, 15, 15, 4, 23, 40, 41, 41 },
148 4, 23, 40, 41, 41, 148400 },
149 }, 108 },
150 50, /* probe interval */ 109 50, /* probe interval */
151 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ 110 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
@@ -156,177 +115,125 @@ static const struct ath_rate_table ar5416_11na_ratetable = {
156 115
157static const struct ath_rate_table ar5416_11ng_ratetable = { 116static const struct ath_rate_table ar5416_11ng_ratetable = {
158 46, 117 46,
118 12, /* MCS start */
159 { 119 {
160 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 120 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
161 900, 0x1b, 0x00, 2, 121 900, 0, 2, 0, 0, 0, 0, 0 },
162 0, 0, 0, 0, 0, 0 },
163 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ 122 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
164 1900, 0x1a, 0x04, 4, 123 1900, 1, 4, 1, 1, 1, 1, 1 },
165 1, 1, 1, 1, 1, 0 },
166 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ 124 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
167 4900, 0x19, 0x04, 11, 125 4900, 2, 11, 2, 2, 2, 2, 2 },
168 2, 2, 2, 2, 2, 0 },
169 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ 126 { VALID_ALL, VALID_ALL, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
170 8100, 0x18, 0x04, 22, 127 8100, 3, 22, 3, 3, 3, 3, 3 },
171 3, 3, 3, 3, 3, 0 },
172 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 128 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
173 5400, 0x0b, 0x00, 12, 129 5400, 4, 12, 4, 4, 4, 4, 4 },
174 4, 4, 4, 4, 4, 0 },
175 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 130 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
176 7800, 0x0f, 0x00, 18, 131 7800, 5, 18, 4, 5, 5, 5, 5 },
177 4, 5, 5, 5, 5, 0 },
178 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 132 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
179 10100, 0x0a, 0x00, 24, 133 10100, 6, 24, 6, 6, 6, 6, 6 },
180 6, 6, 6, 6, 6, 0 },
181 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 134 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
182 14100, 0x0e, 0x00, 36, 135 14100, 7, 36, 6, 7, 7, 7, 7 },
183 6, 7, 7, 7, 7, 0 },
184 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 136 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
185 17700, 0x09, 0x00, 48, 137 17700, 8, 48, 8, 8, 8, 8, 8 },
186 8, 8, 8, 8, 8, 0 },
187 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 138 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
188 23700, 0x0d, 0x00, 72, 139 23700, 9, 72, 8, 9, 9, 9, 9 },
189 8, 9, 9, 9, 9, 0 },
190 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 140 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
191 27400, 0x08, 0x00, 96, 141 27400, 10, 96, 8, 10, 10, 10, 10 },
192 8, 10, 10, 10, 10, 0 },
193 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 142 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
194 30900, 0x0c, 0x00, 108, 143 30900, 11, 108, 8, 11, 11, 11, 11 },
195 8, 11, 11, 11, 11, 0 },
196 { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */ 144 { INVALID, INVALID, WLAN_RC_PHY_HT_20_SS, 6500, /* 6.5 Mb */
197 6400, 0x80, 0x00, 0, 145 6400, 0, 0, 4, 12, 28, 12, 28 },
198 4, 12, 28, 12, 28, 3216 },
199 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */ 146 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 13000, /* 13 Mb */
200 12700, 0x81, 0x00, 1, 147 12700, 1, 1, 6, 13, 29, 13, 29 },
201 6, 13, 29, 13, 29, 6434 },
202 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */ 148 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 19500, /* 19.5 Mb */
203 18800, 0x82, 0x00, 2, 149 18800, 2, 2, 6, 14, 30, 14, 30 },
204 6, 14, 30, 14, 30, 9650 },
205 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */ 150 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 26000, /* 26 Mb */
206 25000, 0x83, 0x00, 3, 151 25000, 3, 3, 8, 15, 31, 15, 31 },
207 8, 15, 31, 15, 31, 12868 },
208 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */ 152 { VALID_20, VALID_20, WLAN_RC_PHY_HT_20_SS, 39000, /* 39 Mb */
209 36700, 0x84, 0x00, 4, 153 36700, 4, 4, 8, 16, 32, 16, 32 },
210 8, 16, 32, 16, 32, 19304 },
211 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */ 154 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 52000, /* 52 Mb */
212 48100, 0x85, 0x00, 5, 155 48100, 5, 5, 8, 17, 33, 17, 33 },
213 8, 17, 33, 17, 33, 25740 },
214 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */ 156 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 58500, /* 58.5 Mb */
215 53500, 0x86, 0x00, 6, 157 53500, 6, 6, 8, 18, 34, 18, 34 },
216 8, 18, 34, 18, 34, 28956 },
217 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */ 158 { INVALID, VALID_20, WLAN_RC_PHY_HT_20_SS, 65000, /* 65 Mb */
218 59000, 0x87, 0x00, 7, 159 59000, 7, 7, 8, 19, 35, 19, 36 },
219 8, 19, 35, 19, 36, 32180 },
220 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */ 160 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 13000, /* 13 Mb */
221 12700, 0x88, 0x00, 8, 161 12700, 8, 8, 4, 20, 37, 20, 37 },
222 4, 20, 37, 20, 37, 6430 },
223 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */ 162 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 26000, /* 26 Mb */
224 24800, 0x89, 0x00, 9, 163 24800, 9, 9, 6, 21, 38, 21, 38 },
225 6, 21, 38, 21, 38, 12860 },
226 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */ 164 { INVALID, INVALID, WLAN_RC_PHY_HT_20_DS, 39000, /* 39 Mb */
227 36600, 0x8a, 0x00, 10, 165 36600, 10, 10, 6, 22, 39, 22, 39 },
228 6, 22, 39, 22, 39, 19300 },
229 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */ 166 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 52000, /* 52 Mb */
230 48100, 0x8b, 0x00, 11, 167 48100, 11, 11, 8, 23, 40, 23, 40 },
231 8, 23, 40, 23, 40, 25736 },
232 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */ 168 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 78000, /* 78 Mb */
233 69500, 0x8c, 0x00, 12, 169 69500, 12, 12, 8, 24, 41, 24, 41 },
234 8, 24, 41, 24, 41, 38600 },
235 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */ 170 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 104000, /* 104 Mb */
236 89500, 0x8d, 0x00, 13, 171 89500, 13, 13, 8, 25, 42, 25, 42 },
237 8, 25, 42, 25, 42, 51472 },
238 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */ 172 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 117000, /* 117 Mb */
239 98900, 0x8e, 0x00, 14, 173 98900, 14, 14, 8, 26, 43, 26, 44 },
240 8, 26, 43, 26, 44, 57890 },
241 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */ 174 { VALID_20, INVALID, WLAN_RC_PHY_HT_20_DS, 130000, /* 130 Mb */
242 108300, 0x8f, 0x00, 15, 175 108300, 15, 15, 8, 27, 44, 27, 45 },
243 8, 27, 44, 27, 45, 64320 },
244 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */ 176 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 13500, /* 13.5 Mb */
245 13200, 0x80, 0x00, 0, 177 13200, 0, 0, 8, 12, 28, 28, 28 },
246 8, 12, 28, 28, 28, 6684 },
247 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */ 178 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 27500, /* 27.0 Mb */
248 25900, 0x81, 0x00, 1, 179 25900, 1, 1, 8, 13, 29, 29, 29 },
249 8, 13, 29, 29, 29, 13368 },
250 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */ 180 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 40500, /* 40.5 Mb */
251 38600, 0x82, 0x00, 2, 181 38600, 2, 2, 8, 14, 30, 30, 30 },
252 8, 14, 30, 30, 30, 20052 },
253 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */ 182 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 54000, /* 54 Mb */
254 49800, 0x83, 0x00, 3, 183 49800, 3, 3, 8, 15, 31, 31, 31 },
255 8, 15, 31, 31, 31, 26738 },
256 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */ 184 { VALID_40, VALID_40, WLAN_RC_PHY_HT_40_SS, 81500, /* 81 Mb */
257 72200, 0x84, 0x00, 4, 185 72200, 4, 4, 8, 16, 32, 32, 32 },
258 8, 16, 32, 32, 32, 40104 },
259 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */ 186 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 108000, /* 108 Mb */
260 92900, 0x85, 0x00, 5, 187 92900, 5, 5, 8, 17, 33, 33, 33 },
261 8, 17, 33, 33, 33, 53476 },
262 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */ 188 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 121500, /* 121.5 Mb */
263 102700, 0x86, 0x00, 6, 189 102700, 6, 6, 8, 18, 34, 34, 34 },
264 8, 18, 34, 34, 34, 60156 },
265 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */ 190 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS, 135000, /* 135 Mb */
266 112000, 0x87, 0x00, 7, 191 112000, 7, 7, 8, 19, 35, 36, 36 },
267 8, 19, 35, 36, 36, 66840 },
268 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */ 192 { INVALID, VALID_40, WLAN_RC_PHY_HT_40_SS_HGI, 150000, /* 150 Mb */
269 122000, 0x87, 0x00, 7, 193 122000, 7, 7, 8, 19, 35, 36, 36 },
270 8, 19, 35, 36, 36, 74200 },
271 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */ 194 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 27000, /* 27 Mb */
272 25800, 0x88, 0x00, 8, 195 25800, 8, 8, 8, 20, 37, 37, 37 },
273 8, 20, 37, 37, 37, 13360 },
274 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */ 196 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 54000, /* 54 Mb */
275 49800, 0x89, 0x00, 9, 197 49800, 9, 9, 8, 21, 38, 38, 38 },
276 8, 21, 38, 38, 38, 26720 },
277 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */ 198 { INVALID, INVALID, WLAN_RC_PHY_HT_40_DS, 81000, /* 81 Mb */
278 71900, 0x8a, 0x00, 10, 199 71900, 10, 10, 8, 22, 39, 39, 39 },
279 8, 22, 39, 39, 39, 40080 },
280 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */ 200 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 108000, /* 108 Mb */
281 92500, 0x8b, 0x00, 11, 201 92500, 11, 11, 8, 23, 40, 40, 40 },
282 8, 23, 40, 40, 40, 53440 },
283 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */ 202 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 162000, /* 162 Mb */
284 130300, 0x8c, 0x00, 12, 203 130300, 12, 12, 8, 24, 41, 41, 41 },
285 8, 24, 41, 41, 41, 80160 },
286 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */ 204 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 216000, /* 216 Mb */
287 162800, 0x8d, 0x00, 13, 205 162800, 13, 13, 8, 25, 42, 42, 42 },
288 8, 25, 42, 42, 42, 106880 },
289 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */ 206 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 243000, /* 243 Mb */
290 178200, 0x8e, 0x00, 14, 207 178200, 14, 14, 8, 26, 43, 43, 43 },
291 8, 26, 43, 43, 43, 120240 },
292 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */ 208 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS, 270000, /* 270 Mb */
293 192100, 0x8f, 0x00, 15, 209 192100, 15, 15, 8, 27, 44, 45, 45 },
294 8, 27, 44, 45, 45, 133600 },
295 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */ 210 { VALID_40, INVALID, WLAN_RC_PHY_HT_40_DS_HGI, 300000, /* 300 Mb */
296 207000, 0x8f, 0x00, 15, 211 207000, 15, 15, 8, 27, 44, 45, 45 },
297 8, 27, 44, 45, 45, 148400 }, 212 },
298 },
299 50, /* probe interval */ 213 50, /* probe interval */
300 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */ 214 WLAN_RC_HT_FLAG, /* Phy rates allowed initially */
301}; 215};
302 216
303static const struct ath_rate_table ar5416_11a_ratetable = { 217static const struct ath_rate_table ar5416_11a_ratetable = {
304 8, 218 8,
219 0,
305 { 220 {
306 { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 221 { VALID, VALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
307 5400, 0x0b, 0x00, (0x80|12), 222 5400, 0, 12, 0, 0, 0 },
308 0, 0, 0 },
309 { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 223 { VALID, VALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
310 7800, 0x0f, 0x00, 18, 224 7800, 1, 18, 0, 1, 0 },
311 0, 1, 0 },
312 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 225 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
313 10000, 0x0a, 0x00, (0x80|24), 226 10000, 2, 24, 2, 2, 0 },
314 2, 2, 0 },
315 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 227 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
316 13900, 0x0e, 0x00, 36, 228 13900, 3, 36, 2, 3, 0 },
317 2, 3, 0 },
318 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 229 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
319 17300, 0x09, 0x00, (0x80|48), 230 17300, 4, 48, 4, 4, 0 },
320 4, 4, 0 },
321 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 231 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
322 23000, 0x0d, 0x00, 72, 232 23000, 5, 72, 4, 5, 0 },
323 4, 5, 0 },
324 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 233 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
325 27400, 0x08, 0x00, 96, 234 27400, 6, 96, 4, 6, 0 },
326 4, 6, 0 },
327 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 235 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
328 29300, 0x0c, 0x00, 108, 236 29300, 7, 108, 4, 7, 0 },
329 4, 7, 0 },
330 }, 237 },
331 50, /* probe interval */ 238 50, /* probe interval */
332 0, /* Phy rates allowed initially */ 239 0, /* Phy rates allowed initially */
@@ -334,48 +241,51 @@ static const struct ath_rate_table ar5416_11a_ratetable = {
334 241
335static const struct ath_rate_table ar5416_11g_ratetable = { 242static const struct ath_rate_table ar5416_11g_ratetable = {
336 12, 243 12,
244 0,
337 { 245 {
338 { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */ 246 { VALID, VALID, WLAN_RC_PHY_CCK, 1000, /* 1 Mb */
339 900, 0x1b, 0x00, 2, 247 900, 0, 2, 0, 0, 0 },
340 0, 0, 0 },
341 { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */ 248 { VALID, VALID, WLAN_RC_PHY_CCK, 2000, /* 2 Mb */
342 1900, 0x1a, 0x04, 4, 249 1900, 1, 4, 1, 1, 0 },
343 1, 1, 0 },
344 { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */ 250 { VALID, VALID, WLAN_RC_PHY_CCK, 5500, /* 5.5 Mb */
345 4900, 0x19, 0x04, 11, 251 4900, 2, 11, 2, 2, 0 },
346 2, 2, 0 },
347 { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */ 252 { VALID, VALID, WLAN_RC_PHY_CCK, 11000, /* 11 Mb */
348 8100, 0x18, 0x04, 22, 253 8100, 3, 22, 3, 3, 0 },
349 3, 3, 0 },
350 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */ 254 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 6000, /* 6 Mb */
351 5400, 0x0b, 0x00, 12, 255 5400, 4, 12, 4, 4, 0 },
352 4, 4, 0 },
353 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */ 256 { INVALID, INVALID, WLAN_RC_PHY_OFDM, 9000, /* 9 Mb */
354 7800, 0x0f, 0x00, 18, 257 7800, 5, 18, 4, 5, 0 },
355 4, 5, 0 },
356 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */ 258 { VALID, VALID, WLAN_RC_PHY_OFDM, 12000, /* 12 Mb */
357 10000, 0x0a, 0x00, 24, 259 10000, 6, 24, 6, 6, 0 },
358 6, 6, 0 },
359 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */ 260 { VALID, VALID, WLAN_RC_PHY_OFDM, 18000, /* 18 Mb */
360 13900, 0x0e, 0x00, 36, 261 13900, 7, 36, 6, 7, 0 },
361 6, 7, 0 },
362 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */ 262 { VALID, VALID, WLAN_RC_PHY_OFDM, 24000, /* 24 Mb */
363 17300, 0x09, 0x00, 48, 263 17300, 8, 48, 8, 8, 0 },
364 8, 8, 0 },
365 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */ 264 { VALID, VALID, WLAN_RC_PHY_OFDM, 36000, /* 36 Mb */
366 23000, 0x0d, 0x00, 72, 265 23000, 9, 72, 8, 9, 0 },
367 8, 9, 0 },
368 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */ 266 { VALID, VALID, WLAN_RC_PHY_OFDM, 48000, /* 48 Mb */
369 27400, 0x08, 0x00, 96, 267 27400, 10, 96, 8, 10, 0 },
370 8, 10, 0 },
371 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */ 268 { VALID, VALID, WLAN_RC_PHY_OFDM, 54000, /* 54 Mb */
372 29300, 0x0c, 0x00, 108, 269 29300, 11, 108, 8, 11, 0 },
373 8, 11, 0 },
374 }, 270 },
375 50, /* probe interval */ 271 50, /* probe interval */
376 0, /* Phy rates allowed initially */ 272 0, /* Phy rates allowed initially */
377}; 273};
378 274
275static const struct ath_rate_table *hw_rate_table[ATH9K_MODE_MAX] = {
276 [ATH9K_MODE_11A] = &ar5416_11a_ratetable,
277 [ATH9K_MODE_11G] = &ar5416_11g_ratetable,
278 [ATH9K_MODE_11NA_HT20] = &ar5416_11na_ratetable,
279 [ATH9K_MODE_11NG_HT20] = &ar5416_11ng_ratetable,
280 [ATH9K_MODE_11NA_HT40PLUS] = &ar5416_11na_ratetable,
281 [ATH9K_MODE_11NA_HT40MINUS] = &ar5416_11na_ratetable,
282 [ATH9K_MODE_11NG_HT40PLUS] = &ar5416_11ng_ratetable,
283 [ATH9K_MODE_11NG_HT40MINUS] = &ar5416_11ng_ratetable,
284};
285
286static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
287 struct ieee80211_tx_rate *rate);
288
379static inline int8_t median(int8_t a, int8_t b, int8_t c) 289static inline int8_t median(int8_t a, int8_t b, int8_t c)
380{ 290{
381 if (a >= b) { 291 if (a >= b) {
@@ -534,7 +444,7 @@ static u8 ath_rc_setvalid_rates(struct ath_rate_priv *ath_rc_priv,
534 * capflag matches one of the validity 444 * capflag matches one of the validity
535 * (VALID/VALID_20/VALID_40) flags */ 445 * (VALID/VALID_20/VALID_40) flags */
536 446
537 if (((rate & 0x7F) == (dot11rate & 0x7F)) && 447 if ((rate == dot11rate) &&
538 ((valid & WLAN_RC_CAP_MODE(capflag)) == 448 ((valid & WLAN_RC_CAP_MODE(capflag)) ==
539 WLAN_RC_CAP_MODE(capflag)) && 449 WLAN_RC_CAP_MODE(capflag)) &&
540 !WLAN_RC_PHY_HT(phy)) { 450 !WLAN_RC_PHY_HT(phy)) {
@@ -576,8 +486,7 @@ static u8 ath_rc_setvalid_htrates(struct ath_rate_priv *ath_rc_priv,
576 u8 rate = rateset->rs_rates[i]; 486 u8 rate = rateset->rs_rates[i];
577 u8 dot11rate = rate_table->info[j].dot11rate; 487 u8 dot11rate = rate_table->info[j].dot11rate;
578 488
579 if (((rate & 0x7F) != (dot11rate & 0x7F)) || 489 if ((rate != dot11rate) || !WLAN_RC_PHY_HT(phy) ||
580 !WLAN_RC_PHY_HT(phy) ||
581 !WLAN_RC_PHY_HT_VALID(valid, capflag)) 490 !WLAN_RC_PHY_HT_VALID(valid, capflag))
582 continue; 491 continue;
583 492
@@ -696,18 +605,20 @@ static void ath_rc_rate_set_series(const struct ath_rate_table *rate_table,
696 u8 tries, u8 rix, int rtsctsenable) 605 u8 tries, u8 rix, int rtsctsenable)
697{ 606{
698 rate->count = tries; 607 rate->count = tries;
699 rate->idx = rix; 608 rate->idx = rate_table->info[rix].ratecode;
700 609
701 if (txrc->short_preamble) 610 if (txrc->short_preamble)
702 rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE; 611 rate->flags |= IEEE80211_TX_RC_USE_SHORT_PREAMBLE;
703 if (txrc->rts || rtsctsenable) 612 if (txrc->rts || rtsctsenable)
704 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS; 613 rate->flags |= IEEE80211_TX_RC_USE_RTS_CTS;
705 if (WLAN_RC_PHY_40(rate_table->info[rix].phy)) 614
706 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH; 615 if (WLAN_RC_PHY_HT(rate_table->info[rix].phy)) {
707 if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
708 rate->flags |= IEEE80211_TX_RC_SHORT_GI;
709 if (WLAN_RC_PHY_HT(rate_table->info[rix].phy))
710 rate->flags |= IEEE80211_TX_RC_MCS; 616 rate->flags |= IEEE80211_TX_RC_MCS;
617 if (WLAN_RC_PHY_40(rate_table->info[rix].phy))
618 rate->flags |= IEEE80211_TX_RC_40_MHZ_WIDTH;
619 if (WLAN_RC_PHY_SGI(rate_table->info[rix].phy))
620 rate->flags |= IEEE80211_TX_RC_SHORT_GI;
621 }
711} 622}
712 623
713static void ath_rc_rate_set_rtscts(struct ath_softc *sc, 624static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
@@ -720,7 +631,7 @@ static void ath_rc_rate_set_rtscts(struct ath_softc *sc,
720 /* get the cix for the lowest valid rix */ 631 /* get the cix for the lowest valid rix */
721 for (i = 3; i >= 0; i--) { 632 for (i = 3; i >= 0; i--) {
722 if (rates[i].count && (rates[i].idx >= 0)) { 633 if (rates[i].count && (rates[i].idx >= 0)) {
723 rix = rates[i].idx; 634 rix = ath_rc_get_rateindex(rate_table, &rates[i]);
724 break; 635 break;
725 } 636 }
726 } 637 }
@@ -1080,15 +991,19 @@ static int ath_rc_get_rateindex(const struct ath_rate_table *rate_table,
1080{ 991{
1081 int rix; 992 int rix;
1082 993
994 if (!(rate->flags & IEEE80211_TX_RC_MCS))
995 return rate->idx;
996
997 rix = rate->idx + rate_table->mcs_start;
1083 if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) && 998 if ((rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) &&
1084 (rate->flags & IEEE80211_TX_RC_SHORT_GI)) 999 (rate->flags & IEEE80211_TX_RC_SHORT_GI))
1085 rix = rate_table->info[rate->idx].ht_index; 1000 rix = rate_table->info[rix].ht_index;
1086 else if (rate->flags & IEEE80211_TX_RC_SHORT_GI) 1001 else if (rate->flags & IEEE80211_TX_RC_SHORT_GI)
1087 rix = rate_table->info[rate->idx].sgi_index; 1002 rix = rate_table->info[rix].sgi_index;
1088 else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH) 1003 else if (rate->flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
1089 rix = rate_table->info[rate->idx].cw40index; 1004 rix = rate_table->info[rix].cw40index;
1090 else 1005 else
1091 rix = rate_table->info[rate->idx].base_index; 1006 rix = rate_table->info[rix].base_index;
1092 1007
1093 return rix; 1008 return rix;
1094} 1009}
@@ -1183,7 +1098,9 @@ struct ath_rate_table *ath_choose_rate_table(struct ath_softc *sc,
1183 1098
1184 ath_print(common, ATH_DBG_CONFIG, 1099 ath_print(common, ATH_DBG_CONFIG,
1185 "Choosing rate table for mode: %d\n", mode); 1100 "Choosing rate table for mode: %d\n", mode);
1186 return sc->hw_rate_table[mode]; 1101
1102 sc->cur_rate_mode = mode;
1103 return hw_rate_table[mode];
1187} 1104}
1188 1105
1189static void ath_rc_init(struct ath_softc *sc, 1106static void ath_rc_init(struct ath_softc *sc,
@@ -1197,12 +1114,6 @@ static void ath_rc_init(struct ath_softc *sc,
1197 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates; 1114 u8 *ht_mcs = (u8 *)&ath_rc_priv->neg_ht_rates;
1198 u8 i, j, k, hi = 0, hthi = 0; 1115 u8 i, j, k, hi = 0, hthi = 0;
1199 1116
1200 if (!rate_table) {
1201 ath_print(common, ATH_DBG_FATAL,
1202 "Rate table not initialized\n");
1203 return;
1204 }
1205
1206 /* Initial rate table size. Will change depending 1117 /* Initial rate table size. Will change depending
1207 * on the working rate set */ 1118 * on the working rate set */
1208 ath_rc_priv->rate_table_size = RATE_TABLE_SIZE; 1119 ath_rc_priv->rate_table_size = RATE_TABLE_SIZE;
@@ -1324,10 +1235,14 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1324 return; 1235 return;
1325 1236
1326 /* 1237 /*
1327 * If underrun error is seen assume it as an excessive retry only 1238 * If an underrun error is seen assume it as an excessive retry only
1328 * if prefetch trigger level have reached the max (0x3f for 5416) 1239 * if max frame trigger level has been reached (2 KB for singel stream,
1329 * Adjust the long retry as if the frame was tried hw->max_rate_tries 1240 * and 4 KB for dual stream). Adjust the long retry as if the frame was
1330 * times. This affects how ratectrl updates PER for the failed rate. 1241 * tried hw->max_rate_tries times to affect how ratectrl updates PER for
1242 * the failed rate. In case of congestion on the bus penalizing these
1243 * type of underruns should help hardware actually transmit new frames
1244 * successfully by eventually preferring slower rates. This itself
1245 * should also alleviate congestion on the bus.
1331 */ 1246 */
1332 if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) && 1247 if ((tx_info->pad[0] & ATH_TX_INFO_UNDERRUN) &&
1333 (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) { 1248 (sc->sc_ah->tx_trig_level >= ath_rc_priv->tx_triglevel_max)) {
@@ -1357,7 +1272,8 @@ static void ath_tx_status(void *priv, struct ieee80211_supported_band *sband,
1357 } 1272 }
1358 } 1273 }
1359 1274
1360 ath_debug_stat_rc(sc, skb); 1275 ath_debug_stat_rc(sc, ath_rc_get_rateindex(sc->cur_rate_table,
1276 &tx_info->status.rates[final_ts_idx]));
1361} 1277}
1362 1278
1363static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband, 1279static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
@@ -1365,7 +1281,7 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1365{ 1281{
1366 struct ath_softc *sc = priv; 1282 struct ath_softc *sc = priv;
1367 struct ath_rate_priv *ath_rc_priv = priv_sta; 1283 struct ath_rate_priv *ath_rc_priv = priv_sta;
1368 const struct ath_rate_table *rate_table = NULL; 1284 const struct ath_rate_table *rate_table;
1369 bool is_cw40, is_sgi40; 1285 bool is_cw40, is_sgi40;
1370 int i, j = 0; 1286 int i, j = 0;
1371 1287
@@ -1397,11 +1313,9 @@ static void ath_rate_init(void *priv, struct ieee80211_supported_band *sband,
1397 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) || 1313 (sc->sc_ah->opmode == NL80211_IFTYPE_MESH_POINT) ||
1398 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) { 1314 (sc->sc_ah->opmode == NL80211_IFTYPE_ADHOC)) {
1399 rate_table = ath_choose_rate_table(sc, sband->band, 1315 rate_table = ath_choose_rate_table(sc, sband->band,
1400 sta->ht_cap.ht_supported, 1316 sta->ht_cap.ht_supported, is_cw40);
1401 is_cw40); 1317 } else {
1402 } else if (sc->sc_ah->opmode == NL80211_IFTYPE_AP) { 1318 rate_table = hw_rate_table[sc->cur_rate_mode];
1403 /* cur_rate_table would be set on init through config() */
1404 rate_table = sc->cur_rate_table;
1405 } 1319 }
1406 1320
1407 ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40); 1321 ath_rc_priv->ht_cap = ath_rc_build_ht_caps(sc, sta, is_cw40, is_sgi40);
@@ -1445,6 +1359,7 @@ static void ath_rate_update(void *priv, struct ieee80211_supported_band *sband,
1445 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG, 1359 ath_print(ath9k_hw_common(sc->sc_ah), ATH_DBG_CONFIG,
1446 "Operating HT Bandwidth changed to: %d\n", 1360 "Operating HT Bandwidth changed to: %d\n",
1447 sc->hw->conf.channel_type); 1361 sc->hw->conf.channel_type);
1362 sc->cur_rate_table = hw_rate_table[sc->cur_rate_mode];
1448 } 1363 }
1449 } 1364 }
1450} 1365}
@@ -1497,26 +1412,6 @@ static struct rate_control_ops ath_rate_ops = {
1497 .free_sta = ath_rate_free_sta, 1412 .free_sta = ath_rate_free_sta,
1498}; 1413};
1499 1414
1500void ath_rate_attach(struct ath_softc *sc)
1501{
1502 sc->hw_rate_table[ATH9K_MODE_11A] =
1503 &ar5416_11a_ratetable;
1504 sc->hw_rate_table[ATH9K_MODE_11G] =
1505 &ar5416_11g_ratetable;
1506 sc->hw_rate_table[ATH9K_MODE_11NA_HT20] =
1507 &ar5416_11na_ratetable;
1508 sc->hw_rate_table[ATH9K_MODE_11NG_HT20] =
1509 &ar5416_11ng_ratetable;
1510 sc->hw_rate_table[ATH9K_MODE_11NA_HT40PLUS] =
1511 &ar5416_11na_ratetable;
1512 sc->hw_rate_table[ATH9K_MODE_11NA_HT40MINUS] =
1513 &ar5416_11na_ratetable;
1514 sc->hw_rate_table[ATH9K_MODE_11NG_HT40PLUS] =
1515 &ar5416_11ng_ratetable;
1516 sc->hw_rate_table[ATH9K_MODE_11NG_HT40MINUS] =
1517 &ar5416_11ng_ratetable;
1518}
1519
1520int ath_rate_control_register(void) 1415int ath_rate_control_register(void)
1521{ 1416{
1522 return ieee80211_rate_control_register(&ath_rate_ops); 1417 return ieee80211_rate_control_register(&ath_rate_ops);
diff --git a/drivers/net/wireless/ath/ath9k/rc.h b/drivers/net/wireless/ath/ath9k/rc.h
index 51f85ecbe88d..9eb96f506998 100644
--- a/drivers/net/wireless/ath/ath9k/rc.h
+++ b/drivers/net/wireless/ath/ath9k/rc.h
@@ -104,6 +104,7 @@ enum {
104 */ 104 */
105struct ath_rate_table { 105struct ath_rate_table {
106 int rate_cnt; 106 int rate_cnt;
107 int mcs_start;
107 struct { 108 struct {
108 int valid; 109 int valid;
109 int valid_single_stream; 110 int valid_single_stream;
@@ -111,14 +112,12 @@ struct ath_rate_table {
111 u32 ratekbps; 112 u32 ratekbps;
112 u32 user_ratekbps; 113 u32 user_ratekbps;
113 u8 ratecode; 114 u8 ratecode;
114 u8 short_preamble;
115 u8 dot11rate; 115 u8 dot11rate;
116 u8 ctrl_rate; 116 u8 ctrl_rate;
117 u8 base_index; 117 u8 base_index;
118 u8 cw40index; 118 u8 cw40index;
119 u8 sgi_index; 119 u8 sgi_index;
120 u8 ht_index; 120 u8 ht_index;
121 u32 max_4ms_framelen;
122 } info[RATE_TABLE_SIZE]; 121 } info[RATE_TABLE_SIZE];
123 u32 probe_interval; 122 u32 probe_interval;
124 u8 initial_ratemax; 123 u8 initial_ratemax;
@@ -179,8 +178,6 @@ enum ath9k_internal_frame_type {
179 ATH9K_INT_UNPAUSE 178 ATH9K_INT_UNPAUSE
180}; 179};
181 180
182void ath_rate_attach(struct ath_softc *sc);
183u8 ath_rate_findrateix(struct ath_softc *sc, u8 dot11_rate);
184int ath_rate_control_register(void); 181int ath_rate_control_register(void);
185void ath_rate_control_unregister(void); 182void ath_rate_control_unregister(void);
186 183
diff --git a/drivers/net/wireless/ath/ath9k/reg.h b/drivers/net/wireless/ath/ath9k/reg.h
index 49ec25f020f0..8e653fb937a1 100644
--- a/drivers/net/wireless/ath/ath9k/reg.h
+++ b/drivers/net/wireless/ath/ath9k/reg.h
@@ -1332,13 +1332,22 @@ enum {
1332#define AR_MCAST_FIL0 0x8040 1332#define AR_MCAST_FIL0 0x8040
1333#define AR_MCAST_FIL1 0x8044 1333#define AR_MCAST_FIL1 0x8044
1334 1334
1335/*
1336 * AR_DIAG_SW - Register which can be used for diagnostics and testing purposes.
1337 *
1338 * The force RX abort (AR_DIAG_RX_ABORT, bit 25) can be used in conjunction with
1339 * RX block (AR_DIAG_RX_DIS, bit 5) to help fast channel change to shut down
1340 * receive. The force RX abort bit will kill any frame which is currently being
1341 * transferred between the MAC and baseband. The RX block bit (AR_DIAG_RX_DIS)
1342 * will prevent any new frames from getting started.
1343 */
1335#define AR_DIAG_SW 0x8048 1344#define AR_DIAG_SW 0x8048
1336#define AR_DIAG_CACHE_ACK 0x00000001 1345#define AR_DIAG_CACHE_ACK 0x00000001
1337#define AR_DIAG_ACK_DIS 0x00000002 1346#define AR_DIAG_ACK_DIS 0x00000002
1338#define AR_DIAG_CTS_DIS 0x00000004 1347#define AR_DIAG_CTS_DIS 0x00000004
1339#define AR_DIAG_ENCRYPT_DIS 0x00000008 1348#define AR_DIAG_ENCRYPT_DIS 0x00000008
1340#define AR_DIAG_DECRYPT_DIS 0x00000010 1349#define AR_DIAG_DECRYPT_DIS 0x00000010
1341#define AR_DIAG_RX_DIS 0x00000020 1350#define AR_DIAG_RX_DIS 0x00000020 /* RX block */
1342#define AR_DIAG_LOOP_BACK 0x00000040 1351#define AR_DIAG_LOOP_BACK 0x00000040
1343#define AR_DIAG_CORR_FCS 0x00000080 1352#define AR_DIAG_CORR_FCS 0x00000080
1344#define AR_DIAG_CHAN_INFO 0x00000100 1353#define AR_DIAG_CHAN_INFO 0x00000100
@@ -1347,12 +1356,12 @@ enum {
1347#define AR_DIAG_FRAME_NV0 0x00020000 1356#define AR_DIAG_FRAME_NV0 0x00020000
1348#define AR_DIAG_OBS_PT_SEL1 0x000C0000 1357#define AR_DIAG_OBS_PT_SEL1 0x000C0000
1349#define AR_DIAG_OBS_PT_SEL1_S 18 1358#define AR_DIAG_OBS_PT_SEL1_S 18
1350#define AR_DIAG_FORCE_RX_CLEAR 0x00100000 1359#define AR_DIAG_FORCE_RX_CLEAR 0x00100000 /* force rx_clear high */
1351#define AR_DIAG_IGNORE_VIRT_CS 0x00200000 1360#define AR_DIAG_IGNORE_VIRT_CS 0x00200000
1352#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000 1361#define AR_DIAG_FORCE_CH_IDLE_HIGH 0x00400000
1353#define AR_DIAG_EIFS_CTRL_ENA 0x00800000 1362#define AR_DIAG_EIFS_CTRL_ENA 0x00800000
1354#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000 1363#define AR_DIAG_DUAL_CHAIN_INFO 0x01000000
1355#define AR_DIAG_RX_ABORT 0x02000000 1364#define AR_DIAG_RX_ABORT 0x02000000 /* Force RX abort */
1356#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000 1365#define AR_DIAG_SATURATE_CYCLE_CNT 0x04000000
1357#define AR_DIAG_OBS_PT_SEL2 0x08000000 1366#define AR_DIAG_OBS_PT_SEL2 0x08000000
1358#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000 1367#define AR_DIAG_RX_CLEAR_CTL_LOW 0x10000000
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 745d91995d78..564c6cb1c2b4 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -70,6 +70,29 @@ static int ath_tx_num_badfrms(struct ath_softc *sc, struct ath_buf *bf,
70static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds, 70static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
71 int nbad, int txok, bool update_rc); 71 int nbad, int txok, bool update_rc);
72 72
73enum {
74 MCS_DEFAULT,
75 MCS_HT40,
76 MCS_HT40_SGI,
77};
78
79static int ath_max_4ms_framelen[3][16] = {
80 [MCS_DEFAULT] = {
81 3216, 6434, 9650, 12868, 19304, 25740, 28956, 32180,
82 6430, 12860, 19300, 25736, 38600, 51472, 57890, 64320,
83 },
84 [MCS_HT40] = {
85 6684, 13368, 20052, 26738, 40104, 53476, 60156, 66840,
86 13360, 26720, 40080, 53440, 80160, 106880, 120240, 133600,
87 },
88 [MCS_HT40_SGI] = {
89 /* TODO: Only MCS 7 and 15 updated, recalculate the rest */
90 6684, 13368, 20052, 26738, 40104, 53476, 60156, 74200,
91 13360, 26720, 40080, 53440, 80160, 106880, 120240, 148400,
92 }
93};
94
95
73/*********************/ 96/*********************/
74/* Aggregation logic */ 97/* Aggregation logic */
75/*********************/ 98/*********************/
@@ -459,7 +482,6 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq,
459static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf, 482static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
460 struct ath_atx_tid *tid) 483 struct ath_atx_tid *tid)
461{ 484{
462 const struct ath_rate_table *rate_table = sc->cur_rate_table;
463 struct sk_buff *skb; 485 struct sk_buff *skb;
464 struct ieee80211_tx_info *tx_info; 486 struct ieee80211_tx_info *tx_info;
465 struct ieee80211_tx_rate *rates; 487 struct ieee80211_tx_rate *rates;
@@ -480,12 +502,20 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
480 502
481 for (i = 0; i < 4; i++) { 503 for (i = 0; i < 4; i++) {
482 if (rates[i].count) { 504 if (rates[i].count) {
483 if (!WLAN_RC_PHY_HT(rate_table->info[rates[i].idx].phy)) { 505 int modeidx;
506 if (!(rates[i].flags & IEEE80211_TX_RC_MCS)) {
484 legacy = 1; 507 legacy = 1;
485 break; 508 break;
486 } 509 }
487 510
488 frmlen = rate_table->info[rates[i].idx].max_4ms_framelen; 511 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
512 modeidx = MCS_HT40_SGI;
513 else if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
514 modeidx = MCS_HT40;
515 else
516 modeidx = MCS_DEFAULT;
517
518 frmlen = ath_max_4ms_framelen[modeidx][rates[i].idx];
489 max_4ms_framelen = min(max_4ms_framelen, frmlen); 519 max_4ms_framelen = min(max_4ms_framelen, frmlen);
490 } 520 }
491 } 521 }
@@ -523,12 +553,11 @@ static u32 ath_lookup_rate(struct ath_softc *sc, struct ath_buf *bf,
523static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid, 553static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
524 struct ath_buf *bf, u16 frmlen) 554 struct ath_buf *bf, u16 frmlen)
525{ 555{
526 const struct ath_rate_table *rt = sc->cur_rate_table;
527 struct sk_buff *skb = bf->bf_mpdu; 556 struct sk_buff *skb = bf->bf_mpdu;
528 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 557 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
529 u32 nsymbits, nsymbols; 558 u32 nsymbits, nsymbols;
530 u16 minlen; 559 u16 minlen;
531 u8 rc, flags, rix; 560 u8 flags, rix;
532 int width, half_gi, ndelim, mindelim; 561 int width, half_gi, ndelim, mindelim;
533 562
534 /* Select standard number of delimiters based on frame length alone */ 563 /* Select standard number of delimiters based on frame length alone */
@@ -558,7 +587,6 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
558 587
559 rix = tx_info->control.rates[0].idx; 588 rix = tx_info->control.rates[0].idx;
560 flags = tx_info->control.rates[0].flags; 589 flags = tx_info->control.rates[0].flags;
561 rc = rt->info[rix].ratecode;
562 width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0; 590 width = (flags & IEEE80211_TX_RC_40_MHZ_WIDTH) ? 1 : 0;
563 half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0; 591 half_gi = (flags & IEEE80211_TX_RC_SHORT_GI) ? 1 : 0;
564 592
@@ -570,7 +598,7 @@ static int ath_compute_num_delims(struct ath_softc *sc, struct ath_atx_tid *tid,
570 if (nsymbols == 0) 598 if (nsymbols == 0)
571 nsymbols = 1; 599 nsymbols = 1;
572 600
573 nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; 601 nsymbits = bits_per_symbol[rix][width];
574 minlen = (nsymbols * nsymbits) / BITS_PER_BYTE; 602 minlen = (nsymbols * nsymbits) / BITS_PER_BYTE;
575 603
576 if (frmlen < minlen) { 604 if (frmlen < minlen) {
@@ -1425,22 +1453,14 @@ static int setup_tx_flags(struct ath_softc *sc, struct sk_buff *skb,
1425static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf, 1453static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
1426 int width, int half_gi, bool shortPreamble) 1454 int width, int half_gi, bool shortPreamble)
1427{ 1455{
1428 const struct ath_rate_table *rate_table = sc->cur_rate_table;
1429 u32 nbits, nsymbits, duration, nsymbols; 1456 u32 nbits, nsymbits, duration, nsymbols;
1430 u8 rc;
1431 int streams, pktlen; 1457 int streams, pktlen;
1432 1458
1433 pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen; 1459 pktlen = bf_isaggr(bf) ? bf->bf_al : bf->bf_frmlen;
1434 rc = rate_table->info[rix].ratecode;
1435
1436 /* for legacy rates, use old function to compute packet duration */
1437 if (!IS_HT_RATE(rc))
1438 return ath9k_hw_computetxtime(sc->sc_ah, rate_table, pktlen,
1439 rix, shortPreamble);
1440 1460
1441 /* find number of symbols: PLCP + data */ 1461 /* find number of symbols: PLCP + data */
1442 nbits = (pktlen << 3) + OFDM_PLCP_BITS; 1462 nbits = (pktlen << 3) + OFDM_PLCP_BITS;
1443 nsymbits = bits_per_symbol[HT_RC_2_MCS(rc)][width]; 1463 nsymbits = bits_per_symbol[rix][width];
1444 nsymbols = (nbits + nsymbits - 1) / nsymbits; 1464 nsymbols = (nbits + nsymbits - 1) / nsymbits;
1445 1465
1446 if (!half_gi) 1466 if (!half_gi)
@@ -1449,7 +1469,7 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
1449 duration = SYMBOL_TIME_HALFGI(nsymbols); 1469 duration = SYMBOL_TIME_HALFGI(nsymbols);
1450 1470
1451 /* addup duration for legacy/ht training and signal fields */ 1471 /* addup duration for legacy/ht training and signal fields */
1452 streams = HT_RC_2_STREAMS(rc); 1472 streams = HT_RC_2_STREAMS(rix);
1453 duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams); 1473 duration += L_STF + L_LTF + L_SIG + HT_SIG + HT_STF + HT_LTF(streams);
1454 1474
1455 return duration; 1475 return duration;
@@ -1458,11 +1478,11 @@ static u32 ath_pkt_duration(struct ath_softc *sc, u8 rix, struct ath_buf *bf,
1458static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf) 1478static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1459{ 1479{
1460 struct ath_common *common = ath9k_hw_common(sc->sc_ah); 1480 struct ath_common *common = ath9k_hw_common(sc->sc_ah);
1461 const struct ath_rate_table *rt = sc->cur_rate_table;
1462 struct ath9k_11n_rate_series series[4]; 1481 struct ath9k_11n_rate_series series[4];
1463 struct sk_buff *skb; 1482 struct sk_buff *skb;
1464 struct ieee80211_tx_info *tx_info; 1483 struct ieee80211_tx_info *tx_info;
1465 struct ieee80211_tx_rate *rates; 1484 struct ieee80211_tx_rate *rates;
1485 const struct ieee80211_rate *rate;
1466 struct ieee80211_hdr *hdr; 1486 struct ieee80211_hdr *hdr;
1467 int i, flags = 0; 1487 int i, flags = 0;
1468 u8 rix = 0, ctsrate = 0; 1488 u8 rix = 0, ctsrate = 0;
@@ -1481,11 +1501,10 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1481 * checking the BSS's global flag. 1501 * checking the BSS's global flag.
1482 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used. 1502 * But for the rate series, IEEE80211_TX_RC_USE_SHORT_PREAMBLE is used.
1483 */ 1503 */
1504 rate = ieee80211_get_rts_cts_rate(sc->hw, tx_info);
1505 ctsrate = rate->hw_value;
1484 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT) 1506 if (sc->sc_flags & SC_OP_PREAMBLE_SHORT)
1485 ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode | 1507 ctsrate |= rate->hw_value_short;
1486 rt->info[tx_info->control.rts_cts_rate_idx].short_preamble;
1487 else
1488 ctsrate = rt->info[tx_info->control.rts_cts_rate_idx].ratecode;
1489 1508
1490 /* 1509 /*
1491 * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive. 1510 * ATH9K_TXDESC_RTSENA and ATH9K_TXDESC_CTSENA are mutually exclusive.
@@ -1508,6 +1527,9 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1508 flags &= ~(ATH9K_TXDESC_RTSENA); 1527 flags &= ~(ATH9K_TXDESC_RTSENA);
1509 1528
1510 for (i = 0; i < 4; i++) { 1529 for (i = 0; i < 4; i++) {
1530 bool is_40, is_sgi, is_sp;
1531 int phy;
1532
1511 if (!rates[i].count || (rates[i].idx < 0)) 1533 if (!rates[i].count || (rates[i].idx < 0))
1512 continue; 1534 continue;
1513 1535
@@ -1515,12 +1537,6 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1515 series[i].Tries = rates[i].count; 1537 series[i].Tries = rates[i].count;
1516 series[i].ChSel = common->tx_chainmask; 1538 series[i].ChSel = common->tx_chainmask;
1517 1539
1518 if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
1519 series[i].Rate = rt->info[rix].ratecode |
1520 rt->info[rix].short_preamble;
1521 else
1522 series[i].Rate = rt->info[rix].ratecode;
1523
1524 if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS) 1540 if (rates[i].flags & IEEE80211_TX_RC_USE_RTS_CTS)
1525 series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS; 1541 series[i].RateFlags |= ATH9K_RATESERIES_RTS_CTS;
1526 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) 1542 if (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH)
@@ -1528,10 +1544,36 @@ static void ath_buf_set_rate(struct ath_softc *sc, struct ath_buf *bf)
1528 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI) 1544 if (rates[i].flags & IEEE80211_TX_RC_SHORT_GI)
1529 series[i].RateFlags |= ATH9K_RATESERIES_HALFGI; 1545 series[i].RateFlags |= ATH9K_RATESERIES_HALFGI;
1530 1546
1531 series[i].PktDuration = ath_pkt_duration(sc, rix, bf, 1547 is_sgi = !!(rates[i].flags & IEEE80211_TX_RC_SHORT_GI);
1532 (rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH) != 0, 1548 is_40 = !!(rates[i].flags & IEEE80211_TX_RC_40_MHZ_WIDTH);
1533 (rates[i].flags & IEEE80211_TX_RC_SHORT_GI), 1549 is_sp = !!(rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE);
1534 (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)); 1550
1551 if (rates[i].flags & IEEE80211_TX_RC_MCS) {
1552 /* MCS rates */
1553 series[i].Rate = rix | 0x80;
1554 series[i].PktDuration = ath_pkt_duration(sc, rix, bf,
1555 is_40, is_sgi, is_sp);
1556 continue;
1557 }
1558
1559 /* legcay rates */
1560 if ((tx_info->band == IEEE80211_BAND_2GHZ) &&
1561 !(rate->flags & IEEE80211_RATE_ERP_G))
1562 phy = WLAN_RC_PHY_CCK;
1563 else
1564 phy = WLAN_RC_PHY_OFDM;
1565
1566 rate = &sc->sbands[tx_info->band].bitrates[rates[i].idx];
1567 series[i].Rate = rate->hw_value;
1568 if (rate->hw_value_short) {
1569 if (rates[i].flags & IEEE80211_TX_RC_USE_SHORT_PREAMBLE)
1570 series[i].Rate |= rate->hw_value_short;
1571 } else {
1572 is_sp = false;
1573 }
1574
1575 series[i].PktDuration = ath9k_hw_computetxtime(sc->sc_ah,
1576 phy, rate->bitrate * 100, bf->bf_frmlen, rix, is_sp);
1535 } 1577 }
1536 1578
1537 /* set dur_update_en for l-sig computation except for PS-Poll frames */ 1579 /* set dur_update_en for l-sig computation except for PS-Poll frames */
@@ -1554,6 +1596,7 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1554 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; 1596 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data;
1555 int hdrlen; 1597 int hdrlen;
1556 __le16 fc; 1598 __le16 fc;
1599 int padpos, padsize;
1557 1600
1558 tx_info->pad[0] = 0; 1601 tx_info->pad[0] = 0;
1559 switch (txctl->frame_type) { 1602 switch (txctl->frame_type) {
@@ -1572,7 +1615,13 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1572 ATH_TXBUF_RESET(bf); 1615 ATH_TXBUF_RESET(bf);
1573 1616
1574 bf->aphy = aphy; 1617 bf->aphy = aphy;
1575 bf->bf_frmlen = skb->len + FCS_LEN - (hdrlen & 3); 1618 bf->bf_frmlen = skb->len + FCS_LEN;
1619 /* Remove the padding size from bf_frmlen, if any */
1620 padpos = ath9k_cmn_padpos(hdr->frame_control);
1621 padsize = padpos & 3;
1622 if (padsize && skb->len>padpos+padsize) {
1623 bf->bf_frmlen -= padsize;
1624 }
1576 1625
1577 if (conf_is_ht(&hw->conf) && !is_pae(skb)) 1626 if (conf_is_ht(&hw->conf) && !is_pae(skb))
1578 bf->bf_state.bf_type |= BUF_HT; 1627 bf->bf_state.bf_type |= BUF_HT;
@@ -1602,6 +1651,14 @@ static int ath_tx_setup_buffer(struct ieee80211_hw *hw, struct ath_buf *bf,
1602 } 1651 }
1603 1652
1604 bf->bf_buf_addr = bf->bf_dmacontext; 1653 bf->bf_buf_addr = bf->bf_dmacontext;
1654
1655 /* tag if this is a nullfunc frame to enable PS when AP acks it */
1656 if (ieee80211_is_nullfunc(fc) && ieee80211_has_pm(fc)) {
1657 bf->bf_isnullfunc = true;
1658 sc->sc_flags &= ~SC_OP_NULLFUNC_COMPLETED;
1659 } else
1660 bf->bf_isnullfunc = false;
1661
1605 return 0; 1662 return 0;
1606} 1663}
1607 1664
@@ -1920,8 +1977,10 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_desc *ds,
1920 } 1977 }
1921 } 1978 }
1922 1979
1923 for (i = tx_rateindex + 1; i < hw->max_rates; i++) 1980 for (i = tx_rateindex + 1; i < hw->max_rates; i++) {
1924 tx_info->status.rates[i].count = 0; 1981 tx_info->status.rates[i].count = 0;
1982 tx_info->status.rates[i].idx = -1;
1983 }
1925 1984
1926 tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1; 1985 tx_info->status.rates[tx_rateindex].count = bf->bf_retries + 1;
1927} 1986}
@@ -1995,6 +2054,19 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
1995 } 2054 }
1996 2055
1997 /* 2056 /*
2057 * We now know the nullfunc frame has been ACKed so we
2058 * can disable RX.
2059 */
2060 if (bf->bf_isnullfunc &&
2061 (ds->ds_txstat.ts_status & ATH9K_TX_ACKED)) {
2062 if ((sc->sc_flags & SC_OP_PS_ENABLED)) {
2063 sc->ps_enabled = true;
2064 ath9k_hw_setrxabort(sc->sc_ah, 1);
2065 } else
2066 sc->sc_flags |= SC_OP_NULLFUNC_COMPLETED;
2067 }
2068
2069 /*
1998 * Remove ath_buf's of the same transmit unit from txq, 2070 * Remove ath_buf's of the same transmit unit from txq,
1999 * however leave the last descriptor back as the holding 2071 * however leave the last descriptor back as the holding
2000 * descriptor for hw. 2072 * descriptor for hw.
diff --git a/drivers/net/wireless/b43/leds.c b/drivers/net/wireless/b43/leds.c
index 1e8dba488004..c587115dd2b9 100644
--- a/drivers/net/wireless/b43/leds.c
+++ b/drivers/net/wireless/b43/leds.c
@@ -246,6 +246,7 @@ static void b43_led_get_sprominfo(struct b43_wldev *dev,
246 *behaviour = B43_LED_OFF; 246 *behaviour = B43_LED_OFF;
247 break; 247 break;
248 default: 248 default:
249 *behaviour = B43_LED_OFF;
249 B43_WARN_ON(1); 250 B43_WARN_ON(1);
250 return; 251 return;
251 } 252 }
diff --git a/drivers/net/wireless/b43/rfkill.c b/drivers/net/wireless/b43/rfkill.c
index ffdce6f3c909..78016ae21c50 100644
--- a/drivers/net/wireless/b43/rfkill.c
+++ b/drivers/net/wireless/b43/rfkill.c
@@ -33,8 +33,14 @@ bool b43_is_hw_radio_enabled(struct b43_wldev *dev)
33 & B43_MMIO_RADIO_HWENABLED_HI_MASK)) 33 & B43_MMIO_RADIO_HWENABLED_HI_MASK))
34 return 1; 34 return 1;
35 } else { 35 } else {
36 if (b43_status(dev) >= B43_STAT_STARTED && 36 /* To prevent CPU fault on PPC, do not read a register
37 b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO) 37 * unless the interface is started; however, on resume
38 * for hibernation, this routine is entered early. When
39 * that happens, unconditionally return TRUE.
40 */
41 if (b43_status(dev) < B43_STAT_STARTED)
42 return 1;
43 if (b43_read16(dev, B43_MMIO_RADIO_HWENABLED_LO)
38 & B43_MMIO_RADIO_HWENABLED_LO_MASK) 44 & B43_MMIO_RADIO_HWENABLED_LO_MASK)
39 return 1; 45 return 1;
40 } 46 }
diff --git a/drivers/net/wireless/b43legacy/rfkill.c b/drivers/net/wireless/b43legacy/rfkill.c
index 8783022db11e..d579df72b783 100644
--- a/drivers/net/wireless/b43legacy/rfkill.c
+++ b/drivers/net/wireless/b43legacy/rfkill.c
@@ -34,6 +34,13 @@ bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev)
34 & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) 34 & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK))
35 return 1; 35 return 1;
36 } else { 36 } else {
37 /* To prevent CPU fault on PPC, do not read a register
38 * unless the interface is started; however, on resume
39 * for hibernation, this routine is entered early. When
40 * that happens, unconditionally return TRUE.
41 */
42 if (b43legacy_status(dev) < B43legacy_STAT_STARTED)
43 return 1;
37 if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO) 44 if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO)
38 & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK) 45 & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK)
39 return 1; 46 return 1;
diff --git a/drivers/net/wireless/ipw2x00/ipw2100.c b/drivers/net/wireless/ipw2x00/ipw2100.c
index 6c836c892e43..17a9cb3528fc 100644
--- a/drivers/net/wireless/ipw2x00/ipw2100.c
+++ b/drivers/net/wireless/ipw2x00/ipw2100.c
@@ -6573,6 +6573,16 @@ static int ipw2100_resume(struct pci_dev *pci_dev)
6573} 6573}
6574#endif 6574#endif
6575 6575
6576static void ipw2100_shutdown(struct pci_dev *pci_dev)
6577{
6578 struct ipw2100_priv *priv = pci_get_drvdata(pci_dev);
6579
6580 /* Take down the device; powers it off, etc. */
6581 ipw2100_down(priv);
6582
6583 pci_disable_device(pci_dev);
6584}
6585
6576#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x } 6586#define IPW2100_DEV_ID(x) { PCI_VENDOR_ID_INTEL, 0x1043, 0x8086, x }
6577 6587
6578static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = { 6588static struct pci_device_id ipw2100_pci_id_table[] __devinitdata = {
@@ -6636,6 +6646,7 @@ static struct pci_driver ipw2100_pci_driver = {
6636 .suspend = ipw2100_suspend, 6646 .suspend = ipw2100_suspend,
6637 .resume = ipw2100_resume, 6647 .resume = ipw2100_resume,
6638#endif 6648#endif
6649 .shutdown = ipw2100_shutdown,
6639}; 6650};
6640 6651
6641/** 6652/**
diff --git a/drivers/net/wireless/ipw2x00/libipw_module.c b/drivers/net/wireless/ipw2x00/libipw_module.c
index e8a1ac5f8e11..bf21eb383dbd 100644
--- a/drivers/net/wireless/ipw2x00/libipw_module.c
+++ b/drivers/net/wireless/ipw2x00/libipw_module.c
@@ -248,17 +248,22 @@ u32 libipw_debug_level = 0;
248EXPORT_SYMBOL_GPL(libipw_debug_level); 248EXPORT_SYMBOL_GPL(libipw_debug_level);
249static struct proc_dir_entry *libipw_proc = NULL; 249static struct proc_dir_entry *libipw_proc = NULL;
250 250
251static int show_debug_level(char *page, char **start, off_t offset, 251static int debug_level_proc_show(struct seq_file *m, void *v)
252 int count, int *eof, void *data)
253{ 252{
254 return snprintf(page, count, "0x%08X\n", libipw_debug_level); 253 seq_printf(m, "0x%08X\n", libipw_debug_level);
254 return 0;
255} 255}
256 256
257static int store_debug_level(struct file *file, const char __user * buffer, 257static int debug_level_proc_open(struct inode *inode, struct file *file)
258 unsigned long count, void *data) 258{
259 return single_open(file, debug_level_proc_show, NULL);
260}
261
262static ssize_t debug_level_proc_write(struct file *file,
263 const char __user *buffer, size_t count, loff_t *pos)
259{ 264{
260 char buf[] = "0x00000000\n"; 265 char buf[] = "0x00000000\n";
261 unsigned long len = min((unsigned long)sizeof(buf) - 1, count); 266 size_t len = min(sizeof(buf) - 1, count);
262 unsigned long val; 267 unsigned long val;
263 268
264 if (copy_from_user(buf, buffer, len)) 269 if (copy_from_user(buf, buffer, len))
@@ -272,6 +277,15 @@ static int store_debug_level(struct file *file, const char __user * buffer,
272 277
273 return strnlen(buf, len); 278 return strnlen(buf, len);
274} 279}
280
281static const struct file_operations debug_level_proc_fops = {
282 .owner = THIS_MODULE,
283 .open = debug_level_proc_open,
284 .read = seq_read,
285 .llseek = seq_lseek,
286 .release = single_release,
287 .write = debug_level_proc_write,
288};
275#endif /* CONFIG_LIBIPW_DEBUG */ 289#endif /* CONFIG_LIBIPW_DEBUG */
276 290
277static int __init libipw_init(void) 291static int __init libipw_init(void)
@@ -286,16 +300,13 @@ static int __init libipw_init(void)
286 " proc directory\n"); 300 " proc directory\n");
287 return -EIO; 301 return -EIO;
288 } 302 }
289 e = create_proc_entry("debug_level", S_IFREG | S_IRUGO | S_IWUSR, 303 e = proc_create("debug_level", S_IRUGO | S_IWUSR, libipw_proc,
290 libipw_proc); 304 &debug_level_proc_fops);
291 if (!e) { 305 if (!e) {
292 remove_proc_entry(DRV_NAME, init_net.proc_net); 306 remove_proc_entry(DRV_NAME, init_net.proc_net);
293 libipw_proc = NULL; 307 libipw_proc = NULL;
294 return -EIO; 308 return -EIO;
295 } 309 }
296 e->read_proc = show_debug_level;
297 e->write_proc = store_debug_level;
298 e->data = NULL;
299#endif /* CONFIG_LIBIPW_DEBUG */ 310#endif /* CONFIG_LIBIPW_DEBUG */
300 311
301 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n"); 312 printk(KERN_INFO DRV_NAME ": " DRV_DESCRIPTION ", " DRV_VERSION "\n");
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index c96513bddb10..b8377efb3ba7 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -1662,7 +1662,9 @@ void iwl_dump_nic_error_log(struct iwl_priv *priv)
1662 base = le32_to_cpu(priv->card_alive.error_event_table_ptr); 1662 base = le32_to_cpu(priv->card_alive.error_event_table_ptr);
1663 1663
1664 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { 1664 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1665 IWL_ERR(priv, "Not valid error log pointer 0x%08X\n", base); 1665 IWL_ERR(priv,
1666 "Not valid error log pointer 0x%08X for %s uCode\n",
1667 base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
1666 return; 1668 return;
1667 } 1669 }
1668 1670
@@ -1807,7 +1809,9 @@ void iwl_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
1807 base = le32_to_cpu(priv->card_alive.log_event_table_ptr); 1809 base = le32_to_cpu(priv->card_alive.log_event_table_ptr);
1808 1810
1809 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) { 1811 if (!priv->cfg->ops->lib->is_valid_rtc_data_addr(base)) {
1810 IWL_ERR(priv, "Invalid event log pointer 0x%08X\n", base); 1812 IWL_ERR(priv,
1813 "Invalid event log pointer 0x%08X for %s uCode\n",
1814 base, (priv->ucode_type == UCODE_INIT) ? "Init" : "RT");
1811 return; 1815 return;
1812 } 1816 }
1813 1817
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index cf7d3df0744e..675b7df632fc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-core.h
+++ b/drivers/net/wireless/iwlwifi/iwl-core.h
@@ -63,6 +63,8 @@
63#ifndef __iwl_core_h__ 63#ifndef __iwl_core_h__
64#define __iwl_core_h__ 64#define __iwl_core_h__
65 65
66#include <linux/utsrelease.h>
67
66/************************ 68/************************
67 * forward declarations * 69 * forward declarations *
68 ************************/ 70 ************************/
@@ -70,7 +72,7 @@ struct iwl_host_cmd;
70struct iwl_cmd; 72struct iwl_cmd;
71 73
72 74
73#define IWLWIFI_VERSION "1.3.27k" 75#define IWLWIFI_VERSION UTS_RELEASE "-k"
74#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" 76#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation"
75#define DRV_AUTHOR "<ilw@linux.intel.com>" 77#define DRV_AUTHOR "<ilw@linux.intel.com>"
76 78
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c
index 0db9b79a69a6..2a28a1f8b1fe 100644
--- a/drivers/net/wireless/iwlwifi/iwl3945-base.c
+++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c
@@ -76,11 +76,9 @@
76#define VS 76#define VS
77#endif 77#endif
78 78
79#define IWL39_VERSION "1.2.26k" VD VS 79#define DRV_VERSION IWLWIFI_VERSION VD VS
80#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation" 80#define DRV_COPYRIGHT "Copyright(c) 2003-2009 Intel Corporation"
81#define DRV_AUTHOR "<ilw@linux.intel.com>" 81#define DRV_AUTHOR "<ilw@linux.intel.com>"
82#define DRV_VERSION IWL39_VERSION
83
84 82
85MODULE_DESCRIPTION(DRV_DESCRIPTION); 83MODULE_DESCRIPTION(DRV_DESCRIPTION);
86MODULE_VERSION(DRV_VERSION); 84MODULE_VERSION(DRV_VERSION);
@@ -1701,15 +1699,6 @@ void iwl3945_dump_nic_event_log(struct iwl_priv *priv, bool full_log)
1701 IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n", 1699 IWL_ERR(priv, "Start IWL Event Log Dump: display last %d count\n",
1702 size); 1700 size);
1703 1701
1704 /* if uCode has wrapped back to top of log, start at the oldest entry,
1705 * i.e the next one that uCode would fill. */
1706 if (num_wraps)
1707 iwl3945_print_event_log(priv, next_entry,
1708 capacity - next_entry, mode);
1709
1710 /* (then/else) start at top of log */
1711 iwl3945_print_event_log(priv, 0, next_entry, mode);
1712
1713#ifdef CONFIG_IWLWIFI_DEBUG 1702#ifdef CONFIG_IWLWIFI_DEBUG
1714 if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) { 1703 if ((iwl_get_debug_level(priv) & IWL_DL_FW_ERRORS) || full_log) {
1715 /* if uCode has wrapped back to top of log, 1704 /* if uCode has wrapped back to top of log,
diff --git a/drivers/net/wireless/iwmc3200wifi/cfg80211.c b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
index 2e00a4b389e6..7c4f44a9c3e6 100644
--- a/drivers/net/wireless/iwmc3200wifi/cfg80211.c
+++ b/drivers/net/wireless/iwmc3200wifi/cfg80211.c
@@ -678,6 +678,9 @@ static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
678 case TX_POWER_AUTOMATIC: 678 case TX_POWER_AUTOMATIC:
679 return 0; 679 return 0;
680 case TX_POWER_FIXED: 680 case TX_POWER_FIXED:
681 if (!test_bit(IWM_STATUS_READY, &iwm->status))
682 return 0;
683
681 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 684 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
682 CFG_TX_PWR_LIMIT_USR, dbm * 2); 685 CFG_TX_PWR_LIMIT_USR, dbm * 2);
683 if (ret < 0) 686 if (ret < 0)
@@ -685,6 +688,7 @@ static int iwm_cfg80211_set_txpower(struct wiphy *wiphy,
685 688
686 return iwm_tx_power_trigger(iwm); 689 return iwm_tx_power_trigger(iwm);
687 default: 690 default:
691 IWM_ERR(iwm, "Unsupported power type: %d\n", type);
688 return -EOPNOTSUPP; 692 return -EOPNOTSUPP;
689 } 693 }
690 694
@@ -721,6 +725,33 @@ static int iwm_cfg80211_set_power_mgmt(struct wiphy *wiphy,
721 CFG_POWER_INDEX, iwm->conf.power_index); 725 CFG_POWER_INDEX, iwm->conf.power_index);
722} 726}
723 727
728int iwm_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *netdev,
729 struct cfg80211_pmksa *pmksa)
730{
731 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
732
733 return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_ADD);
734}
735
736int iwm_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *netdev,
737 struct cfg80211_pmksa *pmksa)
738{
739 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
740
741 return iwm_send_pmkid_update(iwm, pmksa, IWM_CMD_PMKID_DEL);
742}
743
744int iwm_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *netdev)
745{
746 struct iwm_priv *iwm = wiphy_to_iwm(wiphy);
747 struct cfg80211_pmksa pmksa;
748
749 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
750
751 return iwm_send_pmkid_update(iwm, &pmksa, IWM_CMD_PMKID_FLUSH);
752}
753
754
724static struct cfg80211_ops iwm_cfg80211_ops = { 755static struct cfg80211_ops iwm_cfg80211_ops = {
725 .change_virtual_intf = iwm_cfg80211_change_iface, 756 .change_virtual_intf = iwm_cfg80211_change_iface,
726 .add_key = iwm_cfg80211_add_key, 757 .add_key = iwm_cfg80211_add_key,
@@ -737,6 +768,9 @@ static struct cfg80211_ops iwm_cfg80211_ops = {
737 .set_tx_power = iwm_cfg80211_set_txpower, 768 .set_tx_power = iwm_cfg80211_set_txpower,
738 .get_tx_power = iwm_cfg80211_get_txpower, 769 .get_tx_power = iwm_cfg80211_get_txpower,
739 .set_power_mgmt = iwm_cfg80211_set_power_mgmt, 770 .set_power_mgmt = iwm_cfg80211_set_power_mgmt,
771 .set_pmksa = iwm_cfg80211_set_pmksa,
772 .del_pmksa = iwm_cfg80211_del_pmksa,
773 .flush_pmksa = iwm_cfg80211_flush_pmksa,
740}; 774};
741 775
742static const u32 cipher_suites[] = { 776static const u32 cipher_suites[] = {
@@ -782,6 +816,7 @@ struct wireless_dev *iwm_wdev_alloc(int sizeof_bus, struct device *dev)
782 816
783 set_wiphy_dev(wdev->wiphy, dev); 817 set_wiphy_dev(wdev->wiphy, dev);
784 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX; 818 wdev->wiphy->max_scan_ssids = UMAC_WIFI_IF_PROBE_OPTION_MAX;
819 wdev->wiphy->max_num_pmkids = UMAC_MAX_NUM_PMKIDS;
785 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | 820 wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
786 BIT(NL80211_IFTYPE_ADHOC); 821 BIT(NL80211_IFTYPE_ADHOC);
787 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz; 822 wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &iwm_band_2ghz;
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.c b/drivers/net/wireless/iwmc3200wifi/commands.c
index 7e12438551ba..777584d76a88 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.c
+++ b/drivers/net/wireless/iwmc3200wifi/commands.c
@@ -99,6 +99,10 @@ int iwm_send_wifi_if_cmd(struct iwm_priv *iwm, void *payload, u16 payload_size,
99 return ret; 99 return ret;
100} 100}
101 101
102static int modparam_wiwi = COEX_MODE_CM;
103module_param_named(wiwi, modparam_wiwi, int, 0644);
104MODULE_PARM_DESC(wiwi, "Wifi-WiMAX coexistence: 1=SA, 2=XOR, 3=CM (default)");
105
102static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] = 106static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
103{ 107{
104 {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS}, 108 {4, 3, 0, COEX_UNASSOC_IDLE_FLAGS},
@@ -122,18 +126,18 @@ static struct coex_event iwm_sta_xor_prio_tbl[COEX_EVENTS_NUM] =
122static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] = 126static struct coex_event iwm_sta_cm_prio_tbl[COEX_EVENTS_NUM] =
123{ 127{
124 {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS}, 128 {1, 1, 0, COEX_UNASSOC_IDLE_FLAGS},
125 {4, 3, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS}, 129 {4, 4, 0, COEX_UNASSOC_MANUAL_SCAN_FLAGS},
126 {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS}, 130 {3, 3, 0, COEX_UNASSOC_AUTO_SCAN_FLAGS},
127 {5, 5, 0, COEX_CALIBRATION_FLAGS}, 131 {6, 6, 0, COEX_CALIBRATION_FLAGS},
128 {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS}, 132 {3, 3, 0, COEX_PERIODIC_CALIBRATION_FLAGS},
129 {5, 4, 0, COEX_CONNECTION_ESTAB_FLAGS}, 133 {6, 5, 0, COEX_CONNECTION_ESTAB_FLAGS},
130 {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS}, 134 {4, 4, 0, COEX_ASSOCIATED_IDLE_FLAGS},
131 {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS}, 135 {4, 4, 0, COEX_ASSOC_MANUAL_SCAN_FLAGS},
132 {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS}, 136 {4, 4, 0, COEX_ASSOC_AUTO_SCAN_FLAGS},
133 {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS}, 137 {4, 4, 0, COEX_ASSOC_ACTIVE_LEVEL_FLAGS},
134 {1, 1, 0, COEX_RF_ON_FLAGS}, 138 {1, 1, 0, COEX_RF_ON_FLAGS},
135 {1, 1, 0, COEX_RF_OFF_FLAGS}, 139 {1, 1, 0, COEX_RF_OFF_FLAGS},
136 {6, 6, 0, COEX_STAND_ALONE_DEBUG_FLAGS}, 140 {7, 7, 0, COEX_STAND_ALONE_DEBUG_FLAGS},
137 {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS}, 141 {5, 4, 0, COEX_IPAN_ASSOC_LEVEL_FLAGS},
138 {1, 1, 0, COEX_RSRVD1_FLAGS}, 142 {1, 1, 0, COEX_RSRVD1_FLAGS},
139 {1, 1, 0, COEX_RSRVD2_FLAGS} 143 {1, 1, 0, COEX_RSRVD2_FLAGS}
@@ -148,7 +152,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
148 152
149 coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK; 153 coex_table_cmd.flags = COEX_FLAGS_STA_TABLE_VALID_MSK;
150 154
151 switch (iwm->conf.coexist_mode) { 155 switch (modparam_wiwi) {
152 case COEX_MODE_XOR: 156 case COEX_MODE_XOR:
153 case COEX_MODE_CM: 157 case COEX_MODE_CM:
154 coex_enabled = 1; 158 coex_enabled = 1;
@@ -173,7 +177,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
173 COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK | 177 COEX_FLAGS_ASSOC_WAKEUP_UMASK_MSK |
174 COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK; 178 COEX_FLAGS_UNASSOC_WAKEUP_UMASK_MSK;
175 179
176 switch (iwm->conf.coexist_mode) { 180 switch (modparam_wiwi) {
177 case COEX_MODE_XOR: 181 case COEX_MODE_XOR:
178 memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl, 182 memcpy(coex_table_cmd.sta_prio, iwm_sta_xor_prio_tbl,
179 sizeof(iwm_sta_xor_prio_tbl)); 183 sizeof(iwm_sta_xor_prio_tbl));
@@ -184,7 +188,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
184 break; 188 break;
185 default: 189 default:
186 IWM_ERR(iwm, "Invalid coex_mode 0x%x\n", 190 IWM_ERR(iwm, "Invalid coex_mode 0x%x\n",
187 iwm->conf.coexist_mode); 191 modparam_wiwi);
188 break; 192 break;
189 } 193 }
190 } else 194 } else
@@ -192,7 +196,7 @@ int iwm_send_prio_table(struct iwm_priv *iwm)
192 196
193 return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD, 197 return iwm_send_lmac_ptrough_cmd(iwm, COEX_PRIORITY_TABLE_CMD,
194 &coex_table_cmd, 198 &coex_table_cmd,
195 sizeof(struct iwm_coex_prio_table_cmd), 1); 199 sizeof(struct iwm_coex_prio_table_cmd), 0);
196} 200}
197 201
198int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested) 202int iwm_send_init_calib_cfg(struct iwm_priv *iwm, u8 calib_requested)
@@ -396,7 +400,7 @@ int iwm_send_umac_config(struct iwm_priv *iwm, __le32 reset_flags)
396 return ret; 400 return ret;
397 401
398 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX, 402 ret = iwm_umac_set_config_fix(iwm, UMAC_PARAM_TBL_CFG_FIX,
399 CFG_COEX_MODE, iwm->conf.coexist_mode); 403 CFG_COEX_MODE, modparam_wiwi);
400 if (ret < 0) 404 if (ret < 0)
401 return ret; 405 return ret;
402 406
@@ -929,3 +933,58 @@ int iwm_target_reset(struct iwm_priv *iwm)
929 933
930 return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL); 934 return iwm_hal_send_target_cmd(iwm, &target_cmd, NULL);
931} 935}
936
937int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
938 struct iwm_umac_notif_stop_resume_tx *ntf)
939{
940 struct iwm_udma_wifi_cmd udma_cmd = UDMA_UMAC_INIT;
941 struct iwm_umac_cmd umac_cmd;
942 struct iwm_umac_cmd_stop_resume_tx stp_res_cmd;
943 struct iwm_sta_info *sta_info;
944 u8 sta_id = STA_ID_N_COLOR_ID(ntf->sta_id);
945 int i;
946
947 sta_info = &iwm->sta_table[sta_id];
948 if (!sta_info->valid) {
949 IWM_ERR(iwm, "Invalid STA: %d\n", sta_id);
950 return -EINVAL;
951 }
952
953 umac_cmd.id = UMAC_CMD_OPCODE_STOP_RESUME_STA_TX;
954 umac_cmd.resp = 0;
955
956 stp_res_cmd.flags = ntf->flags;
957 stp_res_cmd.sta_id = ntf->sta_id;
958 stp_res_cmd.stop_resume_tid_msk = ntf->stop_resume_tid_msk;
959 for (i = 0; i < IWM_UMAC_TID_NR; i++)
960 stp_res_cmd.last_seq_num[i] =
961 sta_info->tid_info[i].last_seq_num;
962
963 return iwm_hal_send_umac_cmd(iwm, &udma_cmd, &umac_cmd, &stp_res_cmd,
964 sizeof(struct iwm_umac_cmd_stop_resume_tx));
965
966}
967
968int iwm_send_pmkid_update(struct iwm_priv *iwm,
969 struct cfg80211_pmksa *pmksa, u32 command)
970{
971 struct iwm_umac_pmkid_update update;
972 int ret;
973
974 memset(&update, 0, sizeof(struct iwm_umac_pmkid_update));
975
976 update.command = cpu_to_le32(command);
977 if (pmksa->bssid)
978 memcpy(&update.bssid, pmksa->bssid, ETH_ALEN);
979 if (pmksa->pmkid)
980 memcpy(&update.pmkid, pmksa->pmkid, WLAN_PMKID_LEN);
981
982 ret = iwm_send_wifi_if_cmd(iwm, &update,
983 sizeof(struct iwm_umac_pmkid_update), 0);
984 if (ret) {
985 IWM_ERR(iwm, "PMKID update command failed\n");
986 return ret;
987 }
988
989 return 0;
990}
diff --git a/drivers/net/wireless/iwmc3200wifi/commands.h b/drivers/net/wireless/iwmc3200wifi/commands.h
index b36be2b23a3c..06af0552cd75 100644
--- a/drivers/net/wireless/iwmc3200wifi/commands.h
+++ b/drivers/net/wireless/iwmc3200wifi/commands.h
@@ -450,6 +450,25 @@ struct iwm_umac_cmd_stats_req {
450 __le32 flags; 450 __le32 flags;
451} __attribute__ ((packed)); 451} __attribute__ ((packed));
452 452
453struct iwm_umac_cmd_stop_resume_tx {
454 u8 flags;
455 u8 sta_id;
456 __le16 stop_resume_tid_msk;
457 __le16 last_seq_num[IWM_UMAC_TID_NR];
458 u16 reserved;
459} __attribute__ ((packed));
460
461#define IWM_CMD_PMKID_ADD 1
462#define IWM_CMD_PMKID_DEL 2
463#define IWM_CMD_PMKID_FLUSH 3
464
465struct iwm_umac_pmkid_update {
466 __le32 command;
467 u8 bssid[ETH_ALEN];
468 __le16 reserved;
469 u8 pmkid[WLAN_PMKID_LEN];
470} __attribute__ ((packed));
471
453/* LMAC commands */ 472/* LMAC commands */
454int iwm_read_mac(struct iwm_priv *iwm, u8 *mac); 473int iwm_read_mac(struct iwm_priv *iwm, u8 *mac);
455int iwm_send_prio_table(struct iwm_priv *iwm); 474int iwm_send_prio_table(struct iwm_priv *iwm);
@@ -478,6 +497,10 @@ int iwm_send_umac_channel_list(struct iwm_priv *iwm);
478int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids, 497int iwm_scan_ssids(struct iwm_priv *iwm, struct cfg80211_ssid *ssids,
479 int ssid_num); 498 int ssid_num);
480int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len); 499int iwm_scan_one_ssid(struct iwm_priv *iwm, u8 *ssid, int ssid_len);
500int iwm_send_umac_stop_resume_tx(struct iwm_priv *iwm,
501 struct iwm_umac_notif_stop_resume_tx *ntf);
502int iwm_send_pmkid_update(struct iwm_priv *iwm,
503 struct cfg80211_pmksa *pmksa, u32 command);
481 504
482/* UDMA commands */ 505/* UDMA commands */
483int iwm_target_reset(struct iwm_priv *iwm); 506int iwm_target_reset(struct iwm_priv *iwm);
diff --git a/drivers/net/wireless/iwmc3200wifi/debugfs.c b/drivers/net/wireless/iwmc3200wifi/debugfs.c
index 1465379f900a..be992ca41cf1 100644
--- a/drivers/net/wireless/iwmc3200wifi/debugfs.c
+++ b/drivers/net/wireless/iwmc3200wifi/debugfs.c
@@ -158,6 +158,29 @@ static ssize_t iwm_debugfs_txq_read(struct file *filp, char __user *buffer,
158 } 158 }
159 159
160 spin_unlock_irqrestore(&txq->queue.lock, flags); 160 spin_unlock_irqrestore(&txq->queue.lock, flags);
161
162 spin_lock_irqsave(&txq->stopped_queue.lock, flags);
163
164 len += snprintf(buf + len, buf_len - len,
165 "\tStopped Queue len: %d\n",
166 skb_queue_len(&txq->stopped_queue));
167 for (j = 0; j < skb_queue_len(&txq->stopped_queue); j++) {
168 struct iwm_tx_info *tx_info;
169
170 skb = skb->next;
171 tx_info = skb_to_tx_info(skb);
172
173 len += snprintf(buf + len, buf_len - len,
174 "\tSKB #%d\n", j);
175 len += snprintf(buf + len, buf_len - len,
176 "\t\tsta: %d\n", tx_info->sta);
177 len += snprintf(buf + len, buf_len - len,
178 "\t\tcolor: %d\n", tx_info->color);
179 len += snprintf(buf + len, buf_len - len,
180 "\t\ttid: %d\n", tx_info->tid);
181 }
182
183 spin_unlock_irqrestore(&txq->stopped_queue.lock, flags);
161 } 184 }
162 185
163 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len); 186 ret = simple_read_from_buffer(buffer, len, ppos, buf, buf_len);
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.c b/drivers/net/wireless/iwmc3200wifi/eeprom.c
index 365910fbe01e..8091421ee5e5 100644
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.c
+++ b/drivers/net/wireless/iwmc3200wifi/eeprom.c
@@ -66,6 +66,10 @@ static struct iwm_eeprom_entry eeprom_map[] = {
66 [IWM_EEPROM_SKU_CAP] = 66 [IWM_EEPROM_SKU_CAP] =
67 {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN}, 67 {"SKU capabilities", IWM_EEPROM_SKU_CAP_OFF, IWM_EEPROM_SKU_CAP_LEN},
68 68
69 [IWM_EEPROM_FAT_CHANNELS_CAP] =
70 {"HT channels capabilities", IWM_EEPROM_FAT_CHANNELS_CAP_OFF,
71 IWM_EEPROM_FAT_CHANNELS_CAP_LEN},
72
69 [IWM_EEPROM_CALIB_RXIQ_OFFSET] = 73 [IWM_EEPROM_CALIB_RXIQ_OFFSET] =
70 {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN}, 74 {"RX IQ offset", IWM_EEPROM_CALIB_RXIQ_OFF, IWM_EEPROM_INDIRECT_LEN},
71 75
@@ -146,6 +150,52 @@ u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id)
146 return iwm->eeprom + eeprom_map[eeprom_id].offset; 150 return iwm->eeprom + eeprom_map[eeprom_id].offset;
147} 151}
148 152
153int iwm_eeprom_fat_channels(struct iwm_priv *iwm)
154{
155 struct wiphy *wiphy = iwm_to_wiphy(iwm);
156 struct ieee80211_supported_band *band;
157 u16 *channels, i;
158
159 channels = (u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_FAT_CHANNELS_CAP);
160 if (IS_ERR(channels))
161 return PTR_ERR(channels);
162
163 band = wiphy->bands[IEEE80211_BAND_2GHZ];
164 band->ht_cap.ht_supported = true;
165
166 for (i = 0; i < IWM_EEPROM_FAT_CHANNELS_24; i++)
167 if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED))
168 band->ht_cap.ht_supported = false;
169
170 band = wiphy->bands[IEEE80211_BAND_5GHZ];
171 band->ht_cap.ht_supported = true;
172 for (i = IWM_EEPROM_FAT_CHANNELS_24; i < IWM_EEPROM_FAT_CHANNELS; i++)
173 if (!(channels[i] & IWM_EEPROM_FAT_CHANNEL_ENABLED))
174 band->ht_cap.ht_supported = false;
175
176 return 0;
177}
178
179u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm)
180{
181 u16 sku_cap;
182 u32 wireless_mode = 0;
183
184 sku_cap = *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP));
185
186 if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_24GHZ)
187 wireless_mode |= WIRELESS_MODE_11G;
188
189 if (sku_cap & IWM_EEPROM_SKU_CAP_BAND_52GHZ)
190 wireless_mode |= WIRELESS_MODE_11A;
191
192 if (sku_cap & IWM_EEPROM_SKU_CAP_11N_ENABLE)
193 wireless_mode |= WIRELESS_MODE_11N;
194
195 return wireless_mode;
196}
197
198
149int iwm_eeprom_init(struct iwm_priv *iwm) 199int iwm_eeprom_init(struct iwm_priv *iwm)
150{ 200{
151 int i, ret = 0; 201 int i, ret = 0;
diff --git a/drivers/net/wireless/iwmc3200wifi/eeprom.h b/drivers/net/wireless/iwmc3200wifi/eeprom.h
index cdb31a6a1f5f..4e3a3fdab0d3 100644
--- a/drivers/net/wireless/iwmc3200wifi/eeprom.h
+++ b/drivers/net/wireless/iwmc3200wifi/eeprom.h
@@ -48,6 +48,7 @@ enum {
48 IWM_EEPROM_CARD_ID, 48 IWM_EEPROM_CARD_ID,
49 IWM_EEPROM_RADIO_CONF, 49 IWM_EEPROM_RADIO_CONF,
50 IWM_EEPROM_SKU_CAP, 50 IWM_EEPROM_SKU_CAP,
51 IWM_EEPROM_FAT_CHANNELS_CAP,
51 52
52 IWM_EEPROM_INDIRECT_OFFSET, 53 IWM_EEPROM_INDIRECT_OFFSET,
53 IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET, 54 IWM_EEPROM_CALIB_RXIQ_OFFSET = IWM_EEPROM_INDIRECT_OFFSET,
@@ -58,14 +59,15 @@ enum {
58 IWM_EEPROM_LAST, 59 IWM_EEPROM_LAST,
59}; 60};
60 61
61#define IWM_EEPROM_SIG_OFF 0x00 62#define IWM_EEPROM_SIG_OFF 0x00
62#define IWM_EEPROM_VERSION_OFF (0x54 << 1) 63#define IWM_EEPROM_VERSION_OFF (0x54 << 1)
63#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1) 64#define IWM_EEPROM_OEM_HW_VERSION_OFF (0x56 << 1)
64#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1) 65#define IWM_EEPROM_MAC_VERSION_OFF (0x30 << 1)
65#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1) 66#define IWM_EEPROM_CARD_ID_OFF (0x5d << 1)
66#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1) 67#define IWM_EEPROM_RADIO_CONF_OFF (0x58 << 1)
67#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1) 68#define IWM_EEPROM_SKU_CAP_OFF (0x55 << 1)
68#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1) 69#define IWM_EEPROM_CALIB_CONFIG_OFF (0x7c << 1)
70#define IWM_EEPROM_FAT_CHANNELS_CAP_OFF (0xde << 1)
69 71
70#define IWM_EEPROM_SIG_LEN 4 72#define IWM_EEPROM_SIG_LEN 4
71#define IWM_EEPROM_VERSION_LEN 2 73#define IWM_EEPROM_VERSION_LEN 2
@@ -74,6 +76,7 @@ enum {
74#define IWM_EEPROM_CARD_ID_LEN 2 76#define IWM_EEPROM_CARD_ID_LEN 2
75#define IWM_EEPROM_RADIO_CONF_LEN 2 77#define IWM_EEPROM_RADIO_CONF_LEN 2
76#define IWM_EEPROM_SKU_CAP_LEN 2 78#define IWM_EEPROM_SKU_CAP_LEN 2
79#define IWM_EEPROM_FAT_CHANNELS_CAP_LEN 40
77#define IWM_EEPROM_INDIRECT_LEN 2 80#define IWM_EEPROM_INDIRECT_LEN 2
78 81
79#define IWM_MAX_EEPROM_DATA_LEN 240 82#define IWM_MAX_EEPROM_DATA_LEN 240
@@ -87,6 +90,14 @@ enum {
87#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5) 90#define IWM_EEPROM_SKU_CAP_BAND_52GHZ (1 << 5)
88#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6) 91#define IWM_EEPROM_SKU_CAP_11N_ENABLE (1 << 6)
89 92
93#define IWM_EEPROM_FAT_CHANNELS 20
94/* 2.4 gHz FAT primary channels: 1, 2, 3, 4, 5, 6, 7, 8, 9 */
95#define IWM_EEPROM_FAT_CHANNELS_24 9
96/* 5.2 gHz FAT primary channels: 36,44,52,60,100,108,116,124,132,149,157 */
97#define IWM_EEPROM_FAT_CHANNELS_52 11
98
99#define IWM_EEPROM_FAT_CHANNEL_ENABLED (1 << 0)
100
90enum { 101enum {
91 IWM_EEPROM_CALIB_CAL_HDR, 102 IWM_EEPROM_CALIB_CAL_HDR,
92 IWM_EEPROM_CALIB_TX_POWER, 103 IWM_EEPROM_CALIB_TX_POWER,
@@ -110,5 +121,7 @@ struct iwm_eeprom_entry {
110int iwm_eeprom_init(struct iwm_priv *iwm); 121int iwm_eeprom_init(struct iwm_priv *iwm);
111void iwm_eeprom_exit(struct iwm_priv *iwm); 122void iwm_eeprom_exit(struct iwm_priv *iwm);
112u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id); 123u8 *iwm_eeprom_access(struct iwm_priv *iwm, u8 eeprom_id);
124int iwm_eeprom_fat_channels(struct iwm_priv *iwm);
125u32 iwm_eeprom_wireless_mode(struct iwm_priv *iwm);
113 126
114#endif 127#endif
diff --git a/drivers/net/wireless/iwmc3200wifi/iwm.h b/drivers/net/wireless/iwmc3200wifi/iwm.h
index a9bf6bc97bea..5a26bb05a33a 100644
--- a/drivers/net/wireless/iwmc3200wifi/iwm.h
+++ b/drivers/net/wireless/iwmc3200wifi/iwm.h
@@ -81,7 +81,6 @@ struct iwm_conf {
81 u32 assoc_timeout; 81 u32 assoc_timeout;
82 u32 roam_timeout; 82 u32 roam_timeout;
83 u32 wireless_mode; 83 u32 wireless_mode;
84 u32 coexist_mode;
85 84
86 u8 ibss_band; 85 u8 ibss_band;
87 u8 ibss_channel; 86 u8 ibss_channel;
@@ -131,11 +130,18 @@ struct iwm_notif {
131 unsigned long buf_size; 130 unsigned long buf_size;
132}; 131};
133 132
133struct iwm_tid_info {
134 __le16 last_seq_num;
135 bool stopped;
136 struct mutex mutex;
137};
138
134struct iwm_sta_info { 139struct iwm_sta_info {
135 u8 addr[ETH_ALEN]; 140 u8 addr[ETH_ALEN];
136 bool valid; 141 bool valid;
137 bool qos; 142 bool qos;
138 u8 color; 143 u8 color;
144 struct iwm_tid_info tid_info[IWM_UMAC_TID_NR];
139}; 145};
140 146
141struct iwm_tx_info { 147struct iwm_tx_info {
@@ -185,6 +191,8 @@ struct iwm_key {
185struct iwm_tx_queue { 191struct iwm_tx_queue {
186 int id; 192 int id;
187 struct sk_buff_head queue; 193 struct sk_buff_head queue;
194 struct sk_buff_head stopped_queue;
195 spinlock_t lock;
188 struct workqueue_struct *wq; 196 struct workqueue_struct *wq;
189 struct work_struct worker; 197 struct work_struct worker;
190 u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE]; 198 u8 concat_buf[IWM_HAL_CONCATENATE_BUF_SIZE];
@@ -341,6 +349,7 @@ int iwm_up(struct iwm_priv *iwm);
341int iwm_down(struct iwm_priv *iwm); 349int iwm_down(struct iwm_priv *iwm);
342 350
343/* TX API */ 351/* TX API */
352u16 iwm_tid_to_queue(u16 tid);
344void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages); 353void iwm_tx_credit_inc(struct iwm_priv *iwm, int id, int total_freed_pages);
345void iwm_tx_worker(struct work_struct *work); 354void iwm_tx_worker(struct work_struct *work);
346int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev); 355int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev);
diff --git a/drivers/net/wireless/iwmc3200wifi/main.c b/drivers/net/wireless/iwmc3200wifi/main.c
index 75f105a59543..7f34d6dd3c41 100644
--- a/drivers/net/wireless/iwmc3200wifi/main.c
+++ b/drivers/net/wireless/iwmc3200wifi/main.c
@@ -68,7 +68,6 @@ static struct iwm_conf def_iwm_conf = {
68 .ct_kill_exit = 110, 68 .ct_kill_exit = 110,
69 .reset_on_fatal_err = 1, 69 .reset_on_fatal_err = 1,
70 .auto_connect = 1, 70 .auto_connect = 1,
71 .wimax_not_present = 0,
72 .enable_qos = 1, 71 .enable_qos = 1,
73 .mode = UMAC_MODE_BSS, 72 .mode = UMAC_MODE_BSS,
74 73
@@ -80,8 +79,8 @@ static struct iwm_conf def_iwm_conf = {
80 79
81 .assoc_timeout = 2, 80 .assoc_timeout = 2,
82 .roam_timeout = 10, 81 .roam_timeout = 10,
83 .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G, 82 .wireless_mode = WIRELESS_MODE_11A | WIRELESS_MODE_11G |
84 .coexist_mode = COEX_MODE_CM, 83 WIRELESS_MODE_11N,
85 84
86 /* IBSS */ 85 /* IBSS */
87 .ibss_band = UMAC_BAND_2GHZ, 86 .ibss_band = UMAC_BAND_2GHZ,
@@ -94,6 +93,10 @@ static int modparam_reset;
94module_param_named(reset, modparam_reset, bool, 0644); 93module_param_named(reset, modparam_reset, bool, 0644);
95MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])"); 94MODULE_PARM_DESC(reset, "reset on firmware errors (default 0 [not reset])");
96 95
96static int modparam_wimax_enable = 1;
97module_param_named(wimax_enable, modparam_wimax_enable, bool, 0644);
98MODULE_PARM_DESC(wimax_enable, "Enable wimax core (default 1 [wimax enabled])");
99
97int iwm_mode_to_nl80211_iftype(int mode) 100int iwm_mode_to_nl80211_iftype(int mode)
98{ 101{
99 switch (mode) { 102 switch (mode) {
@@ -247,7 +250,7 @@ static void iwm_watchdog(unsigned long data)
247 250
248int iwm_priv_init(struct iwm_priv *iwm) 251int iwm_priv_init(struct iwm_priv *iwm)
249{ 252{
250 int i; 253 int i, j;
251 char name[32]; 254 char name[32];
252 255
253 iwm->status = 0; 256 iwm->status = 0;
@@ -291,6 +294,8 @@ int iwm_priv_init(struct iwm_priv *iwm)
291 return -EAGAIN; 294 return -EAGAIN;
292 295
293 skb_queue_head_init(&iwm->txq[i].queue); 296 skb_queue_head_init(&iwm->txq[i].queue);
297 skb_queue_head_init(&iwm->txq[i].stopped_queue);
298 spin_lock_init(&iwm->txq[i].lock);
294 } 299 }
295 300
296 for (i = 0; i < IWM_NUM_KEYS; i++) 301 for (i = 0; i < IWM_NUM_KEYS; i++)
@@ -298,6 +303,12 @@ int iwm_priv_init(struct iwm_priv *iwm)
298 303
299 iwm->default_key = -1; 304 iwm->default_key = -1;
300 305
306 for (i = 0; i < IWM_STA_TABLE_NUM; i++)
307 for (j = 0; j < IWM_UMAC_TID_NR; j++) {
308 mutex_init(&iwm->sta_table[i].tid_info[j].mutex);
309 iwm->sta_table[i].tid_info[j].stopped = false;
310 }
311
301 init_timer(&iwm->watchdog); 312 init_timer(&iwm->watchdog);
302 iwm->watchdog.function = iwm_watchdog; 313 iwm->watchdog.function = iwm_watchdog;
303 iwm->watchdog.data = (unsigned long)iwm; 314 iwm->watchdog.data = (unsigned long)iwm;
@@ -478,7 +489,7 @@ static int iwm_config_boot_params(struct iwm_priv *iwm)
478 int ret; 489 int ret;
479 490
480 /* check Wimax is off and config debug monitor */ 491 /* check Wimax is off and config debug monitor */
481 if (iwm->conf.wimax_not_present) { 492 if (!modparam_wimax_enable) {
482 u32 data1 = 0x1f; 493 u32 data1 = 0x1f;
483 u32 addr1 = 0x606BE258; 494 u32 addr1 = 0x606BE258;
484 495
@@ -571,6 +582,7 @@ void iwm_link_off(struct iwm_priv *iwm)
571 582
572 for (i = 0; i < IWM_TX_QUEUES; i++) { 583 for (i = 0; i < IWM_TX_QUEUES; i++) {
573 skb_queue_purge(&iwm->txq[i].queue); 584 skb_queue_purge(&iwm->txq[i].queue);
585 skb_queue_purge(&iwm->txq[i].stopped_queue);
574 586
575 iwm->txq[i].concat_count = 0; 587 iwm->txq[i].concat_count = 0;
576 iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf; 588 iwm->txq[i].concat_ptr = iwm->txq[i].concat_buf;
@@ -630,6 +642,7 @@ static int __iwm_up(struct iwm_priv *iwm)
630 int ret; 642 int ret;
631 struct iwm_notif *notif_reboot, *notif_ack = NULL; 643 struct iwm_notif *notif_reboot, *notif_ack = NULL;
632 struct wiphy *wiphy = iwm_to_wiphy(iwm); 644 struct wiphy *wiphy = iwm_to_wiphy(iwm);
645 u32 wireless_mode;
633 646
634 ret = iwm_bus_enable(iwm); 647 ret = iwm_bus_enable(iwm);
635 if (ret) { 648 if (ret) {
@@ -691,6 +704,27 @@ static int __iwm_up(struct iwm_priv *iwm)
691 goto err_disable; 704 goto err_disable;
692 } 705 }
693 706
707 ret = iwm_eeprom_fat_channels(iwm);
708 if (ret) {
709 IWM_ERR(iwm, "Couldnt read HT channels EEPROM entries\n");
710 goto err_fw;
711 }
712
713 /*
714 * Read our SKU capabilities.
715 * If it's valid, we AND the configured wireless mode with the
716 * device EEPROM value as the current profile wireless mode.
717 */
718 wireless_mode = iwm_eeprom_wireless_mode(iwm);
719 if (wireless_mode) {
720 iwm->conf.wireless_mode &= wireless_mode;
721 if (iwm->umac_profile)
722 iwm->umac_profile->wireless_mode =
723 iwm->conf.wireless_mode;
724 } else
725 IWM_ERR(iwm, "Wrong SKU capabilities: 0x%x\n",
726 *((u16 *)iwm_eeprom_access(iwm, IWM_EEPROM_SKU_CAP)));
727
694 snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s", 728 snprintf(wiphy->fw_version, sizeof(wiphy->fw_version), "L%s_U%s",
695 iwm->lmac_version, iwm->umac_version); 729 iwm->lmac_version, iwm->umac_version);
696 730
diff --git a/drivers/net/wireless/iwmc3200wifi/netdev.c b/drivers/net/wireless/iwmc3200wifi/netdev.c
index 4f8dbdd7b917..e4f0f8705f65 100644
--- a/drivers/net/wireless/iwmc3200wifi/netdev.c
+++ b/drivers/net/wireless/iwmc3200wifi/netdev.c
@@ -76,6 +76,14 @@ static int iwm_stop(struct net_device *ndev)
76 */ 76 */
77static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; 77static const u16 iwm_1d_to_queue[8] = { 1, 0, 0, 1, 2, 2, 3, 3 };
78 78
79u16 iwm_tid_to_queue(u16 tid)
80{
81 if (tid > IWM_UMAC_TID_NR - 2)
82 return -EINVAL;
83
84 return iwm_1d_to_queue[tid];
85}
86
79static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb) 87static u16 iwm_select_queue(struct net_device *dev, struct sk_buff *skb)
80{ 88{
81 skb->priority = cfg80211_classify8021d(skb); 89 skb->priority = cfg80211_classify8021d(skb);
diff --git a/drivers/net/wireless/iwmc3200wifi/rx.c b/drivers/net/wireless/iwmc3200wifi/rx.c
index bdb1d7e7979d..72c27a3e5528 100644
--- a/drivers/net/wireless/iwmc3200wifi/rx.c
+++ b/drivers/net/wireless/iwmc3200wifi/rx.c
@@ -1087,6 +1087,71 @@ static int iwm_ntf_channel_info_list(struct iwm_priv *iwm, u8 *buf,
1087 return 0; 1087 return 0;
1088} 1088}
1089 1089
1090static int iwm_ntf_stop_resume_tx(struct iwm_priv *iwm, u8 *buf,
1091 unsigned long buf_size,
1092 struct iwm_wifi_cmd *cmd)
1093{
1094 struct iwm_umac_notif_stop_resume_tx *stp_res_tx =
1095 (struct iwm_umac_notif_stop_resume_tx *)buf;
1096 struct iwm_sta_info *sta_info;
1097 struct iwm_tid_info *tid_info;
1098 u8 sta_id = STA_ID_N_COLOR_ID(stp_res_tx->sta_id);
1099 u16 tid_msk = le16_to_cpu(stp_res_tx->stop_resume_tid_msk);
1100 int bit, ret = 0;
1101 bool stop = false;
1102
1103 IWM_DBG_NTF(iwm, DBG, "stop/resume notification:\n"
1104 "\tflags: 0x%x\n"
1105 "\tSTA id: %d\n"
1106 "\tTID bitmask: 0x%x\n",
1107 stp_res_tx->flags, stp_res_tx->sta_id,
1108 stp_res_tx->stop_resume_tid_msk);
1109
1110 if (stp_res_tx->flags & UMAC_STOP_TX_FLAG)
1111 stop = true;
1112
1113 sta_info = &iwm->sta_table[sta_id];
1114 if (!sta_info->valid) {
1115 IWM_ERR(iwm, "Stoping an invalid STA: %d %d\n",
1116 sta_id, stp_res_tx->sta_id);
1117 return -EINVAL;
1118 }
1119
1120 for_each_bit(bit, (unsigned long *)&tid_msk, IWM_UMAC_TID_NR) {
1121 tid_info = &sta_info->tid_info[bit];
1122
1123 mutex_lock(&tid_info->mutex);
1124 tid_info->stopped = stop;
1125 mutex_unlock(&tid_info->mutex);
1126
1127 if (!stop) {
1128 struct iwm_tx_queue *txq;
1129 u16 queue = iwm_tid_to_queue(bit);
1130
1131 if (queue < 0)
1132 continue;
1133
1134 txq = &iwm->txq[queue];
1135 /*
1136 * If we resume, we have to move our SKBs
1137 * back to the tx queue and queue some work.
1138 */
1139 spin_lock_bh(&txq->lock);
1140 skb_queue_splice_init(&txq->queue, &txq->stopped_queue);
1141 spin_unlock_bh(&txq->lock);
1142
1143 queue_work(txq->wq, &txq->worker);
1144 }
1145
1146 }
1147
1148 /* We send an ACK only for the stop case */
1149 if (stop)
1150 ret = iwm_send_umac_stop_resume_tx(iwm, stp_res_tx);
1151
1152 return ret;
1153}
1154
1090static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf, 1155static int iwm_ntf_wifi_if_wrapper(struct iwm_priv *iwm, u8 *buf,
1091 unsigned long buf_size, 1156 unsigned long buf_size,
1092 struct iwm_wifi_cmd *cmd) 1157 struct iwm_wifi_cmd *cmd)
@@ -1371,6 +1436,7 @@ static const iwm_handler iwm_umac_handlers[] =
1371 [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics, 1436 [UMAC_NOTIFY_OPCODE_STATS] = iwm_ntf_statistics,
1372 [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy, 1437 [UMAC_CMD_OPCODE_EEPROM_PROXY] = iwm_ntf_eeprom_proxy,
1373 [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list, 1438 [UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST] = iwm_ntf_channel_info_list,
1439 [UMAC_CMD_OPCODE_STOP_RESUME_STA_TX] = iwm_ntf_stop_resume_tx,
1374 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet, 1440 [REPLY_RX_MPDU_CMD] = iwm_ntf_rx_packet,
1375 [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper, 1441 [UMAC_CMD_OPCODE_WIFI_IF_WRAPPER] = iwm_ntf_wifi_if_wrapper,
1376}; 1442};
diff --git a/drivers/net/wireless/iwmc3200wifi/tx.c b/drivers/net/wireless/iwmc3200wifi/tx.c
index e3b4f7902daf..55905f02309c 100644
--- a/drivers/net/wireless/iwmc3200wifi/tx.c
+++ b/drivers/net/wireless/iwmc3200wifi/tx.c
@@ -329,7 +329,7 @@ static int iwm_tx_build_packet(struct iwm_priv *iwm, struct sk_buff *skb,
329 329
330 memcpy(buf + sizeof(*hdr), skb->data, skb->len); 330 memcpy(buf + sizeof(*hdr), skb->data, skb->len);
331 331
332 return 0; 332 return umac_cmd.seq_num;
333} 333}
334 334
335static int iwm_tx_send_concat_packets(struct iwm_priv *iwm, 335static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
@@ -354,16 +354,15 @@ static int iwm_tx_send_concat_packets(struct iwm_priv *iwm,
354 return ret; 354 return ret;
355} 355}
356 356
357#define CONFIG_IWM_TX_CONCATENATED 1
358
359void iwm_tx_worker(struct work_struct *work) 357void iwm_tx_worker(struct work_struct *work)
360{ 358{
361 struct iwm_priv *iwm; 359 struct iwm_priv *iwm;
362 struct iwm_tx_info *tx_info = NULL; 360 struct iwm_tx_info *tx_info = NULL;
363 struct sk_buff *skb; 361 struct sk_buff *skb;
364 int cmdlen, ret;
365 struct iwm_tx_queue *txq; 362 struct iwm_tx_queue *txq;
366 int pool_id; 363 struct iwm_sta_info *sta_info;
364 struct iwm_tid_info *tid_info;
365 int cmdlen, ret, pool_id;
367 366
368 txq = container_of(work, struct iwm_tx_queue, worker); 367 txq = container_of(work, struct iwm_tx_queue, worker);
369 iwm = container_of(txq, struct iwm_priv, txq[txq->id]); 368 iwm = container_of(txq, struct iwm_priv, txq[txq->id]);
@@ -373,19 +372,46 @@ void iwm_tx_worker(struct work_struct *work)
373 while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) && 372 while (!test_bit(pool_id, &iwm->tx_credit.full_pools_map) &&
374 !skb_queue_empty(&txq->queue)) { 373 !skb_queue_empty(&txq->queue)) {
375 374
375 spin_lock_bh(&txq->lock);
376 skb = skb_dequeue(&txq->queue); 376 skb = skb_dequeue(&txq->queue);
377 spin_unlock_bh(&txq->lock);
378
377 tx_info = skb_to_tx_info(skb); 379 tx_info = skb_to_tx_info(skb);
380 sta_info = &iwm->sta_table[tx_info->sta];
381 if (!sta_info->valid) {
382 IWM_ERR(iwm, "Trying to send a frame to unknown STA\n");
383 kfree_skb(skb);
384 continue;
385 }
386
387 tid_info = &sta_info->tid_info[tx_info->tid];
388
389 mutex_lock(&tid_info->mutex);
390
391 /*
392 * If the RAxTID is stopped, we queue the skb to the stopped
393 * queue.
394 * Whenever we'll get a UMAC notification to resume the tx flow
395 * for this RAxTID, we'll merge back the stopped queue into the
396 * regular queue. See iwm_ntf_stop_resume_tx() from rx.c.
397 */
398 if (tid_info->stopped) {
399 IWM_DBG_TX(iwm, DBG, "%dx%d stopped\n",
400 tx_info->sta, tx_info->tid);
401 spin_lock_bh(&txq->lock);
402 skb_queue_tail(&txq->stopped_queue, skb);
403 spin_unlock_bh(&txq->lock);
404
405 mutex_unlock(&tid_info->mutex);
406 continue;
407 }
408
378 cmdlen = IWM_UDMA_HDR_LEN + skb->len; 409 cmdlen = IWM_UDMA_HDR_LEN + skb->len;
379 410
380 IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: " 411 IWM_DBG_TX(iwm, DBG, "Tx frame on queue %d: skb: 0x%p, sta: "
381 "%d, color: %d\n", txq->id, skb, tx_info->sta, 412 "%d, color: %d\n", txq->id, skb, tx_info->sta,
382 tx_info->color); 413 tx_info->color);
383 414
384#if !CONFIG_IWM_TX_CONCATENATED
385 /* temporarily keep this to comparing the performance */
386 ret = iwm_send_packet(iwm, skb, pool_id);
387#else
388
389 if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE) 415 if (txq->concat_count + cmdlen > IWM_HAL_CONCATENATE_BUF_SIZE)
390 iwm_tx_send_concat_packets(iwm, txq); 416 iwm_tx_send_concat_packets(iwm, txq);
391 417
@@ -393,14 +419,21 @@ void iwm_tx_worker(struct work_struct *work)
393 if (ret) { 419 if (ret) {
394 IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue " 420 IWM_DBG_TX(iwm, DBG, "not enough tx_credit for queue "
395 "%d, Tx worker stopped\n", txq->id); 421 "%d, Tx worker stopped\n", txq->id);
422 spin_lock_bh(&txq->lock);
396 skb_queue_head(&txq->queue, skb); 423 skb_queue_head(&txq->queue, skb);
424 spin_unlock_bh(&txq->lock);
425
426 mutex_unlock(&tid_info->mutex);
397 break; 427 break;
398 } 428 }
399 429
400 txq->concat_ptr = txq->concat_buf + txq->concat_count; 430 txq->concat_ptr = txq->concat_buf + txq->concat_count;
401 iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr); 431 tid_info->last_seq_num =
432 iwm_tx_build_packet(iwm, skb, pool_id, txq->concat_ptr);
402 txq->concat_count += ALIGN(cmdlen, 16); 433 txq->concat_count += ALIGN(cmdlen, 16);
403#endif 434
435 mutex_unlock(&tid_info->mutex);
436
404 kfree_skb(skb); 437 kfree_skb(skb);
405 } 438 }
406 439
@@ -419,14 +452,14 @@ int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
419 struct iwm_priv *iwm = ndev_to_iwm(netdev); 452 struct iwm_priv *iwm = ndev_to_iwm(netdev);
420 struct net_device *ndev = iwm_to_ndev(iwm); 453 struct net_device *ndev = iwm_to_ndev(iwm);
421 struct wireless_dev *wdev = iwm_to_wdev(iwm); 454 struct wireless_dev *wdev = iwm_to_wdev(iwm);
422 u8 *dst_addr;
423 struct iwm_tx_info *tx_info; 455 struct iwm_tx_info *tx_info;
424 struct iwm_tx_queue *txq; 456 struct iwm_tx_queue *txq;
425 struct iwm_sta_info *sta_info; 457 struct iwm_sta_info *sta_info;
426 u8 sta_id; 458 u8 *dst_addr, sta_id;
427 u16 queue; 459 u16 queue;
428 int ret; 460 int ret;
429 461
462
430 if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) { 463 if (!test_bit(IWM_STATUS_ASSOCIATED, &iwm->status)) {
431 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: " 464 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_all_queues: "
432 "not associated\n"); 465 "not associated\n");
@@ -440,7 +473,8 @@ int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
440 txq = &iwm->txq[queue]; 473 txq = &iwm->txq[queue];
441 474
442 /* No free space for Tx, tx_worker is too slow */ 475 /* No free space for Tx, tx_worker is too slow */
443 if (skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) { 476 if ((skb_queue_len(&txq->queue) > IWM_TX_LIST_SIZE) ||
477 (skb_queue_len(&txq->stopped_queue) > IWM_TX_LIST_SIZE)) {
444 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue); 478 IWM_DBG_TX(iwm, DBG, "LINK: stop netif_subqueue[%d]\n", queue);
445 netif_stop_subqueue(netdev, queue); 479 netif_stop_subqueue(netdev, queue);
446 return NETDEV_TX_BUSY; 480 return NETDEV_TX_BUSY;
@@ -477,7 +511,9 @@ int iwm_xmit_frame(struct sk_buff *skb, struct net_device *netdev)
477 else 511 else
478 tx_info->tid = IWM_UMAC_MGMT_TID; 512 tx_info->tid = IWM_UMAC_MGMT_TID;
479 513
514 spin_lock_bh(&iwm->txq[queue].lock);
480 skb_queue_tail(&iwm->txq[queue].queue, skb); 515 skb_queue_tail(&iwm->txq[queue].queue, skb);
516 spin_unlock_bh(&iwm->txq[queue].lock);
481 517
482 queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker); 518 queue_work(iwm->txq[queue].wq, &iwm->txq[queue].worker);
483 519
diff --git a/drivers/net/wireless/iwmc3200wifi/umac.h b/drivers/net/wireless/iwmc3200wifi/umac.h
index be903543bb47..7f54a145ca65 100644
--- a/drivers/net/wireless/iwmc3200wifi/umac.h
+++ b/drivers/net/wireless/iwmc3200wifi/umac.h
@@ -83,6 +83,20 @@ struct iwm_udma_out_wifi_hdr {
83 ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\ 83 ((UMAC_HDI_ACT_TBL_IDX_RA_UMAC << UMAC_HDI_ACT_TBL_IDX_RA_POS) |\
84 (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS)) 84 (UMAC_HDI_ACT_TBL_IDX_TID_LMAC << UMAC_HDI_ACT_TBL_IDX_TID_POS))
85 85
86/* STA ID and color */
87#define STA_ID_SEED (0x0f)
88#define STA_ID_POS (0)
89#define STA_ID_MSK (STA_ID_SEED << STA_ID_POS)
90
91#define STA_COLOR_SEED (0x7)
92#define STA_COLOR_POS (4)
93#define STA_COLOR_MSK (STA_COLOR_SEED << STA_COLOR_POS)
94
95#define STA_ID_N_COLOR_COLOR(id_n_color) \
96 (((id_n_color) & STA_COLOR_MSK) >> STA_COLOR_POS)
97#define STA_ID_N_COLOR_ID(id_n_color) \
98 (((id_n_color) & STA_ID_MSK) >> STA_ID_POS)
99
86/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */ 100/* iwm_umac_notif_alive.page_grp_state Group number -- bits [3:0] */
87#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0 101#define UMAC_ALIVE_PAGE_STS_GRP_NUM_POS 0
88#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF 102#define UMAC_ALIVE_PAGE_STS_GRP_NUM_SEED 0xF
@@ -260,6 +274,9 @@ struct iwm_udma_out_wifi_hdr {
260#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16 274#define UMAC_CMD_OPCODE_GET_CHAN_INFO_LIST 0x16
261#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17 275#define UMAC_CMD_OPCODE_SET_PARAM_LIST 0x17
262#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18 276#define UMAC_CMD_OPCODE_GET_PARAM_LIST 0x18
277#define UMAC_CMD_OPCODE_STOP_RESUME_STA_TX 0x19
278#define UMAC_CMD_OPCODE_TEST_BLOCK_ACK 0x1A
279
263#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA 280#define UMAC_CMD_OPCODE_BASE_WRAPPER 0xFA
264#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB 281#define UMAC_CMD_OPCODE_LMAC_WRAPPER 0xFB
265#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC 282#define UMAC_CMD_OPCODE_HW_TEST_WRAPPER 0xFC
@@ -281,6 +298,7 @@ struct iwm_udma_out_wifi_hdr {
281#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B 298#define UMAC_WIFI_IF_CMD_GLOBAL_TX_KEY_ID 0x1B
282#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C 299#define UMAC_WIFI_IF_CMD_SET_HOST_EXTENDED_IE 0x1C
283#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E 300#define UMAC_WIFI_IF_CMD_GET_SUPPORTED_CHANNELS 0x1E
301#define UMAC_WIFI_IF_CMD_PMKID_UPDATE 0x1F
284#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20 302#define UMAC_WIFI_IF_CMD_TX_PWR_TRIGGER 0x20
285 303
286/* UMAC WiFi interface ports */ 304/* UMAC WiFi interface ports */
@@ -691,13 +709,13 @@ struct iwm_umac_notif_rx_ticket {
691#define UMAC_PHY_NUM_CHAINS 3 709#define UMAC_PHY_NUM_CHAINS 3
692 710
693#define IWM_UMAC_MGMT_TID 8 711#define IWM_UMAC_MGMT_TID 8
694#define IWM_UMAC_TID_NR 8 712#define IWM_UMAC_TID_NR 9 /* 8 TIDs + MGMT */
695 713
696struct iwm_umac_notif_stats { 714struct iwm_umac_notif_stats {
697 struct iwm_umac_wifi_in_hdr hdr; 715 struct iwm_umac_wifi_in_hdr hdr;
698 __le32 flags; 716 __le32 flags;
699 __le32 timestamp; 717 __le32 timestamp;
700 __le16 tid_load[IWM_UMAC_TID_NR + 2]; /* 1 non-QoS + 1 dword align */ 718 __le16 tid_load[IWM_UMAC_TID_NR + 1]; /* 1 non-QoS + 1 dword align */
701 __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR]; 719 __le16 tx_rate[UMAC_NTF_RATE_SAMPLE_NR];
702 __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR]; 720 __le16 rx_rate[UMAC_NTF_RATE_SAMPLE_NR];
703 __le32 chain_energy[UMAC_PHY_NUM_CHAINS]; 721 __le32 chain_energy[UMAC_PHY_NUM_CHAINS];
@@ -742,6 +760,20 @@ struct iwm_umac_notif_stats {
742 __le32 roam_ap_loadblance; 760 __le32 roam_ap_loadblance;
743} __attribute__ ((packed)); 761} __attribute__ ((packed));
744 762
763#define UMAC_STOP_TX_FLAG 0x1
764#define UMAC_RESUME_TX_FLAG 0x2
765
766#define LAST_SEQ_NUM_INVALID 0xFFFF
767
768struct iwm_umac_notif_stop_resume_tx {
769 struct iwm_umac_wifi_in_hdr hdr;
770 u8 flags; /* UMAC_*_TX_FLAG_* */
771 u8 sta_id;
772 __le16 stop_resume_tid_msk; /* tid bitmask */
773} __attribute__ ((packed));
774
775#define UMAC_MAX_NUM_PMKIDS 4
776
745/* WiFi interface wrapper header */ 777/* WiFi interface wrapper header */
746struct iwm_umac_wifi_if { 778struct iwm_umac_wifi_if {
747 u8 oid; 779 u8 oid;
diff --git a/drivers/net/wireless/libertas/Makefile b/drivers/net/wireless/libertas/Makefile
index fa37039e0eae..b188cd97a053 100644
--- a/drivers/net/wireless/libertas/Makefile
+++ b/drivers/net/wireless/libertas/Makefile
@@ -5,7 +5,7 @@ libertas-y += cmdresp.o
5libertas-y += debugfs.o 5libertas-y += debugfs.o
6libertas-y += ethtool.o 6libertas-y += ethtool.o
7libertas-y += main.o 7libertas-y += main.o
8libertas-y += persistcfg.o 8libertas-y += mesh.o
9libertas-y += rx.o 9libertas-y += rx.o
10libertas-y += scan.o 10libertas-y += scan.o
11libertas-y += tx.o 11libertas-y += tx.o
diff --git a/drivers/net/wireless/libertas/cmd.c b/drivers/net/wireless/libertas/cmd.c
index 1065ce29cd08..b9b371bfa30f 100644
--- a/drivers/net/wireless/libertas/cmd.c
+++ b/drivers/net/wireless/libertas/cmd.c
@@ -3,7 +3,6 @@
3 * It prepares command and sends it to firmware when it is ready. 3 * It prepares command and sends it to firmware when it is ready.
4 */ 4 */
5 5
6#include <net/lib80211.h>
7#include <linux/kfifo.h> 6#include <linux/kfifo.h>
8#include <linux/sched.h> 7#include <linux/sched.h>
9 8
@@ -697,173 +696,6 @@ static int lbs_cmd_reg_access(struct cmd_ds_command *cmdptr,
697 return 0; 696 return 0;
698} 697}
699 698
700static int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
701 u16 cmd_action, void *pdata_buf)
702{
703 struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
704 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
705
706 cmd->command = cpu_to_le16(CMD_BT_ACCESS);
707 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
708 sizeof(struct cmd_header));
709 cmd->result = 0;
710 bt_access->action = cpu_to_le16(cmd_action);
711
712 switch (cmd_action) {
713 case CMD_ACT_BT_ACCESS_ADD:
714 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
715 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr", bt_access->addr1, 6);
716 break;
717 case CMD_ACT_BT_ACCESS_DEL:
718 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
719 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr", bt_access->addr1, 6);
720 break;
721 case CMD_ACT_BT_ACCESS_LIST:
722 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
723 break;
724 case CMD_ACT_BT_ACCESS_RESET:
725 break;
726 case CMD_ACT_BT_ACCESS_SET_INVERT:
727 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
728 break;
729 case CMD_ACT_BT_ACCESS_GET_INVERT:
730 break;
731 default:
732 break;
733 }
734 lbs_deb_leave(LBS_DEB_CMD);
735 return 0;
736}
737
738static int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
739 u16 cmd_action, void *pdata_buf)
740{
741 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
742 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
743
744 cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
745 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
746 sizeof(struct cmd_header));
747 cmd->result = 0;
748
749 if (pdata_buf)
750 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
751 else
752 memset(fwt_access, 0, sizeof(*fwt_access));
753
754 fwt_access->action = cpu_to_le16(cmd_action);
755
756 lbs_deb_leave(LBS_DEB_CMD);
757 return 0;
758}
759
760int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
761 struct cmd_ds_mesh_access *cmd)
762{
763 int ret;
764
765 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
766
767 cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
768 cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
769 cmd->hdr.result = 0;
770
771 cmd->action = cpu_to_le16(cmd_action);
772
773 ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
774
775 lbs_deb_leave(LBS_DEB_CMD);
776 return ret;
777}
778
779static int __lbs_mesh_config_send(struct lbs_private *priv,
780 struct cmd_ds_mesh_config *cmd,
781 uint16_t action, uint16_t type)
782{
783 int ret;
784 u16 command = CMD_MESH_CONFIG_OLD;
785
786 lbs_deb_enter(LBS_DEB_CMD);
787
788 /*
789 * Command id is 0xac for v10 FW along with mesh interface
790 * id in bits 14-13-12.
791 */
792 if (priv->mesh_fw_ver == MESH_FW_NEW)
793 command = CMD_MESH_CONFIG |
794 (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
795
796 cmd->hdr.command = cpu_to_le16(command);
797 cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
798 cmd->hdr.result = 0;
799
800 cmd->type = cpu_to_le16(type);
801 cmd->action = cpu_to_le16(action);
802
803 ret = lbs_cmd_with_response(priv, command, cmd);
804
805 lbs_deb_leave(LBS_DEB_CMD);
806 return ret;
807}
808
809int lbs_mesh_config_send(struct lbs_private *priv,
810 struct cmd_ds_mesh_config *cmd,
811 uint16_t action, uint16_t type)
812{
813 int ret;
814
815 if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
816 return -EOPNOTSUPP;
817
818 ret = __lbs_mesh_config_send(priv, cmd, action, type);
819 return ret;
820}
821
822/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
823 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
824 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
825 * lbs_mesh_config_send.
826 */
827int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
828{
829 struct cmd_ds_mesh_config cmd;
830 struct mrvl_meshie *ie;
831 DECLARE_SSID_BUF(ssid);
832
833 memset(&cmd, 0, sizeof(cmd));
834 cmd.channel = cpu_to_le16(chan);
835 ie = (struct mrvl_meshie *)cmd.data;
836
837 switch (action) {
838 case CMD_ACT_MESH_CONFIG_START:
839 ie->id = WLAN_EID_GENERIC;
840 ie->val.oui[0] = 0x00;
841 ie->val.oui[1] = 0x50;
842 ie->val.oui[2] = 0x43;
843 ie->val.type = MARVELL_MESH_IE_TYPE;
844 ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
845 ie->val.version = MARVELL_MESH_IE_VERSION;
846 ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
847 ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
848 ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
849 ie->val.mesh_id_len = priv->mesh_ssid_len;
850 memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
851 ie->len = sizeof(struct mrvl_meshie_val) -
852 IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
853 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
854 break;
855 case CMD_ACT_MESH_CONFIG_STOP:
856 break;
857 default:
858 return -1;
859 }
860 lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
861 action, priv->mesh_tlv, chan,
862 print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
863
864 return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
865}
866
867static void lbs_queue_cmd(struct lbs_private *priv, 699static void lbs_queue_cmd(struct lbs_private *priv,
868 struct cmd_ctrl_node *cmdnode) 700 struct cmd_ctrl_node *cmdnode)
869{ 701{
diff --git a/drivers/net/wireless/libertas/decl.h b/drivers/net/wireless/libertas/decl.h
index 678f7c9f7503..709ffcad22ad 100644
--- a/drivers/net/wireless/libertas/decl.h
+++ b/drivers/net/wireless/libertas/decl.h
@@ -27,11 +27,6 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb,
27int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *); 27int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *);
28 28
29 29
30/* persistcfg.c */
31void lbs_persist_config_init(struct net_device *net);
32void lbs_persist_config_remove(struct net_device *net);
33
34
35/* main.c */ 30/* main.c */
36struct lbs_private *lbs_add_card(void *card, struct device *dmdev); 31struct lbs_private *lbs_add_card(void *card, struct device *dmdev);
37void lbs_remove_card(struct lbs_private *priv); 32void lbs_remove_card(struct lbs_private *priv);
@@ -39,6 +34,9 @@ int lbs_start_card(struct lbs_private *priv);
39void lbs_stop_card(struct lbs_private *priv); 34void lbs_stop_card(struct lbs_private *priv);
40void lbs_host_to_card_done(struct lbs_private *priv); 35void lbs_host_to_card_done(struct lbs_private *priv);
41 36
37int lbs_set_mac_address(struct net_device *dev, void *addr);
38void lbs_set_multicast_list(struct net_device *dev);
39
42int lbs_suspend(struct lbs_private *priv); 40int lbs_suspend(struct lbs_private *priv);
43void lbs_resume(struct lbs_private *priv); 41void lbs_resume(struct lbs_private *priv);
44 42
diff --git a/drivers/net/wireless/libertas/dev.h b/drivers/net/wireless/libertas/dev.h
index 1a675111300d..6a8d2b291d8c 100644
--- a/drivers/net/wireless/libertas/dev.h
+++ b/drivers/net/wireless/libertas/dev.h
@@ -6,6 +6,7 @@
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"
9#include "scan.h" 10#include "scan.h"
10#include "assoc.h" 11#include "assoc.h"
11 12
@@ -21,17 +22,6 @@ struct sleep_params {
21 uint16_t sp_reserved; 22 uint16_t sp_reserved;
22}; 23};
23 24
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};
35 25
36/** Private structure for the MV device */ 26/** Private structure for the MV device */
37struct lbs_private { 27struct lbs_private {
diff --git a/drivers/net/wireless/libertas/ethtool.c b/drivers/net/wireless/libertas/ethtool.c
index 53d56ab83c03..63d020374c2b 100644
--- a/drivers/net/wireless/libertas/ethtool.c
+++ b/drivers/net/wireless/libertas/ethtool.c
@@ -8,17 +8,8 @@
8#include "dev.h" 8#include "dev.h"
9#include "wext.h" 9#include "wext.h"
10#include "cmd.h" 10#include "cmd.h"
11#include "mesh.h"
11 12
12static const char * mesh_stat_strings[]= {
13 "drop_duplicate_bcast",
14 "drop_ttl_zero",
15 "drop_no_fwd_route",
16 "drop_no_buffers",
17 "fwded_unicast_cnt",
18 "fwded_bcast_cnt",
19 "drop_blind_table",
20 "tx_failed_cnt"
21};
22 13
23static void lbs_ethtool_get_drvinfo(struct net_device *dev, 14static void lbs_ethtool_get_drvinfo(struct net_device *dev,
24 struct ethtool_drvinfo *info) 15 struct ethtool_drvinfo *info)
@@ -73,73 +64,6 @@ out:
73 return ret; 64 return ret;
74} 65}
75 66
76static void lbs_ethtool_get_stats(struct net_device *dev,
77 struct ethtool_stats *stats, uint64_t *data)
78{
79 struct lbs_private *priv = dev->ml_priv;
80 struct cmd_ds_mesh_access mesh_access;
81 int ret;
82
83 lbs_deb_enter(LBS_DEB_ETHTOOL);
84
85 /* Get Mesh Statistics */
86 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
87
88 if (ret) {
89 memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
90 return;
91 }
92
93 priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
94 priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
95 priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
96 priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
97 priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
98 priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
99 priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
100 priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
101
102 data[0] = priv->mstats.fwd_drop_rbt;
103 data[1] = priv->mstats.fwd_drop_ttl;
104 data[2] = priv->mstats.fwd_drop_noroute;
105 data[3] = priv->mstats.fwd_drop_nobuf;
106 data[4] = priv->mstats.fwd_unicast_cnt;
107 data[5] = priv->mstats.fwd_bcast_cnt;
108 data[6] = priv->mstats.drop_blind;
109 data[7] = priv->mstats.tx_failed_cnt;
110
111 lbs_deb_enter(LBS_DEB_ETHTOOL);
112}
113
114static int lbs_ethtool_get_sset_count(struct net_device *dev, int sset)
115{
116 struct lbs_private *priv = dev->ml_priv;
117
118 if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
119 return MESH_STATS_NUM;
120
121 return -EOPNOTSUPP;
122}
123
124static void lbs_ethtool_get_strings(struct net_device *dev,
125 uint32_t stringset, uint8_t *s)
126{
127 int i;
128
129 lbs_deb_enter(LBS_DEB_ETHTOOL);
130
131 switch (stringset) {
132 case ETH_SS_STATS:
133 for (i=0; i < MESH_STATS_NUM; i++) {
134 memcpy(s + i * ETH_GSTRING_LEN,
135 mesh_stat_strings[i],
136 ETH_GSTRING_LEN);
137 }
138 break;
139 }
140 lbs_deb_enter(LBS_DEB_ETHTOOL);
141}
142
143static void lbs_ethtool_get_wol(struct net_device *dev, 67static void lbs_ethtool_get_wol(struct net_device *dev,
144 struct ethtool_wolinfo *wol) 68 struct ethtool_wolinfo *wol)
145{ 69{
@@ -190,9 +114,9 @@ const struct ethtool_ops lbs_ethtool_ops = {
190 .get_drvinfo = lbs_ethtool_get_drvinfo, 114 .get_drvinfo = lbs_ethtool_get_drvinfo,
191 .get_eeprom = lbs_ethtool_get_eeprom, 115 .get_eeprom = lbs_ethtool_get_eeprom,
192 .get_eeprom_len = lbs_ethtool_get_eeprom_len, 116 .get_eeprom_len = lbs_ethtool_get_eeprom_len,
193 .get_sset_count = lbs_ethtool_get_sset_count, 117 .get_sset_count = lbs_mesh_ethtool_get_sset_count,
194 .get_ethtool_stats = lbs_ethtool_get_stats, 118 .get_ethtool_stats = lbs_mesh_ethtool_get_stats,
195 .get_strings = lbs_ethtool_get_strings, 119 .get_strings = lbs_mesh_ethtool_get_strings,
196 .get_wol = lbs_ethtool_get_wol, 120 .get_wol = lbs_ethtool_get_wol,
197 .set_wol = lbs_ethtool_set_wol, 121 .set_wol = lbs_ethtool_set_wol,
198}; 122};
diff --git a/drivers/net/wireless/libertas/main.c b/drivers/net/wireless/libertas/main.c
index 01f46cf288d7..db38a5a719fa 100644
--- a/drivers/net/wireless/libertas/main.c
+++ b/drivers/net/wireless/libertas/main.c
@@ -94,107 +94,9 @@ u8 lbs_data_rate_to_fw_index(u32 rate)
94 return 0; 94 return 0;
95} 95}
96 96
97/**
98 * Attributes exported through sysfs
99 */
100
101/**
102 * @brief Get function for sysfs attribute anycast_mask
103 */
104static ssize_t lbs_anycast_get(struct device *dev,
105 struct device_attribute *attr, char * buf)
106{
107 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
108 struct cmd_ds_mesh_access mesh_access;
109 int ret;
110
111 memset(&mesh_access, 0, sizeof(mesh_access));
112
113 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
114 if (ret)
115 return ret;
116
117 return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
118}
119
120/**
121 * @brief Set function for sysfs attribute anycast_mask
122 */
123static ssize_t lbs_anycast_set(struct device *dev,
124 struct device_attribute *attr, const char * buf, size_t count)
125{
126 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
127 struct cmd_ds_mesh_access mesh_access;
128 uint32_t datum;
129 int ret;
130
131 memset(&mesh_access, 0, sizeof(mesh_access));
132 sscanf(buf, "%x", &datum);
133 mesh_access.data[0] = cpu_to_le32(datum);
134
135 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
136 if (ret)
137 return ret;
138
139 return strlen(buf);
140}
141
142/**
143 * @brief Get function for sysfs attribute prb_rsp_limit
144 */
145static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
146 struct device_attribute *attr, char *buf)
147{
148 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
149 struct cmd_ds_mesh_access mesh_access;
150 int ret;
151 u32 retry_limit;
152
153 memset(&mesh_access, 0, sizeof(mesh_access));
154 mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
155
156 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
157 &mesh_access);
158 if (ret)
159 return ret;
160
161 retry_limit = le32_to_cpu(mesh_access.data[1]);
162 return snprintf(buf, 10, "%d\n", retry_limit);
163}
164
165/**
166 * @brief Set function for sysfs attribute prb_rsp_limit
167 */
168static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
169 struct device_attribute *attr, const char *buf, size_t count)
170{
171 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
172 struct cmd_ds_mesh_access mesh_access;
173 int ret;
174 unsigned long retry_limit;
175
176 memset(&mesh_access, 0, sizeof(mesh_access));
177 mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
178
179 if (!strict_strtoul(buf, 10, &retry_limit))
180 return -ENOTSUPP;
181 if (retry_limit > 15)
182 return -ENOTSUPP;
183
184 mesh_access.data[1] = cpu_to_le32(retry_limit);
185
186 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
187 &mesh_access);
188 if (ret)
189 return ret;
190
191 return strlen(buf);
192}
193 97
194static int lbs_add_rtap(struct lbs_private *priv); 98static int lbs_add_rtap(struct lbs_private *priv);
195static void lbs_remove_rtap(struct lbs_private *priv); 99static void lbs_remove_rtap(struct lbs_private *priv);
196static int lbs_add_mesh(struct lbs_private *priv);
197static void lbs_remove_mesh(struct lbs_private *priv);
198 100
199 101
200/** 102/**
@@ -260,74 +162,7 @@ static ssize_t lbs_rtap_set(struct device *dev,
260static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set ); 162static DEVICE_ATTR(lbs_rtap, 0644, lbs_rtap_get, lbs_rtap_set );
261 163
262/** 164/**
263 * Get function for sysfs attribute mesh 165 * @brief This function opens the ethX interface
264 */
265static ssize_t lbs_mesh_get(struct device *dev,
266 struct device_attribute *attr, char * buf)
267{
268 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
269 return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
270}
271
272/**
273 * Set function for sysfs attribute mesh
274 */
275static ssize_t lbs_mesh_set(struct device *dev,
276 struct device_attribute *attr, const char * buf, size_t count)
277{
278 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
279 int enable;
280 int ret, action = CMD_ACT_MESH_CONFIG_STOP;
281
282 sscanf(buf, "%x", &enable);
283 enable = !!enable;
284 if (enable == !!priv->mesh_dev)
285 return count;
286 if (enable)
287 action = CMD_ACT_MESH_CONFIG_START;
288 ret = lbs_mesh_config(priv, action, priv->channel);
289 if (ret)
290 return ret;
291
292 if (enable)
293 lbs_add_mesh(priv);
294 else
295 lbs_remove_mesh(priv);
296
297 return count;
298}
299
300/**
301 * lbs_mesh attribute to be exported per ethX interface
302 * through sysfs (/sys/class/net/ethX/lbs_mesh)
303 */
304static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
305
306/**
307 * anycast_mask attribute to be exported per mshX interface
308 * through sysfs (/sys/class/net/mshX/anycast_mask)
309 */
310static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
311
312/**
313 * prb_rsp_limit attribute to be exported per mshX interface
314 * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
315 */
316static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
317 lbs_prb_rsp_limit_set);
318
319static struct attribute *lbs_mesh_sysfs_entries[] = {
320 &dev_attr_anycast_mask.attr,
321 &dev_attr_prb_rsp_limit.attr,
322 NULL,
323};
324
325static struct attribute_group lbs_mesh_attr_group = {
326 .attrs = lbs_mesh_sysfs_entries,
327};
328
329/**
330 * @brief This function opens the ethX or mshX interface
331 * 166 *
332 * @param dev A pointer to net_device structure 167 * @param dev A pointer to net_device structure
333 * @return 0 or -EBUSY if monitor mode active 168 * @return 0 or -EBUSY if monitor mode active
@@ -346,18 +181,12 @@ static int lbs_dev_open(struct net_device *dev)
346 goto out; 181 goto out;
347 } 182 }
348 183
349 if (dev == priv->mesh_dev) { 184 priv->infra_open = 1;
350 priv->mesh_open = 1;
351 priv->mesh_connect_status = LBS_CONNECTED;
352 netif_carrier_on(dev);
353 } else {
354 priv->infra_open = 1;
355 185
356 if (priv->connect_status == LBS_CONNECTED) 186 if (priv->connect_status == LBS_CONNECTED)
357 netif_carrier_on(dev); 187 netif_carrier_on(dev);
358 else 188 else
359 netif_carrier_off(dev); 189 netif_carrier_off(dev);
360 }
361 190
362 if (!priv->tx_pending_len) 191 if (!priv->tx_pending_len)
363 netif_wake_queue(dev); 192 netif_wake_queue(dev);
@@ -369,33 +198,6 @@ static int lbs_dev_open(struct net_device *dev)
369} 198}
370 199
371/** 200/**
372 * @brief This function closes the mshX interface
373 *
374 * @param dev A pointer to net_device structure
375 * @return 0
376 */
377static int lbs_mesh_stop(struct net_device *dev)
378{
379 struct lbs_private *priv = dev->ml_priv;
380
381 lbs_deb_enter(LBS_DEB_MESH);
382 spin_lock_irq(&priv->driver_lock);
383
384 priv->mesh_open = 0;
385 priv->mesh_connect_status = LBS_DISCONNECTED;
386
387 netif_stop_queue(dev);
388 netif_carrier_off(dev);
389
390 spin_unlock_irq(&priv->driver_lock);
391
392 schedule_work(&priv->mcast_work);
393
394 lbs_deb_leave(LBS_DEB_MESH);
395 return 0;
396}
397
398/**
399 * @brief This function closes the ethX interface 201 * @brief This function closes the ethX interface
400 * 202 *
401 * @param dev A pointer to net_device structure 203 * @param dev A pointer to net_device structure
@@ -466,7 +268,7 @@ void lbs_host_to_card_done(struct lbs_private *priv)
466} 268}
467EXPORT_SYMBOL_GPL(lbs_host_to_card_done); 269EXPORT_SYMBOL_GPL(lbs_host_to_card_done);
468 270
469static int lbs_set_mac_address(struct net_device *dev, void *addr) 271int lbs_set_mac_address(struct net_device *dev, void *addr)
470{ 272{
471 int ret = 0; 273 int ret = 0;
472 struct lbs_private *priv = dev->ml_priv; 274 struct lbs_private *priv = dev->ml_priv;
@@ -600,7 +402,7 @@ static void lbs_set_mcast_worker(struct work_struct *work)
600 lbs_deb_leave(LBS_DEB_NET); 402 lbs_deb_leave(LBS_DEB_NET);
601} 403}
602 404
603static void lbs_set_multicast_list(struct net_device *dev) 405void lbs_set_multicast_list(struct net_device *dev)
604{ 406{
605 struct lbs_private *priv = dev->ml_priv; 407 struct lbs_private *priv = dev->ml_priv;
606 408
@@ -1177,7 +979,6 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1177 979
1178 980
1179 priv->card = card; 981 priv->card = card;
1180 priv->mesh_open = 0;
1181 priv->infra_open = 0; 982 priv->infra_open = 0;
1182 983
1183 984
@@ -1198,6 +999,7 @@ struct lbs_private *lbs_add_card(void *card, struct device *dmdev)
1198 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker); 999 INIT_WORK(&priv->mcast_work, lbs_set_mcast_worker);
1199 INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker); 1000 INIT_WORK(&priv->sync_channel, lbs_sync_channel_worker);
1200 1001
1002 priv->mesh_open = 0;
1201 sprintf(priv->mesh_ssid, "mesh"); 1003 sprintf(priv->mesh_ssid, "mesh");
1202 priv->mesh_ssid_len = 4; 1004 priv->mesh_ssid_len = 4;
1203 1005
@@ -1292,50 +1094,12 @@ int lbs_start_card(struct lbs_private *priv)
1292 1094
1293 lbs_update_channel(priv); 1095 lbs_update_channel(priv);
1294 1096
1295 /* Check mesh FW version and appropriately send the mesh start 1097 /*
1296 * command 1098 * While rtap isn't related to mesh, only mesh-enabled
1099 * firmware implements the rtap functionality via
1100 * CMD_802_11_MONITOR_MODE.
1297 */ 1101 */
1298 if (priv->mesh_fw_ver == MESH_FW_OLD) { 1102 if (lbs_init_mesh(priv)) {
1299 /* Enable mesh, if supported, and work out which TLV it uses.
1300 0x100 + 291 is an unofficial value used in 5.110.20.pXX
1301 0x100 + 37 is the official value used in 5.110.21.pXX
1302 but we check them in that order because 20.pXX doesn't
1303 give an error -- it just silently fails. */
1304
1305 /* 5.110.20.pXX firmware will fail the command if the channel
1306 doesn't match the existing channel. But only if the TLV
1307 is correct. If the channel is wrong, _BOTH_ versions will
1308 give an error to 0x100+291, and allow 0x100+37 to succeed.
1309 It's just that 5.110.20.pXX will not have done anything
1310 useful */
1311
1312 priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
1313 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1314 priv->channel)) {
1315 priv->mesh_tlv = TLV_TYPE_MESH_ID;
1316 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1317 priv->channel))
1318 priv->mesh_tlv = 0;
1319 }
1320 } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
1321 /* 10.0.0.pXX new firmwares should succeed with TLV
1322 * 0x100+37; Do not invoke command with old TLV.
1323 */
1324 priv->mesh_tlv = TLV_TYPE_MESH_ID;
1325 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
1326 priv->channel))
1327 priv->mesh_tlv = 0;
1328 }
1329 if (priv->mesh_tlv) {
1330 lbs_add_mesh(priv);
1331
1332 if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
1333 lbs_pr_err("cannot register lbs_mesh attribute\n");
1334
1335 /* While rtap isn't related to mesh, only mesh-enabled
1336 * firmware implements the rtap functionality via
1337 * CMD_802_11_MONITOR_MODE.
1338 */
1339 if (device_create_file(&dev->dev, &dev_attr_lbs_rtap)) 1103 if (device_create_file(&dev->dev, &dev_attr_lbs_rtap))
1340 lbs_pr_err("cannot register lbs_rtap attribute\n"); 1104 lbs_pr_err("cannot register lbs_rtap attribute\n");
1341 } 1105 }
@@ -1369,10 +1133,8 @@ void lbs_stop_card(struct lbs_private *priv)
1369 netif_carrier_off(dev); 1133 netif_carrier_off(dev);
1370 1134
1371 lbs_debugfs_remove_one(priv); 1135 lbs_debugfs_remove_one(priv);
1372 if (priv->mesh_tlv) { 1136 if (lbs_deinit_mesh(priv))
1373 device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
1374 device_remove_file(&dev->dev, &dev_attr_lbs_rtap); 1137 device_remove_file(&dev->dev, &dev_attr_lbs_rtap);
1375 }
1376 1138
1377 /* Delete the timeout of the currently processing command */ 1139 /* Delete the timeout of the currently processing command */
1378 del_timer_sync(&priv->command_timer); 1140 del_timer_sync(&priv->command_timer);
@@ -1405,95 +1167,6 @@ out:
1405EXPORT_SYMBOL_GPL(lbs_stop_card); 1167EXPORT_SYMBOL_GPL(lbs_stop_card);
1406 1168
1407 1169
1408static const struct net_device_ops mesh_netdev_ops = {
1409 .ndo_open = lbs_dev_open,
1410 .ndo_stop = lbs_mesh_stop,
1411 .ndo_start_xmit = lbs_hard_start_xmit,
1412 .ndo_set_mac_address = lbs_set_mac_address,
1413 .ndo_set_multicast_list = lbs_set_multicast_list,
1414};
1415
1416/**
1417 * @brief This function adds mshX interface
1418 *
1419 * @param priv A pointer to the struct lbs_private structure
1420 * @return 0 if successful, -X otherwise
1421 */
1422static int lbs_add_mesh(struct lbs_private *priv)
1423{
1424 struct net_device *mesh_dev = NULL;
1425 int ret = 0;
1426
1427 lbs_deb_enter(LBS_DEB_MESH);
1428
1429 /* Allocate a virtual mesh device */
1430 if (!(mesh_dev = alloc_netdev(0, "msh%d", ether_setup))) {
1431 lbs_deb_mesh("init mshX device failed\n");
1432 ret = -ENOMEM;
1433 goto done;
1434 }
1435 mesh_dev->ml_priv = priv;
1436 priv->mesh_dev = mesh_dev;
1437
1438 mesh_dev->netdev_ops = &mesh_netdev_ops;
1439 mesh_dev->ethtool_ops = &lbs_ethtool_ops;
1440 memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
1441 sizeof(priv->dev->dev_addr));
1442
1443 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
1444
1445#ifdef WIRELESS_EXT
1446 mesh_dev->wireless_handlers = (struct iw_handler_def *)&mesh_handler_def;
1447#endif
1448 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
1449 /* Register virtual mesh interface */
1450 ret = register_netdev(mesh_dev);
1451 if (ret) {
1452 lbs_pr_err("cannot register mshX virtual interface\n");
1453 goto err_free;
1454 }
1455
1456 ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
1457 if (ret)
1458 goto err_unregister;
1459
1460 lbs_persist_config_init(mesh_dev);
1461
1462 /* Everything successful */
1463 ret = 0;
1464 goto done;
1465
1466err_unregister:
1467 unregister_netdev(mesh_dev);
1468
1469err_free:
1470 free_netdev(mesh_dev);
1471
1472done:
1473 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
1474 return ret;
1475}
1476
1477static void lbs_remove_mesh(struct lbs_private *priv)
1478{
1479 struct net_device *mesh_dev;
1480
1481
1482 mesh_dev = priv->mesh_dev;
1483 if (!mesh_dev)
1484 return;
1485
1486 lbs_deb_enter(LBS_DEB_MESH);
1487 netif_stop_queue(mesh_dev);
1488 netif_carrier_off(mesh_dev);
1489 sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
1490 lbs_persist_config_remove(mesh_dev);
1491 unregister_netdev(mesh_dev);
1492 priv->mesh_dev = NULL;
1493 free_netdev(mesh_dev);
1494 lbs_deb_leave(LBS_DEB_MESH);
1495}
1496
1497void lbs_queue_event(struct lbs_private *priv, u32 event) 1170void lbs_queue_event(struct lbs_private *priv, u32 event)
1498{ 1171{
1499 unsigned long flags; 1172 unsigned long flags;
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
new file mode 100644
index 000000000000..2f91c9b808af
--- /dev/null
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -0,0 +1,1141 @@
1#include <linux/moduleparam.h>
2#include <linux/delay.h>
3#include <linux/etherdevice.h>
4#include <linux/netdevice.h>
5#include <linux/if_arp.h>
6#include <linux/kthread.h>
7#include <linux/kfifo.h>
8
9#include "mesh.h"
10#include "decl.h"
11#include "cmd.h"
12
13
14/***************************************************************************
15 * Mesh sysfs support
16 */
17
18/**
19 * Attributes exported through sysfs
20 */
21
22/**
23 * @brief Get function for sysfs attribute anycast_mask
24 */
25static ssize_t lbs_anycast_get(struct device *dev,
26 struct device_attribute *attr, char * buf)
27{
28 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
29 struct cmd_ds_mesh_access mesh_access;
30 int ret;
31
32 memset(&mesh_access, 0, sizeof(mesh_access));
33
34 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_ANYCAST, &mesh_access);
35 if (ret)
36 return ret;
37
38 return snprintf(buf, 12, "0x%X\n", le32_to_cpu(mesh_access.data[0]));
39}
40
41/**
42 * @brief Set function for sysfs attribute anycast_mask
43 */
44static ssize_t lbs_anycast_set(struct device *dev,
45 struct device_attribute *attr, const char * buf, size_t count)
46{
47 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
48 struct cmd_ds_mesh_access mesh_access;
49 uint32_t datum;
50 int ret;
51
52 memset(&mesh_access, 0, sizeof(mesh_access));
53 sscanf(buf, "%x", &datum);
54 mesh_access.data[0] = cpu_to_le32(datum);
55
56 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_ANYCAST, &mesh_access);
57 if (ret)
58 return ret;
59
60 return strlen(buf);
61}
62
63/**
64 * @brief Get function for sysfs attribute prb_rsp_limit
65 */
66static ssize_t lbs_prb_rsp_limit_get(struct device *dev,
67 struct device_attribute *attr, char *buf)
68{
69 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
70 struct cmd_ds_mesh_access mesh_access;
71 int ret;
72 u32 retry_limit;
73
74 memset(&mesh_access, 0, sizeof(mesh_access));
75 mesh_access.data[0] = cpu_to_le32(CMD_ACT_GET);
76
77 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
78 &mesh_access);
79 if (ret)
80 return ret;
81
82 retry_limit = le32_to_cpu(mesh_access.data[1]);
83 return snprintf(buf, 10, "%d\n", retry_limit);
84}
85
86/**
87 * @brief Set function for sysfs attribute prb_rsp_limit
88 */
89static ssize_t lbs_prb_rsp_limit_set(struct device *dev,
90 struct device_attribute *attr, const char *buf, size_t count)
91{
92 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
93 struct cmd_ds_mesh_access mesh_access;
94 int ret;
95 unsigned long retry_limit;
96
97 memset(&mesh_access, 0, sizeof(mesh_access));
98 mesh_access.data[0] = cpu_to_le32(CMD_ACT_SET);
99
100 if (!strict_strtoul(buf, 10, &retry_limit))
101 return -ENOTSUPP;
102 if (retry_limit > 15)
103 return -ENOTSUPP;
104
105 mesh_access.data[1] = cpu_to_le32(retry_limit);
106
107 ret = lbs_mesh_access(priv, CMD_ACT_MESH_SET_GET_PRB_RSP_LIMIT,
108 &mesh_access);
109 if (ret)
110 return ret;
111
112 return strlen(buf);
113}
114
115/**
116 * Get function for sysfs attribute mesh
117 */
118static ssize_t lbs_mesh_get(struct device *dev,
119 struct device_attribute *attr, char * buf)
120{
121 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
122 return snprintf(buf, 5, "0x%X\n", !!priv->mesh_dev);
123}
124
125/**
126 * Set function for sysfs attribute mesh
127 */
128static ssize_t lbs_mesh_set(struct device *dev,
129 struct device_attribute *attr, const char * buf, size_t count)
130{
131 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
132 int enable;
133 int ret, action = CMD_ACT_MESH_CONFIG_STOP;
134
135 sscanf(buf, "%x", &enable);
136 enable = !!enable;
137 if (enable == !!priv->mesh_dev)
138 return count;
139 if (enable)
140 action = CMD_ACT_MESH_CONFIG_START;
141 ret = lbs_mesh_config(priv, action, priv->channel);
142 if (ret)
143 return ret;
144
145 if (enable)
146 lbs_add_mesh(priv);
147 else
148 lbs_remove_mesh(priv);
149
150 return count;
151}
152
153/**
154 * lbs_mesh attribute to be exported per ethX interface
155 * through sysfs (/sys/class/net/ethX/lbs_mesh)
156 */
157static DEVICE_ATTR(lbs_mesh, 0644, lbs_mesh_get, lbs_mesh_set);
158
159/**
160 * anycast_mask attribute to be exported per mshX interface
161 * through sysfs (/sys/class/net/mshX/anycast_mask)
162 */
163static DEVICE_ATTR(anycast_mask, 0644, lbs_anycast_get, lbs_anycast_set);
164
165/**
166 * prb_rsp_limit attribute to be exported per mshX interface
167 * through sysfs (/sys/class/net/mshX/prb_rsp_limit)
168 */
169static DEVICE_ATTR(prb_rsp_limit, 0644, lbs_prb_rsp_limit_get,
170 lbs_prb_rsp_limit_set);
171
172static struct attribute *lbs_mesh_sysfs_entries[] = {
173 &dev_attr_anycast_mask.attr,
174 &dev_attr_prb_rsp_limit.attr,
175 NULL,
176};
177
178static struct attribute_group lbs_mesh_attr_group = {
179 .attrs = lbs_mesh_sysfs_entries,
180};
181
182
183
184/***************************************************************************
185 * Initializing and starting, stopping mesh
186 */
187
188/*
189 * Check mesh FW version and appropriately send the mesh start
190 * command
191 */
192int lbs_init_mesh(struct lbs_private *priv)
193{
194 struct net_device *dev = priv->dev;
195 int ret = 0;
196
197 lbs_deb_enter(LBS_DEB_MESH);
198
199 if (priv->mesh_fw_ver == MESH_FW_OLD) {
200 /* Enable mesh, if supported, and work out which TLV it uses.
201 0x100 + 291 is an unofficial value used in 5.110.20.pXX
202 0x100 + 37 is the official value used in 5.110.21.pXX
203 but we check them in that order because 20.pXX doesn't
204 give an error -- it just silently fails. */
205
206 /* 5.110.20.pXX firmware will fail the command if the channel
207 doesn't match the existing channel. But only if the TLV
208 is correct. If the channel is wrong, _BOTH_ versions will
209 give an error to 0x100+291, and allow 0x100+37 to succeed.
210 It's just that 5.110.20.pXX will not have done anything
211 useful */
212
213 priv->mesh_tlv = TLV_TYPE_OLD_MESH_ID;
214 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
215 priv->channel)) {
216 priv->mesh_tlv = TLV_TYPE_MESH_ID;
217 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
218 priv->channel))
219 priv->mesh_tlv = 0;
220 }
221 } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
222 /* 10.0.0.pXX new firmwares should succeed with TLV
223 * 0x100+37; Do not invoke command with old TLV.
224 */
225 priv->mesh_tlv = TLV_TYPE_MESH_ID;
226 if (lbs_mesh_config(priv, CMD_ACT_MESH_CONFIG_START,
227 priv->channel))
228 priv->mesh_tlv = 0;
229 }
230 if (priv->mesh_tlv) {
231 lbs_add_mesh(priv);
232
233 if (device_create_file(&dev->dev, &dev_attr_lbs_mesh))
234 lbs_pr_err("cannot register lbs_mesh attribute\n");
235
236 ret = 1;
237 }
238
239 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
240 return ret;
241}
242
243
244int lbs_deinit_mesh(struct lbs_private *priv)
245{
246 struct net_device *dev = priv->dev;
247 int ret = 0;
248
249 lbs_deb_enter(LBS_DEB_MESH);
250
251 if (priv->mesh_tlv) {
252 device_remove_file(&dev->dev, &dev_attr_lbs_mesh);
253 ret = 1;
254 }
255
256 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
257 return ret;
258}
259
260
261/**
262 * @brief This function closes the mshX interface
263 *
264 * @param dev A pointer to net_device structure
265 * @return 0
266 */
267static int lbs_mesh_stop(struct net_device *dev)
268{
269 struct lbs_private *priv = dev->ml_priv;
270
271 lbs_deb_enter(LBS_DEB_MESH);
272 spin_lock_irq(&priv->driver_lock);
273
274 priv->mesh_open = 0;
275 priv->mesh_connect_status = LBS_DISCONNECTED;
276
277 netif_stop_queue(dev);
278 netif_carrier_off(dev);
279
280 spin_unlock_irq(&priv->driver_lock);
281
282 schedule_work(&priv->mcast_work);
283
284 lbs_deb_leave(LBS_DEB_MESH);
285 return 0;
286}
287
288/**
289 * @brief This function opens the mshX interface
290 *
291 * @param dev A pointer to net_device structure
292 * @return 0 or -EBUSY if monitor mode active
293 */
294static int lbs_mesh_dev_open(struct net_device *dev)
295{
296 struct lbs_private *priv = dev->ml_priv;
297 int ret = 0;
298
299 lbs_deb_enter(LBS_DEB_NET);
300
301 spin_lock_irq(&priv->driver_lock);
302
303 if (priv->monitormode) {
304 ret = -EBUSY;
305 goto out;
306 }
307
308 priv->mesh_open = 1;
309 priv->mesh_connect_status = LBS_CONNECTED;
310 netif_carrier_on(dev);
311
312 if (!priv->tx_pending_len)
313 netif_wake_queue(dev);
314 out:
315
316 spin_unlock_irq(&priv->driver_lock);
317 lbs_deb_leave_args(LBS_DEB_NET, "ret %d", ret);
318 return ret;
319}
320
321static const struct net_device_ops mesh_netdev_ops = {
322 .ndo_open = lbs_mesh_dev_open,
323 .ndo_stop = lbs_mesh_stop,
324 .ndo_start_xmit = lbs_hard_start_xmit,
325 .ndo_set_mac_address = lbs_set_mac_address,
326 .ndo_set_multicast_list = lbs_set_multicast_list,
327};
328
329/**
330 * @brief This function adds mshX interface
331 *
332 * @param priv A pointer to the struct lbs_private structure
333 * @return 0 if successful, -X otherwise
334 */
335int lbs_add_mesh(struct lbs_private *priv)
336{
337 struct net_device *mesh_dev = NULL;
338 int ret = 0;
339
340 lbs_deb_enter(LBS_DEB_MESH);
341
342 /* Allocate a virtual mesh device */
343 mesh_dev = alloc_netdev(0, "msh%d", ether_setup);
344 if (!mesh_dev) {
345 lbs_deb_mesh("init mshX device failed\n");
346 ret = -ENOMEM;
347 goto done;
348 }
349 mesh_dev->ml_priv = priv;
350 priv->mesh_dev = mesh_dev;
351
352 mesh_dev->netdev_ops = &mesh_netdev_ops;
353 mesh_dev->ethtool_ops = &lbs_ethtool_ops;
354 memcpy(mesh_dev->dev_addr, priv->dev->dev_addr,
355 sizeof(priv->dev->dev_addr));
356
357 SET_NETDEV_DEV(priv->mesh_dev, priv->dev->dev.parent);
358
359#ifdef WIRELESS_EXT
360 mesh_dev->wireless_handlers = &mesh_handler_def;
361#endif
362 mesh_dev->flags |= IFF_BROADCAST | IFF_MULTICAST;
363 /* Register virtual mesh interface */
364 ret = register_netdev(mesh_dev);
365 if (ret) {
366 lbs_pr_err("cannot register mshX virtual interface\n");
367 goto err_free;
368 }
369
370 ret = sysfs_create_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
371 if (ret)
372 goto err_unregister;
373
374 lbs_persist_config_init(mesh_dev);
375
376 /* Everything successful */
377 ret = 0;
378 goto done;
379
380err_unregister:
381 unregister_netdev(mesh_dev);
382
383err_free:
384 free_netdev(mesh_dev);
385
386done:
387 lbs_deb_leave_args(LBS_DEB_MESH, "ret %d", ret);
388 return ret;
389}
390
391void lbs_remove_mesh(struct lbs_private *priv)
392{
393 struct net_device *mesh_dev;
394
395 mesh_dev = priv->mesh_dev;
396 if (!mesh_dev)
397 return;
398
399 lbs_deb_enter(LBS_DEB_MESH);
400 netif_stop_queue(mesh_dev);
401 netif_carrier_off(mesh_dev);
402 sysfs_remove_group(&(mesh_dev->dev.kobj), &lbs_mesh_attr_group);
403 lbs_persist_config_remove(mesh_dev);
404 unregister_netdev(mesh_dev);
405 priv->mesh_dev = NULL;
406 free_netdev(mesh_dev);
407 lbs_deb_leave(LBS_DEB_MESH);
408}
409
410
411
412/***************************************************************************
413 * Sending and receiving
414 */
415struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
416 struct net_device *dev, struct rxpd *rxpd)
417{
418 if (priv->mesh_dev) {
419 if (priv->mesh_fw_ver == MESH_FW_OLD) {
420 if (rxpd->rx_control & RxPD_MESH_FRAME)
421 dev = priv->mesh_dev;
422 } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
423 if (rxpd->u.bss.bss_num == MESH_IFACE_ID)
424 dev = priv->mesh_dev;
425 }
426 }
427 return dev;
428}
429
430
431void lbs_mesh_set_txpd(struct lbs_private *priv,
432 struct net_device *dev, struct txpd *txpd)
433{
434 if (dev == priv->mesh_dev) {
435 if (priv->mesh_fw_ver == MESH_FW_OLD)
436 txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
437 else if (priv->mesh_fw_ver == MESH_FW_NEW)
438 txpd->u.bss.bss_num = MESH_IFACE_ID;
439 }
440}
441
442
443/***************************************************************************
444 * Mesh command handling
445 */
446
447int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
448 u16 cmd_action, void *pdata_buf)
449{
450 struct cmd_ds_bt_access *bt_access = &cmd->params.bt;
451 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
452
453 cmd->command = cpu_to_le16(CMD_BT_ACCESS);
454 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_bt_access) +
455 sizeof(struct cmd_header));
456 cmd->result = 0;
457 bt_access->action = cpu_to_le16(cmd_action);
458
459 switch (cmd_action) {
460 case CMD_ACT_BT_ACCESS_ADD:
461 memcpy(bt_access->addr1, pdata_buf, 2 * ETH_ALEN);
462 lbs_deb_hex(LBS_DEB_MESH, "BT_ADD: blinded MAC addr",
463 bt_access->addr1, 6);
464 break;
465 case CMD_ACT_BT_ACCESS_DEL:
466 memcpy(bt_access->addr1, pdata_buf, 1 * ETH_ALEN);
467 lbs_deb_hex(LBS_DEB_MESH, "BT_DEL: blinded MAC addr",
468 bt_access->addr1, 6);
469 break;
470 case CMD_ACT_BT_ACCESS_LIST:
471 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
472 break;
473 case CMD_ACT_BT_ACCESS_RESET:
474 break;
475 case CMD_ACT_BT_ACCESS_SET_INVERT:
476 bt_access->id = cpu_to_le32(*(u32 *) pdata_buf);
477 break;
478 case CMD_ACT_BT_ACCESS_GET_INVERT:
479 break;
480 default:
481 break;
482 }
483 lbs_deb_leave(LBS_DEB_CMD);
484 return 0;
485}
486
487int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
488 u16 cmd_action, void *pdata_buf)
489{
490 struct cmd_ds_fwt_access *fwt_access = &cmd->params.fwt;
491 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
492
493 cmd->command = cpu_to_le16(CMD_FWT_ACCESS);
494 cmd->size = cpu_to_le16(sizeof(struct cmd_ds_fwt_access) +
495 sizeof(struct cmd_header));
496 cmd->result = 0;
497
498 if (pdata_buf)
499 memcpy(fwt_access, pdata_buf, sizeof(*fwt_access));
500 else
501 memset(fwt_access, 0, sizeof(*fwt_access));
502
503 fwt_access->action = cpu_to_le16(cmd_action);
504
505 lbs_deb_leave(LBS_DEB_CMD);
506 return 0;
507}
508
509int lbs_mesh_access(struct lbs_private *priv, uint16_t cmd_action,
510 struct cmd_ds_mesh_access *cmd)
511{
512 int ret;
513
514 lbs_deb_enter_args(LBS_DEB_CMD, "action %d", cmd_action);
515
516 cmd->hdr.command = cpu_to_le16(CMD_MESH_ACCESS);
517 cmd->hdr.size = cpu_to_le16(sizeof(*cmd));
518 cmd->hdr.result = 0;
519
520 cmd->action = cpu_to_le16(cmd_action);
521
522 ret = lbs_cmd_with_response(priv, CMD_MESH_ACCESS, cmd);
523
524 lbs_deb_leave(LBS_DEB_CMD);
525 return ret;
526}
527
528static int __lbs_mesh_config_send(struct lbs_private *priv,
529 struct cmd_ds_mesh_config *cmd,
530 uint16_t action, uint16_t type)
531{
532 int ret;
533 u16 command = CMD_MESH_CONFIG_OLD;
534
535 lbs_deb_enter(LBS_DEB_CMD);
536
537 /*
538 * Command id is 0xac for v10 FW along with mesh interface
539 * id in bits 14-13-12.
540 */
541 if (priv->mesh_fw_ver == MESH_FW_NEW)
542 command = CMD_MESH_CONFIG |
543 (MESH_IFACE_ID << MESH_IFACE_BIT_OFFSET);
544
545 cmd->hdr.command = cpu_to_le16(command);
546 cmd->hdr.size = cpu_to_le16(sizeof(struct cmd_ds_mesh_config));
547 cmd->hdr.result = 0;
548
549 cmd->type = cpu_to_le16(type);
550 cmd->action = cpu_to_le16(action);
551
552 ret = lbs_cmd_with_response(priv, command, cmd);
553
554 lbs_deb_leave(LBS_DEB_CMD);
555 return ret;
556}
557
558int lbs_mesh_config_send(struct lbs_private *priv,
559 struct cmd_ds_mesh_config *cmd,
560 uint16_t action, uint16_t type)
561{
562 int ret;
563
564 if (!(priv->fwcapinfo & FW_CAPINFO_PERSISTENT_CONFIG))
565 return -EOPNOTSUPP;
566
567 ret = __lbs_mesh_config_send(priv, cmd, action, type);
568 return ret;
569}
570
571/* This function is the CMD_MESH_CONFIG legacy function. It only handles the
572 * START and STOP actions. The extended actions supported by CMD_MESH_CONFIG
573 * are all handled by preparing a struct cmd_ds_mesh_config and passing it to
574 * lbs_mesh_config_send.
575 */
576int lbs_mesh_config(struct lbs_private *priv, uint16_t action, uint16_t chan)
577{
578 struct cmd_ds_mesh_config cmd;
579 struct mrvl_meshie *ie;
580 DECLARE_SSID_BUF(ssid);
581
582 memset(&cmd, 0, sizeof(cmd));
583 cmd.channel = cpu_to_le16(chan);
584 ie = (struct mrvl_meshie *)cmd.data;
585
586 switch (action) {
587 case CMD_ACT_MESH_CONFIG_START:
588 ie->id = WLAN_EID_GENERIC;
589 ie->val.oui[0] = 0x00;
590 ie->val.oui[1] = 0x50;
591 ie->val.oui[2] = 0x43;
592 ie->val.type = MARVELL_MESH_IE_TYPE;
593 ie->val.subtype = MARVELL_MESH_IE_SUBTYPE;
594 ie->val.version = MARVELL_MESH_IE_VERSION;
595 ie->val.active_protocol_id = MARVELL_MESH_PROTO_ID_HWMP;
596 ie->val.active_metric_id = MARVELL_MESH_METRIC_ID;
597 ie->val.mesh_capability = MARVELL_MESH_CAPABILITY;
598 ie->val.mesh_id_len = priv->mesh_ssid_len;
599 memcpy(ie->val.mesh_id, priv->mesh_ssid, priv->mesh_ssid_len);
600 ie->len = sizeof(struct mrvl_meshie_val) -
601 IEEE80211_MAX_SSID_LEN + priv->mesh_ssid_len;
602 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie_val));
603 break;
604 case CMD_ACT_MESH_CONFIG_STOP:
605 break;
606 default:
607 return -1;
608 }
609 lbs_deb_cmd("mesh config action %d type %x channel %d SSID %s\n",
610 action, priv->mesh_tlv, chan,
611 print_ssid(ssid, priv->mesh_ssid, priv->mesh_ssid_len));
612
613 return __lbs_mesh_config_send(priv, &cmd, action, priv->mesh_tlv);
614}
615
616
617
618/***************************************************************************
619 * Persistent configuration support
620 */
621
622static int mesh_get_default_parameters(struct device *dev,
623 struct mrvl_mesh_defaults *defs)
624{
625 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
626 struct cmd_ds_mesh_config cmd;
627 int ret;
628
629 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
630 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
631 CMD_TYPE_MESH_GET_DEFAULTS);
632
633 if (ret)
634 return -EOPNOTSUPP;
635
636 memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
637
638 return 0;
639}
640
641/**
642 * @brief Get function for sysfs attribute bootflag
643 */
644static ssize_t bootflag_get(struct device *dev,
645 struct device_attribute *attr, char *buf)
646{
647 struct mrvl_mesh_defaults defs;
648 int ret;
649
650 ret = mesh_get_default_parameters(dev, &defs);
651
652 if (ret)
653 return ret;
654
655 return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
656}
657
658/**
659 * @brief Set function for sysfs attribute bootflag
660 */
661static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
662 const char *buf, size_t count)
663{
664 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
665 struct cmd_ds_mesh_config cmd;
666 uint32_t datum;
667 int ret;
668
669 memset(&cmd, 0, sizeof(cmd));
670 ret = sscanf(buf, "%d", &datum);
671 if ((ret != 1) || (datum > 1))
672 return -EINVAL;
673
674 *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
675 cmd.length = cpu_to_le16(sizeof(uint32_t));
676 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
677 CMD_TYPE_MESH_SET_BOOTFLAG);
678 if (ret)
679 return ret;
680
681 return strlen(buf);
682}
683
684/**
685 * @brief Get function for sysfs attribute boottime
686 */
687static ssize_t boottime_get(struct device *dev,
688 struct device_attribute *attr, char *buf)
689{
690 struct mrvl_mesh_defaults defs;
691 int ret;
692
693 ret = mesh_get_default_parameters(dev, &defs);
694
695 if (ret)
696 return ret;
697
698 return snprintf(buf, 12, "%d\n", defs.boottime);
699}
700
701/**
702 * @brief Set function for sysfs attribute boottime
703 */
704static ssize_t boottime_set(struct device *dev,
705 struct device_attribute *attr, const char *buf, size_t count)
706{
707 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
708 struct cmd_ds_mesh_config cmd;
709 uint32_t datum;
710 int ret;
711
712 memset(&cmd, 0, sizeof(cmd));
713 ret = sscanf(buf, "%d", &datum);
714 if ((ret != 1) || (datum > 255))
715 return -EINVAL;
716
717 /* A too small boot time will result in the device booting into
718 * standalone (no-host) mode before the host can take control of it,
719 * so the change will be hard to revert. This may be a desired
720 * feature (e.g to configure a very fast boot time for devices that
721 * will not be attached to a host), but dangerous. So I'm enforcing a
722 * lower limit of 20 seconds: remove and recompile the driver if this
723 * does not work for you.
724 */
725 datum = (datum < 20) ? 20 : datum;
726 cmd.data[0] = datum;
727 cmd.length = cpu_to_le16(sizeof(uint8_t));
728 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
729 CMD_TYPE_MESH_SET_BOOTTIME);
730 if (ret)
731 return ret;
732
733 return strlen(buf);
734}
735
736/**
737 * @brief Get function for sysfs attribute channel
738 */
739static ssize_t channel_get(struct device *dev,
740 struct device_attribute *attr, char *buf)
741{
742 struct mrvl_mesh_defaults defs;
743 int ret;
744
745 ret = mesh_get_default_parameters(dev, &defs);
746
747 if (ret)
748 return ret;
749
750 return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
751}
752
753/**
754 * @brief Set function for sysfs attribute channel
755 */
756static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
757 const char *buf, size_t count)
758{
759 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
760 struct cmd_ds_mesh_config cmd;
761 uint32_t datum;
762 int ret;
763
764 memset(&cmd, 0, sizeof(cmd));
765 ret = sscanf(buf, "%d", &datum);
766 if (ret != 1 || datum < 1 || datum > 11)
767 return -EINVAL;
768
769 *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum);
770 cmd.length = cpu_to_le16(sizeof(uint16_t));
771 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
772 CMD_TYPE_MESH_SET_DEF_CHANNEL);
773 if (ret)
774 return ret;
775
776 return strlen(buf);
777}
778
779/**
780 * @brief Get function for sysfs attribute mesh_id
781 */
782static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
783 char *buf)
784{
785 struct mrvl_mesh_defaults defs;
786 int maxlen;
787 int ret;
788
789 ret = mesh_get_default_parameters(dev, &defs);
790
791 if (ret)
792 return ret;
793
794 if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) {
795 lbs_pr_err("inconsistent mesh ID length");
796 defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
797 }
798
799 /* SSID not null terminated: reserve room for \0 + \n */
800 maxlen = defs.meshie.val.mesh_id_len + 2;
801 maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
802
803 defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
804
805 return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
806}
807
808/**
809 * @brief Set function for sysfs attribute mesh_id
810 */
811static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
812 const char *buf, size_t count)
813{
814 struct cmd_ds_mesh_config cmd;
815 struct mrvl_mesh_defaults defs;
816 struct mrvl_meshie *ie;
817 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
818 int len;
819 int ret;
820
821 if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1)
822 return -EINVAL;
823
824 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
825 ie = (struct mrvl_meshie *) &cmd.data[0];
826
827 /* fetch all other Information Element parameters */
828 ret = mesh_get_default_parameters(dev, &defs);
829
830 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
831
832 /* transfer IE elements */
833 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
834
835 len = count - 1;
836 memcpy(ie->val.mesh_id, buf, len);
837 /* SSID len */
838 ie->val.mesh_id_len = len;
839 /* IE len */
840 ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len;
841
842 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
843 CMD_TYPE_MESH_SET_MESH_IE);
844 if (ret)
845 return ret;
846
847 return strlen(buf);
848}
849
850/**
851 * @brief Get function for sysfs attribute protocol_id
852 */
853static ssize_t protocol_id_get(struct device *dev,
854 struct device_attribute *attr, char *buf)
855{
856 struct mrvl_mesh_defaults defs;
857 int ret;
858
859 ret = mesh_get_default_parameters(dev, &defs);
860
861 if (ret)
862 return ret;
863
864 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
865}
866
867/**
868 * @brief Set function for sysfs attribute protocol_id
869 */
870static ssize_t protocol_id_set(struct device *dev,
871 struct device_attribute *attr, const char *buf, size_t count)
872{
873 struct cmd_ds_mesh_config cmd;
874 struct mrvl_mesh_defaults defs;
875 struct mrvl_meshie *ie;
876 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
877 uint32_t datum;
878 int ret;
879
880 memset(&cmd, 0, sizeof(cmd));
881 ret = sscanf(buf, "%d", &datum);
882 if ((ret != 1) || (datum > 255))
883 return -EINVAL;
884
885 /* fetch all other Information Element parameters */
886 ret = mesh_get_default_parameters(dev, &defs);
887
888 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
889
890 /* transfer IE elements */
891 ie = (struct mrvl_meshie *) &cmd.data[0];
892 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
893 /* update protocol id */
894 ie->val.active_protocol_id = datum;
895
896 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
897 CMD_TYPE_MESH_SET_MESH_IE);
898 if (ret)
899 return ret;
900
901 return strlen(buf);
902}
903
904/**
905 * @brief Get function for sysfs attribute metric_id
906 */
907static ssize_t metric_id_get(struct device *dev,
908 struct device_attribute *attr, char *buf)
909{
910 struct mrvl_mesh_defaults defs;
911 int ret;
912
913 ret = mesh_get_default_parameters(dev, &defs);
914
915 if (ret)
916 return ret;
917
918 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
919}
920
921/**
922 * @brief Set function for sysfs attribute metric_id
923 */
924static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
925 const char *buf, size_t count)
926{
927 struct cmd_ds_mesh_config cmd;
928 struct mrvl_mesh_defaults defs;
929 struct mrvl_meshie *ie;
930 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
931 uint32_t datum;
932 int ret;
933
934 memset(&cmd, 0, sizeof(cmd));
935 ret = sscanf(buf, "%d", &datum);
936 if ((ret != 1) || (datum > 255))
937 return -EINVAL;
938
939 /* fetch all other Information Element parameters */
940 ret = mesh_get_default_parameters(dev, &defs);
941
942 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
943
944 /* transfer IE elements */
945 ie = (struct mrvl_meshie *) &cmd.data[0];
946 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
947 /* update metric id */
948 ie->val.active_metric_id = datum;
949
950 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
951 CMD_TYPE_MESH_SET_MESH_IE);
952 if (ret)
953 return ret;
954
955 return strlen(buf);
956}
957
958/**
959 * @brief Get function for sysfs attribute capability
960 */
961static ssize_t capability_get(struct device *dev,
962 struct device_attribute *attr, char *buf)
963{
964 struct mrvl_mesh_defaults defs;
965 int ret;
966
967 ret = mesh_get_default_parameters(dev, &defs);
968
969 if (ret)
970 return ret;
971
972 return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
973}
974
975/**
976 * @brief Set function for sysfs attribute capability
977 */
978static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
979 const char *buf, size_t count)
980{
981 struct cmd_ds_mesh_config cmd;
982 struct mrvl_mesh_defaults defs;
983 struct mrvl_meshie *ie;
984 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
985 uint32_t datum;
986 int ret;
987
988 memset(&cmd, 0, sizeof(cmd));
989 ret = sscanf(buf, "%d", &datum);
990 if ((ret != 1) || (datum > 255))
991 return -EINVAL;
992
993 /* fetch all other Information Element parameters */
994 ret = mesh_get_default_parameters(dev, &defs);
995
996 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
997
998 /* transfer IE elements */
999 ie = (struct mrvl_meshie *) &cmd.data[0];
1000 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
1001 /* update value */
1002 ie->val.mesh_capability = datum;
1003
1004 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
1005 CMD_TYPE_MESH_SET_MESH_IE);
1006 if (ret)
1007 return ret;
1008
1009 return strlen(buf);
1010}
1011
1012
1013static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
1014static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
1015static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
1016static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
1017static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
1018static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
1019static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
1020
1021static struct attribute *boot_opts_attrs[] = {
1022 &dev_attr_bootflag.attr,
1023 &dev_attr_boottime.attr,
1024 &dev_attr_channel.attr,
1025 NULL
1026};
1027
1028static struct attribute_group boot_opts_group = {
1029 .name = "boot_options",
1030 .attrs = boot_opts_attrs,
1031};
1032
1033static struct attribute *mesh_ie_attrs[] = {
1034 &dev_attr_mesh_id.attr,
1035 &dev_attr_protocol_id.attr,
1036 &dev_attr_metric_id.attr,
1037 &dev_attr_capability.attr,
1038 NULL
1039};
1040
1041static struct attribute_group mesh_ie_group = {
1042 .name = "mesh_ie",
1043 .attrs = mesh_ie_attrs,
1044};
1045
1046void lbs_persist_config_init(struct net_device *dev)
1047{
1048 int ret;
1049 ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
1050 ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
1051}
1052
1053void lbs_persist_config_remove(struct net_device *dev)
1054{
1055 sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
1056 sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
1057}
1058
1059
1060
1061/***************************************************************************
1062 * Ethtool related
1063 */
1064
1065static const char *mesh_stat_strings[] = {
1066 "drop_duplicate_bcast",
1067 "drop_ttl_zero",
1068 "drop_no_fwd_route",
1069 "drop_no_buffers",
1070 "fwded_unicast_cnt",
1071 "fwded_bcast_cnt",
1072 "drop_blind_table",
1073 "tx_failed_cnt"
1074};
1075
1076void lbs_mesh_ethtool_get_stats(struct net_device *dev,
1077 struct ethtool_stats *stats, uint64_t *data)
1078{
1079 struct lbs_private *priv = dev->ml_priv;
1080 struct cmd_ds_mesh_access mesh_access;
1081 int ret;
1082
1083 lbs_deb_enter(LBS_DEB_ETHTOOL);
1084
1085 /* Get Mesh Statistics */
1086 ret = lbs_mesh_access(priv, CMD_ACT_MESH_GET_STATS, &mesh_access);
1087
1088 if (ret) {
1089 memset(data, 0, MESH_STATS_NUM*(sizeof(uint64_t)));
1090 return;
1091 }
1092
1093 priv->mstats.fwd_drop_rbt = le32_to_cpu(mesh_access.data[0]);
1094 priv->mstats.fwd_drop_ttl = le32_to_cpu(mesh_access.data[1]);
1095 priv->mstats.fwd_drop_noroute = le32_to_cpu(mesh_access.data[2]);
1096 priv->mstats.fwd_drop_nobuf = le32_to_cpu(mesh_access.data[3]);
1097 priv->mstats.fwd_unicast_cnt = le32_to_cpu(mesh_access.data[4]);
1098 priv->mstats.fwd_bcast_cnt = le32_to_cpu(mesh_access.data[5]);
1099 priv->mstats.drop_blind = le32_to_cpu(mesh_access.data[6]);
1100 priv->mstats.tx_failed_cnt = le32_to_cpu(mesh_access.data[7]);
1101
1102 data[0] = priv->mstats.fwd_drop_rbt;
1103 data[1] = priv->mstats.fwd_drop_ttl;
1104 data[2] = priv->mstats.fwd_drop_noroute;
1105 data[3] = priv->mstats.fwd_drop_nobuf;
1106 data[4] = priv->mstats.fwd_unicast_cnt;
1107 data[5] = priv->mstats.fwd_bcast_cnt;
1108 data[6] = priv->mstats.drop_blind;
1109 data[7] = priv->mstats.tx_failed_cnt;
1110
1111 lbs_deb_enter(LBS_DEB_ETHTOOL);
1112}
1113
1114int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset)
1115{
1116 struct lbs_private *priv = dev->ml_priv;
1117
1118 if (sset == ETH_SS_STATS && dev == priv->mesh_dev)
1119 return MESH_STATS_NUM;
1120
1121 return -EOPNOTSUPP;
1122}
1123
1124void lbs_mesh_ethtool_get_strings(struct net_device *dev,
1125 uint32_t stringset, uint8_t *s)
1126{
1127 int i;
1128
1129 lbs_deb_enter(LBS_DEB_ETHTOOL);
1130
1131 switch (stringset) {
1132 case ETH_SS_STATS:
1133 for (i = 0; i < MESH_STATS_NUM; i++) {
1134 memcpy(s + i * ETH_GSTRING_LEN,
1135 mesh_stat_strings[i],
1136 ETH_GSTRING_LEN);
1137 }
1138 break;
1139 }
1140 lbs_deb_enter(LBS_DEB_ETHTOOL);
1141}
diff --git a/drivers/net/wireless/libertas/mesh.h b/drivers/net/wireless/libertas/mesh.h
new file mode 100644
index 000000000000..fea9b5d005fc
--- /dev/null
+++ b/drivers/net/wireless/libertas/mesh.h
@@ -0,0 +1,78 @@
1/**
2 * Contains all definitions needed for the Libertas' MESH implementation.
3 */
4#ifndef _LBS_MESH_H_
5#define _LBS_MESH_H_
6
7
8#include <net/iw_handler.h>
9#include <net/lib80211.h>
10
11
12/* Mesh statistics */
13struct lbs_mesh_stats {
14 u32 fwd_bcast_cnt; /* Fwd: Broadcast counter */
15 u32 fwd_unicast_cnt; /* Fwd: Unicast counter */
16 u32 fwd_drop_ttl; /* Fwd: TTL zero */
17 u32 fwd_drop_rbt; /* Fwd: Recently Broadcasted */
18 u32 fwd_drop_noroute; /* Fwd: No route to Destination */
19 u32 fwd_drop_nobuf; /* Fwd: Run out of internal buffers */
20 u32 drop_blind; /* Rx: Dropped by blinding table */
21 u32 tx_failed_cnt; /* Tx: Failed transmissions */
22};
23
24
25struct net_device;
26struct lbs_private;
27
28int lbs_init_mesh(struct lbs_private *priv);
29int lbs_deinit_mesh(struct lbs_private *priv);
30
31int lbs_add_mesh(struct lbs_private *priv);
32void lbs_remove_mesh(struct lbs_private *priv);
33
34
35/* Sending / Receiving */
36
37struct rxpd;
38struct txpd;
39
40struct net_device *lbs_mesh_set_dev(struct lbs_private *priv,
41 struct net_device *dev, struct rxpd *rxpd);
42void lbs_mesh_set_txpd(struct lbs_private *priv,
43 struct net_device *dev, struct txpd *txpd);
44
45
46/* Command handling */
47
48struct cmd_ds_command;
49
50int lbs_cmd_bt_access(struct cmd_ds_command *cmd,
51 u16 cmd_action, void *pdata_buf);
52int lbs_cmd_fwt_access(struct cmd_ds_command *cmd,
53 u16 cmd_action, void *pdata_buf);
54
55
56/* Persistent configuration */
57
58void lbs_persist_config_init(struct net_device *net);
59void lbs_persist_config_remove(struct net_device *net);
60
61
62/* WEXT handler */
63
64extern struct iw_handler_def mesh_handler_def;
65
66
67/* Ethtool statistics */
68
69struct ethtool_stats;
70
71void lbs_mesh_ethtool_get_stats(struct net_device *dev,
72 struct ethtool_stats *stats, uint64_t *data);
73int lbs_mesh_ethtool_get_sset_count(struct net_device *dev, int sset);
74void lbs_mesh_ethtool_get_strings(struct net_device *dev,
75 uint32_t stringset, uint8_t *s);
76
77
78#endif
diff --git a/drivers/net/wireless/libertas/persistcfg.c b/drivers/net/wireless/libertas/persistcfg.c
deleted file mode 100644
index 871f914a75fc..000000000000
--- a/drivers/net/wireless/libertas/persistcfg.c
+++ /dev/null
@@ -1,453 +0,0 @@
1#include <linux/moduleparam.h>
2#include <linux/delay.h>
3#include <linux/etherdevice.h>
4#include <linux/netdevice.h>
5#include <linux/if_arp.h>
6#include <linux/kthread.h>
7#include <linux/kfifo.h>
8
9#include "host.h"
10#include "decl.h"
11#include "dev.h"
12#include "wext.h"
13#include "debugfs.h"
14#include "scan.h"
15#include "assoc.h"
16#include "cmd.h"
17
18static int mesh_get_default_parameters(struct device *dev,
19 struct mrvl_mesh_defaults *defs)
20{
21 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
22 struct cmd_ds_mesh_config cmd;
23 int ret;
24
25 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
26 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_GET,
27 CMD_TYPE_MESH_GET_DEFAULTS);
28
29 if (ret)
30 return -EOPNOTSUPP;
31
32 memcpy(defs, &cmd.data[0], sizeof(struct mrvl_mesh_defaults));
33
34 return 0;
35}
36
37/**
38 * @brief Get function for sysfs attribute bootflag
39 */
40static ssize_t bootflag_get(struct device *dev,
41 struct device_attribute *attr, char *buf)
42{
43 struct mrvl_mesh_defaults defs;
44 int ret;
45
46 ret = mesh_get_default_parameters(dev, &defs);
47
48 if (ret)
49 return ret;
50
51 return snprintf(buf, 12, "%d\n", le32_to_cpu(defs.bootflag));
52}
53
54/**
55 * @brief Set function for sysfs attribute bootflag
56 */
57static ssize_t bootflag_set(struct device *dev, struct device_attribute *attr,
58 const char *buf, size_t count)
59{
60 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
61 struct cmd_ds_mesh_config cmd;
62 uint32_t datum;
63 int ret;
64
65 memset(&cmd, 0, sizeof(cmd));
66 ret = sscanf(buf, "%d", &datum);
67 if ((ret != 1) || (datum > 1))
68 return -EINVAL;
69
70 *((__le32 *)&cmd.data[0]) = cpu_to_le32(!!datum);
71 cmd.length = cpu_to_le16(sizeof(uint32_t));
72 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
73 CMD_TYPE_MESH_SET_BOOTFLAG);
74 if (ret)
75 return ret;
76
77 return strlen(buf);
78}
79
80/**
81 * @brief Get function for sysfs attribute boottime
82 */
83static ssize_t boottime_get(struct device *dev,
84 struct device_attribute *attr, char *buf)
85{
86 struct mrvl_mesh_defaults defs;
87 int ret;
88
89 ret = mesh_get_default_parameters(dev, &defs);
90
91 if (ret)
92 return ret;
93
94 return snprintf(buf, 12, "%d\n", defs.boottime);
95}
96
97/**
98 * @brief Set function for sysfs attribute boottime
99 */
100static ssize_t boottime_set(struct device *dev,
101 struct device_attribute *attr, const char *buf, size_t count)
102{
103 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
104 struct cmd_ds_mesh_config cmd;
105 uint32_t datum;
106 int ret;
107
108 memset(&cmd, 0, sizeof(cmd));
109 ret = sscanf(buf, "%d", &datum);
110 if ((ret != 1) || (datum > 255))
111 return -EINVAL;
112
113 /* A too small boot time will result in the device booting into
114 * standalone (no-host) mode before the host can take control of it,
115 * so the change will be hard to revert. This may be a desired
116 * feature (e.g to configure a very fast boot time for devices that
117 * will not be attached to a host), but dangerous. So I'm enforcing a
118 * lower limit of 20 seconds: remove and recompile the driver if this
119 * does not work for you.
120 */
121 datum = (datum < 20) ? 20 : datum;
122 cmd.data[0] = datum;
123 cmd.length = cpu_to_le16(sizeof(uint8_t));
124 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
125 CMD_TYPE_MESH_SET_BOOTTIME);
126 if (ret)
127 return ret;
128
129 return strlen(buf);
130}
131
132/**
133 * @brief Get function for sysfs attribute channel
134 */
135static ssize_t channel_get(struct device *dev,
136 struct device_attribute *attr, char *buf)
137{
138 struct mrvl_mesh_defaults defs;
139 int ret;
140
141 ret = mesh_get_default_parameters(dev, &defs);
142
143 if (ret)
144 return ret;
145
146 return snprintf(buf, 12, "%d\n", le16_to_cpu(defs.channel));
147}
148
149/**
150 * @brief Set function for sysfs attribute channel
151 */
152static ssize_t channel_set(struct device *dev, struct device_attribute *attr,
153 const char *buf, size_t count)
154{
155 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
156 struct cmd_ds_mesh_config cmd;
157 uint32_t datum;
158 int ret;
159
160 memset(&cmd, 0, sizeof(cmd));
161 ret = sscanf(buf, "%d", &datum);
162 if (ret != 1 || datum < 1 || datum > 11)
163 return -EINVAL;
164
165 *((__le16 *)&cmd.data[0]) = cpu_to_le16(datum);
166 cmd.length = cpu_to_le16(sizeof(uint16_t));
167 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
168 CMD_TYPE_MESH_SET_DEF_CHANNEL);
169 if (ret)
170 return ret;
171
172 return strlen(buf);
173}
174
175/**
176 * @brief Get function for sysfs attribute mesh_id
177 */
178static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
179 char *buf)
180{
181 struct mrvl_mesh_defaults defs;
182 int maxlen;
183 int ret;
184
185 ret = mesh_get_default_parameters(dev, &defs);
186
187 if (ret)
188 return ret;
189
190 if (defs.meshie.val.mesh_id_len > IEEE80211_MAX_SSID_LEN) {
191 lbs_pr_err("inconsistent mesh ID length");
192 defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
193 }
194
195 /* SSID not null terminated: reserve room for \0 + \n */
196 maxlen = defs.meshie.val.mesh_id_len + 2;
197 maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE;
198
199 defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0';
200
201 return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
202}
203
204/**
205 * @brief Set function for sysfs attribute mesh_id
206 */
207static ssize_t mesh_id_set(struct device *dev, struct device_attribute *attr,
208 const char *buf, size_t count)
209{
210 struct cmd_ds_mesh_config cmd;
211 struct mrvl_mesh_defaults defs;
212 struct mrvl_meshie *ie;
213 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
214 int len;
215 int ret;
216
217 if (count < 2 || count > IEEE80211_MAX_SSID_LEN + 1)
218 return -EINVAL;
219
220 memset(&cmd, 0, sizeof(struct cmd_ds_mesh_config));
221 ie = (struct mrvl_meshie *) &cmd.data[0];
222
223 /* fetch all other Information Element parameters */
224 ret = mesh_get_default_parameters(dev, &defs);
225
226 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
227
228 /* transfer IE elements */
229 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
230
231 len = count - 1;
232 memcpy(ie->val.mesh_id, buf, len);
233 /* SSID len */
234 ie->val.mesh_id_len = len;
235 /* IE len */
236 ie->len = sizeof(struct mrvl_meshie_val) - IEEE80211_MAX_SSID_LEN + len;
237
238 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
239 CMD_TYPE_MESH_SET_MESH_IE);
240 if (ret)
241 return ret;
242
243 return strlen(buf);
244}
245
246/**
247 * @brief Get function for sysfs attribute protocol_id
248 */
249static ssize_t protocol_id_get(struct device *dev,
250 struct device_attribute *attr, char *buf)
251{
252 struct mrvl_mesh_defaults defs;
253 int ret;
254
255 ret = mesh_get_default_parameters(dev, &defs);
256
257 if (ret)
258 return ret;
259
260 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_protocol_id);
261}
262
263/**
264 * @brief Set function for sysfs attribute protocol_id
265 */
266static ssize_t protocol_id_set(struct device *dev,
267 struct device_attribute *attr, const char *buf, size_t count)
268{
269 struct cmd_ds_mesh_config cmd;
270 struct mrvl_mesh_defaults defs;
271 struct mrvl_meshie *ie;
272 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
273 uint32_t datum;
274 int ret;
275
276 memset(&cmd, 0, sizeof(cmd));
277 ret = sscanf(buf, "%d", &datum);
278 if ((ret != 1) || (datum > 255))
279 return -EINVAL;
280
281 /* fetch all other Information Element parameters */
282 ret = mesh_get_default_parameters(dev, &defs);
283
284 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
285
286 /* transfer IE elements */
287 ie = (struct mrvl_meshie *) &cmd.data[0];
288 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
289 /* update protocol id */
290 ie->val.active_protocol_id = datum;
291
292 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
293 CMD_TYPE_MESH_SET_MESH_IE);
294 if (ret)
295 return ret;
296
297 return strlen(buf);
298}
299
300/**
301 * @brief Get function for sysfs attribute metric_id
302 */
303static ssize_t metric_id_get(struct device *dev,
304 struct device_attribute *attr, char *buf)
305{
306 struct mrvl_mesh_defaults defs;
307 int ret;
308
309 ret = mesh_get_default_parameters(dev, &defs);
310
311 if (ret)
312 return ret;
313
314 return snprintf(buf, 5, "%d\n", defs.meshie.val.active_metric_id);
315}
316
317/**
318 * @brief Set function for sysfs attribute metric_id
319 */
320static ssize_t metric_id_set(struct device *dev, struct device_attribute *attr,
321 const char *buf, size_t count)
322{
323 struct cmd_ds_mesh_config cmd;
324 struct mrvl_mesh_defaults defs;
325 struct mrvl_meshie *ie;
326 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
327 uint32_t datum;
328 int ret;
329
330 memset(&cmd, 0, sizeof(cmd));
331 ret = sscanf(buf, "%d", &datum);
332 if ((ret != 1) || (datum > 255))
333 return -EINVAL;
334
335 /* fetch all other Information Element parameters */
336 ret = mesh_get_default_parameters(dev, &defs);
337
338 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
339
340 /* transfer IE elements */
341 ie = (struct mrvl_meshie *) &cmd.data[0];
342 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
343 /* update metric id */
344 ie->val.active_metric_id = datum;
345
346 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
347 CMD_TYPE_MESH_SET_MESH_IE);
348 if (ret)
349 return ret;
350
351 return strlen(buf);
352}
353
354/**
355 * @brief Get function for sysfs attribute capability
356 */
357static ssize_t capability_get(struct device *dev,
358 struct device_attribute *attr, char *buf)
359{
360 struct mrvl_mesh_defaults defs;
361 int ret;
362
363 ret = mesh_get_default_parameters(dev, &defs);
364
365 if (ret)
366 return ret;
367
368 return snprintf(buf, 5, "%d\n", defs.meshie.val.mesh_capability);
369}
370
371/**
372 * @brief Set function for sysfs attribute capability
373 */
374static ssize_t capability_set(struct device *dev, struct device_attribute *attr,
375 const char *buf, size_t count)
376{
377 struct cmd_ds_mesh_config cmd;
378 struct mrvl_mesh_defaults defs;
379 struct mrvl_meshie *ie;
380 struct lbs_private *priv = to_net_dev(dev)->ml_priv;
381 uint32_t datum;
382 int ret;
383
384 memset(&cmd, 0, sizeof(cmd));
385 ret = sscanf(buf, "%d", &datum);
386 if ((ret != 1) || (datum > 255))
387 return -EINVAL;
388
389 /* fetch all other Information Element parameters */
390 ret = mesh_get_default_parameters(dev, &defs);
391
392 cmd.length = cpu_to_le16(sizeof(struct mrvl_meshie));
393
394 /* transfer IE elements */
395 ie = (struct mrvl_meshie *) &cmd.data[0];
396 memcpy(ie, &defs.meshie, sizeof(struct mrvl_meshie));
397 /* update value */
398 ie->val.mesh_capability = datum;
399
400 ret = lbs_mesh_config_send(priv, &cmd, CMD_ACT_MESH_CONFIG_SET,
401 CMD_TYPE_MESH_SET_MESH_IE);
402 if (ret)
403 return ret;
404
405 return strlen(buf);
406}
407
408
409static DEVICE_ATTR(bootflag, 0644, bootflag_get, bootflag_set);
410static DEVICE_ATTR(boottime, 0644, boottime_get, boottime_set);
411static DEVICE_ATTR(channel, 0644, channel_get, channel_set);
412static DEVICE_ATTR(mesh_id, 0644, mesh_id_get, mesh_id_set);
413static DEVICE_ATTR(protocol_id, 0644, protocol_id_get, protocol_id_set);
414static DEVICE_ATTR(metric_id, 0644, metric_id_get, metric_id_set);
415static DEVICE_ATTR(capability, 0644, capability_get, capability_set);
416
417static struct attribute *boot_opts_attrs[] = {
418 &dev_attr_bootflag.attr,
419 &dev_attr_boottime.attr,
420 &dev_attr_channel.attr,
421 NULL
422};
423
424static struct attribute_group boot_opts_group = {
425 .name = "boot_options",
426 .attrs = boot_opts_attrs,
427};
428
429static struct attribute *mesh_ie_attrs[] = {
430 &dev_attr_mesh_id.attr,
431 &dev_attr_protocol_id.attr,
432 &dev_attr_metric_id.attr,
433 &dev_attr_capability.attr,
434 NULL
435};
436
437static struct attribute_group mesh_ie_group = {
438 .name = "mesh_ie",
439 .attrs = mesh_ie_attrs,
440};
441
442void lbs_persist_config_init(struct net_device *dev)
443{
444 int ret;
445 ret = sysfs_create_group(&(dev->dev.kobj), &boot_opts_group);
446 ret = sysfs_create_group(&(dev->dev.kobj), &mesh_ie_group);
447}
448
449void lbs_persist_config_remove(struct net_device *dev)
450{
451 sysfs_remove_group(&(dev->dev.kobj), &boot_opts_group);
452 sysfs_remove_group(&(dev->dev.kobj), &mesh_ie_group);
453}
diff --git a/drivers/net/wireless/libertas/rx.c b/drivers/net/wireless/libertas/rx.c
index 9f18a19cc49d..2daf8ffdb7e1 100644
--- a/drivers/net/wireless/libertas/rx.c
+++ b/drivers/net/wireless/libertas/rx.c
@@ -160,15 +160,8 @@ int lbs_process_rxed_packet(struct lbs_private *priv, struct sk_buff *skb)
160 p_rx_pd = (struct rxpd *) skb->data; 160 p_rx_pd = (struct rxpd *) skb->data;
161 p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd + 161 p_rx_pkt = (struct rxpackethdr *) ((u8 *)p_rx_pd +
162 le32_to_cpu(p_rx_pd->pkt_ptr)); 162 le32_to_cpu(p_rx_pd->pkt_ptr));
163 if (priv->mesh_dev) { 163
164 if (priv->mesh_fw_ver == MESH_FW_OLD) { 164 dev = lbs_mesh_set_dev(priv, dev, p_rx_pd);
165 if (p_rx_pd->rx_control & RxPD_MESH_FRAME)
166 dev = priv->mesh_dev;
167 } else if (priv->mesh_fw_ver == MESH_FW_NEW) {
168 if (p_rx_pd->u.bss.bss_num == MESH_IFACE_ID)
169 dev = priv->mesh_dev;
170 }
171 }
172 165
173 lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data, 166 lbs_deb_hex(LBS_DEB_RX, "RX Data: Before chop rxpd", skb->data,
174 min_t(unsigned int, skb->len, 100)); 167 min_t(unsigned int, skb->len, 100));
diff --git a/drivers/net/wireless/libertas/tx.c b/drivers/net/wireless/libertas/tx.c
index eb856adbf8ea..315d1ce286ca 100644
--- a/drivers/net/wireless/libertas/tx.c
+++ b/drivers/net/wireless/libertas/tx.c
@@ -131,12 +131,7 @@ netdev_tx_t lbs_hard_start_xmit(struct sk_buff *skb, struct net_device *dev)
131 txpd->tx_packet_length = cpu_to_le16(pkt_len); 131 txpd->tx_packet_length = cpu_to_le16(pkt_len);
132 txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd)); 132 txpd->tx_packet_location = cpu_to_le32(sizeof(struct txpd));
133 133
134 if (dev == priv->mesh_dev) { 134 lbs_mesh_set_txpd(priv, dev, txpd);
135 if (priv->mesh_fw_ver == MESH_FW_OLD)
136 txpd->tx_control |= cpu_to_le32(TxPD_MESH_FRAME);
137 else if (priv->mesh_fw_ver == MESH_FW_NEW)
138 txpd->u.bss.bss_num = MESH_IFACE_ID;
139 }
140 135
141 lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd)); 136 lbs_deb_hex(LBS_DEB_TX, "txpd", (u8 *) &txpd, sizeof(struct txpd));
142 137
diff --git a/drivers/net/wireless/libertas/wext.h b/drivers/net/wireless/libertas/wext.h
index 7863baf7d234..f3f19fe8c6c6 100644
--- a/drivers/net/wireless/libertas/wext.h
+++ b/drivers/net/wireless/libertas/wext.h
@@ -7,12 +7,11 @@
7void lbs_send_disconnect_notification(struct lbs_private *priv); 7void lbs_send_disconnect_notification(struct lbs_private *priv);
8void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event); 8void lbs_send_mic_failureevent(struct lbs_private *priv, u32 event);
9 9
10extern struct iw_handler_def lbs_handler_def;
11extern struct iw_handler_def mesh_handler_def;
12
13struct chan_freq_power *lbs_find_cfp_by_band_and_channel( 10struct chan_freq_power *lbs_find_cfp_by_band_and_channel(
14 struct lbs_private *priv, 11 struct lbs_private *priv,
15 u8 band, 12 u8 band,
16 u16 channel); 13 u16 channel);
17 14
15extern struct iw_handler_def lbs_handler_def;
16
18#endif 17#endif
diff --git a/drivers/net/wireless/ray_cs.c b/drivers/net/wireless/ray_cs.c
index 5ee9d2a19360..0366f5aeb914 100644
--- a/drivers/net/wireless/ray_cs.c
+++ b/drivers/net/wireless/ray_cs.c
@@ -2865,18 +2865,8 @@ static int build_auth_frame(ray_dev_t *local, UCHAR *dest, int auth_type)
2865 2865
2866/*===========================================================================*/ 2866/*===========================================================================*/
2867#ifdef CONFIG_PROC_FS 2867#ifdef CONFIG_PROC_FS
2868static void raycs_write(const char *name, write_proc_t *w, void *data) 2868static ssize_t ray_cs_essid_proc_write(struct file *file,
2869{ 2869 const char __user *buffer, size_t count, loff_t *pos)
2870 struct proc_dir_entry *entry =
2871 create_proc_entry(name, S_IFREG | S_IWUSR, NULL);
2872 if (entry) {
2873 entry->write_proc = w;
2874 entry->data = data;
2875 }
2876}
2877
2878static int write_essid(struct file *file, const char __user *buffer,
2879 unsigned long count, void *data)
2880{ 2870{
2881 static char proc_essid[33]; 2871 static char proc_essid[33];
2882 unsigned int len = count; 2872 unsigned int len = count;
@@ -2890,8 +2880,13 @@ static int write_essid(struct file *file, const char __user *buffer,
2890 return count; 2880 return count;
2891} 2881}
2892 2882
2893static int write_int(struct file *file, const char __user *buffer, 2883static const struct file_operations ray_cs_essid_proc_fops = {
2894 unsigned long count, void *data) 2884 .owner = THIS_MODULE,
2885 .write = ray_cs_essid_proc_write,
2886};
2887
2888static ssize_t int_proc_write(struct file *file, const char __user *buffer,
2889 size_t count, loff_t *pos)
2895{ 2890{
2896 static char proc_number[10]; 2891 static char proc_number[10];
2897 char *p; 2892 char *p;
@@ -2914,9 +2909,14 @@ static int write_int(struct file *file, const char __user *buffer,
2914 nr = nr * 10 + c; 2909 nr = nr * 10 + c;
2915 p++; 2910 p++;
2916 } while (--len); 2911 } while (--len);
2917 *(int *)data = nr; 2912 *(int *)PDE(file->f_path.dentry->d_inode)->data = nr;
2918 return count; 2913 return count;
2919} 2914}
2915
2916static const struct file_operations int_proc_fops = {
2917 .owner = THIS_MODULE,
2918 .write = int_proc_write,
2919};
2920#endif 2920#endif
2921 2921
2922static struct pcmcia_device_id ray_ids[] = { 2922static struct pcmcia_device_id ray_ids[] = {
@@ -2951,9 +2951,9 @@ static int __init init_ray_cs(void)
2951 proc_mkdir("driver/ray_cs", NULL); 2951 proc_mkdir("driver/ray_cs", NULL);
2952 2952
2953 proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops); 2953 proc_create("driver/ray_cs/ray_cs", 0, NULL, &ray_cs_proc_fops);
2954 raycs_write("driver/ray_cs/essid", write_essid, NULL); 2954 proc_create("driver/ray_cs/essid", S_IWUSR, NULL, &ray_cs_essid_proc_fops);
2955 raycs_write("driver/ray_cs/net_type", write_int, &net_type); 2955 proc_create_data("driver/ray_cs/net_type", S_IWUSR, NULL, &int_proc_fops, &net_type);
2956 raycs_write("driver/ray_cs/translate", write_int, &translate); 2956 proc_create_data("driver/ray_cs/translate", S_IWUSR, NULL, &int_proc_fops, &translate);
2957#endif 2957#endif
2958 if (translate != 0) 2958 if (translate != 0)
2959 translate = 1; 2959 translate = 1;
diff --git a/drivers/net/wireless/rt2x00/rt2400pci.c b/drivers/net/wireless/rt2x00/rt2400pci.c
index 6e68bc7efd4e..e7f46405a418 100644
--- a/drivers/net/wireless/rt2x00/rt2400pci.c
+++ b/drivers/net/wireless/rt2x00/rt2400pci.c
@@ -1432,7 +1432,6 @@ static int rt2400pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
1432 IEEE80211_HW_SIGNAL_DBM | 1432 IEEE80211_HW_SIGNAL_DBM |
1433 IEEE80211_HW_SUPPORTS_PS | 1433 IEEE80211_HW_SUPPORTS_PS |
1434 IEEE80211_HW_PS_NULLFUNC_STACK; 1434 IEEE80211_HW_PS_NULLFUNC_STACK;
1435 rt2x00dev->hw->extra_tx_headroom = 0;
1436 1435
1437 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 1436 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
1438 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 1437 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -1623,20 +1622,21 @@ static const struct data_queue_desc rt2400pci_queue_atim = {
1623}; 1622};
1624 1623
1625static const struct rt2x00_ops rt2400pci_ops = { 1624static const struct rt2x00_ops rt2400pci_ops = {
1626 .name = KBUILD_MODNAME, 1625 .name = KBUILD_MODNAME,
1627 .max_sta_intf = 1, 1626 .max_sta_intf = 1,
1628 .max_ap_intf = 1, 1627 .max_ap_intf = 1,
1629 .eeprom_size = EEPROM_SIZE, 1628 .eeprom_size = EEPROM_SIZE,
1630 .rf_size = RF_SIZE, 1629 .rf_size = RF_SIZE,
1631 .tx_queues = NUM_TX_QUEUES, 1630 .tx_queues = NUM_TX_QUEUES,
1632 .rx = &rt2400pci_queue_rx, 1631 .extra_tx_headroom = 0,
1633 .tx = &rt2400pci_queue_tx, 1632 .rx = &rt2400pci_queue_rx,
1634 .bcn = &rt2400pci_queue_bcn, 1633 .tx = &rt2400pci_queue_tx,
1635 .atim = &rt2400pci_queue_atim, 1634 .bcn = &rt2400pci_queue_bcn,
1636 .lib = &rt2400pci_rt2x00_ops, 1635 .atim = &rt2400pci_queue_atim,
1637 .hw = &rt2400pci_mac80211_ops, 1636 .lib = &rt2400pci_rt2x00_ops,
1637 .hw = &rt2400pci_mac80211_ops,
1638#ifdef CONFIG_RT2X00_LIB_DEBUGFS 1638#ifdef CONFIG_RT2X00_LIB_DEBUGFS
1639 .debugfs = &rt2400pci_rt2x00debug, 1639 .debugfs = &rt2400pci_rt2x00debug,
1640#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 1640#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
1641}; 1641};
1642 1642
diff --git a/drivers/net/wireless/rt2x00/rt2500pci.c b/drivers/net/wireless/rt2x00/rt2500pci.c
index 9a31e5e7b8df..408fcfc120f5 100644
--- a/drivers/net/wireless/rt2x00/rt2500pci.c
+++ b/drivers/net/wireless/rt2x00/rt2500pci.c
@@ -1733,8 +1733,6 @@ static int rt2500pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
1733 IEEE80211_HW_SUPPORTS_PS | 1733 IEEE80211_HW_SUPPORTS_PS |
1734 IEEE80211_HW_PS_NULLFUNC_STACK; 1734 IEEE80211_HW_PS_NULLFUNC_STACK;
1735 1735
1736 rt2x00dev->hw->extra_tx_headroom = 0;
1737
1738 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 1736 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
1739 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 1737 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
1740 rt2x00_eeprom_addr(rt2x00dev, 1738 rt2x00_eeprom_addr(rt2x00dev,
@@ -1922,20 +1920,21 @@ static const struct data_queue_desc rt2500pci_queue_atim = {
1922}; 1920};
1923 1921
1924static const struct rt2x00_ops rt2500pci_ops = { 1922static const struct rt2x00_ops rt2500pci_ops = {
1925 .name = KBUILD_MODNAME, 1923 .name = KBUILD_MODNAME,
1926 .max_sta_intf = 1, 1924 .max_sta_intf = 1,
1927 .max_ap_intf = 1, 1925 .max_ap_intf = 1,
1928 .eeprom_size = EEPROM_SIZE, 1926 .eeprom_size = EEPROM_SIZE,
1929 .rf_size = RF_SIZE, 1927 .rf_size = RF_SIZE,
1930 .tx_queues = NUM_TX_QUEUES, 1928 .tx_queues = NUM_TX_QUEUES,
1931 .rx = &rt2500pci_queue_rx, 1929 .extra_tx_headroom = 0,
1932 .tx = &rt2500pci_queue_tx, 1930 .rx = &rt2500pci_queue_rx,
1933 .bcn = &rt2500pci_queue_bcn, 1931 .tx = &rt2500pci_queue_tx,
1934 .atim = &rt2500pci_queue_atim, 1932 .bcn = &rt2500pci_queue_bcn,
1935 .lib = &rt2500pci_rt2x00_ops, 1933 .atim = &rt2500pci_queue_atim,
1936 .hw = &rt2500pci_mac80211_ops, 1934 .lib = &rt2500pci_rt2x00_ops,
1935 .hw = &rt2500pci_mac80211_ops,
1937#ifdef CONFIG_RT2X00_LIB_DEBUGFS 1936#ifdef CONFIG_RT2X00_LIB_DEBUGFS
1938 .debugfs = &rt2500pci_rt2x00debug, 1937 .debugfs = &rt2500pci_rt2x00debug,
1939#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 1938#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
1940}; 1939};
1941 1940
diff --git a/drivers/net/wireless/rt2x00/rt2500usb.c b/drivers/net/wireless/rt2x00/rt2500usb.c
index b2de43e4f656..83f2592c59de 100644
--- a/drivers/net/wireless/rt2x00/rt2500usb.c
+++ b/drivers/net/wireless/rt2x00/rt2500usb.c
@@ -1656,8 +1656,6 @@ static int rt2500usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
1656 IEEE80211_HW_SUPPORTS_PS | 1656 IEEE80211_HW_SUPPORTS_PS |
1657 IEEE80211_HW_PS_NULLFUNC_STACK; 1657 IEEE80211_HW_PS_NULLFUNC_STACK;
1658 1658
1659 rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
1660
1661 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 1659 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
1662 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 1660 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
1663 rt2x00_eeprom_addr(rt2x00dev, 1661 rt2x00_eeprom_addr(rt2x00dev,
@@ -1823,20 +1821,21 @@ static const struct data_queue_desc rt2500usb_queue_atim = {
1823}; 1821};
1824 1822
1825static const struct rt2x00_ops rt2500usb_ops = { 1823static const struct rt2x00_ops rt2500usb_ops = {
1826 .name = KBUILD_MODNAME, 1824 .name = KBUILD_MODNAME,
1827 .max_sta_intf = 1, 1825 .max_sta_intf = 1,
1828 .max_ap_intf = 1, 1826 .max_ap_intf = 1,
1829 .eeprom_size = EEPROM_SIZE, 1827 .eeprom_size = EEPROM_SIZE,
1830 .rf_size = RF_SIZE, 1828 .rf_size = RF_SIZE,
1831 .tx_queues = NUM_TX_QUEUES, 1829 .tx_queues = NUM_TX_QUEUES,
1832 .rx = &rt2500usb_queue_rx, 1830 .extra_tx_headroom = TXD_DESC_SIZE,
1833 .tx = &rt2500usb_queue_tx, 1831 .rx = &rt2500usb_queue_rx,
1834 .bcn = &rt2500usb_queue_bcn, 1832 .tx = &rt2500usb_queue_tx,
1835 .atim = &rt2500usb_queue_atim, 1833 .bcn = &rt2500usb_queue_bcn,
1836 .lib = &rt2500usb_rt2x00_ops, 1834 .atim = &rt2500usb_queue_atim,
1837 .hw = &rt2500usb_mac80211_ops, 1835 .lib = &rt2500usb_rt2x00_ops,
1836 .hw = &rt2500usb_mac80211_ops,
1838#ifdef CONFIG_RT2X00_LIB_DEBUGFS 1837#ifdef CONFIG_RT2X00_LIB_DEBUGFS
1839 .debugfs = &rt2500usb_rt2x00debug, 1838 .debugfs = &rt2500usb_rt2x00debug,
1840#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 1839#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
1841}; 1840};
1842 1841
diff --git a/drivers/net/wireless/rt2x00/rt2800lib.c b/drivers/net/wireless/rt2x00/rt2800lib.c
index e94f1e13fea9..eb1e1d00bec3 100644
--- a/drivers/net/wireless/rt2x00/rt2800lib.c
+++ b/drivers/net/wireless/rt2x00/rt2800lib.c
@@ -217,14 +217,12 @@ void rt2800_mcu_request(struct rt2x00_dev *rt2x00dev,
217{ 217{
218 u32 reg; 218 u32 reg;
219 219
220 if (rt2x00_intf_is_pci(rt2x00dev)) { 220 /*
221 /* 221 * RT2880 and RT3052 don't support MCU requests.
222 * RT2880 and RT3052 don't support MCU requests. 222 */
223 */ 223 if (rt2x00_rt(&rt2x00dev->chip, RT2880) ||
224 if (rt2x00_rt(&rt2x00dev->chip, RT2880) || 224 rt2x00_rt(&rt2x00dev->chip, RT3052))
225 rt2x00_rt(&rt2x00dev->chip, RT3052)) 225 return;
226 return;
227 }
228 226
229 mutex_lock(&rt2x00dev->csr_mutex); 227 mutex_lock(&rt2x00dev->csr_mutex);
230 228
@@ -1482,8 +1480,7 @@ int rt2800_init_bbp(struct rt2x00_dev *rt2x00dev)
1482 rt2800_bbp_write(rt2x00dev, 105, 0x05); 1480 rt2800_bbp_write(rt2x00dev, 105, 0x05);
1483 } 1481 }
1484 1482
1485 if (rt2x00_intf_is_pci(rt2x00dev) && 1483 if (rt2x00_rt(&rt2x00dev->chip, RT3052)) {
1486 rt2x00_rt(&rt2x00dev->chip, RT3052)) {
1487 rt2800_bbp_write(rt2x00dev, 31, 0x08); 1484 rt2800_bbp_write(rt2x00dev, 31, 0x08);
1488 rt2800_bbp_write(rt2x00dev, 78, 0x0e); 1485 rt2800_bbp_write(rt2x00dev, 78, 0x0e);
1489 rt2800_bbp_write(rt2x00dev, 80, 0x08); 1486 rt2800_bbp_write(rt2x00dev, 80, 0x08);
@@ -2033,12 +2030,6 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2033 IEEE80211_HW_SUPPORTS_PS | 2030 IEEE80211_HW_SUPPORTS_PS |
2034 IEEE80211_HW_PS_NULLFUNC_STACK; 2031 IEEE80211_HW_PS_NULLFUNC_STACK;
2035 2032
2036 if (rt2x00_intf_is_usb(rt2x00dev))
2037 rt2x00dev->hw->extra_tx_headroom =
2038 TXINFO_DESC_SIZE + TXWI_DESC_SIZE;
2039 else if (rt2x00_intf_is_pci(rt2x00dev))
2040 rt2x00dev->hw->extra_tx_headroom = TXWI_DESC_SIZE;
2041
2042 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 2033 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
2043 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 2034 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
2044 rt2x00_eeprom_addr(rt2x00dev, 2035 rt2x00_eeprom_addr(rt2x00dev,
@@ -2072,7 +2063,11 @@ int rt2800_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2072 /* 2063 /*
2073 * Initialize HT information. 2064 * Initialize HT information.
2074 */ 2065 */
2075 spec->ht.ht_supported = true; 2066 if (!rt2x00_rf(chip, RF2020))
2067 spec->ht.ht_supported = true;
2068 else
2069 spec->ht.ht_supported = false;
2070
2076 spec->ht.cap = 2071 spec->ht.cap =
2077 IEEE80211_HT_CAP_SUP_WIDTH_20_40 | 2072 IEEE80211_HT_CAP_SUP_WIDTH_20_40 |
2078 IEEE80211_HT_CAP_GRN_FLD | 2073 IEEE80211_HT_CAP_GRN_FLD |
diff --git a/drivers/net/wireless/rt2x00/rt2800pci.c b/drivers/net/wireless/rt2x00/rt2800pci.c
index 87a5094ae953..dfc886fcb44d 100644
--- a/drivers/net/wireless/rt2x00/rt2800pci.c
+++ b/drivers/net/wireless/rt2x00/rt2800pci.c
@@ -652,7 +652,7 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
652{ 652{
653 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb); 653 struct skb_frame_desc *skbdesc = get_skb_frame_desc(skb);
654 __le32 *txd = skbdesc->desc; 654 __le32 *txd = skbdesc->desc;
655 __le32 *txwi = (__le32 *)(skb->data - rt2x00dev->hw->extra_tx_headroom); 655 __le32 *txwi = (__le32 *)(skb->data - rt2x00dev->ops->extra_tx_headroom);
656 u32 word; 656 u32 word;
657 657
658 /* 658 /*
@@ -725,14 +725,14 @@ static void rt2800pci_write_tx_desc(struct rt2x00_dev *rt2x00dev,
725 rt2x00_set_field32(&word, TXD_W1_BURST, 725 rt2x00_set_field32(&word, TXD_W1_BURST,
726 test_bit(ENTRY_TXD_BURST, &txdesc->flags)); 726 test_bit(ENTRY_TXD_BURST, &txdesc->flags));
727 rt2x00_set_field32(&word, TXD_W1_SD_LEN0, 727 rt2x00_set_field32(&word, TXD_W1_SD_LEN0,
728 rt2x00dev->hw->extra_tx_headroom); 728 rt2x00dev->ops->extra_tx_headroom);
729 rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0); 729 rt2x00_set_field32(&word, TXD_W1_LAST_SEC0, 0);
730 rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0); 730 rt2x00_set_field32(&word, TXD_W1_DMA_DONE, 0);
731 rt2x00_desc_write(txd, 1, word); 731 rt2x00_desc_write(txd, 1, word);
732 732
733 rt2x00_desc_read(txd, 2, &word); 733 rt2x00_desc_read(txd, 2, &word);
734 rt2x00_set_field32(&word, TXD_W2_SD_PTR1, 734 rt2x00_set_field32(&word, TXD_W2_SD_PTR1,
735 skbdesc->skb_dma + rt2x00dev->hw->extra_tx_headroom); 735 skbdesc->skb_dma + rt2x00dev->ops->extra_tx_headroom);
736 rt2x00_desc_write(txd, 2, word); 736 rt2x00_desc_write(txd, 2, word);
737 737
738 rt2x00_desc_read(txd, 3, &word); 738 rt2x00_desc_read(txd, 3, &word);
@@ -1201,19 +1201,20 @@ static const struct data_queue_desc rt2800pci_queue_bcn = {
1201}; 1201};
1202 1202
1203static const struct rt2x00_ops rt2800pci_ops = { 1203static const struct rt2x00_ops rt2800pci_ops = {
1204 .name = KBUILD_MODNAME, 1204 .name = KBUILD_MODNAME,
1205 .max_sta_intf = 1, 1205 .max_sta_intf = 1,
1206 .max_ap_intf = 8, 1206 .max_ap_intf = 8,
1207 .eeprom_size = EEPROM_SIZE, 1207 .eeprom_size = EEPROM_SIZE,
1208 .rf_size = RF_SIZE, 1208 .rf_size = RF_SIZE,
1209 .tx_queues = NUM_TX_QUEUES, 1209 .tx_queues = NUM_TX_QUEUES,
1210 .rx = &rt2800pci_queue_rx, 1210 .extra_tx_headroom = TXWI_DESC_SIZE,
1211 .tx = &rt2800pci_queue_tx, 1211 .rx = &rt2800pci_queue_rx,
1212 .bcn = &rt2800pci_queue_bcn, 1212 .tx = &rt2800pci_queue_tx,
1213 .lib = &rt2800pci_rt2x00_ops, 1213 .bcn = &rt2800pci_queue_bcn,
1214 .hw = &rt2800_mac80211_ops, 1214 .lib = &rt2800pci_rt2x00_ops,
1215 .hw = &rt2800_mac80211_ops,
1215#ifdef CONFIG_RT2X00_LIB_DEBUGFS 1216#ifdef CONFIG_RT2X00_LIB_DEBUGFS
1216 .debugfs = &rt2800_rt2x00debug, 1217 .debugfs = &rt2800_rt2x00debug,
1217#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 1218#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
1218}; 1219};
1219 1220
diff --git a/drivers/net/wireless/rt2x00/rt2800usb.c b/drivers/net/wireless/rt2x00/rt2800usb.c
index 9ab15c480701..af85d18cdbe7 100644
--- a/drivers/net/wireless/rt2x00/rt2800usb.c
+++ b/drivers/net/wireless/rt2x00/rt2800usb.c
@@ -790,19 +790,20 @@ static const struct data_queue_desc rt2800usb_queue_bcn = {
790}; 790};
791 791
792static const struct rt2x00_ops rt2800usb_ops = { 792static const struct rt2x00_ops rt2800usb_ops = {
793 .name = KBUILD_MODNAME, 793 .name = KBUILD_MODNAME,
794 .max_sta_intf = 1, 794 .max_sta_intf = 1,
795 .max_ap_intf = 8, 795 .max_ap_intf = 8,
796 .eeprom_size = EEPROM_SIZE, 796 .eeprom_size = EEPROM_SIZE,
797 .rf_size = RF_SIZE, 797 .rf_size = RF_SIZE,
798 .tx_queues = NUM_TX_QUEUES, 798 .tx_queues = NUM_TX_QUEUES,
799 .rx = &rt2800usb_queue_rx, 799 .extra_tx_headroom = TXINFO_DESC_SIZE + TXWI_DESC_SIZE,
800 .tx = &rt2800usb_queue_tx, 800 .rx = &rt2800usb_queue_rx,
801 .bcn = &rt2800usb_queue_bcn, 801 .tx = &rt2800usb_queue_tx,
802 .lib = &rt2800usb_rt2x00_ops, 802 .bcn = &rt2800usb_queue_bcn,
803 .hw = &rt2800_mac80211_ops, 803 .lib = &rt2800usb_rt2x00_ops,
804 .hw = &rt2800_mac80211_ops,
804#ifdef CONFIG_RT2X00_LIB_DEBUGFS 805#ifdef CONFIG_RT2X00_LIB_DEBUGFS
805 .debugfs = &rt2800_rt2x00debug, 806 .debugfs = &rt2800_rt2x00debug,
806#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 807#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
807}; 808};
808 809
diff --git a/drivers/net/wireless/rt2x00/rt2x00.h b/drivers/net/wireless/rt2x00/rt2x00.h
index 1cbb7ac2f32f..4d841c07c970 100644
--- a/drivers/net/wireless/rt2x00/rt2x00.h
+++ b/drivers/net/wireless/rt2x00/rt2x00.h
@@ -588,6 +588,7 @@ struct rt2x00_ops {
588 const unsigned int eeprom_size; 588 const unsigned int eeprom_size;
589 const unsigned int rf_size; 589 const unsigned int rf_size;
590 const unsigned int tx_queues; 590 const unsigned int tx_queues;
591 const unsigned int extra_tx_headroom;
591 const struct data_queue_desc *rx; 592 const struct data_queue_desc *rx;
592 const struct data_queue_desc *tx; 593 const struct data_queue_desc *tx;
593 const struct data_queue_desc *bcn; 594 const struct data_queue_desc *bcn;
diff --git a/drivers/net/wireless/rt2x00/rt2x00dev.c b/drivers/net/wireless/rt2x00/rt2x00dev.c
index 4a4b7e42fe6e..06c43ca39bf8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00dev.c
+++ b/drivers/net/wireless/rt2x00/rt2x00dev.c
@@ -684,6 +684,11 @@ static int rt2x00lib_probe_hw(struct rt2x00_dev *rt2x00dev)
684 rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues; 684 rt2x00dev->hw->queues = rt2x00dev->ops->tx_queues;
685 685
686 /* 686 /*
687 * Initialize extra TX headroom required.
688 */
689 rt2x00dev->hw->extra_tx_headroom = rt2x00dev->ops->extra_tx_headroom;
690
691 /*
687 * Register HW. 692 * Register HW.
688 */ 693 */
689 status = ieee80211_register_hw(rt2x00dev->hw); 694 status = ieee80211_register_hw(rt2x00dev->hw);
diff --git a/drivers/net/wireless/rt2x00/rt2x00mac.c b/drivers/net/wireless/rt2x00/rt2x00mac.c
index 9c90ceb0ffcc..de549c244ed8 100644
--- a/drivers/net/wireless/rt2x00/rt2x00mac.c
+++ b/drivers/net/wireless/rt2x00/rt2x00mac.c
@@ -103,10 +103,8 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
103{ 103{
104 struct rt2x00_dev *rt2x00dev = hw->priv; 104 struct rt2x00_dev *rt2x00dev = hw->priv;
105 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); 105 struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
106 struct ieee80211_hdr *ieee80211hdr = (struct ieee80211_hdr *)skb->data;
107 enum data_queue_qid qid = skb_get_queue_mapping(skb); 106 enum data_queue_qid qid = skb_get_queue_mapping(skb);
108 struct data_queue *queue; 107 struct data_queue *queue;
109 u16 frame_control;
110 108
111 /* 109 /*
112 * Mac80211 might be calling this function while we are trying 110 * Mac80211 might be calling this function while we are trying
@@ -141,7 +139,6 @@ int rt2x00mac_tx(struct ieee80211_hw *hw, struct sk_buff *skb)
141 * either RTS or CTS-to-self frame and handles everything 139 * either RTS or CTS-to-self frame and handles everything
142 * inside the hardware. 140 * inside the hardware.
143 */ 141 */
144 frame_control = le16_to_cpu(ieee80211hdr->frame_control);
145 if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS | 142 if ((tx_info->control.rates[0].flags & (IEEE80211_TX_RC_USE_RTS_CTS |
146 IEEE80211_TX_RC_USE_CTS_PROTECT)) && 143 IEEE80211_TX_RC_USE_CTS_PROTECT)) &&
147 !rt2x00dev->ops->hw->set_rts_threshold) { 144 !rt2x00dev->ops->hw->set_rts_threshold) {
diff --git a/drivers/net/wireless/rt2x00/rt2x00queue.c b/drivers/net/wireless/rt2x00/rt2x00queue.c
index eaedee8c05c8..239afc7a9c0b 100644
--- a/drivers/net/wireless/rt2x00/rt2x00queue.c
+++ b/drivers/net/wireless/rt2x00/rt2x00queue.c
@@ -162,10 +162,10 @@ void rt2x00queue_align_frame(struct sk_buff *skb)
162 skb_trim(skb, frame_length); 162 skb_trim(skb, frame_length);
163} 163}
164 164
165void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_lengt) 165void rt2x00queue_align_payload(struct sk_buff *skb, unsigned int header_length)
166{ 166{
167 unsigned int frame_length = skb->len; 167 unsigned int frame_length = skb->len;
168 unsigned int align = ALIGN_SIZE(skb, header_lengt); 168 unsigned int align = ALIGN_SIZE(skb, header_length);
169 169
170 if (!align) 170 if (!align)
171 return; 171 return;
@@ -214,7 +214,7 @@ void rt2x00queue_insert_l2pad(struct sk_buff *skb, unsigned int header_length)
214 skb_push(skb, header_align); 214 skb_push(skb, header_align);
215 memmove(skb->data, skb->data + header_align, header_length); 215 memmove(skb->data, skb->data + header_align, header_length);
216 memmove(skb->data + header_length + l2pad, 216 memmove(skb->data + header_length + l2pad,
217 skb->data + header_length + l2pad + header_align, 217 skb->data + header_length + l2pad + payload_align,
218 frame_length - header_length); 218 frame_length - header_length);
219 skbdesc->flags |= SKBDESC_L2_PADDED; 219 skbdesc->flags |= SKBDESC_L2_PADDED;
220 } 220 }
diff --git a/drivers/net/wireless/rt2x00/rt61pci.c b/drivers/net/wireless/rt2x00/rt61pci.c
index bf04605896c7..687e17dc2e9f 100644
--- a/drivers/net/wireless/rt2x00/rt61pci.c
+++ b/drivers/net/wireless/rt2x00/rt61pci.c
@@ -2546,7 +2546,6 @@ static int rt61pci_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2546 IEEE80211_HW_SIGNAL_DBM | 2546 IEEE80211_HW_SIGNAL_DBM |
2547 IEEE80211_HW_SUPPORTS_PS | 2547 IEEE80211_HW_SUPPORTS_PS |
2548 IEEE80211_HW_PS_NULLFUNC_STACK; 2548 IEEE80211_HW_PS_NULLFUNC_STACK;
2549 rt2x00dev->hw->extra_tx_headroom = 0;
2550 2549
2551 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 2550 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
2552 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 2551 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2788,19 +2787,20 @@ static const struct data_queue_desc rt61pci_queue_bcn = {
2788}; 2787};
2789 2788
2790static const struct rt2x00_ops rt61pci_ops = { 2789static const struct rt2x00_ops rt61pci_ops = {
2791 .name = KBUILD_MODNAME, 2790 .name = KBUILD_MODNAME,
2792 .max_sta_intf = 1, 2791 .max_sta_intf = 1,
2793 .max_ap_intf = 4, 2792 .max_ap_intf = 4,
2794 .eeprom_size = EEPROM_SIZE, 2793 .eeprom_size = EEPROM_SIZE,
2795 .rf_size = RF_SIZE, 2794 .rf_size = RF_SIZE,
2796 .tx_queues = NUM_TX_QUEUES, 2795 .tx_queues = NUM_TX_QUEUES,
2797 .rx = &rt61pci_queue_rx, 2796 .extra_tx_headroom = 0,
2798 .tx = &rt61pci_queue_tx, 2797 .rx = &rt61pci_queue_rx,
2799 .bcn = &rt61pci_queue_bcn, 2798 .tx = &rt61pci_queue_tx,
2800 .lib = &rt61pci_rt2x00_ops, 2799 .bcn = &rt61pci_queue_bcn,
2801 .hw = &rt61pci_mac80211_ops, 2800 .lib = &rt61pci_rt2x00_ops,
2801 .hw = &rt61pci_mac80211_ops,
2802#ifdef CONFIG_RT2X00_LIB_DEBUGFS 2802#ifdef CONFIG_RT2X00_LIB_DEBUGFS
2803 .debugfs = &rt61pci_rt2x00debug, 2803 .debugfs = &rt61pci_rt2x00debug,
2804#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 2804#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
2805}; 2805};
2806 2806
diff --git a/drivers/net/wireless/rt2x00/rt73usb.c b/drivers/net/wireless/rt2x00/rt73usb.c
index 5bbcf6626f7d..ced3b6ab5e16 100644
--- a/drivers/net/wireless/rt2x00/rt73usb.c
+++ b/drivers/net/wireless/rt2x00/rt73usb.c
@@ -2069,7 +2069,6 @@ static int rt73usb_probe_hw_mode(struct rt2x00_dev *rt2x00dev)
2069 IEEE80211_HW_SIGNAL_DBM | 2069 IEEE80211_HW_SIGNAL_DBM |
2070 IEEE80211_HW_SUPPORTS_PS | 2070 IEEE80211_HW_SUPPORTS_PS |
2071 IEEE80211_HW_PS_NULLFUNC_STACK; 2071 IEEE80211_HW_PS_NULLFUNC_STACK;
2072 rt2x00dev->hw->extra_tx_headroom = TXD_DESC_SIZE;
2073 2072
2074 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev); 2073 SET_IEEE80211_DEV(rt2x00dev->hw, rt2x00dev->dev);
2075 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw, 2074 SET_IEEE80211_PERM_ADDR(rt2x00dev->hw,
@@ -2306,19 +2305,20 @@ static const struct data_queue_desc rt73usb_queue_bcn = {
2306}; 2305};
2307 2306
2308static const struct rt2x00_ops rt73usb_ops = { 2307static const struct rt2x00_ops rt73usb_ops = {
2309 .name = KBUILD_MODNAME, 2308 .name = KBUILD_MODNAME,
2310 .max_sta_intf = 1, 2309 .max_sta_intf = 1,
2311 .max_ap_intf = 4, 2310 .max_ap_intf = 4,
2312 .eeprom_size = EEPROM_SIZE, 2311 .eeprom_size = EEPROM_SIZE,
2313 .rf_size = RF_SIZE, 2312 .rf_size = RF_SIZE,
2314 .tx_queues = NUM_TX_QUEUES, 2313 .tx_queues = NUM_TX_QUEUES,
2315 .rx = &rt73usb_queue_rx, 2314 .extra_tx_headroom = TXD_DESC_SIZE,
2316 .tx = &rt73usb_queue_tx, 2315 .rx = &rt73usb_queue_rx,
2317 .bcn = &rt73usb_queue_bcn, 2316 .tx = &rt73usb_queue_tx,
2318 .lib = &rt73usb_rt2x00_ops, 2317 .bcn = &rt73usb_queue_bcn,
2319 .hw = &rt73usb_mac80211_ops, 2318 .lib = &rt73usb_rt2x00_ops,
2319 .hw = &rt73usb_mac80211_ops,
2320#ifdef CONFIG_RT2X00_LIB_DEBUGFS 2320#ifdef CONFIG_RT2X00_LIB_DEBUGFS
2321 .debugfs = &rt73usb_rt2x00debug, 2321 .debugfs = &rt73usb_rt2x00debug,
2322#endif /* CONFIG_RT2X00_LIB_DEBUGFS */ 2322#endif /* CONFIG_RT2X00_LIB_DEBUGFS */
2323}; 2323};
2324 2324
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.c b/drivers/net/wireless/wl12xx/wl1271_cmd.c
index 990eb01b4c71..886a9bc39cc1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.c
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.c
@@ -188,6 +188,113 @@ static int wl1271_cmd_cal(struct wl1271 *wl)
188 return ret; 188 return ret;
189} 189}
190 190
191int wl1271_cmd_general_parms(struct wl1271 *wl)
192{
193 struct wl1271_general_parms_cmd *gen_parms;
194 struct conf_general_parms *g = &wl->conf.init.genparam;
195 int ret;
196
197 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
198 if (!gen_parms)
199 return -ENOMEM;
200
201 gen_parms->test.id = TEST_CMD_INI_FILE_GENERAL_PARAM;
202
203 gen_parms->ref_clk = g->ref_clk;
204 gen_parms->settling_time = g->settling_time;
205 gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup;
206 gen_parms->dc2dcmode = g->dc2dcmode;
207 gen_parms->single_dual_band = g->single_dual_band;
208 gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect;
209 gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
210 gen_parms->settings = g->settings;
211
212 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
213 if (ret < 0)
214 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
215
216 kfree(gen_parms);
217 return ret;
218}
219
220int wl1271_cmd_radio_parms(struct wl1271 *wl)
221{
222 struct wl1271_radio_parms_cmd *radio_parms;
223 struct conf_radio_parms *r = &wl->conf.init.radioparam;
224 int i, ret;
225
226 radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
227 if (!radio_parms)
228 return -ENOMEM;
229
230 radio_parms->test.id = TEST_CMD_INI_FILE_RADIO_PARAM;
231
232 /* Static radio parameters */
233 radio_parms->rx_trace_loss = r->rx_trace_loss;
234 radio_parms->tx_trace_loss = r->tx_trace_loss;
235 memcpy(radio_parms->rx_rssi_and_proc_compens,
236 r->rx_rssi_and_proc_compens,
237 CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
238
239 memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5,
240 CONF_NUMBER_OF_SUB_BANDS_5);
241 memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5,
242 CONF_NUMBER_OF_SUB_BANDS_5);
243 memcpy(radio_parms->rx_rssi_and_proc_compens_5,
244 r->rx_rssi_and_proc_compens_5,
245 CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
246
247 /* Dynamic radio parameters */
248 radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage);
249 radio_parms->tx_ref_power = r->tx_ref_power;
250 radio_parms->tx_offset_db = r->tx_offset_db;
251
252 memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal,
253 CONF_NUMBER_OF_RATE_GROUPS);
254 memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
255 CONF_NUMBER_OF_RATE_GROUPS);
256
257 memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
258 CONF_NUMBER_OF_CHANNELS_2_4);
259 memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm,
260 CONF_NUMBER_OF_CHANNELS_2_4);
261 memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets,
262 CONF_NUMBER_OF_RATE_GROUPS);
263 memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
264
265 radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
266
267 for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
268 radio_parms->tx_ref_pd_voltage_5[i] =
269 cpu_to_le16(r->tx_ref_pd_voltage_5[i]);
270 memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5,
271 CONF_NUMBER_OF_SUB_BANDS_5);
272 memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5,
273 CONF_NUMBER_OF_SUB_BANDS_5);
274 memcpy(radio_parms->tx_rate_limits_normal_5,
275 r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
276 memcpy(radio_parms->tx_rate_limits_degraded_5,
277 r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
278 memcpy(radio_parms->tx_channel_limits_ofdm_5,
279 r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
280 memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
281 CONF_NUMBER_OF_RATE_GROUPS);
282 memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5,
283 CONF_NUMBER_OF_RATE_GROUPS);
284 memcpy(radio_parms->rx_fem_insertion_loss_5,
285 r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
286
287 wl1271_dump(DEBUG_CMD, "TEST_CMD_INI_FILE_RADIO_PARAM: ",
288 radio_parms, sizeof(*radio_parms));
289
290 ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
291 if (ret < 0)
292 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
293
294 kfree(radio_parms);
295 return ret;
296}
297
191int wl1271_cmd_join(struct wl1271 *wl) 298int wl1271_cmd_join(struct wl1271 *wl)
192{ 299{
193 static bool do_cal = true; 300 static bool do_cal = true;
diff --git a/drivers/net/wireless/wl12xx/wl1271_cmd.h b/drivers/net/wireless/wl12xx/wl1271_cmd.h
index 9d7061b3c8a0..b4fa4acb9229 100644
--- a/drivers/net/wireless/wl12xx/wl1271_cmd.h
+++ b/drivers/net/wireless/wl12xx/wl1271_cmd.h
@@ -31,6 +31,8 @@ struct acx_header;
31 31
32int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len, 32int wl1271_cmd_send(struct wl1271 *wl, u16 id, void *buf, size_t len,
33 size_t res_len); 33 size_t res_len);
34int wl1271_cmd_general_parms(struct wl1271 *wl);
35int wl1271_cmd_radio_parms(struct wl1271 *wl);
34int wl1271_cmd_join(struct wl1271 *wl); 36int wl1271_cmd_join(struct wl1271 *wl);
35int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer); 37int wl1271_cmd_test(struct wl1271 *wl, void *buf, size_t buf_len, u8 answer);
36int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len); 38int wl1271_cmd_interrogate(struct wl1271 *wl, u16 id, void *buf, size_t len);
@@ -418,6 +420,76 @@ enum wl1271_channel_tune_bands {
418#define TEST_CMD_P2G_CAL 0x02 420#define TEST_CMD_P2G_CAL 0x02
419#define TEST_CMD_CHANNEL_TUNE 0x0d 421#define TEST_CMD_CHANNEL_TUNE 0x0d
420#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d 422#define TEST_CMD_UPDATE_PD_REFERENCE_POINT 0x1d
423#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
424#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
425
426struct wl1271_general_parms_cmd {
427 struct wl1271_cmd_header header;
428
429 struct wl1271_cmd_test_header test;
430
431 u8 ref_clk;
432 u8 settling_time;
433 u8 clk_valid_on_wakeup;
434 u8 dc2dcmode;
435 u8 single_dual_band;
436
437 u8 tx_bip_fem_autodetect;
438 u8 tx_bip_fem_manufacturer;
439 u8 settings;
440} __attribute__ ((packed));
441
442struct wl1271_radio_parms_cmd {
443 struct wl1271_cmd_header header;
444
445 struct wl1271_cmd_test_header test;
446
447 /* Static radio parameters */
448 /* 2.4GHz */
449 u8 rx_trace_loss;
450 u8 tx_trace_loss;
451 s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
452
453 /* 5GHz */
454 u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
455 u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
456 s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
457
458 /* Dynamic radio parameters */
459 /* 2.4GHz */
460 __le16 tx_ref_pd_voltage;
461 s8 tx_ref_power;
462 s8 tx_offset_db;
463
464 s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
465 s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
466
467 s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
468 s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
469 s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
470
471 u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
472 u8 rx_fem_insertion_loss;
473
474 u8 padding2;
475
476 /* 5GHz */
477 __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
478 s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
479 s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
480
481 s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
482 s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
483
484 s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
485 s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
486
487 /* FIXME: this is inconsistent with the types for 2.4GHz */
488 s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
489 s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
490
491 u8 padding3[2];
492} __attribute__ ((packed));
421 493
422struct wl1271_cmd_cal_channel_tune { 494struct wl1271_cmd_cal_channel_tune {
423 struct wl1271_cmd_header header; 495 struct wl1271_cmd_header header;
diff --git a/drivers/net/wireless/wl12xx/wl1271_event.c b/drivers/net/wireless/wl12xx/wl1271_event.c
index e135d894b42a..d13fdd99c85c 100644
--- a/drivers/net/wireless/wl12xx/wl1271_event.c
+++ b/drivers/net/wireless/wl12xx/wl1271_event.c
@@ -78,12 +78,16 @@ static int wl1271_event_ps_report(struct wl1271 *wl,
78 78
79 switch (mbox->ps_status) { 79 switch (mbox->ps_status) {
80 case EVENT_ENTER_POWER_SAVE_FAIL: 80 case EVENT_ENTER_POWER_SAVE_FAIL:
81 if (!wl->psm) {
82 wl->psm_entry_retry = 0;
83 break;
84 }
85
81 if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) { 86 if (wl->psm_entry_retry < wl->conf.conn.psm_entry_retries) {
82 wl->psm_entry_retry++; 87 wl->psm_entry_retry++;
83 wl1271_error("PSM entry failed, retrying %d\n",
84 wl->psm_entry_retry);
85 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE); 88 ret = wl1271_ps_set_mode(wl, STATION_POWER_SAVE_MODE);
86 } else { 89 } else {
90 wl1271_error("PSM entry failed, giving up.\n");
87 wl->psm_entry_retry = 0; 91 wl->psm_entry_retry = 0;
88 *beacon_loss = true; 92 *beacon_loss = true;
89 } 93 }
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.c b/drivers/net/wireless/wl12xx/wl1271_init.c
index 7c2017f480ea..11249b436cf1 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.c
+++ b/drivers/net/wireless/wl12xx/wl1271_init.c
@@ -193,125 +193,16 @@ static int wl1271_init_beacon_broadcast(struct wl1271 *wl)
193 return 0; 193 return 0;
194} 194}
195 195
196static int wl1271_init_general_parms(struct wl1271 *wl)
197{
198 struct wl1271_general_parms *gen_parms;
199 struct conf_general_parms *g = &wl->conf.init.genparam;
200 int ret;
201
202 gen_parms = kzalloc(sizeof(*gen_parms), GFP_KERNEL);
203 if (!gen_parms)
204 return -ENOMEM;
205
206 gen_parms->id = TEST_CMD_INI_FILE_GENERAL_PARAM;
207
208 gen_parms->ref_clk = g->ref_clk;
209 gen_parms->settling_time = g->settling_time;
210 gen_parms->clk_valid_on_wakeup = g->clk_valid_on_wakeup;
211 gen_parms->dc2dcmode = g->dc2dcmode;
212 gen_parms->single_dual_band = g->single_dual_band;
213 gen_parms->tx_bip_fem_autodetect = g->tx_bip_fem_autodetect;
214 gen_parms->tx_bip_fem_manufacturer = g->tx_bip_fem_manufacturer;
215 gen_parms->settings = g->settings;
216
217 ret = wl1271_cmd_test(wl, gen_parms, sizeof(*gen_parms), 0);
218 if (ret < 0) {
219 wl1271_warning("CMD_INI_FILE_GENERAL_PARAM failed");
220 return ret;
221 }
222
223 kfree(gen_parms);
224 return 0;
225}
226
227static int wl1271_init_radio_parms(struct wl1271 *wl)
228{
229 struct wl1271_radio_parms *radio_parms;
230 struct conf_radio_parms *r = &wl->conf.init.radioparam;
231 int i, ret;
232
233 radio_parms = kzalloc(sizeof(*radio_parms), GFP_KERNEL);
234 if (!radio_parms)
235 return -ENOMEM;
236
237 radio_parms->id = TEST_CMD_INI_FILE_RADIO_PARAM;
238
239 /* Static radio parameters */
240 radio_parms->rx_trace_loss = r->rx_trace_loss;
241 radio_parms->tx_trace_loss = r->tx_trace_loss;
242 memcpy(radio_parms->rx_rssi_and_proc_compens,
243 r->rx_rssi_and_proc_compens,
244 CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
245
246 memcpy(radio_parms->rx_trace_loss_5, r->rx_trace_loss_5,
247 CONF_NUMBER_OF_SUB_BANDS_5);
248 memcpy(radio_parms->tx_trace_loss_5, r->tx_trace_loss_5,
249 CONF_NUMBER_OF_SUB_BANDS_5);
250 memcpy(radio_parms->rx_rssi_and_proc_compens_5,
251 r->rx_rssi_and_proc_compens_5,
252 CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE);
253
254 /* Dynamic radio parameters */
255 radio_parms->tx_ref_pd_voltage = cpu_to_le16(r->tx_ref_pd_voltage);
256 radio_parms->tx_ref_power = r->tx_ref_power;
257 radio_parms->tx_offset_db = r->tx_offset_db;
258
259 memcpy(radio_parms->tx_rate_limits_normal, r->tx_rate_limits_normal,
260 CONF_NUMBER_OF_RATE_GROUPS);
261 memcpy(radio_parms->tx_rate_limits_degraded, r->tx_rate_limits_degraded,
262 CONF_NUMBER_OF_RATE_GROUPS);
263
264 memcpy(radio_parms->tx_channel_limits_11b, r->tx_channel_limits_11b,
265 CONF_NUMBER_OF_CHANNELS_2_4);
266 memcpy(radio_parms->tx_channel_limits_ofdm, r->tx_channel_limits_ofdm,
267 CONF_NUMBER_OF_CHANNELS_2_4);
268 memcpy(radio_parms->tx_pdv_rate_offsets, r->tx_pdv_rate_offsets,
269 CONF_NUMBER_OF_RATE_GROUPS);
270 memcpy(radio_parms->tx_ibias, r->tx_ibias, CONF_NUMBER_OF_RATE_GROUPS);
271
272 radio_parms->rx_fem_insertion_loss = r->rx_fem_insertion_loss;
273
274 for (i = 0; i < CONF_NUMBER_OF_SUB_BANDS_5; i++)
275 radio_parms->tx_ref_pd_voltage_5[i] =
276 cpu_to_le16(r->tx_ref_pd_voltage_5[i]);
277 memcpy(radio_parms->tx_ref_power_5, r->tx_ref_power_5,
278 CONF_NUMBER_OF_SUB_BANDS_5);
279 memcpy(radio_parms->tx_offset_db_5, r->tx_offset_db_5,
280 CONF_NUMBER_OF_SUB_BANDS_5);
281 memcpy(radio_parms->tx_rate_limits_normal_5,
282 r->tx_rate_limits_normal_5, CONF_NUMBER_OF_RATE_GROUPS);
283 memcpy(radio_parms->tx_rate_limits_degraded_5,
284 r->tx_rate_limits_degraded_5, CONF_NUMBER_OF_RATE_GROUPS);
285 memcpy(radio_parms->tx_channel_limits_ofdm_5,
286 r->tx_channel_limits_ofdm_5, CONF_NUMBER_OF_CHANNELS_5);
287 memcpy(radio_parms->tx_pdv_rate_offsets_5, r->tx_pdv_rate_offsets_5,
288 CONF_NUMBER_OF_RATE_GROUPS);
289 memcpy(radio_parms->tx_ibias_5, r->tx_ibias_5,
290 CONF_NUMBER_OF_RATE_GROUPS);
291 memcpy(radio_parms->rx_fem_insertion_loss_5,
292 r->rx_fem_insertion_loss_5, CONF_NUMBER_OF_SUB_BANDS_5);
293
294 ret = wl1271_cmd_test(wl, radio_parms, sizeof(*radio_parms), 0);
295 if (ret < 0)
296 wl1271_warning("CMD_INI_FILE_RADIO_PARAM failed");
297
298 kfree(radio_parms);
299 return ret;
300}
301
302int wl1271_hw_init(struct wl1271 *wl) 196int wl1271_hw_init(struct wl1271 *wl)
303{ 197{
304 int ret; 198 int ret;
305 199
306 /* FIXME: the following parameter setting functions return error 200 ret = wl1271_cmd_general_parms(wl);
307 * codes - the reason is so far unknown. The -EIO is therefore 201 if (ret < 0)
308 * ignored for the time being. */
309 ret = wl1271_init_general_parms(wl);
310 if (ret < 0 && ret != -EIO)
311 return ret; 202 return ret;
312 203
313 ret = wl1271_init_radio_parms(wl); 204 ret = wl1271_cmd_radio_parms(wl);
314 if (ret < 0 && ret != -EIO) 205 if (ret < 0)
315 return ret; 206 return ret;
316 207
317 /* Template settings */ 208 /* Template settings */
diff --git a/drivers/net/wireless/wl12xx/wl1271_init.h b/drivers/net/wireless/wl12xx/wl1271_init.h
index 6e21ceee76a6..930677fbe852 100644
--- a/drivers/net/wireless/wl12xx/wl1271_init.h
+++ b/drivers/net/wireless/wl12xx/wl1271_init.h
@@ -29,74 +29,4 @@
29int wl1271_hw_init_power_auth(struct wl1271 *wl); 29int wl1271_hw_init_power_auth(struct wl1271 *wl);
30int wl1271_hw_init(struct wl1271 *wl); 30int wl1271_hw_init(struct wl1271 *wl);
31 31
32/* These are not really a TEST_CMD, but the ref driver uses them as such */
33#define TEST_CMD_INI_FILE_RADIO_PARAM 0x19
34#define TEST_CMD_INI_FILE_GENERAL_PARAM 0x1E
35
36struct wl1271_general_parms {
37 u8 id;
38 u8 padding[3];
39
40 u8 ref_clk;
41 u8 settling_time;
42 u8 clk_valid_on_wakeup;
43 u8 dc2dcmode;
44 u8 single_dual_band;
45
46 u8 tx_bip_fem_autodetect;
47 u8 tx_bip_fem_manufacturer;
48 u8 settings;
49} __attribute__ ((packed));
50
51struct wl1271_radio_parms {
52 u8 id;
53 u8 padding[3];
54
55 /* Static radio parameters */
56 /* 2.4GHz */
57 u8 rx_trace_loss;
58 u8 tx_trace_loss;
59 s8 rx_rssi_and_proc_compens[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
60
61 /* 5GHz */
62 u8 rx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
63 u8 tx_trace_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
64 s8 rx_rssi_and_proc_compens_5[CONF_RSSI_AND_PROCESS_COMPENSATION_SIZE];
65
66 /* Dynamic radio parameters */
67 /* 2.4GHz */
68 __le16 tx_ref_pd_voltage;
69 s8 tx_ref_power;
70 s8 tx_offset_db;
71
72 s8 tx_rate_limits_normal[CONF_NUMBER_OF_RATE_GROUPS];
73 s8 tx_rate_limits_degraded[CONF_NUMBER_OF_RATE_GROUPS];
74
75 s8 tx_channel_limits_11b[CONF_NUMBER_OF_CHANNELS_2_4];
76 s8 tx_channel_limits_ofdm[CONF_NUMBER_OF_CHANNELS_2_4];
77 s8 tx_pdv_rate_offsets[CONF_NUMBER_OF_RATE_GROUPS];
78
79 u8 tx_ibias[CONF_NUMBER_OF_RATE_GROUPS];
80 u8 rx_fem_insertion_loss;
81
82 u8 padding2;
83
84 /* 5GHz */
85 __le16 tx_ref_pd_voltage_5[CONF_NUMBER_OF_SUB_BANDS_5];
86 s8 tx_ref_power_5[CONF_NUMBER_OF_SUB_BANDS_5];
87 s8 tx_offset_db_5[CONF_NUMBER_OF_SUB_BANDS_5];
88
89 s8 tx_rate_limits_normal_5[CONF_NUMBER_OF_RATE_GROUPS];
90 s8 tx_rate_limits_degraded_5[CONF_NUMBER_OF_RATE_GROUPS];
91
92 s8 tx_channel_limits_ofdm_5[CONF_NUMBER_OF_CHANNELS_5];
93 s8 tx_pdv_rate_offsets_5[CONF_NUMBER_OF_RATE_GROUPS];
94
95 /* FIXME: this is inconsistent with the types for 2.4GHz */
96 s8 tx_ibias_5[CONF_NUMBER_OF_RATE_GROUPS];
97 s8 rx_fem_insertion_loss_5[CONF_NUMBER_OF_SUB_BANDS_5];
98
99 u8 padding3[2];
100} __attribute__ ((packed));
101
102#endif 32#endif
diff --git a/drivers/net/wireless/wl12xx/wl1271_main.c b/drivers/net/wireless/wl12xx/wl1271_main.c
index 00ddcc2d37c1..b62c00ff42fe 100644
--- a/drivers/net/wireless/wl12xx/wl1271_main.c
+++ b/drivers/net/wireless/wl12xx/wl1271_main.c
@@ -222,7 +222,7 @@ static struct conf_drv_settings default_conf = {
222 .snr_pkt_avg_weight = 10 222 .snr_pkt_avg_weight = 10
223 }, 223 },
224 .bet_enable = CONF_BET_MODE_ENABLE, 224 .bet_enable = CONF_BET_MODE_ENABLE,
225 .bet_max_consecutive = 100, 225 .bet_max_consecutive = 10,
226 .psm_entry_retries = 3 226 .psm_entry_retries = 3
227 }, 227 },
228 .init = { 228 .init = {
@@ -251,14 +251,7 @@ static struct conf_drv_settings default_conf = {
251 }, 251 },
252 .sr_enable = 1, 252 .sr_enable = 1,
253 .genparam = { 253 .genparam = {
254 /* 254 .ref_clk = CONF_REF_CLK_38_4_E,
255 * FIXME: The correct value CONF_REF_CLK_38_4_E
256 * causes the firmware to crash on boot.
257 * The value 5 apparently is an
258 * unnoficial XTAL configuration of the
259 * same frequency, which appears to work.
260 */
261 .ref_clk = 5,
262 .settling_time = 5, 255 .settling_time = 5,
263 .clk_valid_on_wakeup = 0, 256 .clk_valid_on_wakeup = 0,
264 .dc2dcmode = 0, 257 .dc2dcmode = 0,
@@ -354,6 +347,14 @@ static int wl1271_plt_init(struct wl1271 *wl)
354{ 347{
355 int ret; 348 int ret;
356 349
350 ret = wl1271_cmd_general_parms(wl);
351 if (ret < 0)
352 return ret;
353
354 ret = wl1271_cmd_radio_parms(wl);
355 if (ret < 0)
356 return ret;
357
357 ret = wl1271_acx_init_mem_config(wl); 358 ret = wl1271_acx_init_mem_config(wl);
358 if (ret < 0) 359 if (ret < 0)
359 return ret; 360 return ret;
@@ -815,15 +816,15 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
815 816
816 wdev = dev->ieee80211_ptr; 817 wdev = dev->ieee80211_ptr;
817 if (wdev == NULL) 818 if (wdev == NULL)
818 return -ENODEV; 819 return NOTIFY_DONE;
819 820
820 wiphy = wdev->wiphy; 821 wiphy = wdev->wiphy;
821 if (wiphy == NULL) 822 if (wiphy == NULL)
822 return -ENODEV; 823 return NOTIFY_DONE;
823 824
824 hw = wiphy_priv(wiphy); 825 hw = wiphy_priv(wiphy);
825 if (hw == NULL) 826 if (hw == NULL)
826 return -ENODEV; 827 return NOTIFY_DONE;
827 828
828 /* Check that the interface is one supported by this driver. */ 829 /* Check that the interface is one supported by this driver. */
829 wl_temp = hw->priv; 830 wl_temp = hw->priv;
@@ -832,7 +833,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
832 break; 833 break;
833 } 834 }
834 if (wl == NULL) 835 if (wl == NULL)
835 return -ENODEV; 836 return NOTIFY_DONE;
836 837
837 /* Get the interface IP address for the device. "ifa" will become 838 /* Get the interface IP address for the device. "ifa" will become
838 NULL if: 839 NULL if:
@@ -868,7 +869,7 @@ static int wl1271_dev_notify(struct notifier_block *me, unsigned long what,
868out: 869out:
869 mutex_unlock(&wl->mutex); 870 mutex_unlock(&wl->mutex);
870 871
871 return ret; 872 return NOTIFY_OK;
872} 873}
873 874
874static struct notifier_block wl1271_dev_notifier = { 875static struct notifier_block wl1271_dev_notifier = {
@@ -1753,7 +1754,8 @@ static int wl1271_init_ieee80211(struct wl1271 *wl)
1753 1754
1754 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM | 1755 wl->hw->flags = IEEE80211_HW_SIGNAL_DBM |
1755 IEEE80211_HW_NOISE_DBM | 1756 IEEE80211_HW_NOISE_DBM |
1756 IEEE80211_HW_BEACON_FILTER; 1757 IEEE80211_HW_BEACON_FILTER |
1758 IEEE80211_HW_SUPPORTS_PS;
1757 1759
1758 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION); 1760 wl->hw->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION);
1759 wl->hw->wiphy->max_scan_ssids = 1; 1761 wl->hw->wiphy->max_scan_ssids = 1;
diff --git a/include/linux/ieee80211.h b/include/linux/ieee80211.h
index afa8e0ac27a7..d9724a28c0c2 100644
--- a/include/linux/ieee80211.h
+++ b/include/linux/ieee80211.h
@@ -1266,6 +1266,8 @@ enum ieee80211_sa_query_action {
1266 1266
1267#define WLAN_MAX_KEY_LEN 32 1267#define WLAN_MAX_KEY_LEN 32
1268 1268
1269#define WLAN_PMKID_LEN 16
1270
1269/** 1271/**
1270 * ieee80211_get_qos_ctl - get pointer to qos control bytes 1272 * ieee80211_get_qos_ctl - get pointer to qos control bytes
1271 * @hdr: the frame 1273 * @hdr: the frame
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h
index 45db17f81aa3..da8ea2e19273 100644
--- a/include/linux/nl80211.h
+++ b/include/linux/nl80211.h
@@ -349,6 +349,10 @@ enum nl80211_commands {
349 NL80211_CMD_GET_SURVEY, 349 NL80211_CMD_GET_SURVEY,
350 NL80211_CMD_NEW_SURVEY_RESULTS, 350 NL80211_CMD_NEW_SURVEY_RESULTS,
351 351
352 NL80211_CMD_SET_PMKSA,
353 NL80211_CMD_DEL_PMKSA,
354 NL80211_CMD_FLUSH_PMKSA,
355
352 /* add new commands above here */ 356 /* add new commands above here */
353 357
354 /* used to define NL80211_CMD_MAX below */ 358 /* used to define NL80211_CMD_MAX below */
@@ -598,6 +602,10 @@ enum nl80211_commands {
598 * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute 602 * the survey response for %NL80211_CMD_GET_SURVEY, nested attribute
599 * containing info as possible, see &enum survey_info. 603 * containing info as possible, see &enum survey_info.
600 * 604 *
605 * @NL80211_ATTR_PMKID: PMK material for PMKSA caching.
606 * @NL80211_ATTR_MAX_NUM_PMKIDS: maximum number of PMKIDs a firmware can
607 * cache, a wiphy attribute.
608 *
601 * @NL80211_ATTR_MAX: highest attribute number currently defined 609 * @NL80211_ATTR_MAX: highest attribute number currently defined
602 * @__NL80211_ATTR_AFTER_LAST: internal use 610 * @__NL80211_ATTR_AFTER_LAST: internal use
603 */ 611 */
@@ -732,6 +740,9 @@ enum nl80211_attrs {
732 740
733 NL80211_ATTR_SURVEY_INFO, 741 NL80211_ATTR_SURVEY_INFO,
734 742
743 NL80211_ATTR_PMKID,
744 NL80211_ATTR_MAX_NUM_PMKIDS,
745
735 /* add attributes here, update the policy in nl80211.c */ 746 /* add attributes here, update the policy in nl80211.c */
736 747
737 __NL80211_ATTR_AFTER_LAST, 748 __NL80211_ATTR_AFTER_LAST,
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index a6492e9bca97..0884b9a0f778 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -871,6 +871,19 @@ struct cfg80211_bitrate_mask {
871 u32 fixed; /* fixed bitrate, 0 == not fixed */ 871 u32 fixed; /* fixed bitrate, 0 == not fixed */
872 u32 maxrate; /* in kbps, 0 == no limit */ 872 u32 maxrate; /* in kbps, 0 == no limit */
873}; 873};
874/**
875 * struct cfg80211_pmksa - PMK Security Association
876 *
877 * This structure is passed to the set/del_pmksa() method for PMKSA
878 * caching.
879 *
880 * @bssid: The AP's BSSID.
881 * @pmkid: The PMK material itself.
882 */
883struct cfg80211_pmksa {
884 u8 *bssid;
885 u8 *pmkid;
886};
874 887
875/** 888/**
876 * struct cfg80211_ops - backend description for wireless configuration 889 * struct cfg80211_ops - backend description for wireless configuration
@@ -976,6 +989,13 @@ struct cfg80211_bitrate_mask {
976 * @dump_survey: get site survey information. 989 * @dump_survey: get site survey information.
977 * 990 *
978 * @testmode_cmd: run a test mode command 991 * @testmode_cmd: run a test mode command
992 *
993 * @set_pmksa: Cache a PMKID for a BSSID. This is mostly useful for fullmac
994 * devices running firmwares capable of generating the (re) association
995 * RSN IE. It allows for faster roaming between WPA2 BSSIDs.
996 * @del_pmksa: Delete a cached PMKID.
997 * @flush_pmksa: Flush all cached PMKIDs.
998 *
979 */ 999 */
980struct cfg80211_ops { 1000struct cfg80211_ops {
981 int (*suspend)(struct wiphy *wiphy); 1001 int (*suspend)(struct wiphy *wiphy);
@@ -1097,6 +1117,12 @@ struct cfg80211_ops {
1097 int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev, 1117 int (*dump_survey)(struct wiphy *wiphy, struct net_device *netdev,
1098 int idx, struct survey_info *info); 1118 int idx, struct survey_info *info);
1099 1119
1120 int (*set_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
1121 struct cfg80211_pmksa *pmksa);
1122 int (*del_pmksa)(struct wiphy *wiphy, struct net_device *netdev,
1123 struct cfg80211_pmksa *pmksa);
1124 int (*flush_pmksa)(struct wiphy *wiphy, struct net_device *netdev);
1125
1100 /* some temporary stuff to finish wext */ 1126 /* some temporary stuff to finish wext */
1101 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev, 1127 int (*set_power_mgmt)(struct wiphy *wiphy, struct net_device *dev,
1102 bool enabled, int timeout); 1128 bool enabled, int timeout);
@@ -1195,6 +1221,8 @@ struct wiphy {
1195 char fw_version[ETHTOOL_BUSINFO_LEN]; 1221 char fw_version[ETHTOOL_BUSINFO_LEN];
1196 u32 hw_version; 1222 u32 hw_version;
1197 1223
1224 u8 max_num_pmkids;
1225
1198 /* If multiple wiphys are registered and you're handed e.g. 1226 /* If multiple wiphys are registered and you're handed e.g.
1199 * a regular netdev with assigned ieee80211_ptr, you won't 1227 * a regular netdev with assigned ieee80211_ptr, you won't
1200 * know whether it points to a wiphy your driver has registered 1228 * know whether it points to a wiphy your driver has registered
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 68a9c5f3412f..2aff4906b2ae 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -513,6 +513,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info)
513 * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index 513 * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index
514 * @RX_FLAG_40MHZ: HT40 (40 MHz) was used 514 * @RX_FLAG_40MHZ: HT40 (40 MHz) was used
515 * @RX_FLAG_SHORT_GI: Short guard interval was used 515 * @RX_FLAG_SHORT_GI: Short guard interval was used
516 * @RX_FLAG_INTERNAL_CMTR: set internally after frame was reported
517 * on cooked monitor to avoid double-reporting it for multiple
518 * virtual interfaces
516 */ 519 */
517enum mac80211_rx_flags { 520enum mac80211_rx_flags {
518 RX_FLAG_MMIC_ERROR = 1<<0, 521 RX_FLAG_MMIC_ERROR = 1<<0,
@@ -526,6 +529,7 @@ enum mac80211_rx_flags {
526 RX_FLAG_HT = 1<<9, 529 RX_FLAG_HT = 1<<9,
527 RX_FLAG_40MHZ = 1<<10, 530 RX_FLAG_40MHZ = 1<<10,
528 RX_FLAG_SHORT_GI = 1<<11, 531 RX_FLAG_SHORT_GI = 1<<11,
532 RX_FLAG_INTERNAL_CMTR = 1<<12,
529}; 533};
530 534
531/** 535/**
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index b8fef1d11369..ee94ea0c67e9 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -131,17 +131,35 @@ TRACE_EVENT(drv_config,
131 LOCAL_ENTRY 131 LOCAL_ENTRY
132 __field(u32, changed) 132 __field(u32, changed)
133 __field(int, ret) 133 __field(int, ret)
134 __field(u32, flags)
135 __field(int, power_level)
136 __field(int, dynamic_ps_timeout)
137 __field(int, max_sleep_period)
138 __field(u16, listen_interval)
139 __field(u8, long_frame_max_tx_count)
140 __field(u8, short_frame_max_tx_count)
141 __field(int, center_freq)
142 __field(int, channel_type)
134 ), 143 ),
135 144
136 TP_fast_assign( 145 TP_fast_assign(
137 LOCAL_ASSIGN; 146 LOCAL_ASSIGN;
138 __entry->changed = changed; 147 __entry->changed = changed;
139 __entry->ret = ret; 148 __entry->ret = ret;
149 __entry->flags = local->hw.conf.flags;
150 __entry->power_level = local->hw.conf.power_level;
151 __entry->dynamic_ps_timeout = local->hw.conf.dynamic_ps_timeout;
152 __entry->max_sleep_period = local->hw.conf.max_sleep_period;
153 __entry->listen_interval = local->hw.conf.listen_interval;
154 __entry->long_frame_max_tx_count = local->hw.conf.long_frame_max_tx_count;
155 __entry->short_frame_max_tx_count = local->hw.conf.short_frame_max_tx_count;
156 __entry->center_freq = local->hw.conf.channel->center_freq;
157 __entry->channel_type = local->hw.conf.channel_type;
140 ), 158 ),
141 159
142 TP_printk( 160 TP_printk(
143 LOCAL_PR_FMT " ch:%#x ret:%d", 161 LOCAL_PR_FMT " ch:%#x freq:%d ret:%d",
144 LOCAL_PR_ARG, __entry->changed, __entry->ret 162 LOCAL_PR_ARG, __entry->changed, __entry->center_freq, __entry->ret
145 ) 163 )
146); 164);
147 165
@@ -167,6 +185,8 @@ TRACE_EVENT(drv_bss_info_changed,
167 __field(u64, timestamp) 185 __field(u64, timestamp)
168 __field(u32, basic_rates) 186 __field(u32, basic_rates)
169 __field(u32, changed) 187 __field(u32, changed)
188 __field(bool, enable_beacon)
189 __field(u16, ht_operation_mode)
170 ), 190 ),
171 191
172 TP_fast_assign( 192 TP_fast_assign(
@@ -183,6 +203,8 @@ TRACE_EVENT(drv_bss_info_changed,
183 __entry->assoc_cap = info->assoc_capability; 203 __entry->assoc_cap = info->assoc_capability;
184 __entry->timestamp = info->timestamp; 204 __entry->timestamp = info->timestamp;
185 __entry->basic_rates = info->basic_rates; 205 __entry->basic_rates = info->basic_rates;
206 __entry->enable_beacon = info->enable_beacon;
207 __entry->ht_operation_mode = info->ht_operation_mode;
186 ), 208 ),
187 209
188 TP_printk( 210 TP_printk(
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 039affa7c871..419f186cfcf0 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -163,8 +163,8 @@ typedef unsigned __bitwise__ ieee80211_rx_result;
163/* frame is destined to interface currently processed (incl. multicast frames) */ 163/* frame is destined to interface currently processed (incl. multicast frames) */
164#define IEEE80211_RX_RA_MATCH BIT(1) 164#define IEEE80211_RX_RA_MATCH BIT(1)
165#define IEEE80211_RX_AMSDU BIT(2) 165#define IEEE80211_RX_AMSDU BIT(2)
166#define IEEE80211_RX_CMNTR_REPORTED BIT(3) 166#define IEEE80211_RX_FRAGMENTED BIT(3)
167#define IEEE80211_RX_FRAGMENTED BIT(4) 167/* only add flags here that do not change with subframes of an aMPDU */
168 168
169struct ieee80211_rx_data { 169struct ieee80211_rx_data {
170 struct sk_buff *skb; 170 struct sk_buff *skb;
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 1bf12a26b45e..80c16f6e2af6 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -860,22 +860,18 @@ void ieee80211_if_remove(struct ieee80211_sub_if_data *sdata)
860void ieee80211_remove_interfaces(struct ieee80211_local *local) 860void ieee80211_remove_interfaces(struct ieee80211_local *local)
861{ 861{
862 struct ieee80211_sub_if_data *sdata, *tmp; 862 struct ieee80211_sub_if_data *sdata, *tmp;
863 LIST_HEAD(unreg_list);
863 864
864 ASSERT_RTNL(); 865 ASSERT_RTNL();
865 866
867 mutex_lock(&local->iflist_mtx);
866 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) { 868 list_for_each_entry_safe(sdata, tmp, &local->interfaces, list) {
867 /*
868 * we cannot hold the iflist_mtx across unregister_netdevice,
869 * but we only need to hold it for list modifications to lock
870 * out readers since we're under the RTNL here as all other
871 * writers.
872 */
873 mutex_lock(&local->iflist_mtx);
874 list_del(&sdata->list); 869 list_del(&sdata->list);
875 mutex_unlock(&local->iflist_mtx);
876 870
877 unregister_netdevice(sdata->dev); 871 unregister_netdevice_queue(sdata->dev, &unreg_list);
878 } 872 }
873 mutex_unlock(&local->iflist_mtx);
874 unregister_netdevice_many(&unreg_list);
879} 875}
880 876
881static u32 ieee80211_idle_off(struct ieee80211_local *local, 877static u32 ieee80211_idle_off(struct ieee80211_local *local,
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c
index beecf50fbd10..4ed60ae81b99 100644
--- a/net/mac80211/rx.c
+++ b/net/mac80211/rx.c
@@ -27,10 +27,6 @@
27#include "tkip.h" 27#include "tkip.h"
28#include "wme.h" 28#include "wme.h"
29 29
30static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
31 struct tid_ampdu_rx *tid_agg_rx,
32 u16 head_seq_num);
33
34/* 30/*
35 * monitor mode reception 31 * monitor mode reception
36 * 32 *
@@ -534,6 +530,242 @@ ieee80211_rx_mesh_check(struct ieee80211_rx_data *rx)
534 return RX_CONTINUE; 530 return RX_CONTINUE;
535} 531}
536 532
533#define SEQ_MODULO 0x1000
534#define SEQ_MASK 0xfff
535
536static inline int seq_less(u16 sq1, u16 sq2)
537{
538 return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);
539}
540
541static inline u16 seq_inc(u16 sq)
542{
543 return (sq + 1) & SEQ_MASK;
544}
545
546static inline u16 seq_sub(u16 sq1, u16 sq2)
547{
548 return (sq1 - sq2) & SEQ_MASK;
549}
550
551
552static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
553 struct tid_ampdu_rx *tid_agg_rx,
554 int index,
555 struct sk_buff_head *frames)
556{
557 struct ieee80211_supported_band *sband;
558 struct ieee80211_rate *rate = NULL;
559 struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
560 struct ieee80211_rx_status *status;
561
562 if (!skb)
563 goto no_frame;
564
565 status = IEEE80211_SKB_RXCB(skb);
566
567 /* release the reordered frames to stack */
568 sband = hw->wiphy->bands[status->band];
569 if (!(status->flag & RX_FLAG_HT))
570 rate = &sband->bitrates[status->rate_idx];
571 tid_agg_rx->stored_mpdu_num--;
572 tid_agg_rx->reorder_buf[index] = NULL;
573 skb_queue_tail(frames, skb);
574
575no_frame:
576 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
577}
578
579static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
580 struct tid_ampdu_rx *tid_agg_rx,
581 u16 head_seq_num,
582 struct sk_buff_head *frames)
583{
584 int index;
585
586 while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
587 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
588 tid_agg_rx->buf_size;
589 ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
590 }
591}
592
593/*
594 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
595 * the skb was added to the buffer longer than this time ago, the earlier
596 * frames that have not yet been received are assumed to be lost and the skb
597 * can be released for processing. This may also release other skb's from the
598 * reorder buffer if there are no additional gaps between the frames.
599 */
600#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
601
602/*
603 * As this function belongs to the RX path it must be under
604 * rcu_read_lock protection. It returns false if the frame
605 * can be processed immediately, true if it was consumed.
606 */
607static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
608 struct tid_ampdu_rx *tid_agg_rx,
609 struct sk_buff *skb,
610 struct sk_buff_head *frames)
611{
612 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
613 u16 sc = le16_to_cpu(hdr->seq_ctrl);
614 u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
615 u16 head_seq_num, buf_size;
616 int index;
617
618 buf_size = tid_agg_rx->buf_size;
619 head_seq_num = tid_agg_rx->head_seq_num;
620
621 /* frame with out of date sequence number */
622 if (seq_less(mpdu_seq_num, head_seq_num)) {
623 dev_kfree_skb(skb);
624 return true;
625 }
626
627 /*
628 * If frame the sequence number exceeds our buffering window
629 * size release some previous frames to make room for this one.
630 */
631 if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
632 head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
633 /* release stored frames up to new head to stack */
634 ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num,
635 frames);
636 }
637
638 /* Now the new frame is always in the range of the reordering buffer */
639
640 index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
641
642 /* check if we already stored this frame */
643 if (tid_agg_rx->reorder_buf[index]) {
644 dev_kfree_skb(skb);
645 return true;
646 }
647
648 /*
649 * If the current MPDU is in the right order and nothing else
650 * is stored we can process it directly, no need to buffer it.
651 */
652 if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
653 tid_agg_rx->stored_mpdu_num == 0) {
654 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
655 return false;
656 }
657
658 /* put the frame in the reordering buffer */
659 tid_agg_rx->reorder_buf[index] = skb;
660 tid_agg_rx->reorder_time[index] = jiffies;
661 tid_agg_rx->stored_mpdu_num++;
662 /* release the buffer until next missing frame */
663 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
664 tid_agg_rx->buf_size;
665 if (!tid_agg_rx->reorder_buf[index] &&
666 tid_agg_rx->stored_mpdu_num > 1) {
667 /*
668 * No buffers ready to be released, but check whether any
669 * frames in the reorder buffer have timed out.
670 */
671 int j;
672 int skipped = 1;
673 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
674 j = (j + 1) % tid_agg_rx->buf_size) {
675 if (!tid_agg_rx->reorder_buf[j]) {
676 skipped++;
677 continue;
678 }
679 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
680 HT_RX_REORDER_BUF_TIMEOUT))
681 break;
682
683#ifdef CONFIG_MAC80211_HT_DEBUG
684 if (net_ratelimit())
685 printk(KERN_DEBUG "%s: release an RX reorder "
686 "frame due to timeout on earlier "
687 "frames\n",
688 wiphy_name(hw->wiphy));
689#endif
690 ieee80211_release_reorder_frame(hw, tid_agg_rx,
691 j, frames);
692
693 /*
694 * Increment the head seq# also for the skipped slots.
695 */
696 tid_agg_rx->head_seq_num =
697 (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
698 skipped = 0;
699 }
700 } else while (tid_agg_rx->reorder_buf[index]) {
701 ieee80211_release_reorder_frame(hw, tid_agg_rx, index, frames);
702 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
703 tid_agg_rx->buf_size;
704 }
705
706 return true;
707}
708
709/*
710 * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
711 * true if the MPDU was buffered, false if it should be processed.
712 */
713static void ieee80211_rx_reorder_ampdu(struct ieee80211_rx_data *rx,
714 struct sk_buff_head *frames)
715{
716 struct sk_buff *skb = rx->skb;
717 struct ieee80211_local *local = rx->local;
718 struct ieee80211_hw *hw = &local->hw;
719 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
720 struct sta_info *sta = rx->sta;
721 struct tid_ampdu_rx *tid_agg_rx;
722 u16 sc;
723 int tid;
724
725 if (!ieee80211_is_data_qos(hdr->frame_control))
726 goto dont_reorder;
727
728 /*
729 * filter the QoS data rx stream according to
730 * STA/TID and check if this STA/TID is on aggregation
731 */
732
733 if (!sta)
734 goto dont_reorder;
735
736 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
737
738 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
739 goto dont_reorder;
740
741 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
742
743 /* qos null data frames are excluded */
744 if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
745 goto dont_reorder;
746
747 /* new, potentially un-ordered, ampdu frame - process it */
748
749 /* reset session timer */
750 if (tid_agg_rx->timeout)
751 mod_timer(&tid_agg_rx->session_timer,
752 TU_TO_EXP_TIME(tid_agg_rx->timeout));
753
754 /* if this mpdu is fragmented - terminate rx aggregation session */
755 sc = le16_to_cpu(hdr->seq_ctrl);
756 if (sc & IEEE80211_SCTL_FRAG) {
757 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
758 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
759 dev_kfree_skb(skb);
760 return;
761 }
762
763 if (ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb, frames))
764 return;
765
766 dont_reorder:
767 __skb_queue_tail(frames, skb);
768}
537 769
538static ieee80211_rx_result debug_noinline 770static ieee80211_rx_result debug_noinline
539ieee80211_rx_h_check(struct ieee80211_rx_data *rx) 771ieee80211_rx_h_check(struct ieee80211_rx_data *rx)
@@ -637,6 +869,9 @@ ieee80211_rx_h_decrypt(struct ieee80211_rx_data *rx)
637 if (!(rx->flags & IEEE80211_RX_RA_MATCH)) 869 if (!(rx->flags & IEEE80211_RX_RA_MATCH))
638 return RX_CONTINUE; 870 return RX_CONTINUE;
639 871
872 /* start without a key */
873 rx->key = NULL;
874
640 if (rx->sta) 875 if (rx->sta)
641 stakey = rcu_dereference(rx->sta->key); 876 stakey = rcu_dereference(rx->sta->key);
642 877
@@ -1589,7 +1824,7 @@ ieee80211_rx_h_data(struct ieee80211_rx_data *rx)
1589} 1824}
1590 1825
1591static ieee80211_rx_result debug_noinline 1826static ieee80211_rx_result debug_noinline
1592ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx) 1827ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx, struct sk_buff_head *frames)
1593{ 1828{
1594 struct ieee80211_local *local = rx->local; 1829 struct ieee80211_local *local = rx->local;
1595 struct ieee80211_hw *hw = &local->hw; 1830 struct ieee80211_hw *hw = &local->hw;
@@ -1619,7 +1854,8 @@ ieee80211_rx_h_ctrl(struct ieee80211_rx_data *rx)
1619 TU_TO_EXP_TIME(tid_agg_rx->timeout)); 1854 TU_TO_EXP_TIME(tid_agg_rx->timeout));
1620 1855
1621 /* release stored frames up to start of BAR */ 1856 /* release stored frames up to start of BAR */
1622 ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num); 1857 ieee80211_release_reorder_frames(hw, tid_agg_rx, start_seq_num,
1858 frames);
1623 kfree_skb(skb); 1859 kfree_skb(skb);
1624 return RX_QUEUED; 1860 return RX_QUEUED;
1625 } 1861 }
@@ -1868,7 +2104,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
1868 struct net_device *prev_dev = NULL; 2104 struct net_device *prev_dev = NULL;
1869 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb); 2105 struct ieee80211_rx_status *status = IEEE80211_SKB_RXCB(skb);
1870 2106
1871 if (rx->flags & IEEE80211_RX_CMNTR_REPORTED) 2107 if (status->flag & RX_FLAG_INTERNAL_CMTR)
1872 goto out_free_skb; 2108 goto out_free_skb;
1873 2109
1874 if (skb_headroom(skb) < sizeof(*rthdr) && 2110 if (skb_headroom(skb) < sizeof(*rthdr) &&
@@ -1929,7 +2165,7 @@ static void ieee80211_rx_cooked_monitor(struct ieee80211_rx_data *rx,
1929 } else 2165 } else
1930 goto out_free_skb; 2166 goto out_free_skb;
1931 2167
1932 rx->flags |= IEEE80211_RX_CMNTR_REPORTED; 2168 status->flag |= RX_FLAG_INTERNAL_CMTR;
1933 return; 2169 return;
1934 2170
1935 out_free_skb: 2171 out_free_skb:
@@ -1942,8 +2178,11 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
1942 struct sk_buff *skb, 2178 struct sk_buff *skb,
1943 struct ieee80211_rate *rate) 2179 struct ieee80211_rate *rate)
1944{ 2180{
2181 struct sk_buff_head reorder_release;
1945 ieee80211_rx_result res = RX_DROP_MONITOR; 2182 ieee80211_rx_result res = RX_DROP_MONITOR;
1946 2183
2184 __skb_queue_head_init(&reorder_release);
2185
1947 rx->skb = skb; 2186 rx->skb = skb;
1948 rx->sdata = sdata; 2187 rx->sdata = sdata;
1949 2188
@@ -1951,50 +2190,72 @@ static void ieee80211_invoke_rx_handlers(struct ieee80211_sub_if_data *sdata,
1951 do { \ 2190 do { \
1952 res = rxh(rx); \ 2191 res = rxh(rx); \
1953 if (res != RX_CONTINUE) \ 2192 if (res != RX_CONTINUE) \
1954 goto rxh_done; \ 2193 goto rxh_next; \
1955 } while (0); 2194 } while (0);
1956 2195
2196 /*
2197 * NB: the rxh_next label works even if we jump
2198 * to it from here because then the list will
2199 * be empty, which is a trivial check
2200 */
1957 CALL_RXH(ieee80211_rx_h_passive_scan) 2201 CALL_RXH(ieee80211_rx_h_passive_scan)
1958 CALL_RXH(ieee80211_rx_h_check) 2202 CALL_RXH(ieee80211_rx_h_check)
1959 CALL_RXH(ieee80211_rx_h_decrypt) 2203
1960 CALL_RXH(ieee80211_rx_h_check_more_data) 2204 ieee80211_rx_reorder_ampdu(rx, &reorder_release);
1961 CALL_RXH(ieee80211_rx_h_sta_process) 2205
1962 CALL_RXH(ieee80211_rx_h_defragment) 2206 while ((skb = __skb_dequeue(&reorder_release))) {
1963 CALL_RXH(ieee80211_rx_h_ps_poll) 2207 /*
1964 CALL_RXH(ieee80211_rx_h_michael_mic_verify) 2208 * all the other fields are valid across frames
1965 /* must be after MMIC verify so header is counted in MPDU mic */ 2209 * that belong to an aMPDU since they are on the
1966 CALL_RXH(ieee80211_rx_h_remove_qos_control) 2210 * same TID from the same station
1967 CALL_RXH(ieee80211_rx_h_amsdu) 2211 */
2212 rx->skb = skb;
2213
2214 CALL_RXH(ieee80211_rx_h_decrypt)
2215 CALL_RXH(ieee80211_rx_h_check_more_data)
2216 CALL_RXH(ieee80211_rx_h_sta_process)
2217 CALL_RXH(ieee80211_rx_h_defragment)
2218 CALL_RXH(ieee80211_rx_h_ps_poll)
2219 CALL_RXH(ieee80211_rx_h_michael_mic_verify)
2220 /* must be after MMIC verify so header is counted in MPDU mic */
2221 CALL_RXH(ieee80211_rx_h_remove_qos_control)
2222 CALL_RXH(ieee80211_rx_h_amsdu)
1968#ifdef CONFIG_MAC80211_MESH 2223#ifdef CONFIG_MAC80211_MESH
1969 if (ieee80211_vif_is_mesh(&sdata->vif)) 2224 if (ieee80211_vif_is_mesh(&sdata->vif))
1970 CALL_RXH(ieee80211_rx_h_mesh_fwding); 2225 CALL_RXH(ieee80211_rx_h_mesh_fwding);
1971#endif 2226#endif
1972 CALL_RXH(ieee80211_rx_h_data) 2227 CALL_RXH(ieee80211_rx_h_data)
1973 CALL_RXH(ieee80211_rx_h_ctrl) 2228
1974 CALL_RXH(ieee80211_rx_h_action) 2229 /* special treatment -- needs the queue */
1975 CALL_RXH(ieee80211_rx_h_mgmt) 2230 res = ieee80211_rx_h_ctrl(rx, &reorder_release);
2231 if (res != RX_CONTINUE)
2232 goto rxh_next;
2233
2234 CALL_RXH(ieee80211_rx_h_action)
2235 CALL_RXH(ieee80211_rx_h_mgmt)
1976 2236
1977#undef CALL_RXH 2237#undef CALL_RXH
1978 2238
1979 rxh_done: 2239 rxh_next:
1980 switch (res) { 2240 switch (res) {
1981 case RX_DROP_MONITOR: 2241 case RX_DROP_MONITOR:
1982 I802_DEBUG_INC(sdata->local->rx_handlers_drop); 2242 I802_DEBUG_INC(sdata->local->rx_handlers_drop);
1983 if (rx->sta) 2243 if (rx->sta)
1984 rx->sta->rx_dropped++; 2244 rx->sta->rx_dropped++;
1985 /* fall through */ 2245 /* fall through */
1986 case RX_CONTINUE: 2246 case RX_CONTINUE:
1987 ieee80211_rx_cooked_monitor(rx, rate); 2247 ieee80211_rx_cooked_monitor(rx, rate);
1988 break; 2248 break;
1989 case RX_DROP_UNUSABLE: 2249 case RX_DROP_UNUSABLE:
1990 I802_DEBUG_INC(sdata->local->rx_handlers_drop); 2250 I802_DEBUG_INC(sdata->local->rx_handlers_drop);
1991 if (rx->sta) 2251 if (rx->sta)
1992 rx->sta->rx_dropped++; 2252 rx->sta->rx_dropped++;
1993 dev_kfree_skb(rx->skb); 2253 dev_kfree_skb(rx->skb);
1994 break; 2254 break;
1995 case RX_QUEUED: 2255 case RX_QUEUED:
1996 I802_DEBUG_INC(sdata->local->rx_handlers_queued); 2256 I802_DEBUG_INC(sdata->local->rx_handlers_queued);
1997 break; 2257 break;
2258 }
1998 } 2259 }
1999} 2260}
2000 2261
@@ -2187,233 +2448,6 @@ static void __ieee80211_rx_handle_packet(struct ieee80211_hw *hw,
2187 dev_kfree_skb(skb); 2448 dev_kfree_skb(skb);
2188} 2449}
2189 2450
2190#define SEQ_MODULO 0x1000
2191#define SEQ_MASK 0xfff
2192
2193static inline int seq_less(u16 sq1, u16 sq2)
2194{
2195 return ((sq1 - sq2) & SEQ_MASK) > (SEQ_MODULO >> 1);
2196}
2197
2198static inline u16 seq_inc(u16 sq)
2199{
2200 return (sq + 1) & SEQ_MASK;
2201}
2202
2203static inline u16 seq_sub(u16 sq1, u16 sq2)
2204{
2205 return (sq1 - sq2) & SEQ_MASK;
2206}
2207
2208
2209static void ieee80211_release_reorder_frame(struct ieee80211_hw *hw,
2210 struct tid_ampdu_rx *tid_agg_rx,
2211 int index)
2212{
2213 struct ieee80211_supported_band *sband;
2214 struct ieee80211_rate *rate = NULL;
2215 struct sk_buff *skb = tid_agg_rx->reorder_buf[index];
2216 struct ieee80211_rx_status *status;
2217
2218 if (!skb)
2219 goto no_frame;
2220
2221 status = IEEE80211_SKB_RXCB(skb);
2222
2223 /* release the reordered frames to stack */
2224 sband = hw->wiphy->bands[status->band];
2225 if (!(status->flag & RX_FLAG_HT))
2226 rate = &sband->bitrates[status->rate_idx];
2227 __ieee80211_rx_handle_packet(hw, skb, rate);
2228 tid_agg_rx->stored_mpdu_num--;
2229 tid_agg_rx->reorder_buf[index] = NULL;
2230
2231no_frame:
2232 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
2233}
2234
2235static void ieee80211_release_reorder_frames(struct ieee80211_hw *hw,
2236 struct tid_ampdu_rx *tid_agg_rx,
2237 u16 head_seq_num)
2238{
2239 int index;
2240
2241 while (seq_less(tid_agg_rx->head_seq_num, head_seq_num)) {
2242 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
2243 tid_agg_rx->buf_size;
2244 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2245 }
2246}
2247
2248/*
2249 * Timeout (in jiffies) for skb's that are waiting in the RX reorder buffer. If
2250 * the skb was added to the buffer longer than this time ago, the earlier
2251 * frames that have not yet been received are assumed to be lost and the skb
2252 * can be released for processing. This may also release other skb's from the
2253 * reorder buffer if there are no additional gaps between the frames.
2254 */
2255#define HT_RX_REORDER_BUF_TIMEOUT (HZ / 10)
2256
2257/*
2258 * As this function belongs to the RX path it must be under
2259 * rcu_read_lock protection. It returns false if the frame
2260 * can be processed immediately, true if it was consumed.
2261 */
2262static bool ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw,
2263 struct tid_ampdu_rx *tid_agg_rx,
2264 struct sk_buff *skb)
2265{
2266 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2267 u16 sc = le16_to_cpu(hdr->seq_ctrl);
2268 u16 mpdu_seq_num = (sc & IEEE80211_SCTL_SEQ) >> 4;
2269 u16 head_seq_num, buf_size;
2270 int index;
2271
2272 buf_size = tid_agg_rx->buf_size;
2273 head_seq_num = tid_agg_rx->head_seq_num;
2274
2275 /* frame with out of date sequence number */
2276 if (seq_less(mpdu_seq_num, head_seq_num)) {
2277 dev_kfree_skb(skb);
2278 return true;
2279 }
2280
2281 /*
2282 * If frame the sequence number exceeds our buffering window
2283 * size release some previous frames to make room for this one.
2284 */
2285 if (!seq_less(mpdu_seq_num, head_seq_num + buf_size)) {
2286 head_seq_num = seq_inc(seq_sub(mpdu_seq_num, buf_size));
2287 /* release stored frames up to new head to stack */
2288 ieee80211_release_reorder_frames(hw, tid_agg_rx, head_seq_num);
2289 }
2290
2291 /* Now the new frame is always in the range of the reordering buffer */
2292
2293 index = seq_sub(mpdu_seq_num, tid_agg_rx->ssn) % tid_agg_rx->buf_size;
2294
2295 /* check if we already stored this frame */
2296 if (tid_agg_rx->reorder_buf[index]) {
2297 dev_kfree_skb(skb);
2298 return true;
2299 }
2300
2301 /*
2302 * If the current MPDU is in the right order and nothing else
2303 * is stored we can process it directly, no need to buffer it.
2304 */
2305 if (mpdu_seq_num == tid_agg_rx->head_seq_num &&
2306 tid_agg_rx->stored_mpdu_num == 0) {
2307 tid_agg_rx->head_seq_num = seq_inc(tid_agg_rx->head_seq_num);
2308 return false;
2309 }
2310
2311 /* put the frame in the reordering buffer */
2312 tid_agg_rx->reorder_buf[index] = skb;
2313 tid_agg_rx->reorder_time[index] = jiffies;
2314 tid_agg_rx->stored_mpdu_num++;
2315 /* release the buffer until next missing frame */
2316 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
2317 tid_agg_rx->buf_size;
2318 if (!tid_agg_rx->reorder_buf[index] &&
2319 tid_agg_rx->stored_mpdu_num > 1) {
2320 /*
2321 * No buffers ready to be released, but check whether any
2322 * frames in the reorder buffer have timed out.
2323 */
2324 int j;
2325 int skipped = 1;
2326 for (j = (index + 1) % tid_agg_rx->buf_size; j != index;
2327 j = (j + 1) % tid_agg_rx->buf_size) {
2328 if (!tid_agg_rx->reorder_buf[j]) {
2329 skipped++;
2330 continue;
2331 }
2332 if (!time_after(jiffies, tid_agg_rx->reorder_time[j] +
2333 HT_RX_REORDER_BUF_TIMEOUT))
2334 break;
2335
2336#ifdef CONFIG_MAC80211_HT_DEBUG
2337 if (net_ratelimit())
2338 printk(KERN_DEBUG "%s: release an RX reorder "
2339 "frame due to timeout on earlier "
2340 "frames\n",
2341 wiphy_name(hw->wiphy));
2342#endif
2343 ieee80211_release_reorder_frame(hw, tid_agg_rx, j);
2344
2345 /*
2346 * Increment the head seq# also for the skipped slots.
2347 */
2348 tid_agg_rx->head_seq_num =
2349 (tid_agg_rx->head_seq_num + skipped) & SEQ_MASK;
2350 skipped = 0;
2351 }
2352 } else while (tid_agg_rx->reorder_buf[index]) {
2353 ieee80211_release_reorder_frame(hw, tid_agg_rx, index);
2354 index = seq_sub(tid_agg_rx->head_seq_num, tid_agg_rx->ssn) %
2355 tid_agg_rx->buf_size;
2356 }
2357
2358 return true;
2359}
2360
2361/*
2362 * Reorder MPDUs from A-MPDUs, keeping them on a buffer. Returns
2363 * true if the MPDU was buffered, false if it should be processed.
2364 */
2365static bool ieee80211_rx_reorder_ampdu(struct ieee80211_local *local,
2366 struct sk_buff *skb)
2367{
2368 struct ieee80211_hw *hw = &local->hw;
2369 struct ieee80211_hdr *hdr = (struct ieee80211_hdr *) skb->data;
2370 struct sta_info *sta;
2371 struct tid_ampdu_rx *tid_agg_rx;
2372 u16 sc;
2373 int tid;
2374
2375 if (!ieee80211_is_data_qos(hdr->frame_control))
2376 return false;
2377
2378 /*
2379 * filter the QoS data rx stream according to
2380 * STA/TID and check if this STA/TID is on aggregation
2381 */
2382
2383 sta = sta_info_get(local, hdr->addr2);
2384 if (!sta)
2385 return false;
2386
2387 tid = *ieee80211_get_qos_ctl(hdr) & IEEE80211_QOS_CTL_TID_MASK;
2388
2389 if (sta->ampdu_mlme.tid_state_rx[tid] != HT_AGG_STATE_OPERATIONAL)
2390 return false;
2391
2392 tid_agg_rx = sta->ampdu_mlme.tid_rx[tid];
2393
2394 /* qos null data frames are excluded */
2395 if (unlikely(hdr->frame_control & cpu_to_le16(IEEE80211_STYPE_NULLFUNC)))
2396 return false;
2397
2398 /* new, potentially un-ordered, ampdu frame - process it */
2399
2400 /* reset session timer */
2401 if (tid_agg_rx->timeout)
2402 mod_timer(&tid_agg_rx->session_timer,
2403 TU_TO_EXP_TIME(tid_agg_rx->timeout));
2404
2405 /* if this mpdu is fragmented - terminate rx aggregation session */
2406 sc = le16_to_cpu(hdr->seq_ctrl);
2407 if (sc & IEEE80211_SCTL_FRAG) {
2408 ieee80211_sta_stop_rx_ba_session(sta->sdata, sta->sta.addr,
2409 tid, 0, WLAN_REASON_QSTA_REQUIRE_SETUP);
2410 dev_kfree_skb(skb);
2411 return true;
2412 }
2413
2414 return ieee80211_sta_manage_reorder_buf(hw, tid_agg_rx, skb);
2415}
2416
2417/* 2451/*
2418 * This is the receive path handler. It is called by a low level driver when an 2452 * This is the receive path handler. It is called by a low level driver when an
2419 * 802.11 MPDU is received from the hardware. 2453 * 802.11 MPDU is received from the hardware.
@@ -2495,20 +2529,7 @@ void ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb)
2495 return; 2529 return;
2496 } 2530 }
2497 2531
2498 /* 2532 __ieee80211_rx_handle_packet(hw, skb, rate);
2499 * In theory, the block ack reordering should happen after duplicate
2500 * removal (ieee80211_rx_h_check(), which is an RX handler). As such,
2501 * the call to ieee80211_rx_reorder_ampdu() should really be moved to
2502 * happen as a new RX handler between ieee80211_rx_h_check and
2503 * ieee80211_rx_h_decrypt. This cleanup may eventually happen, but for
2504 * the time being, the call can be here since RX reorder buf processing
2505 * will implicitly skip duplicates. We could, in theory at least,
2506 * process frames that ieee80211_rx_h_passive_scan would drop (e.g.,
2507 * frames from other than operational channel), but that should not
2508 * happen in normal networks.
2509 */
2510 if (!ieee80211_rx_reorder_ampdu(local, skb))
2511 __ieee80211_rx_handle_packet(hw, skb, rate);
2512 2533
2513 rcu_read_unlock(); 2534 rcu_read_unlock();
2514 2535
diff --git a/net/mac80211/status.c b/net/mac80211/status.c
index 9f91fd8e6efb..d78f36c64c7b 100644
--- a/net/mac80211/status.c
+++ b/net/mac80211/status.c
@@ -148,6 +148,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
148 struct net_device *prev_dev = NULL; 148 struct net_device *prev_dev = NULL;
149 struct sta_info *sta; 149 struct sta_info *sta;
150 int retry_count = -1, i; 150 int retry_count = -1, i;
151 bool injected;
151 152
152 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) { 153 for (i = 0; i < IEEE80211_TX_MAX_RATES; i++) {
153 /* the HW cannot have attempted that rate */ 154 /* the HW cannot have attempted that rate */
@@ -297,6 +298,9 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
297 /* for now report the total retry_count */ 298 /* for now report the total retry_count */
298 rthdr->data_retries = retry_count; 299 rthdr->data_retries = retry_count;
299 300
301 /* Need to make a copy before skb->cb gets cleared */
302 injected = !!(info->flags & IEEE80211_TX_CTL_INJECTED);
303
300 /* XXX: is this sufficient for BPF? */ 304 /* XXX: is this sufficient for BPF? */
301 skb_set_mac_header(skb, 0); 305 skb_set_mac_header(skb, 0);
302 skb->ip_summed = CHECKSUM_UNNECESSARY; 306 skb->ip_summed = CHECKSUM_UNNECESSARY;
@@ -311,7 +315,7 @@ void ieee80211_tx_status(struct ieee80211_hw *hw, struct sk_buff *skb)
311 continue; 315 continue;
312 316
313 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) && 317 if ((sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) &&
314 !(info->flags & IEEE80211_TX_CTL_INJECTED) && 318 !injected &&
315 (type == IEEE80211_FTYPE_DATA)) 319 (type == IEEE80211_FTYPE_DATA))
316 continue; 320 continue;
317 321
diff --git a/net/wireless/core.c b/net/wireless/core.c
index fe6f402a22af..c2a2c563d21a 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -45,6 +45,9 @@ DEFINE_MUTEX(cfg80211_mutex);
45/* for debugfs */ 45/* for debugfs */
46static struct dentry *ieee80211_debugfs_dir; 46static struct dentry *ieee80211_debugfs_dir;
47 47
48/* for the cleanup, scan and event works */
49struct workqueue_struct *cfg80211_wq;
50
48/* requires cfg80211_mutex to be held! */ 51/* requires cfg80211_mutex to be held! */
49struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx) 52struct cfg80211_registered_device *cfg80211_rdev_by_wiphy_idx(int wiphy_idx)
50{ 53{
@@ -727,7 +730,7 @@ static int cfg80211_netdev_notifier_call(struct notifier_block * nb,
727 break; 730 break;
728 case NETDEV_DOWN: 731 case NETDEV_DOWN:
729 dev_hold(dev); 732 dev_hold(dev);
730 schedule_work(&wdev->cleanup_work); 733 queue_work(cfg80211_wq, &wdev->cleanup_work);
731 break; 734 break;
732 case NETDEV_UP: 735 case NETDEV_UP:
733 /* 736 /*
@@ -845,8 +848,14 @@ static int __init cfg80211_init(void)
845 if (err) 848 if (err)
846 goto out_fail_reg; 849 goto out_fail_reg;
847 850
851 cfg80211_wq = create_singlethread_workqueue("cfg80211");
852 if (!cfg80211_wq)
853 goto out_fail_wq;
854
848 return 0; 855 return 0;
849 856
857out_fail_wq:
858 regulatory_exit();
850out_fail_reg: 859out_fail_reg:
851 debugfs_remove(ieee80211_debugfs_dir); 860 debugfs_remove(ieee80211_debugfs_dir);
852out_fail_nl80211: 861out_fail_nl80211:
@@ -868,5 +877,6 @@ static void cfg80211_exit(void)
868 wiphy_sysfs_exit(); 877 wiphy_sysfs_exit();
869 regulatory_exit(); 878 regulatory_exit();
870 unregister_pernet_device(&cfg80211_pernet_ops); 879 unregister_pernet_device(&cfg80211_pernet_ops);
880 destroy_workqueue(cfg80211_wq);
871} 881}
872module_exit(cfg80211_exit); 882module_exit(cfg80211_exit);
diff --git a/net/wireless/core.h b/net/wireless/core.h
index a9db9e6255bb..4ef3efc94106 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -91,6 +91,8 @@ bool wiphy_idx_valid(int wiphy_idx)
91 return (wiphy_idx >= 0); 91 return (wiphy_idx >= 0);
92} 92}
93 93
94
95extern struct workqueue_struct *cfg80211_wq;
94extern struct mutex cfg80211_mutex; 96extern struct mutex cfg80211_mutex;
95extern struct list_head cfg80211_rdev_list; 97extern struct list_head cfg80211_rdev_list;
96extern int cfg80211_rdev_list_generation; 98extern int cfg80211_rdev_list_generation;
diff --git a/net/wireless/ibss.c b/net/wireless/ibss.c
index 34dfc93fa713..6ef5a491fb4b 100644
--- a/net/wireless/ibss.c
+++ b/net/wireless/ibss.c
@@ -70,7 +70,7 @@ void cfg80211_ibss_joined(struct net_device *dev, const u8 *bssid, gfp_t gfp)
70 spin_lock_irqsave(&wdev->event_lock, flags); 70 spin_lock_irqsave(&wdev->event_lock, flags);
71 list_add_tail(&ev->list, &wdev->event_list); 71 list_add_tail(&ev->list, &wdev->event_list);
72 spin_unlock_irqrestore(&wdev->event_lock, flags); 72 spin_unlock_irqrestore(&wdev->event_lock, flags);
73 schedule_work(&rdev->event_work); 73 queue_work(cfg80211_wq, &rdev->event_work);
74} 74}
75EXPORT_SYMBOL(cfg80211_ibss_joined); 75EXPORT_SYMBOL(cfg80211_ibss_joined);
76 76
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 149539ade15e..a6028433e3a0 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -139,6 +139,8 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = {
139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 }, 139 [NL80211_ATTR_WPA_VERSIONS] = { .type = NLA_U32 },
140 [NL80211_ATTR_PID] = { .type = NLA_U32 }, 140 [NL80211_ATTR_PID] = { .type = NLA_U32 },
141 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 }, 141 [NL80211_ATTR_4ADDR] = { .type = NLA_U8 },
142 [NL80211_ATTR_PMKID] = { .type = NLA_BINARY,
143 .len = WLAN_PMKID_LEN },
142}; 144};
143 145
144/* policy for the attributes */ 146/* policy for the attributes */
@@ -450,6 +452,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
450 sizeof(u32) * dev->wiphy.n_cipher_suites, 452 sizeof(u32) * dev->wiphy.n_cipher_suites,
451 dev->wiphy.cipher_suites); 453 dev->wiphy.cipher_suites);
452 454
455 NLA_PUT_U8(msg, NL80211_ATTR_MAX_NUM_PMKIDS,
456 dev->wiphy.max_num_pmkids);
457
453 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES); 458 nl_modes = nla_nest_start(msg, NL80211_ATTR_SUPPORTED_IFTYPES);
454 if (!nl_modes) 459 if (!nl_modes)
455 goto nla_put_failure; 460 goto nla_put_failure;
@@ -561,6 +566,9 @@ static int nl80211_send_wiphy(struct sk_buff *msg, u32 pid, u32 seq, int flags,
561 CMD(deauth, DEAUTHENTICATE); 566 CMD(deauth, DEAUTHENTICATE);
562 CMD(disassoc, DISASSOCIATE); 567 CMD(disassoc, DISASSOCIATE);
563 CMD(join_ibss, JOIN_IBSS); 568 CMD(join_ibss, JOIN_IBSS);
569 CMD(set_pmksa, SET_PMKSA);
570 CMD(del_pmksa, DEL_PMKSA);
571 CMD(flush_pmksa, FLUSH_PMKSA);
564 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) { 572 if (dev->wiphy.flags & WIPHY_FLAG_NETNS_OK) {
565 i++; 573 i++;
566 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS); 574 NLA_PUT_U32(msg, i, NL80211_CMD_SET_WIPHY_NETNS);
@@ -4221,6 +4229,99 @@ static int nl80211_wiphy_netns(struct sk_buff *skb, struct genl_info *info)
4221 return err; 4229 return err;
4222} 4230}
4223 4231
4232static int nl80211_setdel_pmksa(struct sk_buff *skb, struct genl_info *info)
4233{
4234 struct cfg80211_registered_device *rdev;
4235 int (*rdev_ops)(struct wiphy *wiphy, struct net_device *dev,
4236 struct cfg80211_pmksa *pmksa) = NULL;
4237 int err;
4238 struct net_device *dev;
4239 struct cfg80211_pmksa pmksa;
4240
4241 memset(&pmksa, 0, sizeof(struct cfg80211_pmksa));
4242
4243 if (!info->attrs[NL80211_ATTR_MAC])
4244 return -EINVAL;
4245
4246 if (!info->attrs[NL80211_ATTR_PMKID])
4247 return -EINVAL;
4248
4249 rtnl_lock();
4250
4251 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4252 if (err)
4253 goto out_rtnl;
4254
4255 pmksa.pmkid = nla_data(info->attrs[NL80211_ATTR_PMKID]);
4256 pmksa.bssid = nla_data(info->attrs[NL80211_ATTR_MAC]);
4257
4258 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
4259 err = -EOPNOTSUPP;
4260 goto out;
4261 }
4262
4263 switch (info->genlhdr->cmd) {
4264 case NL80211_CMD_SET_PMKSA:
4265 rdev_ops = rdev->ops->set_pmksa;
4266 break;
4267 case NL80211_CMD_DEL_PMKSA:
4268 rdev_ops = rdev->ops->del_pmksa;
4269 break;
4270 default:
4271 WARN_ON(1);
4272 break;
4273 }
4274
4275 if (!rdev_ops) {
4276 err = -EOPNOTSUPP;
4277 goto out;
4278 }
4279
4280 err = rdev_ops(&rdev->wiphy, dev, &pmksa);
4281
4282 out:
4283 cfg80211_unlock_rdev(rdev);
4284 dev_put(dev);
4285 out_rtnl:
4286 rtnl_unlock();
4287
4288 return err;
4289}
4290
4291static int nl80211_flush_pmksa(struct sk_buff *skb, struct genl_info *info)
4292{
4293 struct cfg80211_registered_device *rdev;
4294 int err;
4295 struct net_device *dev;
4296
4297 rtnl_lock();
4298
4299 err = get_rdev_dev_by_info_ifindex(info, &rdev, &dev);
4300 if (err)
4301 goto out_rtnl;
4302
4303 if (dev->ieee80211_ptr->iftype != NL80211_IFTYPE_STATION) {
4304 err = -EOPNOTSUPP;
4305 goto out;
4306 }
4307
4308 if (!rdev->ops->flush_pmksa) {
4309 err = -EOPNOTSUPP;
4310 goto out;
4311 }
4312
4313 err = rdev->ops->flush_pmksa(&rdev->wiphy, dev);
4314
4315 out:
4316 cfg80211_unlock_rdev(rdev);
4317 dev_put(dev);
4318 out_rtnl:
4319 rtnl_unlock();
4320
4321 return err;
4322
4323}
4324
4224static struct genl_ops nl80211_ops[] = { 4325static struct genl_ops nl80211_ops[] = {
4225 { 4326 {
4226 .cmd = NL80211_CMD_GET_WIPHY, 4327 .cmd = NL80211_CMD_GET_WIPHY,
@@ -4465,6 +4566,25 @@ static struct genl_ops nl80211_ops[] = {
4465 .policy = nl80211_policy, 4566 .policy = nl80211_policy,
4466 .dumpit = nl80211_dump_survey, 4567 .dumpit = nl80211_dump_survey,
4467 }, 4568 },
4569 {
4570 .cmd = NL80211_CMD_SET_PMKSA,
4571 .doit = nl80211_setdel_pmksa,
4572 .policy = nl80211_policy,
4573 .flags = GENL_ADMIN_PERM,
4574 },
4575 {
4576 .cmd = NL80211_CMD_DEL_PMKSA,
4577 .doit = nl80211_setdel_pmksa,
4578 .policy = nl80211_policy,
4579 .flags = GENL_ADMIN_PERM,
4580 },
4581 {
4582 .cmd = NL80211_CMD_FLUSH_PMKSA,
4583 .doit = nl80211_flush_pmksa,
4584 .policy = nl80211_policy,
4585 .flags = GENL_ADMIN_PERM,
4586 },
4587
4468}; 4588};
4469static struct genl_multicast_group nl80211_mlme_mcgrp = { 4589static struct genl_multicast_group nl80211_mlme_mcgrp = {
4470 .name = "mlme", 4590 .name = "mlme",
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 1f33017737fd..c01470e7de15 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -1931,7 +1931,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
1931 const struct ieee80211_freq_range *freq_range = NULL; 1931 const struct ieee80211_freq_range *freq_range = NULL;
1932 const struct ieee80211_power_rule *power_rule = NULL; 1932 const struct ieee80211_power_rule *power_rule = NULL;
1933 1933
1934 printk(KERN_INFO "\t(start_freq - end_freq @ bandwidth), " 1934 printk(KERN_INFO " (start_freq - end_freq @ bandwidth), "
1935 "(max_antenna_gain, max_eirp)\n"); 1935 "(max_antenna_gain, max_eirp)\n");
1936 1936
1937 for (i = 0; i < rd->n_reg_rules; i++) { 1937 for (i = 0; i < rd->n_reg_rules; i++) {
@@ -1944,7 +1944,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
1944 * in certain regions 1944 * in certain regions
1945 */ 1945 */
1946 if (power_rule->max_antenna_gain) 1946 if (power_rule->max_antenna_gain)
1947 printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " 1947 printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), "
1948 "(%d mBi, %d mBm)\n", 1948 "(%d mBi, %d mBm)\n",
1949 freq_range->start_freq_khz, 1949 freq_range->start_freq_khz,
1950 freq_range->end_freq_khz, 1950 freq_range->end_freq_khz,
@@ -1952,7 +1952,7 @@ static void print_rd_rules(const struct ieee80211_regdomain *rd)
1952 power_rule->max_antenna_gain, 1952 power_rule->max_antenna_gain,
1953 power_rule->max_eirp); 1953 power_rule->max_eirp);
1954 else 1954 else
1955 printk(KERN_INFO "\t(%d KHz - %d KHz @ %d KHz), " 1955 printk(KERN_INFO " (%d KHz - %d KHz @ %d KHz), "
1956 "(N/A, %d mBm)\n", 1956 "(N/A, %d mBm)\n",
1957 freq_range->start_freq_khz, 1957 freq_range->start_freq_khz,
1958 freq_range->end_freq_khz, 1958 freq_range->end_freq_khz,
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 96df34c3c6ee..12dfa62aad18 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -88,7 +88,7 @@ void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted)
88 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req); 88 WARN_ON(request != wiphy_to_dev(request->wiphy)->scan_req);
89 89
90 request->aborted = aborted; 90 request->aborted = aborted;
91 schedule_work(&wiphy_to_dev(request->wiphy)->scan_done_wk); 91 queue_work(cfg80211_wq, &wiphy_to_dev(request->wiphy)->scan_done_wk);
92} 92}
93EXPORT_SYMBOL(cfg80211_scan_done); 93EXPORT_SYMBOL(cfg80211_scan_done);
94 94
diff --git a/net/wireless/sme.c b/net/wireless/sme.c
index 0115d07d2c1a..2333d78187e4 100644
--- a/net/wireless/sme.c
+++ b/net/wireless/sme.c
@@ -488,7 +488,7 @@ void cfg80211_connect_result(struct net_device *dev, const u8 *bssid,
488 spin_lock_irqsave(&wdev->event_lock, flags); 488 spin_lock_irqsave(&wdev->event_lock, flags);
489 list_add_tail(&ev->list, &wdev->event_list); 489 list_add_tail(&ev->list, &wdev->event_list);
490 spin_unlock_irqrestore(&wdev->event_lock, flags); 490 spin_unlock_irqrestore(&wdev->event_lock, flags);
491 schedule_work(&rdev->event_work); 491 queue_work(cfg80211_wq, &rdev->event_work);
492} 492}
493EXPORT_SYMBOL(cfg80211_connect_result); 493EXPORT_SYMBOL(cfg80211_connect_result);
494 494
@@ -583,7 +583,7 @@ void cfg80211_roamed(struct net_device *dev, const u8 *bssid,
583 spin_lock_irqsave(&wdev->event_lock, flags); 583 spin_lock_irqsave(&wdev->event_lock, flags);
584 list_add_tail(&ev->list, &wdev->event_list); 584 list_add_tail(&ev->list, &wdev->event_list);
585 spin_unlock_irqrestore(&wdev->event_lock, flags); 585 spin_unlock_irqrestore(&wdev->event_lock, flags);
586 schedule_work(&rdev->event_work); 586 queue_work(cfg80211_wq, &rdev->event_work);
587} 587}
588EXPORT_SYMBOL(cfg80211_roamed); 588EXPORT_SYMBOL(cfg80211_roamed);
589 589
@@ -681,7 +681,7 @@ void cfg80211_disconnected(struct net_device *dev, u16 reason,
681 spin_lock_irqsave(&wdev->event_lock, flags); 681 spin_lock_irqsave(&wdev->event_lock, flags);
682 list_add_tail(&ev->list, &wdev->event_list); 682 list_add_tail(&ev->list, &wdev->event_list);
683 spin_unlock_irqrestore(&wdev->event_lock, flags); 683 spin_unlock_irqrestore(&wdev->event_lock, flags);
684 schedule_work(&rdev->event_work); 684 queue_work(cfg80211_wq, &rdev->event_work);
685} 685}
686EXPORT_SYMBOL(cfg80211_disconnected); 686EXPORT_SYMBOL(cfg80211_disconnected);
687 687
diff --git a/net/wireless/wext-compat.c b/net/wireless/wext-compat.c
index 29091ac9f989..584eb4826e02 100644
--- a/net/wireless/wext-compat.c
+++ b/net/wireless/wext-compat.c
@@ -1401,6 +1401,47 @@ int cfg80211_wext_giwessid(struct net_device *dev,
1401} 1401}
1402EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid); 1402EXPORT_SYMBOL_GPL(cfg80211_wext_giwessid);
1403 1403
1404int cfg80211_wext_siwpmksa(struct net_device *dev,
1405 struct iw_request_info *info,
1406 struct iw_point *data, char *extra)
1407{
1408 struct wireless_dev *wdev = dev->ieee80211_ptr;
1409 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
1410 struct cfg80211_pmksa cfg_pmksa;
1411 struct iw_pmksa *pmksa = (struct iw_pmksa *)extra;
1412
1413 memset(&cfg_pmksa, 0, sizeof(struct cfg80211_pmksa));
1414
1415 if (wdev->iftype != NL80211_IFTYPE_STATION)
1416 return -EINVAL;
1417
1418 cfg_pmksa.bssid = pmksa->bssid.sa_data;
1419 cfg_pmksa.pmkid = pmksa->pmkid;
1420
1421 switch (pmksa->cmd) {
1422 case IW_PMKSA_ADD:
1423 if (!rdev->ops->set_pmksa)
1424 return -EOPNOTSUPP;
1425
1426 return rdev->ops->set_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1427
1428 case IW_PMKSA_REMOVE:
1429 if (!rdev->ops->del_pmksa)
1430 return -EOPNOTSUPP;
1431
1432 return rdev->ops->del_pmksa(&rdev->wiphy, dev, &cfg_pmksa);
1433
1434 case IW_PMKSA_FLUSH:
1435 if (!rdev->ops->flush_pmksa)
1436 return -EOPNOTSUPP;
1437
1438 return rdev->ops->flush_pmksa(&rdev->wiphy, dev);
1439
1440 default:
1441 return -EOPNOTSUPP;
1442 }
1443}
1444
1404static const iw_handler cfg80211_handlers[] = { 1445static const iw_handler cfg80211_handlers[] = {
1405 [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname, 1446 [IW_IOCTL_IDX(SIOCGIWNAME)] = (iw_handler) cfg80211_wext_giwname,
1406 [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq, 1447 [IW_IOCTL_IDX(SIOCSIWFREQ)] = (iw_handler) cfg80211_wext_siwfreq,
@@ -1433,6 +1474,7 @@ static const iw_handler cfg80211_handlers[] = {
1433 [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth, 1474 [IW_IOCTL_IDX(SIOCSIWAUTH)] = (iw_handler) cfg80211_wext_siwauth,
1434 [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth, 1475 [IW_IOCTL_IDX(SIOCGIWAUTH)] = (iw_handler) cfg80211_wext_giwauth,
1435 [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext, 1476 [IW_IOCTL_IDX(SIOCSIWENCODEEXT)]= (iw_handler) cfg80211_wext_siwencodeext,
1477 [IW_IOCTL_IDX(SIOCSIWPMKSA)] = (iw_handler) cfg80211_wext_siwpmksa,
1436}; 1478};
1437 1479
1438const struct iw_handler_def cfg80211_wext_handler = { 1480const struct iw_handler_def cfg80211_wext_handler = {
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index 58dfb954974a..5e1656bdf23b 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -802,7 +802,8 @@ static int ioctl_standard_iw_point(struct iw_point *iwp, unsigned int cmd,
802 } 802 }
803 803
804 /* Generate an event to notify listeners of the change */ 804 /* Generate an event to notify listeners of the change */
805 if ((descr->flags & IW_DESCR_FLAG_EVENT) && err == -EIWCOMMIT) { 805 if ((descr->flags & IW_DESCR_FLAG_EVENT) &&
806 ((err == 0) || (err == -EIWCOMMIT))) {
806 union iwreq_data *data = (union iwreq_data *) iwp; 807 union iwreq_data *data = (union iwreq_data *) iwp;
807 808
808 if (descr->flags & IW_DESCR_FLAG_RESTRICT) 809 if (descr->flags & IW_DESCR_FLAG_RESTRICT)