aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohn W. Linville <linville@tuxdriver.com>2011-03-15 14:16:48 -0400
committerJohn W. Linville <linville@tuxdriver.com>2011-03-15 14:16:48 -0400
commit106af2c99a5249b809aaed45b8353ac087821f4a (patch)
treeb9d13cc35cfdc3b763408287b4e50daf32fda53b
parent0c0217b016ba8a970a6f6ab62ad0d858f39881ca (diff)
parent7d2c16befae67b901e6750b845661c1fdffd19f1 (diff)
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6 into for-davem
-rw-r--r--drivers/net/wireless/ath/ath5k/base.c3
-rw-r--r--drivers/net/wireless/ath/ath5k/base.h1
-rw-r--r--drivers/net/wireless/ath/ath5k/mac80211-ops.c43
-rw-r--r--drivers/net/wireless/ath/ath9k/ar9485_initvals.h2
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h1
-rw-r--r--drivers/net/wireless/ath/ath9k/beacon.c13
-rw-r--r--drivers/net/wireless/ath/ath9k/calib.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/hw.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.c89
-rw-r--r--drivers/net/wireless/ath/ath9k/mac.h3
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c56
-rw-r--r--drivers/net/wireless/ath/ath9k/recv.c4
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c44
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn-lib.c135
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-agn.c87
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-commands.h8
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-core.h6
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-dev.h12
-rw-r--r--drivers/net/wireless/iwlwifi/iwl-scan.c41
-rw-r--r--drivers/net/wireless/libertas/mesh.c11
-rw-r--r--drivers/net/wireless/wl1251/ps.c41
-rw-r--r--include/net/cfg80211.h8
-rw-r--r--include/net/mac80211.h7
-rw-r--r--net/mac80211/cfg.c21
-rw-r--r--net/mac80211/chan.c3
-rw-r--r--net/mac80211/driver-ops.h26
-rw-r--r--net/mac80211/driver-trace.h52
-rw-r--r--net/mac80211/mlme.c37
-rw-r--r--net/mac80211/rc80211_minstrel_ht.c41
-rw-r--r--net/wireless/ethtool.c33
31 files changed, 596 insertions, 244 deletions
diff --git a/drivers/net/wireless/ath/ath5k/base.c b/drivers/net/wireless/ath/ath5k/base.c
index e6ff62e60a7..4d7f21ee111 100644
--- a/drivers/net/wireless/ath/ath5k/base.c
+++ b/drivers/net/wireless/ath/ath5k/base.c
@@ -943,6 +943,7 @@ ath5k_txq_setup(struct ath5k_softc *sc,
943 spin_lock_init(&txq->lock); 943 spin_lock_init(&txq->lock);
944 txq->setup = true; 944 txq->setup = true;
945 txq->txq_len = 0; 945 txq->txq_len = 0;
946 txq->txq_max = ATH5K_TXQ_LEN_MAX;
946 txq->txq_poll_mark = false; 947 txq->txq_poll_mark = false;
947 txq->txq_stuck = 0; 948 txq->txq_stuck = 0;
948 } 949 }
@@ -1534,7 +1535,7 @@ ath5k_tx_queue(struct ieee80211_hw *hw, struct sk_buff *skb,
1534 goto drop_packet; 1535 goto drop_packet;
1535 } 1536 }
1536 1537
1537 if (txq->txq_len >= ATH5K_TXQ_LEN_MAX) 1538 if (txq->txq_len >= txq->txq_max)
1538 ieee80211_stop_queue(hw, txq->qnum); 1539 ieee80211_stop_queue(hw, txq->qnum);
1539 1540
1540 spin_lock_irqsave(&sc->txbuflock, flags); 1541 spin_lock_irqsave(&sc->txbuflock, flags);
diff --git a/drivers/net/wireless/ath/ath5k/base.h b/drivers/net/wireless/ath/ath5k/base.h
index 8d1df1fa235..978f1f4ac2f 100644
--- a/drivers/net/wireless/ath/ath5k/base.h
+++ b/drivers/net/wireless/ath/ath5k/base.h
@@ -86,6 +86,7 @@ struct ath5k_txq {
86 spinlock_t lock; /* lock on q and link */ 86 spinlock_t lock; /* lock on q and link */
87 bool setup; 87 bool setup;
88 int txq_len; /* number of queued buffers */ 88 int txq_len; /* number of queued buffers */
89 int txq_max; /* max allowed num of queued buffers */
89 bool txq_poll_mark; 90 bool txq_poll_mark;
90 unsigned int txq_stuck; /* informational counter */ 91 unsigned int txq_stuck; /* informational counter */
91}; 92};
diff --git a/drivers/net/wireless/ath/ath5k/mac80211-ops.c b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
index c9b0b676add..9be29b728b1 100644
--- a/drivers/net/wireless/ath/ath5k/mac80211-ops.c
+++ b/drivers/net/wireless/ath/ath5k/mac80211-ops.c
@@ -740,6 +740,47 @@ ath5k_get_antenna(struct ieee80211_hw *hw, u32 *tx_ant, u32 *rx_ant)
740} 740}
741 741
742 742
743static void ath5k_get_ringparam(struct ieee80211_hw *hw,
744 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
745{
746 struct ath5k_softc *sc = hw->priv;
747
748 *tx = sc->txqs[AR5K_TX_QUEUE_ID_DATA_MIN].txq_max;
749
750 *tx_max = ATH5K_TXQ_LEN_MAX;
751 *rx = *rx_max = ATH_RXBUF;
752}
753
754
755static int ath5k_set_ringparam(struct ieee80211_hw *hw, u32 tx, u32 rx)
756{
757 struct ath5k_softc *sc = hw->priv;
758 u16 qnum;
759
760 /* only support setting tx ring size for now */
761 if (rx != ATH_RXBUF)
762 return -EINVAL;
763
764 /* restrict tx ring size min/max */
765 if (!tx || tx > ATH5K_TXQ_LEN_MAX)
766 return -EINVAL;
767
768 for (qnum = 0; qnum < ARRAY_SIZE(sc->txqs); qnum++) {
769 if (!sc->txqs[qnum].setup)
770 continue;
771 if (sc->txqs[qnum].qnum < AR5K_TX_QUEUE_ID_DATA_MIN ||
772 sc->txqs[qnum].qnum > AR5K_TX_QUEUE_ID_DATA_MAX)
773 continue;
774
775 sc->txqs[qnum].txq_max = tx;
776 if (sc->txqs[qnum].txq_len >= sc->txqs[qnum].txq_max)
777 ieee80211_stop_queue(hw, sc->txqs[qnum].qnum);
778 }
779
780 return 0;
781}
782
783
743const struct ieee80211_ops ath5k_hw_ops = { 784const struct ieee80211_ops ath5k_hw_ops = {
744 .tx = ath5k_tx, 785 .tx = ath5k_tx,
745 .start = ath5k_start, 786 .start = ath5k_start,
@@ -778,4 +819,6 @@ const struct ieee80211_ops ath5k_hw_ops = {
778 /* .napi_poll = not implemented */ 819 /* .napi_poll = not implemented */
779 .set_antenna = ath5k_set_antenna, 820 .set_antenna = ath5k_set_antenna,
780 .get_antenna = ath5k_get_antenna, 821 .get_antenna = ath5k_get_antenna,
822 .set_ringparam = ath5k_set_ringparam,
823 .get_ringparam = ath5k_get_ringparam,
781}; 824};
diff --git a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
index eac4d8526fc..71cc0a3a29f 100644
--- a/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
+++ b/drivers/net/wireless/ath/ath9k/ar9485_initvals.h
@@ -667,6 +667,7 @@ static const u32 ar9485_1_0_pcie_phy_clkreq_enable_L1[][2] = {
667 667
668static const u32 ar9485_1_0_soc_preamble[][2] = { 668static const u32 ar9485_1_0_soc_preamble[][2] = {
669 /* Addr allmodes */ 669 /* Addr allmodes */
670 {0x00004090, 0x00aa10aa},
670 {0x000040a4, 0x00a0c9c9}, 671 {0x000040a4, 0x00a0c9c9},
671 {0x00007048, 0x00000004}, 672 {0x00007048, 0x00000004},
672}; 673};
@@ -1708,6 +1709,7 @@ static const u32 ar9485_1_1_pcie_phy_clkreq_disable_L1[][2] = {
1708static const u32 ar9485_1_1_soc_preamble[][2] = { 1709static const u32 ar9485_1_1_soc_preamble[][2] = {
1709 /* Addr allmodes */ 1710 /* Addr allmodes */
1710 {0x00004014, 0xba280400}, 1711 {0x00004014, 0xba280400},
1712 {0x00004090, 0x00aa10aa},
1711 {0x000040a4, 0x00a0c9c9}, 1713 {0x000040a4, 0x00a0c9c9},
1712 {0x00007010, 0x00000022}, 1714 {0x00007010, 0x00000022},
1713 {0x00007020, 0x00000000}, 1715 {0x00007020, 0x00000000},
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index c718ab512a9..099bd4183ad 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -189,7 +189,6 @@ struct ath_txq {
189 u32 axq_ampdu_depth; 189 u32 axq_ampdu_depth;
190 bool stopped; 190 bool stopped;
191 bool axq_tx_inprogress; 191 bool axq_tx_inprogress;
192 bool txq_flush_inprogress;
193 struct list_head axq_acq; 192 struct list_head axq_acq;
194 struct list_head txq_fifo[ATH_TXFIFO_DEPTH]; 193 struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
195 struct list_head txq_fifo_pending; 194 struct list_head txq_fifo_pending;
diff --git a/drivers/net/wireless/ath/ath9k/beacon.c b/drivers/net/wireless/ath/ath9k/beacon.c
index a4bdfdb043e..6d2a545fc35 100644
--- a/drivers/net/wireless/ath/ath9k/beacon.c
+++ b/drivers/net/wireless/ath/ath9k/beacon.c
@@ -373,6 +373,7 @@ void ath_beacon_tasklet(unsigned long data)
373 ath_dbg(common, ATH_DBG_BSTUCK, 373 ath_dbg(common, ATH_DBG_BSTUCK,
374 "missed %u consecutive beacons\n", 374 "missed %u consecutive beacons\n",
375 sc->beacon.bmisscnt); 375 sc->beacon.bmisscnt);
376 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
376 ath9k_hw_bstuck_nfcal(ah); 377 ath9k_hw_bstuck_nfcal(ah);
377 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) { 378 } else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
378 ath_dbg(common, ATH_DBG_BSTUCK, 379 ath_dbg(common, ATH_DBG_BSTUCK,
@@ -450,16 +451,6 @@ void ath_beacon_tasklet(unsigned long data)
450 sc->beacon.updateslot = OK; 451 sc->beacon.updateslot = OK;
451 } 452 }
452 if (bfaddr != 0) { 453 if (bfaddr != 0) {
453 /*
454 * Stop any current dma and put the new frame(s) on the queue.
455 * This should never fail since we check above that no frames
456 * are still pending on the queue.
457 */
458 if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
459 ath_err(common, "beacon queue %u did not stop?\n",
460 sc->beacon.beaconq);
461 }
462
463 /* NB: cabq traffic should already be queued and primed */ 454 /* NB: cabq traffic should already be queued and primed */
464 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr); 455 ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
465 ath9k_hw_txstart(ah, sc->beacon.beaconq); 456 ath9k_hw_txstart(ah, sc->beacon.beaconq);
@@ -780,7 +771,7 @@ void ath9k_set_beaconing_status(struct ath_softc *sc, bool status)
780 ah->imask &= ~ATH9K_INT_SWBA; 771 ah->imask &= ~ATH9K_INT_SWBA;
781 ath9k_hw_set_interrupts(ah, ah->imask); 772 ath9k_hw_set_interrupts(ah, ah->imask);
782 tasklet_kill(&sc->bcon_tasklet); 773 tasklet_kill(&sc->bcon_tasklet);
783 ath9k_hw_stoptxdma(ah, sc->beacon.beaconq); 774 ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
784 } 775 }
785 ath9k_ps_restore(sc); 776 ath9k_ps_restore(sc);
786} 777}
diff --git a/drivers/net/wireless/ath/ath9k/calib.c b/drivers/net/wireless/ath/ath9k/calib.c
index b4a92a4313f..8649581fa4d 100644
--- a/drivers/net/wireless/ath/ath9k/calib.c
+++ b/drivers/net/wireless/ath/ath9k/calib.c
@@ -262,7 +262,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
262 * since 250us often results in NF load timeout and causes deaf 262 * since 250us often results in NF load timeout and causes deaf
263 * condition during stress testing 12/12/2009 263 * condition during stress testing 12/12/2009
264 */ 264 */
265 for (j = 0; j < 1000; j++) { 265 for (j = 0; j < 10000; j++) {
266 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) & 266 if ((REG_READ(ah, AR_PHY_AGC_CONTROL) &
267 AR_PHY_AGC_CONTROL_NF) == 0) 267 AR_PHY_AGC_CONTROL_NF) == 0)
268 break; 268 break;
@@ -278,7 +278,7 @@ void ath9k_hw_loadnf(struct ath_hw *ah, struct ath9k_channel *chan)
278 * here, the baseband nf cal will just be capped by our present 278 * here, the baseband nf cal will just be capped by our present
279 * noisefloor until the next calibration timer. 279 * noisefloor until the next calibration timer.
280 */ 280 */
281 if (j == 1000) { 281 if (j == 10000) {
282 ath_dbg(common, ATH_DBG_ANY, 282 ath_dbg(common, ATH_DBG_ANY,
283 "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n", 283 "Timeout while waiting for nf to load: AR_PHY_AGC_CONTROL=0x%x\n",
284 REG_READ(ah, AR_PHY_AGC_CONTROL)); 284 REG_READ(ah, AR_PHY_AGC_CONTROL));
diff --git a/drivers/net/wireless/ath/ath9k/hw.c b/drivers/net/wireless/ath/ath9k/hw.c
index 9a3438174f8..338b07502f1 100644
--- a/drivers/net/wireless/ath/ath9k/hw.c
+++ b/drivers/net/wireless/ath/ath9k/hw.c
@@ -701,7 +701,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
701 AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); 701 AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
702 702
703 REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c); 703 REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x1142c);
704 udelay(100); 704 udelay(1000);
705 705
706 REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666); 706 REG_WRITE(ah, AR_RTC_PLL_CONTROL2, 0x886666);
707 707
@@ -713,7 +713,7 @@ static void ath9k_hw_init_pll(struct ath_hw *ah,
713 REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3, 713 REG_RMW_FIELD(ah, AR_CH0_BB_DPLL3,
714 AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL); 714 AR_CH0_DPLL3_PHASE_SHIFT, DPLL3_PHASE_SHIFT_VAL);
715 REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c); 715 REG_WRITE(ah, AR_RTC_PLL_CONTROL, 0x142c);
716 udelay(110); 716 udelay(1000);
717 } 717 }
718 718
719 pll = ath9k_hw_compute_pll_control(ah, chan); 719 pll = ath9k_hw_compute_pll_control(ah, chan);
diff --git a/drivers/net/wireless/ath/ath9k/hw.h b/drivers/net/wireless/ath/ath9k/hw.h
index ef79f4c876c..6650fd48415 100644
--- a/drivers/net/wireless/ath/ath9k/hw.h
+++ b/drivers/net/wireless/ath/ath9k/hw.h
@@ -95,9 +95,9 @@
95#define REG_READ_FIELD(_a, _r, _f) \ 95#define REG_READ_FIELD(_a, _r, _f) \
96 (((REG_READ(_a, _r) & _f) >> _f##_S)) 96 (((REG_READ(_a, _r) & _f) >> _f##_S))
97#define REG_SET_BIT(_a, _r, _f) \ 97#define REG_SET_BIT(_a, _r, _f) \
98 REG_WRITE(_a, _r, REG_READ(_a, _r) | _f) 98 REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
99#define REG_CLR_BIT(_a, _r, _f) \ 99#define REG_CLR_BIT(_a, _r, _f) \
100 REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f) 100 REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
101 101
102#define DO_DELAY(x) do { \ 102#define DO_DELAY(x) do { \
103 if ((++(x) % 64) == 0) \ 103 if ((++(x) % 64) == 0) \
diff --git a/drivers/net/wireless/ath/ath9k/mac.c b/drivers/net/wireless/ath/ath9k/mac.c
index 5efc869d65f..562257ac52c 100644
--- a/drivers/net/wireless/ath/ath9k/mac.c
+++ b/drivers/net/wireless/ath/ath9k/mac.c
@@ -143,84 +143,59 @@ bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel)
143} 143}
144EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel); 144EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
145 145
146bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q) 146void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
147{ 147{
148#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */ 148 int i, q;
149#define ATH9K_TIME_QUANTUM 100 /* usec */
150 struct ath_common *common = ath9k_hw_common(ah);
151 struct ath9k_hw_capabilities *pCap = &ah->caps;
152 struct ath9k_tx_queue_info *qi;
153 u32 tsfLow, j, wait;
154 u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
155 149
156 if (q >= pCap->total_queues) { 150 REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
157 ath_dbg(common, ATH_DBG_QUEUE,
158 "Stopping TX DMA, invalid queue: %u\n", q);
159 return false;
160 }
161 151
162 qi = &ah->txq[q]; 152 REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
163 if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) { 153 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
164 ath_dbg(common, ATH_DBG_QUEUE, 154 REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
165 "Stopping TX DMA, inactive queue: %u\n", q);
166 return false;
167 }
168 155
169 REG_WRITE(ah, AR_Q_TXD, 1 << q); 156 for (q = 0; q < AR_NUM_QCU; q++) {
157 for (i = 0; i < 1000; i++) {
158 if (i)
159 udelay(5);
170 160
171 for (wait = wait_time; wait != 0; wait--) { 161 if (!ath9k_hw_numtxpending(ah, q))
172 if (ath9k_hw_numtxpending(ah, q) == 0) 162 break;
173 break; 163 }
174 udelay(ATH9K_TIME_QUANTUM);
175 } 164 }
176 165
177 if (ath9k_hw_numtxpending(ah, q)) { 166 REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
178 ath_dbg(common, ATH_DBG_QUEUE, 167 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
179 "%s: Num of pending TX Frames %d on Q %d\n", 168 REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
180 __func__, ath9k_hw_numtxpending(ah, q), q);
181
182 for (j = 0; j < 2; j++) {
183 tsfLow = REG_READ(ah, AR_TSF_L32);
184 REG_WRITE(ah, AR_QUIET2,
185 SM(10, AR_QUIET2_QUIET_DUR));
186 REG_WRITE(ah, AR_QUIET_PERIOD, 100);
187 REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
188 REG_SET_BIT(ah, AR_TIMER_MODE,
189 AR_QUIET_TIMER_EN);
190
191 if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
192 break;
193 169
194 ath_dbg(common, ATH_DBG_QUEUE, 170 REG_WRITE(ah, AR_Q_TXD, 0);
195 "TSF has moved while trying to set quiet time TSF: 0x%08x\n", 171}
196 tsfLow); 172EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
197 }
198 173
199 REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 174bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
175{
176#define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */
177#define ATH9K_TIME_QUANTUM 100 /* usec */
178 int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
179 int wait;
200 180
201 udelay(200); 181 REG_WRITE(ah, AR_Q_TXD, 1 << q);
202 REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
203 182
204 wait = wait_time; 183 for (wait = wait_time; wait != 0; wait--) {
205 while (ath9k_hw_numtxpending(ah, q)) { 184 if (wait != wait_time)
206 if ((--wait) == 0) {
207 ath_err(common,
208 "Failed to stop TX DMA in 100 msec after killing last frame\n");
209 break;
210 }
211 udelay(ATH9K_TIME_QUANTUM); 185 udelay(ATH9K_TIME_QUANTUM);
212 }
213 186
214 REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH); 187 if (ath9k_hw_numtxpending(ah, q) == 0)
188 break;
215 } 189 }
216 190
217 REG_WRITE(ah, AR_Q_TXD, 0); 191 REG_WRITE(ah, AR_Q_TXD, 0);
192
218 return wait != 0; 193 return wait != 0;
219 194
220#undef ATH9K_TX_STOP_DMA_TIMEOUT 195#undef ATH9K_TX_STOP_DMA_TIMEOUT
221#undef ATH9K_TIME_QUANTUM 196#undef ATH9K_TIME_QUANTUM
222} 197}
223EXPORT_SYMBOL(ath9k_hw_stoptxdma); 198EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
224 199
225void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs) 200void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
226{ 201{
diff --git a/drivers/net/wireless/ath/ath9k/mac.h b/drivers/net/wireless/ath/ath9k/mac.h
index 04d58ae923b..b2b2ff852c3 100644
--- a/drivers/net/wireless/ath/ath9k/mac.h
+++ b/drivers/net/wireless/ath/ath9k/mac.h
@@ -676,7 +676,8 @@ void ath9k_hw_txstart(struct ath_hw *ah, u32 q);
676void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds); 676void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
677u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q); 677u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
678bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel); 678bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
679bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q); 679bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
680void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
680void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs); 681void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
681bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q, 682bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
682 const struct ath9k_tx_queue_info *qinfo); 683 const struct ath9k_tx_queue_info *qinfo);
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2e228aada1a..115f162c617 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -2128,56 +2128,42 @@ static void ath9k_set_coverage_class(struct ieee80211_hw *hw, u8 coverage_class)
2128 2128
2129static void ath9k_flush(struct ieee80211_hw *hw, bool drop) 2129static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
2130{ 2130{
2131#define ATH_FLUSH_TIMEOUT 60 /* ms */
2132 struct ath_softc *sc = hw->priv; 2131 struct ath_softc *sc = hw->priv;
2133 struct ath_txq *txq = NULL; 2132 int timeout = 200; /* ms */
2134 struct ath_hw *ah = sc->sc_ah; 2133 int i, j;
2135 struct ath_common *common = ath9k_hw_common(ah);
2136 int i, j, npend = 0;
2137 2134
2135 ath9k_ps_wakeup(sc);
2138 mutex_lock(&sc->mutex); 2136 mutex_lock(&sc->mutex);
2139 2137
2140 cancel_delayed_work_sync(&sc->tx_complete_work); 2138 cancel_delayed_work_sync(&sc->tx_complete_work);
2141 2139
2142 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 2140 if (drop)
2143 if (!ATH_TXQ_SETUP(sc, i)) 2141 timeout = 1;
2144 continue;
2145 txq = &sc->tx.txq[i];
2146 2142
2147 if (!drop) { 2143 for (j = 0; j < timeout; j++) {
2148 for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) { 2144 int npend = 0;
2149 if (!ath9k_has_pending_frames(sc, txq)) 2145
2150 break; 2146 if (j)
2151 usleep_range(1000, 2000); 2147 usleep_range(1000, 2000);
2152 }
2153 }
2154 2148
2155 if (drop || ath9k_has_pending_frames(sc, txq)) { 2149 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
2156 ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n", 2150 if (!ATH_TXQ_SETUP(sc, i))
2157 txq->axq_qnum); 2151 continue;
2158 spin_lock_bh(&txq->axq_lock); 2152
2159 txq->txq_flush_inprogress = true; 2153 npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
2160 spin_unlock_bh(&txq->axq_lock);
2161
2162 ath9k_ps_wakeup(sc);
2163 ath9k_hw_stoptxdma(ah, txq->axq_qnum);
2164 npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
2165 ath9k_ps_restore(sc);
2166 if (npend)
2167 break;
2168
2169 ath_draintxq(sc, txq, false);
2170 txq->txq_flush_inprogress = false;
2171 } 2154 }
2155
2156 if (!npend)
2157 goto out;
2172 } 2158 }
2173 2159
2174 if (npend) { 2160 if (!ath_drain_all_txq(sc, false))
2175 ath_reset(sc, false); 2161 ath_reset(sc, false);
2176 txq->txq_flush_inprogress = false;
2177 }
2178 2162
2163out:
2179 ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0); 2164 ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
2180 mutex_unlock(&sc->mutex); 2165 mutex_unlock(&sc->mutex);
2166 ath9k_ps_restore(sc);
2181} 2167}
2182 2168
2183struct ieee80211_ops ath9k_ops = { 2169struct ieee80211_ops ath9k_ops = {
diff --git a/drivers/net/wireless/ath/ath9k/recv.c b/drivers/net/wireless/ath/ath9k/recv.c
index cb559e345b8..a9c3f4672aa 100644
--- a/drivers/net/wireless/ath/ath9k/recv.c
+++ b/drivers/net/wireless/ath/ath9k/recv.c
@@ -413,9 +413,7 @@ u32 ath_calcrxfilter(struct ath_softc *sc)
413 * mode interface or when in monitor mode. AP mode does not need this 413 * mode interface or when in monitor mode. AP mode does not need this
414 * since it receives all in-BSS frames anyway. 414 * since it receives all in-BSS frames anyway.
415 */ 415 */
416 if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) && 416 if (sc->sc_ah->is_monitoring)
417 (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
418 (sc->sc_ah->is_monitoring))
419 rfilt |= ATH9K_RX_FILTER_PROM; 417 rfilt |= ATH9K_RX_FILTER_PROM;
420 418
421 if (sc->rx.rxfilter & FIF_CONTROL) 419 if (sc->rx.rxfilter & FIF_CONTROL)
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index e16136d6179..ef22096d40c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -166,7 +166,7 @@ static void ath_tx_flush_tid(struct ath_softc *sc, struct ath_atx_tid *tid)
166 fi = get_frame_info(bf->bf_mpdu); 166 fi = get_frame_info(bf->bf_mpdu);
167 if (fi->retries) { 167 if (fi->retries) {
168 ath_tx_update_baw(sc, tid, fi->seqno); 168 ath_tx_update_baw(sc, tid, fi->seqno);
169 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0); 169 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
170 } else { 170 } else {
171 ath_tx_send_normal(sc, txq, NULL, &bf_head); 171 ath_tx_send_normal(sc, txq, NULL, &bf_head);
172 } 172 }
@@ -1194,16 +1194,14 @@ bool ath_drain_all_txq(struct ath_softc *sc, bool retry_tx)
1194 if (sc->sc_flags & SC_OP_INVALID) 1194 if (sc->sc_flags & SC_OP_INVALID)
1195 return true; 1195 return true;
1196 1196
1197 /* Stop beacon queue */ 1197 ath9k_hw_abort_tx_dma(ah);
1198 ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
1199 1198
1200 /* Stop data queues */ 1199 /* Check if any queue remains active */
1201 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { 1200 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
1202 if (ATH_TXQ_SETUP(sc, i)) { 1201 if (!ATH_TXQ_SETUP(sc, i))
1203 txq = &sc->tx.txq[i]; 1202 continue;
1204 ath9k_hw_stoptxdma(ah, txq->axq_qnum); 1203
1205 npend += ath9k_hw_numtxpending(ah, txq->axq_qnum); 1204 npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
1206 }
1207 } 1205 }
1208 1206
1209 if (npend) 1207 if (npend)
@@ -2014,8 +2012,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2014 spin_lock_bh(&txq->axq_lock); 2012 spin_lock_bh(&txq->axq_lock);
2015 if (list_empty(&txq->axq_q)) { 2013 if (list_empty(&txq->axq_q)) {
2016 txq->axq_link = NULL; 2014 txq->axq_link = NULL;
2017 if (sc->sc_flags & SC_OP_TXAGGR && 2015 if (sc->sc_flags & SC_OP_TXAGGR)
2018 !txq->txq_flush_inprogress)
2019 ath_txq_schedule(sc, txq); 2016 ath_txq_schedule(sc, txq);
2020 spin_unlock_bh(&txq->axq_lock); 2017 spin_unlock_bh(&txq->axq_lock);
2021 break; 2018 break;
@@ -2096,7 +2093,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2096 2093
2097 spin_lock_bh(&txq->axq_lock); 2094 spin_lock_bh(&txq->axq_lock);
2098 2095
2099 if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress) 2096 if (sc->sc_flags & SC_OP_TXAGGR)
2100 ath_txq_schedule(sc, txq); 2097 ath_txq_schedule(sc, txq);
2101 spin_unlock_bh(&txq->axq_lock); 2098 spin_unlock_bh(&txq->axq_lock);
2102 } 2099 }
@@ -2267,18 +2264,17 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2267 2264
2268 spin_lock_bh(&txq->axq_lock); 2265 spin_lock_bh(&txq->axq_lock);
2269 2266
2270 if (!txq->txq_flush_inprogress) { 2267 if (!list_empty(&txq->txq_fifo_pending)) {
2271 if (!list_empty(&txq->txq_fifo_pending)) { 2268 INIT_LIST_HEAD(&bf_head);
2272 INIT_LIST_HEAD(&bf_head); 2269 bf = list_first_entry(&txq->txq_fifo_pending,
2273 bf = list_first_entry(&txq->txq_fifo_pending, 2270 struct ath_buf, list);
2274 struct ath_buf, list); 2271 list_cut_position(&bf_head,
2275 list_cut_position(&bf_head, 2272 &txq->txq_fifo_pending,
2276 &txq->txq_fifo_pending, 2273 &bf->bf_lastbf->list);
2277 &bf->bf_lastbf->list); 2274 ath_tx_txqaddbuf(sc, txq, &bf_head);
2278 ath_tx_txqaddbuf(sc, txq, &bf_head); 2275 } else if (sc->sc_flags & SC_OP_TXAGGR)
2279 } else if (sc->sc_flags & SC_OP_TXAGGR) 2276 ath_txq_schedule(sc, txq);
2280 ath_txq_schedule(sc, txq); 2277
2281 }
2282 spin_unlock_bh(&txq->axq_lock); 2278 spin_unlock_bh(&txq->axq_lock);
2283 } 2279 }
2284} 2280}
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
index 25fccf9a300..2003c1d4295 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn-lib.c
@@ -1115,6 +1115,18 @@ static int iwl_get_channels_for_scan(struct iwl_priv *priv,
1115 return added; 1115 return added;
1116} 1116}
1117 1117
1118static int iwl_fill_offch_tx(struct iwl_priv *priv, void *data, size_t maxlen)
1119{
1120 struct sk_buff *skb = priv->_agn.offchan_tx_skb;
1121
1122 if (skb->len < maxlen)
1123 maxlen = skb->len;
1124
1125 memcpy(data, skb->data, maxlen);
1126
1127 return maxlen;
1128}
1129
1118int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif) 1130int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1119{ 1131{
1120 struct iwl_host_cmd cmd = { 1132 struct iwl_host_cmd cmd = {
@@ -1157,17 +1169,25 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1157 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH; 1169 scan->quiet_plcp_th = IWL_PLCP_QUIET_THRESH;
1158 scan->quiet_time = IWL_ACTIVE_QUIET_TIME; 1170 scan->quiet_time = IWL_ACTIVE_QUIET_TIME;
1159 1171
1160 if (iwl_is_any_associated(priv)) { 1172 if (priv->scan_type != IWL_SCAN_OFFCH_TX &&
1173 iwl_is_any_associated(priv)) {
1161 u16 interval = 0; 1174 u16 interval = 0;
1162 u32 extra; 1175 u32 extra;
1163 u32 suspend_time = 100; 1176 u32 suspend_time = 100;
1164 u32 scan_suspend_time = 100; 1177 u32 scan_suspend_time = 100;
1165 1178
1166 IWL_DEBUG_INFO(priv, "Scanning while associated...\n"); 1179 IWL_DEBUG_INFO(priv, "Scanning while associated...\n");
1167 if (priv->is_internal_short_scan) 1180 switch (priv->scan_type) {
1181 case IWL_SCAN_OFFCH_TX:
1182 WARN_ON(1);
1183 break;
1184 case IWL_SCAN_RADIO_RESET:
1168 interval = 0; 1185 interval = 0;
1169 else 1186 break;
1187 case IWL_SCAN_NORMAL:
1170 interval = vif->bss_conf.beacon_int; 1188 interval = vif->bss_conf.beacon_int;
1189 break;
1190 }
1171 1191
1172 scan->suspend_time = 0; 1192 scan->suspend_time = 0;
1173 scan->max_out_time = cpu_to_le32(200 * 1024); 1193 scan->max_out_time = cpu_to_le32(200 * 1024);
@@ -1180,29 +1200,41 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1180 scan->suspend_time = cpu_to_le32(scan_suspend_time); 1200 scan->suspend_time = cpu_to_le32(scan_suspend_time);
1181 IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n", 1201 IWL_DEBUG_SCAN(priv, "suspend_time 0x%X beacon interval %d\n",
1182 scan_suspend_time, interval); 1202 scan_suspend_time, interval);
1203 } else if (priv->scan_type == IWL_SCAN_OFFCH_TX) {
1204 scan->suspend_time = 0;
1205 scan->max_out_time =
1206 cpu_to_le32(1024 * priv->_agn.offchan_tx_timeout);
1183 } 1207 }
1184 1208
1185 if (priv->is_internal_short_scan) { 1209 switch (priv->scan_type) {
1210 case IWL_SCAN_RADIO_RESET:
1186 IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n"); 1211 IWL_DEBUG_SCAN(priv, "Start internal passive scan.\n");
1187 } else if (priv->scan_request->n_ssids) { 1212 break;
1188 int i, p = 0; 1213 case IWL_SCAN_NORMAL:
1189 IWL_DEBUG_SCAN(priv, "Kicking off active scan\n"); 1214 if (priv->scan_request->n_ssids) {
1190 for (i = 0; i < priv->scan_request->n_ssids; i++) { 1215 int i, p = 0;
1191 /* always does wildcard anyway */ 1216 IWL_DEBUG_SCAN(priv, "Kicking off active scan\n");
1192 if (!priv->scan_request->ssids[i].ssid_len) 1217 for (i = 0; i < priv->scan_request->n_ssids; i++) {
1193 continue; 1218 /* always does wildcard anyway */
1194 scan->direct_scan[p].id = WLAN_EID_SSID; 1219 if (!priv->scan_request->ssids[i].ssid_len)
1195 scan->direct_scan[p].len = 1220 continue;
1196 priv->scan_request->ssids[i].ssid_len; 1221 scan->direct_scan[p].id = WLAN_EID_SSID;
1197 memcpy(scan->direct_scan[p].ssid, 1222 scan->direct_scan[p].len =
1198 priv->scan_request->ssids[i].ssid, 1223 priv->scan_request->ssids[i].ssid_len;
1199 priv->scan_request->ssids[i].ssid_len); 1224 memcpy(scan->direct_scan[p].ssid,
1200 n_probes++; 1225 priv->scan_request->ssids[i].ssid,
1201 p++; 1226 priv->scan_request->ssids[i].ssid_len);
1202 } 1227 n_probes++;
1203 is_active = true; 1228 p++;
1204 } else 1229 }
1205 IWL_DEBUG_SCAN(priv, "Start passive scan.\n"); 1230 is_active = true;
1231 } else
1232 IWL_DEBUG_SCAN(priv, "Start passive scan.\n");
1233 break;
1234 case IWL_SCAN_OFFCH_TX:
1235 IWL_DEBUG_SCAN(priv, "Start offchannel TX scan.\n");
1236 break;
1237 }
1206 1238
1207 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK; 1239 scan->tx_cmd.tx_flags = TX_CMD_FLG_SEQ_CTL_MSK;
1208 scan->tx_cmd.sta_id = ctx->bcast_sta_id; 1240 scan->tx_cmd.sta_id = ctx->bcast_sta_id;
@@ -1300,38 +1332,77 @@ int iwlagn_request_scan(struct iwl_priv *priv, struct ieee80211_vif *vif)
1300 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS; 1332 rx_chain |= rx_ant << RXON_RX_CHAIN_FORCE_SEL_POS;
1301 rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS; 1333 rx_chain |= 0x1 << RXON_RX_CHAIN_DRIVER_FORCE_POS;
1302 scan->rx_chain = cpu_to_le16(rx_chain); 1334 scan->rx_chain = cpu_to_le16(rx_chain);
1303 if (!priv->is_internal_short_scan) { 1335 switch (priv->scan_type) {
1336 case IWL_SCAN_NORMAL:
1304 cmd_len = iwl_fill_probe_req(priv, 1337 cmd_len = iwl_fill_probe_req(priv,
1305 (struct ieee80211_mgmt *)scan->data, 1338 (struct ieee80211_mgmt *)scan->data,
1306 vif->addr, 1339 vif->addr,
1307 priv->scan_request->ie, 1340 priv->scan_request->ie,
1308 priv->scan_request->ie_len, 1341 priv->scan_request->ie_len,
1309 IWL_MAX_SCAN_SIZE - sizeof(*scan)); 1342 IWL_MAX_SCAN_SIZE - sizeof(*scan));
1310 } else { 1343 break;
1344 case IWL_SCAN_RADIO_RESET:
1311 /* use bcast addr, will not be transmitted but must be valid */ 1345 /* use bcast addr, will not be transmitted but must be valid */
1312 cmd_len = iwl_fill_probe_req(priv, 1346 cmd_len = iwl_fill_probe_req(priv,
1313 (struct ieee80211_mgmt *)scan->data, 1347 (struct ieee80211_mgmt *)scan->data,
1314 iwl_bcast_addr, NULL, 0, 1348 iwl_bcast_addr, NULL, 0,
1315 IWL_MAX_SCAN_SIZE - sizeof(*scan)); 1349 IWL_MAX_SCAN_SIZE - sizeof(*scan));
1316 1350 break;
1351 case IWL_SCAN_OFFCH_TX:
1352 cmd_len = iwl_fill_offch_tx(priv, scan->data,
1353 IWL_MAX_SCAN_SIZE
1354 - sizeof(*scan)
1355 - sizeof(struct iwl_scan_channel));
1356 scan->scan_flags |= IWL_SCAN_FLAGS_ACTION_FRAME_TX;
1357 break;
1358 default:
1359 BUG();
1317 } 1360 }
1318 scan->tx_cmd.len = cpu_to_le16(cmd_len); 1361 scan->tx_cmd.len = cpu_to_le16(cmd_len);
1319 1362
1320 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK | 1363 scan->filter_flags |= (RXON_FILTER_ACCEPT_GRP_MSK |
1321 RXON_FILTER_BCON_AWARE_MSK); 1364 RXON_FILTER_BCON_AWARE_MSK);
1322 1365
1323 if (priv->is_internal_short_scan) { 1366 switch (priv->scan_type) {
1367 case IWL_SCAN_RADIO_RESET:
1324 scan->channel_count = 1368 scan->channel_count =
1325 iwl_get_single_channel_for_scan(priv, vif, band, 1369 iwl_get_single_channel_for_scan(priv, vif, band,
1326 (void *)&scan->data[le16_to_cpu( 1370 (void *)&scan->data[cmd_len]);
1327 scan->tx_cmd.len)]); 1371 break;
1328 } else { 1372 case IWL_SCAN_NORMAL:
1329 scan->channel_count = 1373 scan->channel_count =
1330 iwl_get_channels_for_scan(priv, vif, band, 1374 iwl_get_channels_for_scan(priv, vif, band,
1331 is_active, n_probes, 1375 is_active, n_probes,
1332 (void *)&scan->data[le16_to_cpu( 1376 (void *)&scan->data[cmd_len]);
1333 scan->tx_cmd.len)]); 1377 break;
1378 case IWL_SCAN_OFFCH_TX: {
1379 struct iwl_scan_channel *scan_ch;
1380
1381 scan->channel_count = 1;
1382
1383 scan_ch = (void *)&scan->data[cmd_len];
1384 scan_ch->type = SCAN_CHANNEL_TYPE_ACTIVE;
1385 scan_ch->channel =
1386 cpu_to_le16(priv->_agn.offchan_tx_chan->hw_value);
1387 scan_ch->active_dwell =
1388 cpu_to_le16(priv->_agn.offchan_tx_timeout);
1389 scan_ch->passive_dwell = 0;
1390
1391 /* Set txpower levels to defaults */
1392 scan_ch->dsp_atten = 110;
1393
1394 /* NOTE: if we were doing 6Mb OFDM for scans we'd use
1395 * power level:
1396 * scan_ch->tx_gain = ((1 << 5) | (2 << 3)) | 3;
1397 */
1398 if (priv->_agn.offchan_tx_chan->band == IEEE80211_BAND_5GHZ)
1399 scan_ch->tx_gain = ((1 << 5) | (3 << 3)) | 3;
1400 else
1401 scan_ch->tx_gain = ((1 << 5) | (5 << 3));
1402 }
1403 break;
1334 } 1404 }
1405
1335 if (scan->channel_count == 0) { 1406 if (scan->channel_count == 0) {
1336 IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count); 1407 IWL_DEBUG_SCAN(priv, "channel count %d\n", scan->channel_count);
1337 return -EIO; 1408 return -EIO;
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c
index e0cd3e27a0d..581dc9f1027 100644
--- a/drivers/net/wireless/iwlwifi/iwl-agn.c
+++ b/drivers/net/wireless/iwlwifi/iwl-agn.c
@@ -2937,6 +2937,91 @@ static void iwl_bg_rx_replenish(struct work_struct *data)
2937 mutex_unlock(&priv->mutex); 2937 mutex_unlock(&priv->mutex);
2938} 2938}
2939 2939
2940static int iwl_mac_offchannel_tx(struct ieee80211_hw *hw, struct sk_buff *skb,
2941 struct ieee80211_channel *chan,
2942 enum nl80211_channel_type channel_type,
2943 unsigned int wait)
2944{
2945 struct iwl_priv *priv = hw->priv;
2946 int ret;
2947
2948 /* Not supported if we don't have PAN */
2949 if (!(priv->valid_contexts & BIT(IWL_RXON_CTX_PAN))) {
2950 ret = -EOPNOTSUPP;
2951 goto free;
2952 }
2953
2954 /* Not supported on pre-P2P firmware */
2955 if (!(priv->contexts[IWL_RXON_CTX_PAN].interface_modes &
2956 BIT(NL80211_IFTYPE_P2P_CLIENT))) {
2957 ret = -EOPNOTSUPP;
2958 goto free;
2959 }
2960
2961 mutex_lock(&priv->mutex);
2962
2963 if (!priv->contexts[IWL_RXON_CTX_PAN].is_active) {
2964 /*
2965 * If the PAN context is free, use the normal
2966 * way of doing remain-on-channel offload + TX.
2967 */
2968 ret = 1;
2969 goto out;
2970 }
2971
2972 /* TODO: queue up if scanning? */
2973 if (test_bit(STATUS_SCANNING, &priv->status) ||
2974 priv->_agn.offchan_tx_skb) {
2975 ret = -EBUSY;
2976 goto out;
2977 }
2978
2979 /*
2980 * max_scan_ie_len doesn't include the blank SSID or the header,
2981 * so need to add that again here.
2982 */
2983 if (skb->len > hw->wiphy->max_scan_ie_len + 24 + 2) {
2984 ret = -ENOBUFS;
2985 goto out;
2986 }
2987
2988 priv->_agn.offchan_tx_skb = skb;
2989 priv->_agn.offchan_tx_timeout = wait;
2990 priv->_agn.offchan_tx_chan = chan;
2991
2992 ret = iwl_scan_initiate(priv, priv->contexts[IWL_RXON_CTX_PAN].vif,
2993 IWL_SCAN_OFFCH_TX, chan->band);
2994 if (ret)
2995 priv->_agn.offchan_tx_skb = NULL;
2996 out:
2997 mutex_unlock(&priv->mutex);
2998 free:
2999 if (ret < 0)
3000 kfree_skb(skb);
3001
3002 return ret;
3003}
3004
3005static int iwl_mac_offchannel_tx_cancel_wait(struct ieee80211_hw *hw)
3006{
3007 struct iwl_priv *priv = hw->priv;
3008 int ret;
3009
3010 mutex_lock(&priv->mutex);
3011
3012 if (!priv->_agn.offchan_tx_skb)
3013 return -EINVAL;
3014
3015 priv->_agn.offchan_tx_skb = NULL;
3016
3017 ret = iwl_scan_cancel_timeout(priv, 200);
3018 if (ret)
3019 ret = -EIO;
3020 mutex_unlock(&priv->mutex);
3021
3022 return ret;
3023}
3024
2940/***************************************************************************** 3025/*****************************************************************************
2941 * 3026 *
2942 * mac80211 entry point functions 3027 * mac80211 entry point functions
@@ -3815,6 +3900,8 @@ struct ieee80211_ops iwlagn_hw_ops = {
3815 .tx_last_beacon = iwl_mac_tx_last_beacon, 3900 .tx_last_beacon = iwl_mac_tx_last_beacon,
3816 .remain_on_channel = iwl_mac_remain_on_channel, 3901 .remain_on_channel = iwl_mac_remain_on_channel,
3817 .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel, 3902 .cancel_remain_on_channel = iwl_mac_cancel_remain_on_channel,
3903 .offchannel_tx = iwl_mac_offchannel_tx,
3904 .offchannel_tx_cancel_wait = iwl_mac_offchannel_tx_cancel_wait,
3818}; 3905};
3819 3906
3820static void iwl_hw_detect(struct iwl_priv *priv) 3907static void iwl_hw_detect(struct iwl_priv *priv)
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h
index 03cfb74da2b..ca42ffa63ed 100644
--- a/drivers/net/wireless/iwlwifi/iwl-commands.h
+++ b/drivers/net/wireless/iwlwifi/iwl-commands.h
@@ -2964,9 +2964,15 @@ struct iwl3945_scan_cmd {
2964 u8 data[0]; 2964 u8 data[0];
2965} __packed; 2965} __packed;
2966 2966
2967enum iwl_scan_flags {
2968 /* BIT(0) currently unused */
2969 IWL_SCAN_FLAGS_ACTION_FRAME_TX = BIT(1),
2970 /* bits 2-7 reserved */
2971};
2972
2967struct iwl_scan_cmd { 2973struct iwl_scan_cmd {
2968 __le16 len; 2974 __le16 len;
2969 u8 reserved0; 2975 u8 scan_flags; /* scan flags: see enum iwl_scan_flags */
2970 u8 channel_count; /* # channels in channel list */ 2976 u8 channel_count; /* # channels in channel list */
2971 __le16 quiet_time; /* dwell only this # millisecs on quiet channel 2977 __le16 quiet_time; /* dwell only this # millisecs on quiet channel
2972 * (only for active scan) */ 2978 * (only for active scan) */
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h
index af47750f898..b316d833d9a 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 "iwl-dev.h"
67
66/************************ 68/************************
67 * forward declarations * 69 * forward declarations *
68 ************************/ 70 ************************/
@@ -551,6 +553,10 @@ u16 iwl_get_passive_dwell_time(struct iwl_priv *priv,
551 struct ieee80211_vif *vif); 553 struct ieee80211_vif *vif);
552void iwl_setup_scan_deferred_work(struct iwl_priv *priv); 554void iwl_setup_scan_deferred_work(struct iwl_priv *priv);
553void iwl_cancel_scan_deferred_work(struct iwl_priv *priv); 555void iwl_cancel_scan_deferred_work(struct iwl_priv *priv);
556int __must_check iwl_scan_initiate(struct iwl_priv *priv,
557 struct ieee80211_vif *vif,
558 enum iwl_scan_type scan_type,
559 enum ieee80211_band band);
554 560
555/* For faster active scanning, scan will move to the next channel if fewer than 561/* For faster active scanning, scan will move to the next channel if fewer than
556 * PLCP_QUIET_THRESH packets are heard on this channel within 562 * PLCP_QUIET_THRESH packets are heard on this channel within
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h
index 6a41deba686..68b953f2bdc 100644
--- a/drivers/net/wireless/iwlwifi/iwl-dev.h
+++ b/drivers/net/wireless/iwlwifi/iwl-dev.h
@@ -1230,6 +1230,12 @@ struct iwl_rxon_context {
1230 } ht; 1230 } ht;
1231}; 1231};
1232 1232
1233enum iwl_scan_type {
1234 IWL_SCAN_NORMAL,
1235 IWL_SCAN_RADIO_RESET,
1236 IWL_SCAN_OFFCH_TX,
1237};
1238
1233struct iwl_priv { 1239struct iwl_priv {
1234 1240
1235 /* ieee device used by generic ieee processing code */ 1241 /* ieee device used by generic ieee processing code */
@@ -1290,7 +1296,7 @@ struct iwl_priv {
1290 enum ieee80211_band scan_band; 1296 enum ieee80211_band scan_band;
1291 struct cfg80211_scan_request *scan_request; 1297 struct cfg80211_scan_request *scan_request;
1292 struct ieee80211_vif *scan_vif; 1298 struct ieee80211_vif *scan_vif;
1293 bool is_internal_short_scan; 1299 enum iwl_scan_type scan_type;
1294 u8 scan_tx_ant[IEEE80211_NUM_BANDS]; 1300 u8 scan_tx_ant[IEEE80211_NUM_BANDS];
1295 u8 mgmt_tx_ant; 1301 u8 mgmt_tx_ant;
1296 1302
@@ -1504,6 +1510,10 @@ struct iwl_priv {
1504 struct delayed_work hw_roc_work; 1510 struct delayed_work hw_roc_work;
1505 enum nl80211_channel_type hw_roc_chantype; 1511 enum nl80211_channel_type hw_roc_chantype;
1506 int hw_roc_duration; 1512 int hw_roc_duration;
1513
1514 struct sk_buff *offchan_tx_skb;
1515 int offchan_tx_timeout;
1516 struct ieee80211_channel *offchan_tx_chan;
1507 } _agn; 1517 } _agn;
1508#endif 1518#endif
1509 }; 1519 };
diff --git a/drivers/net/wireless/iwlwifi/iwl-scan.c b/drivers/net/wireless/iwlwifi/iwl-scan.c
index faa6d34cb65..3a4d9e6b042 100644
--- a/drivers/net/wireless/iwlwifi/iwl-scan.c
+++ b/drivers/net/wireless/iwlwifi/iwl-scan.c
@@ -101,7 +101,7 @@ static void iwl_complete_scan(struct iwl_priv *priv, bool aborted)
101 ieee80211_scan_completed(priv->hw, aborted); 101 ieee80211_scan_completed(priv->hw, aborted);
102 } 102 }
103 103
104 priv->is_internal_short_scan = false; 104 priv->scan_type = IWL_SCAN_NORMAL;
105 priv->scan_vif = NULL; 105 priv->scan_vif = NULL;
106 priv->scan_request = NULL; 106 priv->scan_request = NULL;
107} 107}
@@ -339,10 +339,10 @@ void iwl_init_scan_params(struct iwl_priv *priv)
339 priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx; 339 priv->scan_tx_ant[IEEE80211_BAND_2GHZ] = ant_idx;
340} 340}
341 341
342static int __must_check iwl_scan_initiate(struct iwl_priv *priv, 342int __must_check iwl_scan_initiate(struct iwl_priv *priv,
343 struct ieee80211_vif *vif, 343 struct ieee80211_vif *vif,
344 bool internal, 344 enum iwl_scan_type scan_type,
345 enum ieee80211_band band) 345 enum ieee80211_band band)
346{ 346{
347 int ret; 347 int ret;
348 348
@@ -370,17 +370,19 @@ static int __must_check iwl_scan_initiate(struct iwl_priv *priv,
370 } 370 }
371 371
372 IWL_DEBUG_SCAN(priv, "Starting %sscan...\n", 372 IWL_DEBUG_SCAN(priv, "Starting %sscan...\n",
373 internal ? "internal short " : ""); 373 scan_type == IWL_SCAN_NORMAL ? "" :
374 scan_type == IWL_SCAN_OFFCH_TX ? "offchan TX " :
375 "internal short ");
374 376
375 set_bit(STATUS_SCANNING, &priv->status); 377 set_bit(STATUS_SCANNING, &priv->status);
376 priv->is_internal_short_scan = internal; 378 priv->scan_type = scan_type;
377 priv->scan_start = jiffies; 379 priv->scan_start = jiffies;
378 priv->scan_band = band; 380 priv->scan_band = band;
379 381
380 ret = priv->cfg->ops->utils->request_scan(priv, vif); 382 ret = priv->cfg->ops->utils->request_scan(priv, vif);
381 if (ret) { 383 if (ret) {
382 clear_bit(STATUS_SCANNING, &priv->status); 384 clear_bit(STATUS_SCANNING, &priv->status);
383 priv->is_internal_short_scan = false; 385 priv->scan_type = IWL_SCAN_NORMAL;
384 return ret; 386 return ret;
385 } 387 }
386 388
@@ -405,7 +407,7 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
405 mutex_lock(&priv->mutex); 407 mutex_lock(&priv->mutex);
406 408
407 if (test_bit(STATUS_SCANNING, &priv->status) && 409 if (test_bit(STATUS_SCANNING, &priv->status) &&
408 !priv->is_internal_short_scan) { 410 priv->scan_type != IWL_SCAN_NORMAL) {
409 IWL_DEBUG_SCAN(priv, "Scan already in progress.\n"); 411 IWL_DEBUG_SCAN(priv, "Scan already in progress.\n");
410 ret = -EAGAIN; 412 ret = -EAGAIN;
411 goto out_unlock; 413 goto out_unlock;
@@ -419,11 +421,11 @@ int iwl_mac_hw_scan(struct ieee80211_hw *hw,
419 * If an internal scan is in progress, just set 421 * If an internal scan is in progress, just set
420 * up the scan_request as per above. 422 * up the scan_request as per above.
421 */ 423 */
422 if (priv->is_internal_short_scan) { 424 if (priv->scan_type != IWL_SCAN_NORMAL) {
423 IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n"); 425 IWL_DEBUG_SCAN(priv, "SCAN request during internal scan\n");
424 ret = 0; 426 ret = 0;
425 } else 427 } else
426 ret = iwl_scan_initiate(priv, vif, false, 428 ret = iwl_scan_initiate(priv, vif, IWL_SCAN_NORMAL,
427 req->channels[0]->band); 429 req->channels[0]->band);
428 430
429 IWL_DEBUG_MAC80211(priv, "leave\n"); 431 IWL_DEBUG_MAC80211(priv, "leave\n");
@@ -452,7 +454,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
452 454
453 mutex_lock(&priv->mutex); 455 mutex_lock(&priv->mutex);
454 456
455 if (priv->is_internal_short_scan == true) { 457 if (priv->scan_type == IWL_SCAN_RADIO_RESET) {
456 IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n"); 458 IWL_DEBUG_SCAN(priv, "Internal scan already in progress\n");
457 goto unlock; 459 goto unlock;
458 } 460 }
@@ -462,7 +464,7 @@ static void iwl_bg_start_internal_scan(struct work_struct *work)
462 goto unlock; 464 goto unlock;
463 } 465 }
464 466
465 if (iwl_scan_initiate(priv, NULL, true, priv->band)) 467 if (iwl_scan_initiate(priv, NULL, IWL_SCAN_RADIO_RESET, priv->band))
466 IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n"); 468 IWL_DEBUG_SCAN(priv, "failed to start internal short scan\n");
467 unlock: 469 unlock:
468 mutex_unlock(&priv->mutex); 470 mutex_unlock(&priv->mutex);
@@ -549,8 +551,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
549 container_of(work, struct iwl_priv, scan_completed); 551 container_of(work, struct iwl_priv, scan_completed);
550 bool aborted; 552 bool aborted;
551 553
552 IWL_DEBUG_SCAN(priv, "Completed %sscan.\n", 554 IWL_DEBUG_SCAN(priv, "Completed scan.\n");
553 priv->is_internal_short_scan ? "internal short " : "");
554 555
555 cancel_delayed_work(&priv->scan_check); 556 cancel_delayed_work(&priv->scan_check);
556 557
@@ -565,7 +566,13 @@ static void iwl_bg_scan_completed(struct work_struct *work)
565 goto out_settings; 566 goto out_settings;
566 } 567 }
567 568
568 if (priv->is_internal_short_scan && !aborted) { 569 if (priv->scan_type == IWL_SCAN_OFFCH_TX && priv->_agn.offchan_tx_skb) {
570 ieee80211_tx_status_irqsafe(priv->hw,
571 priv->_agn.offchan_tx_skb);
572 priv->_agn.offchan_tx_skb = NULL;
573 }
574
575 if (priv->scan_type != IWL_SCAN_NORMAL && !aborted) {
569 int err; 576 int err;
570 577
571 /* Check if mac80211 requested scan during our internal scan */ 578 /* Check if mac80211 requested scan during our internal scan */
@@ -573,7 +580,7 @@ static void iwl_bg_scan_completed(struct work_struct *work)
573 goto out_complete; 580 goto out_complete;
574 581
575 /* If so request a new scan */ 582 /* If so request a new scan */
576 err = iwl_scan_initiate(priv, priv->scan_vif, false, 583 err = iwl_scan_initiate(priv, priv->scan_vif, IWL_SCAN_NORMAL,
577 priv->scan_request->channels[0]->band); 584 priv->scan_request->channels[0]->band);
578 if (err) { 585 if (err) {
579 IWL_DEBUG_SCAN(priv, 586 IWL_DEBUG_SCAN(priv,
diff --git a/drivers/net/wireless/libertas/mesh.c b/drivers/net/wireless/libertas/mesh.c
index acf3bf63ee3..9d097b9c800 100644
--- a/drivers/net/wireless/libertas/mesh.c
+++ b/drivers/net/wireless/libertas/mesh.c
@@ -918,7 +918,6 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
918 char *buf) 918 char *buf)
919{ 919{
920 struct mrvl_mesh_defaults defs; 920 struct mrvl_mesh_defaults defs;
921 int maxlen;
922 int ret; 921 int ret;
923 922
924 ret = mesh_get_default_parameters(dev, &defs); 923 ret = mesh_get_default_parameters(dev, &defs);
@@ -931,13 +930,11 @@ static ssize_t mesh_id_get(struct device *dev, struct device_attribute *attr,
931 defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN; 930 defs.meshie.val.mesh_id_len = IEEE80211_MAX_SSID_LEN;
932 } 931 }
933 932
934 /* SSID not null terminated: reserve room for \0 + \n */ 933 memcpy(buf, defs.meshie.val.mesh_id, defs.meshie.val.mesh_id_len);
935 maxlen = defs.meshie.val.mesh_id_len + 2; 934 buf[defs.meshie.val.mesh_id_len] = '\n';
936 maxlen = (PAGE_SIZE > maxlen) ? maxlen : PAGE_SIZE; 935 buf[defs.meshie.val.mesh_id_len + 1] = '\0';
937 936
938 defs.meshie.val.mesh_id[defs.meshie.val.mesh_id_len] = '\0'; 937 return defs.meshie.val.mesh_id_len + 1;
939
940 return snprintf(buf, maxlen, "%s\n", defs.meshie.val.mesh_id);
941} 938}
942 939
943/** 940/**
diff --git a/drivers/net/wireless/wl1251/ps.c b/drivers/net/wireless/wl1251/ps.c
index 9ba23ede51b..9cc514703d2 100644
--- a/drivers/net/wireless/wl1251/ps.c
+++ b/drivers/net/wireless/wl1251/ps.c
@@ -58,7 +58,6 @@ void wl1251_ps_elp_sleep(struct wl1251 *wl)
58 unsigned long delay; 58 unsigned long delay;
59 59
60 if (wl->psm) { 60 if (wl->psm) {
61 cancel_delayed_work(&wl->elp_work);
62 delay = msecs_to_jiffies(ELP_ENTRY_DELAY); 61 delay = msecs_to_jiffies(ELP_ENTRY_DELAY);
63 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay); 62 ieee80211_queue_delayed_work(wl->hw, &wl->elp_work, delay);
64 } 63 }
@@ -69,6 +68,9 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
69 unsigned long timeout, start; 68 unsigned long timeout, start;
70 u32 elp_reg; 69 u32 elp_reg;
71 70
71 if (delayed_work_pending(&wl->elp_work))
72 cancel_delayed_work(&wl->elp_work);
73
72 if (!wl->elp) 74 if (!wl->elp)
73 return 0; 75 return 0;
74 76
@@ -102,38 +104,6 @@ int wl1251_ps_elp_wakeup(struct wl1251 *wl)
102 return 0; 104 return 0;
103} 105}
104 106
105static int wl1251_ps_set_elp(struct wl1251 *wl, bool enable)
106{
107 int ret;
108
109 if (enable) {
110 wl1251_debug(DEBUG_PSM, "sleep auth psm/elp");
111
112 ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
113 if (ret < 0)
114 return ret;
115
116 wl1251_ps_elp_sleep(wl);
117 } else {
118 wl1251_debug(DEBUG_PSM, "sleep auth cam");
119
120 /*
121 * When the target is in ELP, we can only
122 * access the ELP control register. Thus,
123 * we have to wake the target up before
124 * changing the power authorization.
125 */
126
127 wl1251_ps_elp_wakeup(wl);
128
129 ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
130 if (ret < 0)
131 return ret;
132 }
133
134 return 0;
135}
136
137int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode) 107int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
138{ 108{
139 int ret; 109 int ret;
@@ -162,7 +132,7 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
162 if (ret < 0) 132 if (ret < 0)
163 return ret; 133 return ret;
164 134
165 ret = wl1251_ps_set_elp(wl, true); 135 ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_ELP);
166 if (ret < 0) 136 if (ret < 0)
167 return ret; 137 return ret;
168 138
@@ -171,7 +141,8 @@ int wl1251_ps_set_mode(struct wl1251 *wl, enum wl1251_cmd_ps_mode mode)
171 case STATION_ACTIVE_MODE: 141 case STATION_ACTIVE_MODE:
172 default: 142 default:
173 wl1251_debug(DEBUG_PSM, "leaving psm"); 143 wl1251_debug(DEBUG_PSM, "leaving psm");
174 ret = wl1251_ps_set_elp(wl, false); 144
145 ret = wl1251_acx_sleep_auth(wl, WL1251_PSM_CAM);
175 if (ret < 0) 146 if (ret < 0)
176 return ret; 147 return ret;
177 148
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h
index 1ac5786da14..60f7876b6da 100644
--- a/include/net/cfg80211.h
+++ b/include/net/cfg80211.h
@@ -1197,6 +1197,10 @@ struct cfg80211_pmksa {
1197 * (also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX). 1197 * (also see nl80211.h @NL80211_ATTR_WIPHY_ANTENNA_TX).
1198 * 1198 *
1199 * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant). 1199 * @get_antenna: Get current antenna configuration from device (tx_ant, rx_ant).
1200 *
1201 * @set_ringparam: Set tx and rx ring sizes.
1202 *
1203 * @get_ringparam: Get tx and rx ring current and maximum sizes.
1200 */ 1204 */
1201struct cfg80211_ops { 1205struct cfg80211_ops {
1202 int (*suspend)(struct wiphy *wiphy); 1206 int (*suspend)(struct wiphy *wiphy);
@@ -1364,6 +1368,10 @@ struct cfg80211_ops {
1364 1368
1365 int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant); 1369 int (*set_antenna)(struct wiphy *wiphy, u32 tx_ant, u32 rx_ant);
1366 int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant); 1370 int (*get_antenna)(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant);
1371
1372 int (*set_ringparam)(struct wiphy *wiphy, u32 tx, u32 rx);
1373 void (*get_ringparam)(struct wiphy *wiphy,
1374 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
1367}; 1375};
1368 1376
1369/* 1377/*
diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 2b072fa9939..8650e7bf2ed 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -1804,6 +1804,10 @@ enum ieee80211_ampdu_mlme_action {
1804 * return value is 1, then the @remain_on_channel will be used with a 1804 * return value is 1, then the @remain_on_channel will be used with a
1805 * regular transmission (if supported.) 1805 * regular transmission (if supported.)
1806 * @offchannel_tx_cancel_wait: cancel wait associated with offchannel TX 1806 * @offchannel_tx_cancel_wait: cancel wait associated with offchannel TX
1807 *
1808 * @set_ringparam: Set tx and rx ring sizes.
1809 *
1810 * @get_ringparam: Get tx and rx ring current and maximum sizes.
1807 */ 1811 */
1808struct ieee80211_ops { 1812struct ieee80211_ops {
1809 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb); 1813 void (*tx)(struct ieee80211_hw *hw, struct sk_buff *skb);
@@ -1888,6 +1892,9 @@ struct ieee80211_ops {
1888 enum nl80211_channel_type channel_type, 1892 enum nl80211_channel_type channel_type,
1889 unsigned int wait); 1893 unsigned int wait);
1890 int (*offchannel_tx_cancel_wait)(struct ieee80211_hw *hw); 1894 int (*offchannel_tx_cancel_wait)(struct ieee80211_hw *hw);
1895 int (*set_ringparam)(struct ieee80211_hw *hw, u32 tx, u32 rx);
1896 void (*get_ringparam)(struct ieee80211_hw *hw,
1897 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max);
1891}; 1898};
1892 1899
1893/** 1900/**
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 7b701dcddb5..334213571ad 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -834,6 +834,10 @@ static int ieee80211_change_station(struct wiphy *wiphy,
834 834
835 rcu_read_unlock(); 835 rcu_read_unlock();
836 836
837 if (sdata->vif.type == NL80211_IFTYPE_STATION &&
838 params->sta_flags_mask & BIT(NL80211_STA_FLAG_AUTHORIZED))
839 ieee80211_recalc_ps(local, -1);
840
837 return 0; 841 return 0;
838} 842}
839 843
@@ -2008,6 +2012,21 @@ static int ieee80211_get_antenna(struct wiphy *wiphy, u32 *tx_ant, u32 *rx_ant)
2008 return drv_get_antenna(local, tx_ant, rx_ant); 2012 return drv_get_antenna(local, tx_ant, rx_ant);
2009} 2013}
2010 2014
2015static int ieee80211_set_ringparam(struct wiphy *wiphy, u32 tx, u32 rx)
2016{
2017 struct ieee80211_local *local = wiphy_priv(wiphy);
2018
2019 return drv_set_ringparam(local, tx, rx);
2020}
2021
2022static void ieee80211_get_ringparam(struct wiphy *wiphy,
2023 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
2024{
2025 struct ieee80211_local *local = wiphy_priv(wiphy);
2026
2027 drv_get_ringparam(local, tx, tx_max, rx, rx_max);
2028}
2029
2011struct cfg80211_ops mac80211_config_ops = { 2030struct cfg80211_ops mac80211_config_ops = {
2012 .add_virtual_intf = ieee80211_add_iface, 2031 .add_virtual_intf = ieee80211_add_iface,
2013 .del_virtual_intf = ieee80211_del_iface, 2032 .del_virtual_intf = ieee80211_del_iface,
@@ -2065,4 +2084,6 @@ struct cfg80211_ops mac80211_config_ops = {
2065 .mgmt_frame_register = ieee80211_mgmt_frame_register, 2084 .mgmt_frame_register = ieee80211_mgmt_frame_register,
2066 .set_antenna = ieee80211_set_antenna, 2085 .set_antenna = ieee80211_set_antenna,
2067 .get_antenna = ieee80211_get_antenna, 2086 .get_antenna = ieee80211_get_antenna,
2087 .set_ringparam = ieee80211_set_ringparam,
2088 .get_ringparam = ieee80211_get_ringparam,
2068}; 2089};
diff --git a/net/mac80211/chan.c b/net/mac80211/chan.c
index 5b24740fc0b..889c3e93e0f 100644
--- a/net/mac80211/chan.c
+++ b/net/mac80211/chan.c
@@ -77,6 +77,9 @@ bool ieee80211_set_channel_type(struct ieee80211_local *local,
77 switch (tmp->vif.bss_conf.channel_type) { 77 switch (tmp->vif.bss_conf.channel_type) {
78 case NL80211_CHAN_NO_HT: 78 case NL80211_CHAN_NO_HT:
79 case NL80211_CHAN_HT20: 79 case NL80211_CHAN_HT20:
80 if (superchan > tmp->vif.bss_conf.channel_type)
81 break;
82
80 superchan = tmp->vif.bss_conf.channel_type; 83 superchan = tmp->vif.bss_conf.channel_type;
81 break; 84 break;
82 case NL80211_CHAN_HT40PLUS: 85 case NL80211_CHAN_HT40PLUS:
diff --git a/net/mac80211/driver-ops.h b/net/mac80211/driver-ops.h
index 3729296f6f9..9c0d62bb0ea 100644
--- a/net/mac80211/driver-ops.h
+++ b/net/mac80211/driver-ops.h
@@ -526,4 +526,30 @@ static inline int drv_offchannel_tx_cancel_wait(struct ieee80211_local *local)
526 return ret; 526 return ret;
527} 527}
528 528
529static inline int drv_set_ringparam(struct ieee80211_local *local,
530 u32 tx, u32 rx)
531{
532 int ret = -ENOTSUPP;
533
534 might_sleep();
535
536 trace_drv_set_ringparam(local, tx, rx);
537 if (local->ops->set_ringparam)
538 ret = local->ops->set_ringparam(&local->hw, tx, rx);
539 trace_drv_return_int(local, ret);
540
541 return ret;
542}
543
544static inline void drv_get_ringparam(struct ieee80211_local *local,
545 u32 *tx, u32 *tx_max, u32 *rx, u32 *rx_max)
546{
547 might_sleep();
548
549 trace_drv_get_ringparam(local, tx, tx_max, rx, rx_max);
550 if (local->ops->get_ringparam)
551 local->ops->get_ringparam(&local->hw, tx, tx_max, rx, rx_max);
552 trace_drv_return_void(local);
553}
554
529#endif /* __MAC80211_DRIVER_OPS */ 555#endif /* __MAC80211_DRIVER_OPS */
diff --git a/net/mac80211/driver-trace.h b/net/mac80211/driver-trace.h
index 520fe244489..45aab80738e 100644
--- a/net/mac80211/driver-trace.h
+++ b/net/mac80211/driver-trace.h
@@ -912,6 +912,58 @@ TRACE_EVENT(drv_offchannel_tx,
912 ) 912 )
913); 913);
914 914
915TRACE_EVENT(drv_set_ringparam,
916 TP_PROTO(struct ieee80211_local *local, u32 tx, u32 rx),
917
918 TP_ARGS(local, tx, rx),
919
920 TP_STRUCT__entry(
921 LOCAL_ENTRY
922 __field(u32, tx)
923 __field(u32, rx)
924 ),
925
926 TP_fast_assign(
927 LOCAL_ASSIGN;
928 __entry->tx = tx;
929 __entry->rx = rx;
930 ),
931
932 TP_printk(
933 LOCAL_PR_FMT " tx:%d rx %d",
934 LOCAL_PR_ARG, __entry->tx, __entry->rx
935 )
936);
937
938TRACE_EVENT(drv_get_ringparam,
939 TP_PROTO(struct ieee80211_local *local, u32 *tx, u32 *tx_max,
940 u32 *rx, u32 *rx_max),
941
942 TP_ARGS(local, tx, tx_max, rx, rx_max),
943
944 TP_STRUCT__entry(
945 LOCAL_ENTRY
946 __field(u32, tx)
947 __field(u32, tx_max)
948 __field(u32, rx)
949 __field(u32, rx_max)
950 ),
951
952 TP_fast_assign(
953 LOCAL_ASSIGN;
954 __entry->tx = *tx;
955 __entry->tx_max = *tx_max;
956 __entry->rx = *rx;
957 __entry->rx_max = *rx_max;
958 ),
959
960 TP_printk(
961 LOCAL_PR_FMT " tx:%d tx_max %d rx %d rx_max %d",
962 LOCAL_PR_ARG,
963 __entry->tx, __entry->tx_max, __entry->rx, __entry->rx_max
964 )
965);
966
915DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait, 967DEFINE_EVENT(local_only_evt, drv_offchannel_tx_cancel_wait,
916 TP_PROTO(struct ieee80211_local *local), 968 TP_PROTO(struct ieee80211_local *local),
917 TP_ARGS(local) 969 TP_ARGS(local)
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c
index cc984bd861c..64d92d5a7f4 100644
--- a/net/mac80211/mlme.c
+++ b/net/mac80211/mlme.c
@@ -613,6 +613,37 @@ static void ieee80211_change_ps(struct ieee80211_local *local)
613 } 613 }
614} 614}
615 615
616static bool ieee80211_powersave_allowed(struct ieee80211_sub_if_data *sdata)
617{
618 struct ieee80211_if_managed *mgd = &sdata->u.mgd;
619 struct sta_info *sta = NULL;
620 u32 sta_flags = 0;
621
622 if (!mgd->powersave)
623 return false;
624
625 if (!mgd->associated)
626 return false;
627
628 if (!mgd->associated->beacon_ies)
629 return false;
630
631 if (mgd->flags & (IEEE80211_STA_BEACON_POLL |
632 IEEE80211_STA_CONNECTION_POLL))
633 return false;
634
635 rcu_read_lock();
636 sta = sta_info_get(sdata, mgd->bssid);
637 if (sta)
638 sta_flags = get_sta_flags(sta);
639 rcu_read_unlock();
640
641 if (!(sta_flags & WLAN_STA_AUTHORIZED))
642 return false;
643
644 return true;
645}
646
616/* need to hold RTNL or interface lock */ 647/* need to hold RTNL or interface lock */
617void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency) 648void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
618{ 649{
@@ -647,11 +678,7 @@ void ieee80211_recalc_ps(struct ieee80211_local *local, s32 latency)
647 count++; 678 count++;
648 } 679 }
649 680
650 if (count == 1 && found->u.mgd.powersave && 681 if (count == 1 && ieee80211_powersave_allowed(found)) {
651 found->u.mgd.associated &&
652 found->u.mgd.associated->beacon_ies &&
653 !(found->u.mgd.flags & (IEEE80211_STA_BEACON_POLL |
654 IEEE80211_STA_CONNECTION_POLL))) {
655 struct ieee80211_conf *conf = &local->hw.conf; 682 struct ieee80211_conf *conf = &local->hw.conf;
656 s32 beaconint_us; 683 s32 beaconint_us;
657 684
diff --git a/net/mac80211/rc80211_minstrel_ht.c b/net/mac80211/rc80211_minstrel_ht.c
index bce14fbfc3b..8212a8bebf0 100644
--- a/net/mac80211/rc80211_minstrel_ht.c
+++ b/net/mac80211/rc80211_minstrel_ht.c
@@ -598,19 +598,46 @@ minstrel_ht_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta,
598 sample = true; 598 sample = true;
599 minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx, 599 minstrel_ht_set_rate(mp, mi, &ar[0], sample_idx,
600 txrc, true, false); 600 txrc, true, false);
601 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
602 txrc, false, false);
603 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE; 601 info->flags |= IEEE80211_TX_CTL_RATE_CTRL_PROBE;
604 } else { 602 } else {
605 minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate, 603 minstrel_ht_set_rate(mp, mi, &ar[0], mi->max_tp_rate,
606 txrc, false, false); 604 txrc, false, false);
607 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
608 txrc, false, true);
609 } 605 }
610 minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate, txrc, false, !sample);
611 606
612 ar[3].count = 0; 607 if (mp->hw->max_rates >= 3) {
613 ar[3].idx = -1; 608 /*
609 * At least 3 tx rates supported, use
610 * sample_rate -> max_tp_rate -> max_prob_rate for sampling and
611 * max_tp_rate -> max_tp_rate2 -> max_prob_rate by default.
612 */
613 if (sample_idx >= 0)
614 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate,
615 txrc, false, false);
616 else
617 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_tp_rate2,
618 txrc, false, true);
619
620 minstrel_ht_set_rate(mp, mi, &ar[2], mi->max_prob_rate,
621 txrc, false, !sample);
622
623 ar[3].count = 0;
624 ar[3].idx = -1;
625 } else if (mp->hw->max_rates == 2) {
626 /*
627 * Only 2 tx rates supported, use
628 * sample_rate -> max_prob_rate for sampling and
629 * max_tp_rate -> max_prob_rate by default.
630 */
631 minstrel_ht_set_rate(mp, mi, &ar[1], mi->max_prob_rate,
632 txrc, false, !sample);
633
634 ar[2].count = 0;
635 ar[2].idx = -1;
636 } else {
637 /* Not using MRR, only use the first rate */
638 ar[1].count = 0;
639 ar[1].idx = -1;
640 }
614 641
615 mi->total_packets++; 642 mi->total_packets++;
616 643
diff --git a/net/wireless/ethtool.c b/net/wireless/ethtool.c
index ca4c825be93..9bde4d1d3e9 100644
--- a/net/wireless/ethtool.c
+++ b/net/wireless/ethtool.c
@@ -1,5 +1,6 @@
1#include <linux/utsname.h> 1#include <linux/utsname.h>
2#include <net/cfg80211.h> 2#include <net/cfg80211.h>
3#include "core.h"
3#include "ethtool.h" 4#include "ethtool.h"
4 5
5static void cfg80211_get_drvinfo(struct net_device *dev, 6static void cfg80211_get_drvinfo(struct net_device *dev,
@@ -37,9 +38,41 @@ static void cfg80211_get_regs(struct net_device *dev, struct ethtool_regs *regs,
37 regs->len = 0; 38 regs->len = 0;
38} 39}
39 40
41static void cfg80211_get_ringparam(struct net_device *dev,
42 struct ethtool_ringparam *rp)
43{
44 struct wireless_dev *wdev = dev->ieee80211_ptr;
45 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
46
47 memset(rp, 0, sizeof(*rp));
48
49 if (rdev->ops->get_ringparam)
50 rdev->ops->get_ringparam(wdev->wiphy,
51 &rp->tx_pending, &rp->tx_max_pending,
52 &rp->rx_pending, &rp->rx_max_pending);
53}
54
55static int cfg80211_set_ringparam(struct net_device *dev,
56 struct ethtool_ringparam *rp)
57{
58 struct wireless_dev *wdev = dev->ieee80211_ptr;
59 struct cfg80211_registered_device *rdev = wiphy_to_dev(wdev->wiphy);
60
61 if (rp->rx_mini_pending != 0 || rp->rx_jumbo_pending != 0)
62 return -EINVAL;
63
64 if (rdev->ops->set_ringparam)
65 return rdev->ops->set_ringparam(wdev->wiphy,
66 rp->tx_pending, rp->rx_pending);
67
68 return -ENOTSUPP;
69}
70
40const struct ethtool_ops cfg80211_ethtool_ops = { 71const struct ethtool_ops cfg80211_ethtool_ops = {
41 .get_drvinfo = cfg80211_get_drvinfo, 72 .get_drvinfo = cfg80211_get_drvinfo,
42 .get_regs_len = cfg80211_get_regs_len, 73 .get_regs_len = cfg80211_get_regs_len,
43 .get_regs = cfg80211_get_regs, 74 .get_regs = cfg80211_get_regs,
44 .get_link = ethtool_op_get_link, 75 .get_link = ethtool_op_get_link,
76 .get_ringparam = cfg80211_get_ringparam,
77 .set_ringparam = cfg80211_set_ringparam,
45}; 78};