mac80211: update to wireless-testing 2011-03-11
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@26128 3c298f89-4303-0410-b956-a3cf2f4a3e73master
parent
b2b9c9a950
commit
b3c2781814
|
@ -10,10 +10,10 @@ include $(INCLUDE_DIR)/kernel.mk
|
|||
|
||||
PKG_NAME:=mac80211
|
||||
|
||||
PKG_VERSION:=2011-02-25
|
||||
PKG_VERSION:=2011-03-11
|
||||
PKG_RELEASE:=1
|
||||
PKG_SOURCE_URL:=http://mirror2.openwrt.org/sources
|
||||
PKG_MD5SUM:=c0242cc152a157902ff60fe05d1773b2
|
||||
PKG_MD5SUM:=123b9220fa2b016979b7b3874f349643
|
||||
|
||||
PKG_SOURCE:=compat-wireless-$(PKG_VERSION).tar.bz2
|
||||
PKG_BUILD_DIR:=$(KERNEL_BUILD_DIR)/compat-wireless-$(PKG_VERSION)
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
--- a/include/linux/compat-2.6.36.h
|
||||
+++ b/include/linux/compat-2.6.36.h
|
||||
@@ -102,6 +102,8 @@ int no_printk(const char *s, ...) { retu
|
||||
#define alloc_workqueue(name, flags, max_active) __create_workqueue(name, flags, max_active, 0)
|
||||
#endif
|
||||
@@ -104,6 +104,8 @@ int no_printk(const char *s, ...) { retu
|
||||
|
||||
#define PCI_EEPROM_WIDTH_93C86 8
|
||||
|
||||
+#define PCI_EEPROM_WIDTH_93C86 8
|
||||
+
|
||||
|
|
|
@ -1,10 +0,0 @@
|
|||
--- a/compat/compat-2.6.39.c
|
||||
+++ b/compat/compat-2.6.39.c
|
||||
@@ -10,6 +10,7 @@
|
||||
|
||||
#include <linux/compat.h>
|
||||
#include <linux/tty.h>
|
||||
+#include <linux/sched.h>
|
||||
|
||||
/*
|
||||
* Termios Helper Methods
|
|
@ -1,7 +1,7 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1091,6 +1091,12 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
sc->debug.debugfs_phy, &ah->config.cwm_ignore_extcca))
|
||||
@@ -1145,6 +1145,12 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
sc, &fops_regdump))
|
||||
goto err;
|
||||
|
||||
+ debugfs_create_u32("gpio_mask", S_IRUSR | S_IWUSR,
|
||||
|
|
|
@ -0,0 +1,366 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -189,7 +189,6 @@ struct ath_txq {
|
||||
u32 axq_ampdu_depth;
|
||||
bool stopped;
|
||||
bool axq_tx_inprogress;
|
||||
- bool txq_flush_inprogress;
|
||||
struct list_head axq_acq;
|
||||
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
|
||||
struct list_head txq_fifo_pending;
|
||||
--- 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 da
|
||||
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||
"missed %u consecutive beacons\n",
|
||||
sc->beacon.bmisscnt);
|
||||
+ ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
|
||||
ath9k_hw_bstuck_nfcal(ah);
|
||||
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
|
||||
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||
@@ -450,16 +451,6 @@ void ath_beacon_tasklet(unsigned long da
|
||||
sc->beacon.updateslot = OK;
|
||||
}
|
||||
if (bfaddr != 0) {
|
||||
- /*
|
||||
- * Stop any current dma and put the new frame(s) on the queue.
|
||||
- * This should never fail since we check above that no frames
|
||||
- * are still pending on the queue.
|
||||
- */
|
||||
- if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
|
||||
- ath_err(common, "beacon queue %u did not stop?\n",
|
||||
- sc->beacon.beaconq);
|
||||
- }
|
||||
-
|
||||
/* NB: cabq traffic should already be queued and primed */
|
||||
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
|
||||
ath9k_hw_txstart(ah, sc->beacon.beaconq);
|
||||
@@ -780,7 +771,7 @@ void ath9k_set_beaconing_status(struct a
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
tasklet_kill(&sc->bcon_tasklet);
|
||||
- ath9k_hw_stoptxdma(ah, sc->beacon.beaconq);
|
||||
+ ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
|
||||
}
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
||||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -95,9 +95,9 @@
|
||||
#define REG_READ_FIELD(_a, _r, _f) \
|
||||
(((REG_READ(_a, _r) & _f) >> _f##_S))
|
||||
#define REG_SET_BIT(_a, _r, _f) \
|
||||
- REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
|
||||
+ REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
|
||||
#define REG_CLR_BIT(_a, _r, _f) \
|
||||
- REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
|
||||
+ REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
|
||||
|
||||
#define DO_DELAY(x) do { \
|
||||
if ((++(x) % 64) == 0) \
|
||||
--- 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 a
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
|
||||
|
||||
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
|
||||
{
|
||||
-#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
|
||||
-#define ATH9K_TIME_QUANTUM 100 /* usec */
|
||||
- struct ath_common *common = ath9k_hw_common(ah);
|
||||
- struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
- struct ath9k_tx_queue_info *qi;
|
||||
- u32 tsfLow, j, wait;
|
||||
- u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
|
||||
+ int i, q;
|
||||
|
||||
- if (q >= pCap->total_queues) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "Stopping TX DMA, invalid queue: %u\n", q);
|
||||
- return false;
|
||||
- }
|
||||
+ REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
|
||||
|
||||
- qi = &ah->txq[q];
|
||||
- if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "Stopping TX DMA, inactive queue: %u\n", q);
|
||||
- return false;
|
||||
- }
|
||||
+ REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
|
||||
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+ REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
|
||||
|
||||
- REG_WRITE(ah, AR_Q_TXD, 1 << q);
|
||||
+ for (q = 0; q < AR_NUM_QCU; q++) {
|
||||
+ for (i = 0; i < 1000; i++) {
|
||||
+ if (i)
|
||||
+ udelay(5);
|
||||
|
||||
- for (wait = wait_time; wait != 0; wait--) {
|
||||
- if (ath9k_hw_numtxpending(ah, q) == 0)
|
||||
- break;
|
||||
- udelay(ATH9K_TIME_QUANTUM);
|
||||
+ if (!ath9k_hw_numtxpending(ah, q))
|
||||
+ break;
|
||||
+ }
|
||||
}
|
||||
|
||||
- if (ath9k_hw_numtxpending(ah, q)) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "%s: Num of pending TX Frames %d on Q %d\n",
|
||||
- __func__, ath9k_hw_numtxpending(ah, q), q);
|
||||
-
|
||||
- for (j = 0; j < 2; j++) {
|
||||
- tsfLow = REG_READ(ah, AR_TSF_L32);
|
||||
- REG_WRITE(ah, AR_QUIET2,
|
||||
- SM(10, AR_QUIET2_QUIET_DUR));
|
||||
- REG_WRITE(ah, AR_QUIET_PERIOD, 100);
|
||||
- REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
|
||||
- REG_SET_BIT(ah, AR_TIMER_MODE,
|
||||
- AR_QUIET_TIMER_EN);
|
||||
-
|
||||
- if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
|
||||
- break;
|
||||
+ REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
|
||||
+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+ REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
|
||||
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "TSF has moved while trying to set quiet time TSF: 0x%08x\n",
|
||||
- tsfLow);
|
||||
- }
|
||||
+ REG_WRITE(ah, AR_Q_TXD, 0);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
|
||||
|
||||
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
|
||||
+{
|
||||
+#define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */
|
||||
+#define ATH9K_TIME_QUANTUM 100 /* usec */
|
||||
+ int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
|
||||
+ int wait;
|
||||
|
||||
- udelay(200);
|
||||
- REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
|
||||
+ REG_WRITE(ah, AR_Q_TXD, 1 << q);
|
||||
|
||||
- wait = wait_time;
|
||||
- while (ath9k_hw_numtxpending(ah, q)) {
|
||||
- if ((--wait) == 0) {
|
||||
- ath_err(common,
|
||||
- "Failed to stop TX DMA in 100 msec after killing last frame\n");
|
||||
- break;
|
||||
- }
|
||||
+ for (wait = wait_time; wait != 0; wait--) {
|
||||
+ if (wait != wait_time)
|
||||
udelay(ATH9K_TIME_QUANTUM);
|
||||
- }
|
||||
|
||||
- REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+ if (ath9k_hw_numtxpending(ah, q) == 0)
|
||||
+ break;
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_Q_TXD, 0);
|
||||
+
|
||||
return wait != 0;
|
||||
|
||||
#undef ATH9K_TX_STOP_DMA_TIMEOUT
|
||||
#undef ATH9K_TIME_QUANTUM
|
||||
}
|
||||
-EXPORT_SYMBOL(ath9k_hw_stoptxdma);
|
||||
+EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
|
||||
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
|
||||
{
|
||||
--- 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,
|
||||
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
|
||||
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
|
||||
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
|
||||
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
|
||||
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
|
||||
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
||||
--- 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(str
|
||||
|
||||
static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
-#define ATH_FLUSH_TIMEOUT 60 /* ms */
|
||||
struct ath_softc *sc = hw->priv;
|
||||
- struct ath_txq *txq = NULL;
|
||||
- struct ath_hw *ah = sc->sc_ah;
|
||||
- struct ath_common *common = ath9k_hw_common(ah);
|
||||
- int i, j, npend = 0;
|
||||
+ int timeout = 200; /* ms */
|
||||
+ int i, j;
|
||||
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
|
||||
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
- if (!ATH_TXQ_SETUP(sc, i))
|
||||
- continue;
|
||||
- txq = &sc->tx.txq[i];
|
||||
-
|
||||
- if (!drop) {
|
||||
- for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
|
||||
- if (!ath9k_has_pending_frames(sc, txq))
|
||||
- break;
|
||||
- usleep_range(1000, 2000);
|
||||
- }
|
||||
- }
|
||||
+ if (drop)
|
||||
+ timeout = 1;
|
||||
+
|
||||
+ for (j = 0; j < timeout; j++) {
|
||||
+ int npend = 0;
|
||||
+
|
||||
+ if (j)
|
||||
+ usleep_range(1000, 2000);
|
||||
|
||||
- if (drop || ath9k_has_pending_frames(sc, txq)) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
|
||||
- txq->axq_qnum);
|
||||
- spin_lock_bh(&txq->axq_lock);
|
||||
- txq->txq_flush_inprogress = true;
|
||||
- spin_unlock_bh(&txq->axq_lock);
|
||||
-
|
||||
- ath9k_ps_wakeup(sc);
|
||||
- ath9k_hw_stoptxdma(ah, txq->axq_qnum);
|
||||
- npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
|
||||
- ath9k_ps_restore(sc);
|
||||
- if (npend)
|
||||
- break;
|
||||
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
+ if (!ATH_TXQ_SETUP(sc, i))
|
||||
+ continue;
|
||||
|
||||
- ath_draintxq(sc, txq, false);
|
||||
- txq->txq_flush_inprogress = false;
|
||||
+ npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
|
||||
}
|
||||
+
|
||||
+ if (!npend)
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
- if (npend) {
|
||||
+ if (!ath_drain_all_txq(sc, false))
|
||||
ath_reset(sc, false);
|
||||
- txq->txq_flush_inprogress = false;
|
||||
- }
|
||||
|
||||
+out:
|
||||
ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
|
||||
mutex_unlock(&sc->mutex);
|
||||
+ ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
struct ieee80211_ops ath9k_ops = {
|
||||
--- 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_
|
||||
fi = get_frame_info(bf->bf_mpdu);
|
||||
if (fi->retries) {
|
||||
ath_tx_update_baw(sc, tid, fi->seqno);
|
||||
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
|
||||
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
|
||||
} else {
|
||||
ath_tx_send_normal(sc, txq, NULL, &bf_head);
|
||||
}
|
||||
@@ -1194,16 +1194,14 @@ bool ath_drain_all_txq(struct ath_softc
|
||||
if (sc->sc_flags & SC_OP_INVALID)
|
||||
return true;
|
||||
|
||||
- /* Stop beacon queue */
|
||||
- ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
+ ath9k_hw_abort_tx_dma(ah);
|
||||
|
||||
- /* Stop data queues */
|
||||
+ /* Check if any queue remains active */
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
- if (ATH_TXQ_SETUP(sc, i)) {
|
||||
- txq = &sc->tx.txq[i];
|
||||
- ath9k_hw_stoptxdma(ah, txq->axq_qnum);
|
||||
- npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
|
||||
- }
|
||||
+ if (!ATH_TXQ_SETUP(sc, i))
|
||||
+ continue;
|
||||
+
|
||||
+ npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
|
||||
}
|
||||
|
||||
if (npend)
|
||||
@@ -2014,8 +2012,7 @@ static void ath_tx_processq(struct ath_s
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (list_empty(&txq->axq_q)) {
|
||||
txq->axq_link = NULL;
|
||||
- if (sc->sc_flags & SC_OP_TXAGGR &&
|
||||
- !txq->txq_flush_inprogress)
|
||||
+ if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
break;
|
||||
@@ -2096,7 +2093,7 @@ static void ath_tx_processq(struct ath_s
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
- if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress)
|
||||
+ if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
@@ -2267,18 +2264,17 @@ void ath_tx_edma_tasklet(struct ath_soft
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
- if (!txq->txq_flush_inprogress) {
|
||||
- if (!list_empty(&txq->txq_fifo_pending)) {
|
||||
- INIT_LIST_HEAD(&bf_head);
|
||||
- bf = list_first_entry(&txq->txq_fifo_pending,
|
||||
- struct ath_buf, list);
|
||||
- list_cut_position(&bf_head,
|
||||
- &txq->txq_fifo_pending,
|
||||
- &bf->bf_lastbf->list);
|
||||
- ath_tx_txqaddbuf(sc, txq, &bf_head);
|
||||
- } else if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
- ath_txq_schedule(sc, txq);
|
||||
- }
|
||||
+ if (!list_empty(&txq->txq_fifo_pending)) {
|
||||
+ INIT_LIST_HEAD(&bf_head);
|
||||
+ bf = list_first_entry(&txq->txq_fifo_pending,
|
||||
+ struct ath_buf, list);
|
||||
+ list_cut_position(&bf_head,
|
||||
+ &txq->txq_fifo_pending,
|
||||
+ &bf->bf_lastbf->list);
|
||||
+ ath_tx_txqaddbuf(sc, txq, &bf_head);
|
||||
+ } else if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
+ ath_txq_schedule(sc, txq);
|
||||
+
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
}
|
||||
--- a/net/mac80211/chan.c
|
||||
+++ b/net/mac80211/chan.c
|
||||
@@ -77,6 +77,9 @@ bool ieee80211_set_channel_type(struct i
|
||||
switch (tmp->vif.bss_conf.channel_type) {
|
||||
case NL80211_CHAN_NO_HT:
|
||||
case NL80211_CHAN_HT20:
|
||||
+ if (superchan > tmp->vif.bss_conf.channel_type)
|
||||
+ break;
|
||||
+
|
||||
superchan = tmp->vif.bss_conf.channel_type;
|
||||
break;
|
||||
case NL80211_CHAN_HT40PLUS:
|
|
@ -1,17 +1,7 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -120,6 +120,9 @@ static void ath_unregister_led(struct at
|
||||
|
||||
void ath_deinit_leds(struct ath_softc *sc)
|
||||
@@ -41,6 +41,9 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
+ if (AR_SREV_9100(sc->sc_ah))
|
||||
+ return;
|
||||
+
|
||||
ath_unregister_led(&sc->assoc_led);
|
||||
sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
ath_unregister_led(&sc->tx_led);
|
||||
@@ -133,6 +136,9 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
char *trigger;
|
||||
int ret;
|
||||
|
||||
+ if (AR_SREV_9100(sc->sc_ah))
|
||||
|
@ -19,4 +9,4 @@
|
|||
+
|
||||
if (AR_SREV_9287(sc->sc_ah))
|
||||
sc->sc_ah->led_pin = ATH_LED_PIN_9287;
|
||||
else
|
||||
else if (AR_SREV_9485(sc->sc_ah))
|
||||
|
|
|
@ -18,7 +18,7 @@
|
|||
|
||||
#include "ath9k.h"
|
||||
|
||||
@@ -522,6 +523,7 @@ static void ath9k_init_misc(struct ath_s
|
||||
@@ -537,6 +538,7 @@ static void ath9k_init_misc(struct ath_s
|
||||
static int ath9k_init_softc(u16 devid, struct ath_softc *sc, u16 subsysid,
|
||||
const struct ath_bus_ops *bus_ops)
|
||||
{
|
||||
|
@ -26,7 +26,7 @@
|
|||
struct ath_hw *ah = NULL;
|
||||
struct ath_common *common;
|
||||
int ret = 0, i;
|
||||
@@ -536,7 +538,7 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -551,7 +553,7 @@ static int ath9k_init_softc(u16 devid, s
|
||||
ah->hw_version.subsysid = subsysid;
|
||||
sc->sc_ah = ah;
|
||||
|
||||
|
@ -35,7 +35,7 @@
|
|||
ah->ah_flags |= AH_USE_EEPROM;
|
||||
|
||||
common = ath9k_hw_common(ah);
|
||||
@@ -572,6 +574,9 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -587,6 +589,9 @@ static int ath9k_init_softc(u16 devid, s
|
||||
if (ret)
|
||||
goto err_hw;
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -538,8 +538,14 @@ static int ath9k_init_softc(u16 devid, s
|
||||
@@ -553,8 +553,14 @@ static int ath9k_init_softc(u16 devid, s
|
||||
ah->hw_version.subsysid = subsysid;
|
||||
sc->sc_ah = ah;
|
||||
|
||||
|
@ -29,17 +29,21 @@
|
|||
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -139,10 +139,12 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
@@ -44,12 +44,14 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
if (AR_SREV_9100(sc->sc_ah))
|
||||
return;
|
||||
|
||||
- if (AR_SREV_9287(sc->sc_ah))
|
||||
- sc->sc_ah->led_pin = ATH_LED_PIN_9287;
|
||||
- else if (AR_SREV_9485(sc->sc_ah))
|
||||
- sc->sc_ah->led_pin = ATH_LED_PIN_9485;
|
||||
- else
|
||||
- sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
|
||||
+ if (sc->sc_ah->led_pin < 0) {
|
||||
+ if (AR_SREV_9287(sc->sc_ah))
|
||||
+ sc->sc_ah->led_pin = ATH_LED_PIN_9287;
|
||||
+ else if (AR_SREV_9485(sc->sc_ah))
|
||||
+ sc->sc_ah->led_pin = ATH_LED_PIN_9485;
|
||||
+ else
|
||||
+ sc->sc_ah->led_pin = ATH_LED_PIN_DEF;
|
||||
+ }
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/debug.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/debug.c
|
||||
@@ -1027,6 +1027,53 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,
|
||||
@@ -1077,6 +1077,53 @@ static const struct file_operations fops
|
||||
.llseek = default_llseek,/* read accesses f_pos */
|
||||
};
|
||||
|
||||
+static ssize_t read_file_eeprom(struct file *file, char __user *user_buf,
|
||||
|
@ -54,7 +54,7 @@
|
|||
int ath9k_init_debug(struct ath_hw *ah)
|
||||
{
|
||||
struct ath_common *common = ath9k_hw_common(ah);
|
||||
@@ -1097,6 +1144,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
@@ -1151,6 +1198,10 @@ int ath9k_init_debug(struct ath_hw *ah)
|
||||
debugfs_create_u32("gpio_val", S_IRUSR | S_IWUSR,
|
||||
sc->debug.debugfs_phy, &sc->sc_ah->gpio_val);
|
||||
|
||||
|
|
|
@ -1,303 +0,0 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -449,26 +449,20 @@ void ath9k_btcoex_timer_pause(struct ath
|
||||
|
||||
#define ATH_LED_PIN_DEF 1
|
||||
#define ATH_LED_PIN_9287 8
|
||||
-#define ATH_LED_ON_DURATION_IDLE 350 /* in msecs */
|
||||
-#define ATH_LED_OFF_DURATION_IDLE 250 /* in msecs */
|
||||
-
|
||||
-enum ath_led_type {
|
||||
- ATH_LED_RADIO,
|
||||
- ATH_LED_ASSOC,
|
||||
- ATH_LED_TX,
|
||||
- ATH_LED_RX
|
||||
-};
|
||||
-
|
||||
-struct ath_led {
|
||||
- struct ath_softc *sc;
|
||||
- struct led_classdev led_cdev;
|
||||
- enum ath_led_type led_type;
|
||||
- char name[32];
|
||||
- bool registered;
|
||||
-};
|
||||
|
||||
+#ifdef CONFIG_MAC80211_LEDS
|
||||
void ath_init_leds(struct ath_softc *sc);
|
||||
void ath_deinit_leds(struct ath_softc *sc);
|
||||
+#else
|
||||
+static inline void ath_init_leds(struct ath_softc *sc)
|
||||
+{
|
||||
+}
|
||||
+
|
||||
+static inline void ath_deinit_leds(struct ath_softc *sc)
|
||||
+{
|
||||
+}
|
||||
+#endif
|
||||
+
|
||||
|
||||
/* Antenna diversity/combining */
|
||||
#define ATH_ANT_RX_CURRENT_SHIFT 4
|
||||
@@ -620,15 +614,11 @@ struct ath_softc {
|
||||
struct ath_beacon beacon;
|
||||
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
|
||||
|
||||
- struct ath_led radio_led;
|
||||
- struct ath_led assoc_led;
|
||||
- struct ath_led tx_led;
|
||||
- struct ath_led rx_led;
|
||||
- struct delayed_work ath_led_blink_work;
|
||||
- int led_on_duration;
|
||||
- int led_off_duration;
|
||||
- int led_on_cnt;
|
||||
- int led_off_cnt;
|
||||
+#ifdef CONFIG_MAC80211_LEDS
|
||||
+ bool led_registered;
|
||||
+ char led_name[32];
|
||||
+ struct led_classdev led_cdev;
|
||||
+#endif
|
||||
|
||||
struct ath9k_hw_cal_data caldata;
|
||||
int last_rssi;
|
||||
--- a/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/gpio.c
|
||||
@@ -20,120 +20,25 @@
|
||||
/* LED functions */
|
||||
/********************************/
|
||||
|
||||
-static void ath_led_blink_work(struct work_struct *work)
|
||||
-{
|
||||
- struct ath_softc *sc = container_of(work, struct ath_softc,
|
||||
- ath_led_blink_work.work);
|
||||
-
|
||||
- if (!(sc->sc_flags & SC_OP_LED_ASSOCIATED))
|
||||
- return;
|
||||
-
|
||||
- if ((sc->led_on_duration == ATH_LED_ON_DURATION_IDLE) ||
|
||||
- (sc->led_off_duration == ATH_LED_OFF_DURATION_IDLE))
|
||||
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
|
||||
- else
|
||||
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
|
||||
- (sc->sc_flags & SC_OP_LED_ON) ? 1 : 0);
|
||||
-
|
||||
- ieee80211_queue_delayed_work(sc->hw,
|
||||
- &sc->ath_led_blink_work,
|
||||
- (sc->sc_flags & SC_OP_LED_ON) ?
|
||||
- msecs_to_jiffies(sc->led_off_duration) :
|
||||
- msecs_to_jiffies(sc->led_on_duration));
|
||||
-
|
||||
- sc->led_on_duration = sc->led_on_cnt ?
|
||||
- max((ATH_LED_ON_DURATION_IDLE - sc->led_on_cnt), 25) :
|
||||
- ATH_LED_ON_DURATION_IDLE;
|
||||
- sc->led_off_duration = sc->led_off_cnt ?
|
||||
- max((ATH_LED_OFF_DURATION_IDLE - sc->led_off_cnt), 10) :
|
||||
- ATH_LED_OFF_DURATION_IDLE;
|
||||
- sc->led_on_cnt = sc->led_off_cnt = 0;
|
||||
- if (sc->sc_flags & SC_OP_LED_ON)
|
||||
- sc->sc_flags &= ~SC_OP_LED_ON;
|
||||
- else
|
||||
- sc->sc_flags |= SC_OP_LED_ON;
|
||||
-}
|
||||
-
|
||||
+#ifdef CONFIG_MAC80211_LEDS
|
||||
static void ath_led_brightness(struct led_classdev *led_cdev,
|
||||
enum led_brightness brightness)
|
||||
{
|
||||
- struct ath_led *led = container_of(led_cdev, struct ath_led, led_cdev);
|
||||
- struct ath_softc *sc = led->sc;
|
||||
-
|
||||
- switch (brightness) {
|
||||
- case LED_OFF:
|
||||
- if (led->led_type == ATH_LED_ASSOC ||
|
||||
- led->led_type == ATH_LED_RADIO) {
|
||||
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin,
|
||||
- (led->led_type == ATH_LED_RADIO));
|
||||
- sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
- if (led->led_type == ATH_LED_RADIO)
|
||||
- sc->sc_flags &= ~SC_OP_LED_ON;
|
||||
- } else {
|
||||
- sc->led_off_cnt++;
|
||||
- }
|
||||
- break;
|
||||
- case LED_FULL:
|
||||
- if (led->led_type == ATH_LED_ASSOC) {
|
||||
- sc->sc_flags |= SC_OP_LED_ASSOCIATED;
|
||||
- if (led_blink)
|
||||
- ieee80211_queue_delayed_work(sc->hw,
|
||||
- &sc->ath_led_blink_work, 0);
|
||||
- } else if (led->led_type == ATH_LED_RADIO) {
|
||||
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 0);
|
||||
- sc->sc_flags |= SC_OP_LED_ON;
|
||||
- } else {
|
||||
- sc->led_on_cnt++;
|
||||
- }
|
||||
- break;
|
||||
- default:
|
||||
- break;
|
||||
- }
|
||||
-}
|
||||
-
|
||||
-static int ath_register_led(struct ath_softc *sc, struct ath_led *led,
|
||||
- char *trigger)
|
||||
-{
|
||||
- int ret;
|
||||
-
|
||||
- led->sc = sc;
|
||||
- led->led_cdev.name = led->name;
|
||||
- led->led_cdev.default_trigger = trigger;
|
||||
- led->led_cdev.brightness_set = ath_led_brightness;
|
||||
-
|
||||
- ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &led->led_cdev);
|
||||
- if (ret)
|
||||
- ath_err(ath9k_hw_common(sc->sc_ah),
|
||||
- "Failed to register led:%s", led->name);
|
||||
- else
|
||||
- led->registered = 1;
|
||||
- return ret;
|
||||
-}
|
||||
-
|
||||
-static void ath_unregister_led(struct ath_led *led)
|
||||
-{
|
||||
- if (led->registered) {
|
||||
- led_classdev_unregister(&led->led_cdev);
|
||||
- led->registered = 0;
|
||||
- }
|
||||
+ struct ath_softc *sc = container_of(led_cdev, struct ath_softc, led_cdev);
|
||||
+ ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, (brightness == LED_OFF));
|
||||
}
|
||||
|
||||
void ath_deinit_leds(struct ath_softc *sc)
|
||||
{
|
||||
- if (AR_SREV_9100(sc->sc_ah))
|
||||
+ if (!sc->led_registered)
|
||||
return;
|
||||
|
||||
- ath_unregister_led(&sc->assoc_led);
|
||||
- sc->sc_flags &= ~SC_OP_LED_ASSOCIATED;
|
||||
- ath_unregister_led(&sc->tx_led);
|
||||
- ath_unregister_led(&sc->rx_led);
|
||||
- ath_unregister_led(&sc->radio_led);
|
||||
- ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
+ ath_led_brightness(&sc->led_cdev, LED_OFF);
|
||||
+ led_classdev_unregister(&sc->led_cdev);
|
||||
}
|
||||
|
||||
void ath_init_leds(struct ath_softc *sc)
|
||||
{
|
||||
- char *trigger;
|
||||
int ret;
|
||||
|
||||
if (AR_SREV_9100(sc->sc_ah))
|
||||
@@ -152,48 +57,22 @@ void ath_init_leds(struct ath_softc *sc)
|
||||
/* LED off, active low */
|
||||
ath9k_hw_set_gpio(sc->sc_ah, sc->sc_ah->led_pin, 1);
|
||||
|
||||
- if (led_blink)
|
||||
- INIT_DELAYED_WORK(&sc->ath_led_blink_work, ath_led_blink_work);
|
||||
+ if (!led_blink)
|
||||
+ sc->led_cdev.default_trigger =
|
||||
+ ieee80211_get_radio_led_name(sc->hw);
|
||||
+
|
||||
+ snprintf(sc->led_name, sizeof(sc->led_name),
|
||||
+ "ath9k-%s", wiphy_name(sc->hw->wiphy));
|
||||
+ sc->led_cdev.name = sc->led_name;
|
||||
+ sc->led_cdev.brightness_set = ath_led_brightness;
|
||||
+
|
||||
+ ret = led_classdev_register(wiphy_dev(sc->hw->wiphy), &sc->led_cdev);
|
||||
+ if (ret < 0)
|
||||
+ return;
|
||||
|
||||
- trigger = ieee80211_get_radio_led_name(sc->hw);
|
||||
- snprintf(sc->radio_led.name, sizeof(sc->radio_led.name),
|
||||
- "ath9k-%s::radio", wiphy_name(sc->hw->wiphy));
|
||||
- ret = ath_register_led(sc, &sc->radio_led, trigger);
|
||||
- sc->radio_led.led_type = ATH_LED_RADIO;
|
||||
- if (ret)
|
||||
- goto fail;
|
||||
-
|
||||
- trigger = ieee80211_get_assoc_led_name(sc->hw);
|
||||
- snprintf(sc->assoc_led.name, sizeof(sc->assoc_led.name),
|
||||
- "ath9k-%s::assoc", wiphy_name(sc->hw->wiphy));
|
||||
- ret = ath_register_led(sc, &sc->assoc_led, trigger);
|
||||
- sc->assoc_led.led_type = ATH_LED_ASSOC;
|
||||
- if (ret)
|
||||
- goto fail;
|
||||
-
|
||||
- trigger = ieee80211_get_tx_led_name(sc->hw);
|
||||
- snprintf(sc->tx_led.name, sizeof(sc->tx_led.name),
|
||||
- "ath9k-%s::tx", wiphy_name(sc->hw->wiphy));
|
||||
- ret = ath_register_led(sc, &sc->tx_led, trigger);
|
||||
- sc->tx_led.led_type = ATH_LED_TX;
|
||||
- if (ret)
|
||||
- goto fail;
|
||||
-
|
||||
- trigger = ieee80211_get_rx_led_name(sc->hw);
|
||||
- snprintf(sc->rx_led.name, sizeof(sc->rx_led.name),
|
||||
- "ath9k-%s::rx", wiphy_name(sc->hw->wiphy));
|
||||
- ret = ath_register_led(sc, &sc->rx_led, trigger);
|
||||
- sc->rx_led.led_type = ATH_LED_RX;
|
||||
- if (ret)
|
||||
- goto fail;
|
||||
-
|
||||
- return;
|
||||
-
|
||||
-fail:
|
||||
- if (led_blink)
|
||||
- cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
- ath_deinit_leds(sc);
|
||||
+ sc->led_registered = true;
|
||||
}
|
||||
+#endif
|
||||
|
||||
/*******************/
|
||||
/* Rfkill */
|
||||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -1216,9 +1216,6 @@ static void ath9k_stop(struct ieee80211_
|
||||
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
- if (led_blink)
|
||||
- cancel_delayed_work_sync(&sc->ath_led_blink_work);
|
||||
-
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
cancel_delayed_work_sync(&sc->hw_pll_work);
|
||||
cancel_work_sync(&sc->paprd_work);
|
||||
--- a/drivers/net/wireless/ath/ath9k/init.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/init.c
|
||||
@@ -141,6 +141,21 @@ static struct ieee80211_rate ath9k_legac
|
||||
RATE(540, 0x0c, 0),
|
||||
};
|
||||
|
||||
+#ifdef CONFIG_MAC80211_LEDS
|
||||
+static const struct ieee80211_tpt_blink ath9k_tpt_blink[] = {
|
||||
+ { .throughput = 0 * 1024, .blink_time = 334 },
|
||||
+ { .throughput = 1 * 1024, .blink_time = 260 },
|
||||
+ { .throughput = 5 * 1024, .blink_time = 220 },
|
||||
+ { .throughput = 10 * 1024, .blink_time = 190 },
|
||||
+ { .throughput = 20 * 1024, .blink_time = 170 },
|
||||
+ { .throughput = 50 * 1024, .blink_time = 150 },
|
||||
+ { .throughput = 70 * 1024, .blink_time = 130 },
|
||||
+ { .throughput = 100 * 1024, .blink_time = 110 },
|
||||
+ { .throughput = 200 * 1024, .blink_time = 80 },
|
||||
+ { .throughput = 300 * 1024, .blink_time = 50 },
|
||||
+};
|
||||
+#endif
|
||||
+
|
||||
static void ath9k_deinit_softc(struct ath_softc *sc);
|
||||
|
||||
/*
|
||||
@@ -742,6 +757,13 @@ int ath9k_init_device(u16 devid, struct
|
||||
|
||||
ath9k_init_txpower_limits(sc);
|
||||
|
||||
+#ifdef CONFIG_MAC80211_LEDS
|
||||
+ /* must be initialized before ieee80211_register_hw */
|
||||
+ sc->led_cdev.default_trigger = ieee80211_create_tpt_led_trigger(sc->hw,
|
||||
+ IEEE80211_TPT_LEDTRIG_FL_RADIO, ath9k_tpt_blink,
|
||||
+ ARRAY_SIZE(ath9k_tpt_blink));
|
||||
+#endif
|
||||
+
|
||||
/* Register with mac80211 */
|
||||
error = ieee80211_register_hw(hw);
|
||||
if (error)
|
|
@ -1,6 +1,6 @@
|
|||
--- a/include/net/mac80211.h
|
||||
+++ b/include/net/mac80211.h
|
||||
@@ -2209,6 +2209,18 @@ static inline int ieee80211_sta_ps_trans
|
||||
@@ -2216,6 +2216,18 @@ static inline int ieee80211_sta_ps_trans
|
||||
#define IEEE80211_TX_STATUS_HEADROOM 13
|
||||
|
||||
/**
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -203,6 +203,7 @@ struct ath_atx_ac {
|
||||
@@ -202,6 +202,7 @@ struct ath_atx_ac {
|
||||
int sched;
|
||||
struct list_head list;
|
||||
struct list_head tid_q;
|
||||
|
@ -8,7 +8,7 @@
|
|||
};
|
||||
|
||||
struct ath_frame_info {
|
||||
@@ -260,6 +261,8 @@ struct ath_node {
|
||||
@@ -259,6 +260,8 @@ struct ath_node {
|
||||
struct ath_atx_ac ac[WME_NUM_AC];
|
||||
u16 maxampdu;
|
||||
u8 mpdudensity;
|
||||
|
@ -17,7 +17,7 @@
|
|||
};
|
||||
|
||||
#define AGGR_CLEANUP BIT(1)
|
||||
@@ -341,6 +344,9 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||
@@ -340,6 +343,9 @@ int ath_tx_aggr_start(struct ath_softc *
|
||||
void ath_tx_aggr_stop(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid);
|
||||
|
||||
|
@ -57,7 +57,7 @@
|
|||
static int ath9k_conf_tx(struct ieee80211_hw *hw, u16 queue,
|
||||
const struct ieee80211_tx_queue_params *params)
|
||||
{
|
||||
@@ -2191,6 +2212,7 @@ struct ieee80211_ops ath9k_ops = {
|
||||
@@ -2177,6 +2198,7 @@ struct ieee80211_ops ath9k_ops = {
|
||||
.configure_filter = ath9k_configure_filter,
|
||||
.sta_add = ath9k_sta_add,
|
||||
.sta_remove = ath9k_sta_remove,
|
||||
|
@ -189,7 +189,7 @@
|
|||
void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, u16 tid)
|
||||
{
|
||||
struct ath_atx_tid *txtid;
|
||||
@@ -1493,7 +1570,6 @@ static int setup_tx_flags(struct sk_buff
|
||||
@@ -1491,7 +1568,6 @@ static int setup_tx_flags(struct sk_buff
|
||||
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
|
||||
int flags = 0;
|
||||
|
||||
|
@ -197,7 +197,7 @@
|
|||
flags |= ATH9K_TXDESC_INTREQ;
|
||||
|
||||
if (tx_info->flags & IEEE80211_TX_CTL_NO_ACK)
|
||||
@@ -1756,6 +1832,9 @@ static void ath_tx_start_dma(struct ath_
|
||||
@@ -1754,6 +1830,9 @@ static void ath_tx_start_dma(struct ath_
|
||||
if (txctl->paprd)
|
||||
bf->bf_state.bfs_paprd_timestamp = jiffies;
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -2226,33 +2226,6 @@ static void ath_tx_complete_poll_work(st
|
||||
@@ -2223,33 +2223,6 @@ static void ath_tx_complete_poll_work(st
|
||||
} else {
|
||||
txq->axq_tx_inprogress = true;
|
||||
}
|
|
@ -1,232 +0,0 @@
|
|||
--- a/include/net/cfg80211.h
|
||||
+++ b/include/net/cfg80211.h
|
||||
@@ -414,7 +414,7 @@ struct station_parameters {
|
||||
* @STATION_INFO_PLID: @plid filled
|
||||
* @STATION_INFO_PLINK_STATE: @plink_state filled
|
||||
* @STATION_INFO_SIGNAL: @signal filled
|
||||
- * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled
|
||||
+ * @STATION_INFO_TX_BITRATE: @txrate fields are filled
|
||||
* (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs)
|
||||
* @STATION_INFO_RX_PACKETS: @rx_packets filled
|
||||
* @STATION_INFO_TX_PACKETS: @tx_packets filled
|
||||
@@ -422,6 +422,7 @@ struct station_parameters {
|
||||
* @STATION_INFO_TX_FAILED: @tx_failed filled
|
||||
* @STATION_INFO_RX_DROP_MISC: @rx_dropped_misc filled
|
||||
* @STATION_INFO_SIGNAL_AVG: @signal_avg filled
|
||||
+ * @STATION_INFO_RX_BITRATE: @rxrate fields are filled
|
||||
*/
|
||||
enum station_info_flags {
|
||||
STATION_INFO_INACTIVE_TIME = 1<<0,
|
||||
@@ -438,6 +439,7 @@ enum station_info_flags {
|
||||
STATION_INFO_TX_FAILED = 1<<11,
|
||||
STATION_INFO_RX_DROP_MISC = 1<<12,
|
||||
STATION_INFO_SIGNAL_AVG = 1<<13,
|
||||
+ STATION_INFO_RX_BITRATE = 1<<14,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -507,6 +509,7 @@ struct station_info {
|
||||
s8 signal;
|
||||
s8 signal_avg;
|
||||
struct rate_info txrate;
|
||||
+ struct rate_info rxrate;
|
||||
u32 rx_packets;
|
||||
u32 tx_packets;
|
||||
u32 tx_retries;
|
||||
--- a/include/linux/nl80211.h
|
||||
+++ b/include/linux/nl80211.h
|
||||
@@ -1243,6 +1243,8 @@ enum nl80211_rate_info {
|
||||
* @NL80211_STA_INFO_LLID: the station's mesh LLID
|
||||
* @NL80211_STA_INFO_PLID: the station's mesh PLID
|
||||
* @NL80211_STA_INFO_PLINK_STATE: peer link state for the station
|
||||
+ * @NL80211_STA_INFO_RX_BITRATE: last unicast rx rate, nested attribute
|
||||
+ * containing info as possible, see &enum nl80211_sta_info_txrate.
|
||||
* @__NL80211_STA_INFO_AFTER_LAST: internal
|
||||
* @NL80211_STA_INFO_MAX: highest possible station info attribute
|
||||
*/
|
||||
@@ -1261,6 +1263,7 @@ enum nl80211_sta_info {
|
||||
NL80211_STA_INFO_TX_RETRIES,
|
||||
NL80211_STA_INFO_TX_FAILED,
|
||||
NL80211_STA_INFO_SIGNAL_AVG,
|
||||
+ NL80211_STA_INFO_RX_BITRATE,
|
||||
|
||||
/* keep last */
|
||||
__NL80211_STA_INFO_AFTER_LAST,
|
||||
--- a/net/wireless/nl80211.c
|
||||
+++ b/net/wireless/nl80211.c
|
||||
@@ -1968,13 +1968,41 @@ static int parse_station_flags(struct ge
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static bool nl80211_put_sta_rate(struct sk_buff *msg, struct rate_info *info,
|
||||
+ int attr)
|
||||
+{
|
||||
+ struct nlattr *rate;
|
||||
+ u16 bitrate;
|
||||
+
|
||||
+ rate = nla_nest_start(msg, attr);
|
||||
+ if (!rate)
|
||||
+ goto nla_put_failure;
|
||||
+
|
||||
+ /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
|
||||
+ bitrate = cfg80211_calculate_bitrate(info);
|
||||
+ if (bitrate > 0)
|
||||
+ NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
|
||||
+
|
||||
+ if (info->flags & RATE_INFO_FLAGS_MCS)
|
||||
+ NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, info->mcs);
|
||||
+ if (info->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
|
||||
+ NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
|
||||
+ if (info->flags & RATE_INFO_FLAGS_SHORT_GI)
|
||||
+ NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
|
||||
+
|
||||
+ nla_nest_end(msg, rate);
|
||||
+ return true;
|
||||
+
|
||||
+nla_put_failure:
|
||||
+ return false;
|
||||
+}
|
||||
+
|
||||
static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq,
|
||||
int flags, struct net_device *dev,
|
||||
const u8 *mac_addr, struct station_info *sinfo)
|
||||
{
|
||||
void *hdr;
|
||||
- struct nlattr *sinfoattr, *txrate;
|
||||
- u16 bitrate;
|
||||
+ struct nlattr *sinfoattr;
|
||||
|
||||
hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION);
|
||||
if (!hdr)
|
||||
@@ -2013,24 +2041,14 @@ static int nl80211_send_station(struct s
|
||||
NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL_AVG,
|
||||
sinfo->signal_avg);
|
||||
if (sinfo->filled & STATION_INFO_TX_BITRATE) {
|
||||
- txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE);
|
||||
- if (!txrate)
|
||||
+ if (!nl80211_put_sta_rate(msg, &sinfo->txrate,
|
||||
+ NL80211_STA_INFO_TX_BITRATE))
|
||||
+ goto nla_put_failure;
|
||||
+ }
|
||||
+ if (sinfo->filled & STATION_INFO_RX_BITRATE) {
|
||||
+ if (!nl80211_put_sta_rate(msg, &sinfo->rxrate,
|
||||
+ NL80211_STA_INFO_RX_BITRATE))
|
||||
goto nla_put_failure;
|
||||
-
|
||||
- /* cfg80211_calculate_bitrate will return 0 for mcs >= 32 */
|
||||
- bitrate = cfg80211_calculate_bitrate(&sinfo->txrate);
|
||||
- if (bitrate > 0)
|
||||
- NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate);
|
||||
-
|
||||
- if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS)
|
||||
- NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS,
|
||||
- sinfo->txrate.mcs);
|
||||
- if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH)
|
||||
- NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH);
|
||||
- if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI)
|
||||
- NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI);
|
||||
-
|
||||
- nla_nest_end(msg, txrate);
|
||||
}
|
||||
if (sinfo->filled & STATION_INFO_RX_PACKETS)
|
||||
NLA_PUT_U32(msg, NL80211_STA_INFO_RX_PACKETS,
|
||||
--- a/net/mac80211/sta_info.h
|
||||
+++ b/net/mac80211/sta_info.h
|
||||
@@ -212,6 +212,8 @@ enum plink_state {
|
||||
* @rate_ctrl_priv: rate control private per-STA pointer
|
||||
* @last_tx_rate: rate used for last transmit, to report to userspace as
|
||||
* "the" transmit rate
|
||||
+ * @last_rx_rate_idx: rx status rate index of the last data packet
|
||||
+ * @last_rx_rate_flag: rx status flag of the last data packet
|
||||
* @lock: used for locking all fields that require locking, see comments
|
||||
* in the header file.
|
||||
* @flaglock: spinlock for flags accesses
|
||||
@@ -314,6 +316,8 @@ struct sta_info {
|
||||
unsigned long tx_bytes;
|
||||
unsigned long tx_fragments;
|
||||
struct ieee80211_tx_rate last_tx_rate;
|
||||
+ int last_rx_rate_idx;
|
||||
+ int last_rx_rate_flag;
|
||||
u16 tid_seq[IEEE80211_QOS_CTL_TID_MASK + 1];
|
||||
|
||||
/*
|
||||
--- a/net/mac80211/rx.c
|
||||
+++ b/net/mac80211/rx.c
|
||||
@@ -1156,14 +1156,23 @@ ieee80211_rx_h_sta_process(struct ieee80
|
||||
if (rx->sdata->vif.type == NL80211_IFTYPE_ADHOC) {
|
||||
u8 *bssid = ieee80211_get_bssid(hdr, rx->skb->len,
|
||||
NL80211_IFTYPE_ADHOC);
|
||||
- if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0)
|
||||
+ if (compare_ether_addr(bssid, rx->sdata->u.ibss.bssid) == 0) {
|
||||
sta->last_rx = jiffies;
|
||||
+ if (ieee80211_is_data(hdr->frame_control)) {
|
||||
+ sta->last_rx_rate_idx = status->rate_idx;
|
||||
+ sta->last_rx_rate_flag = status->flag;
|
||||
+ }
|
||||
+ }
|
||||
} else if (!is_multicast_ether_addr(hdr->addr1)) {
|
||||
/*
|
||||
* Mesh beacons will update last_rx when if they are found to
|
||||
* match the current local configuration when processed.
|
||||
*/
|
||||
sta->last_rx = jiffies;
|
||||
+ if (ieee80211_is_data(hdr->frame_control)) {
|
||||
+ sta->last_rx_rate_idx = status->rate_idx;
|
||||
+ sta->last_rx_rate_flag = status->flag;
|
||||
+ }
|
||||
}
|
||||
|
||||
if (!(status->rx_flags & IEEE80211_RX_RA_MATCH))
|
||||
--- a/net/mac80211/cfg.c
|
||||
+++ b/net/mac80211/cfg.c
|
||||
@@ -316,6 +316,17 @@ static int ieee80211_config_default_mgmt
|
||||
return 0;
|
||||
}
|
||||
|
||||
+static void rate_idx_to_bitrate(struct rate_info *rate, struct sta_info *sta, int idx)
|
||||
+{
|
||||
+ if (!(rate->flags & RATE_INFO_FLAGS_MCS)) {
|
||||
+ struct ieee80211_supported_band *sband;
|
||||
+ sband = sta->local->hw.wiphy->bands[
|
||||
+ sta->local->hw.conf.channel->band];
|
||||
+ rate->legacy = sband->bitrates[idx].bitrate;
|
||||
+ } else
|
||||
+ rate->mcs = idx;
|
||||
+}
|
||||
+
|
||||
static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo)
|
||||
{
|
||||
struct ieee80211_sub_if_data *sdata = sta->sdata;
|
||||
@@ -330,6 +341,7 @@ static void sta_set_sinfo(struct sta_inf
|
||||
STATION_INFO_TX_RETRIES |
|
||||
STATION_INFO_TX_FAILED |
|
||||
STATION_INFO_TX_BITRATE |
|
||||
+ STATION_INFO_RX_BITRATE |
|
||||
STATION_INFO_RX_DROP_MISC;
|
||||
|
||||
sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx);
|
||||
@@ -355,15 +367,16 @@ static void sta_set_sinfo(struct sta_inf
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI)
|
||||
sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
+ rate_idx_to_bitrate(&sinfo->txrate, sta, sta->last_tx_rate.idx);
|
||||
|
||||
- if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) {
|
||||
- struct ieee80211_supported_band *sband;
|
||||
- sband = sta->local->hw.wiphy->bands[
|
||||
- sta->local->hw.conf.channel->band];
|
||||
- sinfo->txrate.legacy =
|
||||
- sband->bitrates[sta->last_tx_rate.idx].bitrate;
|
||||
- } else
|
||||
- sinfo->txrate.mcs = sta->last_tx_rate.idx;
|
||||
+ sinfo->rxrate.flags = 0;
|
||||
+ if (sta->last_rx_rate_flag & RX_FLAG_HT)
|
||||
+ sinfo->rxrate.flags |= RATE_INFO_FLAGS_MCS;
|
||||
+ if (sta->last_rx_rate_flag & RX_FLAG_40MHZ)
|
||||
+ sinfo->rxrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH;
|
||||
+ if (sta->last_rx_rate_flag & RX_FLAG_SHORT_GI)
|
||||
+ sinfo->rxrate.flags |= RATE_INFO_FLAGS_SHORT_GI;
|
||||
+ rate_idx_to_bitrate(&sinfo->rxrate, sta, sta->last_rx_rate_idx);
|
||||
|
||||
if (ieee80211_vif_is_mesh(&sdata->vif)) {
|
||||
#ifdef CONFIG_MAC80211_MESH
|
|
@ -1,13 +0,0 @@
|
|||
--- 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 *s
|
||||
* mode interface or when in monitor mode. AP mode does not need this
|
||||
* since it receives all in-BSS frames anyway.
|
||||
*/
|
||||
- if (((sc->sc_ah->opmode != NL80211_IFTYPE_AP) &&
|
||||
- (sc->rx.rxfilter & FIF_PROMISC_IN_BSS)) ||
|
||||
- (sc->sc_ah->is_monitoring))
|
||||
+ if (sc->sc_ah->is_monitoring)
|
||||
rfilt |= ATH9K_RX_FILTER_PROM;
|
||||
|
||||
if (sc->rx.rxfilter & FIF_CONTROL)
|
|
@ -1,50 +0,0 @@
|
|||
--- a/net/mac80211/rc80211_minstrel_ht.c
|
||||
+++ b/net/mac80211/rc80211_minstrel_ht.c
|
||||
@@ -415,10 +415,8 @@ minstrel_ht_tx_status(void *priv, struct
|
||||
mi->sample_count--;
|
||||
}
|
||||
|
||||
- if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE) {
|
||||
+ if (info->flags & IEEE80211_TX_CTL_RATE_CTRL_PROBE)
|
||||
mi->sample_packets += info->status.ampdu_len;
|
||||
- minstrel_next_sample_idx(mi);
|
||||
- }
|
||||
|
||||
for (i = 0; !last; i++) {
|
||||
last = (i == IEEE80211_TX_MAX_RATES - 1) ||
|
||||
@@ -553,13 +551,14 @@ minstrel_get_sample_rate(struct minstrel
|
||||
sample_idx = sample_table[mg->column][mg->index];
|
||||
mr = &mg->rates[sample_idx];
|
||||
sample_idx += mi->sample_group * MCS_GROUP_RATES;
|
||||
+ minstrel_next_sample_idx(mi);
|
||||
|
||||
/*
|
||||
* When not using MRR, do not sample if the probability is already
|
||||
* higher than 95% to avoid wasting airtime
|
||||
*/
|
||||
if (!mp->has_mrr && (mr->probability > MINSTREL_FRAC(95, 100)))
|
||||
- goto next;
|
||||
+ return -1;
|
||||
|
||||
/*
|
||||
* Make sure that lower rates get sampled only occasionally,
|
||||
@@ -568,17 +567,13 @@ minstrel_get_sample_rate(struct minstrel
|
||||
if (minstrel_get_duration(sample_idx) >
|
||||
minstrel_get_duration(mi->max_tp_rate)) {
|
||||
if (mr->sample_skipped < 20)
|
||||
- goto next;
|
||||
+ return -1;
|
||||
|
||||
if (mi->sample_slow++ > 2)
|
||||
- goto next;
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
return sample_idx;
|
||||
-
|
||||
-next:
|
||||
- minstrel_next_sample_idx(mi);
|
||||
- return -1;
|
||||
}
|
||||
|
||||
static void
|
|
@ -1,14 +0,0 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/hw.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/hw.h
|
||||
@@ -95,9 +95,9 @@
|
||||
#define REG_READ_FIELD(_a, _r, _f) \
|
||||
(((REG_READ(_a, _r) & _f) >> _f##_S))
|
||||
#define REG_SET_BIT(_a, _r, _f) \
|
||||
- REG_WRITE(_a, _r, REG_READ(_a, _r) | _f)
|
||||
+ REG_WRITE(_a, _r, REG_READ(_a, _r) | (_f))
|
||||
#define REG_CLR_BIT(_a, _r, _f) \
|
||||
- REG_WRITE(_a, _r, REG_READ(_a, _r) & ~_f)
|
||||
+ REG_WRITE(_a, _r, REG_READ(_a, _r) & ~(_f))
|
||||
|
||||
#define DO_DELAY(x) do { \
|
||||
if ((++(x) % 64) == 0) \
|
|
@ -1,72 +0,0 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -1271,16 +1271,14 @@ bool ath_drain_all_txq(struct ath_softc
|
||||
if (sc->sc_flags & SC_OP_INVALID)
|
||||
return true;
|
||||
|
||||
- /* Stop beacon queue */
|
||||
- ath9k_hw_stoptxdma(sc->sc_ah, sc->beacon.beaconq);
|
||||
+ ath9k_hw_abort_tx_dma(ah);
|
||||
|
||||
- /* Stop data queues */
|
||||
+ /* Check if any queue remains active */
|
||||
for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
- if (ATH_TXQ_SETUP(sc, i)) {
|
||||
- txq = &sc->tx.txq[i];
|
||||
- ath9k_hw_stoptxdma(ah, txq->axq_qnum);
|
||||
- npend += ath9k_hw_numtxpending(ah, txq->axq_qnum);
|
||||
- }
|
||||
+ if (!ATH_TXQ_SETUP(sc, i))
|
||||
+ continue;
|
||||
+
|
||||
+ npend += ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum);
|
||||
}
|
||||
|
||||
if (npend)
|
||||
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||
@@ -143,6 +143,34 @@ bool ath9k_hw_updatetxtriglevel(struct a
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_updatetxtriglevel);
|
||||
|
||||
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah)
|
||||
+{
|
||||
+ int i, q;
|
||||
+
|
||||
+ REG_WRITE(ah, AR_Q_TXD, AR_Q_TXD_M);
|
||||
+
|
||||
+ REG_SET_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
|
||||
+ REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+ REG_SET_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
|
||||
+
|
||||
+ for (q = 0; q < AR_NUM_QCU; q++) {
|
||||
+ for (i = 0; i < 1000; i++) {
|
||||
+ if (i)
|
||||
+ udelay(5);
|
||||
+
|
||||
+ if (!ath9k_hw_numtxpending(ah, q))
|
||||
+ break;
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ REG_CLR_BIT(ah, AR_PCU_MISC, AR_PCU_FORCE_QUIET_COLL | AR_PCU_CLEAR_VMF);
|
||||
+ REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+ REG_CLR_BIT(ah, AR_D_GBL_IFS_MISC, AR_D_GBL_IFS_MISC_IGNORE_BACKOFF);
|
||||
+
|
||||
+ REG_WRITE(ah, AR_Q_TXD, 0);
|
||||
+}
|
||||
+EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
|
||||
+
|
||||
bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
|
||||
--- a/drivers/net/wireless/ath/ath9k/mac.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.h
|
||||
@@ -676,6 +676,7 @@ void ath9k_hw_cleartxdesc(struct ath_hw
|
||||
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
|
||||
bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
|
||||
+void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
|
||||
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
const struct ath9k_tx_queue_info *qinfo);
|
|
@ -1,141 +0,0 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/main.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/main.c
|
||||
@@ -2149,56 +2149,42 @@ static void ath9k_set_coverage_class(str
|
||||
|
||||
static void ath9k_flush(struct ieee80211_hw *hw, bool drop)
|
||||
{
|
||||
-#define ATH_FLUSH_TIMEOUT 60 /* ms */
|
||||
struct ath_softc *sc = hw->priv;
|
||||
- struct ath_txq *txq = NULL;
|
||||
- struct ath_hw *ah = sc->sc_ah;
|
||||
- struct ath_common *common = ath9k_hw_common(ah);
|
||||
- int i, j, npend = 0;
|
||||
+ int timeout = 200; /* ms */
|
||||
+ int i, j;
|
||||
|
||||
+ ath9k_ps_wakeup(sc);
|
||||
mutex_lock(&sc->mutex);
|
||||
|
||||
cancel_delayed_work_sync(&sc->tx_complete_work);
|
||||
|
||||
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
- if (!ATH_TXQ_SETUP(sc, i))
|
||||
- continue;
|
||||
- txq = &sc->tx.txq[i];
|
||||
-
|
||||
- if (!drop) {
|
||||
- for (j = 0; j < ATH_FLUSH_TIMEOUT; j++) {
|
||||
- if (!ath9k_has_pending_frames(sc, txq))
|
||||
- break;
|
||||
- usleep_range(1000, 2000);
|
||||
- }
|
||||
- }
|
||||
+ if (drop)
|
||||
+ timeout = 1;
|
||||
+
|
||||
+ for (j = 0; j < timeout; j++) {
|
||||
+ int npend = 0;
|
||||
+
|
||||
+ if (j)
|
||||
+ usleep_range(1000, 2000);
|
||||
|
||||
- if (drop || ath9k_has_pending_frames(sc, txq)) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE, "Drop frames from hw queue:%d\n",
|
||||
- txq->axq_qnum);
|
||||
- spin_lock_bh(&txq->axq_lock);
|
||||
- txq->txq_flush_inprogress = true;
|
||||
- spin_unlock_bh(&txq->axq_lock);
|
||||
-
|
||||
- ath9k_ps_wakeup(sc);
|
||||
- ath9k_hw_stoptxdma(ah, txq->axq_qnum);
|
||||
- npend = ath9k_hw_numtxpending(ah, txq->axq_qnum);
|
||||
- ath9k_ps_restore(sc);
|
||||
- if (npend)
|
||||
- break;
|
||||
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
|
||||
+ if (!ATH_TXQ_SETUP(sc, i))
|
||||
+ continue;
|
||||
|
||||
- ath_draintxq(sc, txq, false);
|
||||
- txq->txq_flush_inprogress = false;
|
||||
+ npend += ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
|
||||
}
|
||||
+
|
||||
+ if (!npend)
|
||||
+ goto out;
|
||||
}
|
||||
|
||||
- if (npend) {
|
||||
+ if (!ath_drain_all_txq(sc, false))
|
||||
ath_reset(sc, false);
|
||||
- txq->txq_flush_inprogress = false;
|
||||
- }
|
||||
|
||||
+out:
|
||||
ieee80211_queue_delayed_work(hw, &sc->tx_complete_work, 0);
|
||||
mutex_unlock(&sc->mutex);
|
||||
+ ath9k_ps_restore(sc);
|
||||
}
|
||||
|
||||
struct ieee80211_ops ath9k_ops = {
|
||||
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
|
||||
@@ -189,7 +189,6 @@ struct ath_txq {
|
||||
u32 axq_ampdu_depth;
|
||||
bool stopped;
|
||||
bool axq_tx_inprogress;
|
||||
- bool txq_flush_inprogress;
|
||||
struct list_head axq_acq;
|
||||
struct list_head txq_fifo[ATH_TXFIFO_DEPTH];
|
||||
struct list_head txq_fifo_pending;
|
||||
--- a/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
|
||||
@@ -2091,8 +2091,7 @@ static void ath_tx_processq(struct ath_s
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
if (list_empty(&txq->axq_q)) {
|
||||
txq->axq_link = NULL;
|
||||
- if (sc->sc_flags & SC_OP_TXAGGR &&
|
||||
- !txq->txq_flush_inprogress)
|
||||
+ if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
break;
|
||||
@@ -2173,7 +2172,7 @@ static void ath_tx_processq(struct ath_s
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
- if (sc->sc_flags & SC_OP_TXAGGR && !txq->txq_flush_inprogress)
|
||||
+ if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
ath_txq_schedule(sc, txq);
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
@@ -2317,18 +2316,17 @@ void ath_tx_edma_tasklet(struct ath_soft
|
||||
|
||||
spin_lock_bh(&txq->axq_lock);
|
||||
|
||||
- if (!txq->txq_flush_inprogress) {
|
||||
- if (!list_empty(&txq->txq_fifo_pending)) {
|
||||
- INIT_LIST_HEAD(&bf_head);
|
||||
- bf = list_first_entry(&txq->txq_fifo_pending,
|
||||
- struct ath_buf, list);
|
||||
- list_cut_position(&bf_head,
|
||||
- &txq->txq_fifo_pending,
|
||||
- &bf->bf_lastbf->list);
|
||||
- ath_tx_txqaddbuf(sc, txq, &bf_head);
|
||||
- } else if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
- ath_txq_schedule(sc, txq);
|
||||
- }
|
||||
+ if (!list_empty(&txq->txq_fifo_pending)) {
|
||||
+ INIT_LIST_HEAD(&bf_head);
|
||||
+ bf = list_first_entry(&txq->txq_fifo_pending,
|
||||
+ struct ath_buf, list);
|
||||
+ list_cut_position(&bf_head,
|
||||
+ &txq->txq_fifo_pending,
|
||||
+ &bf->bf_lastbf->list);
|
||||
+ ath_tx_txqaddbuf(sc, txq, &bf_head);
|
||||
+ } else if (sc->sc_flags & SC_OP_TXAGGR)
|
||||
+ ath_txq_schedule(sc, txq);
|
||||
+
|
||||
spin_unlock_bh(&txq->axq_lock);
|
||||
}
|
||||
}
|
|
@ -1,143 +0,0 @@
|
|||
--- a/drivers/net/wireless/ath/ath9k/mac.c
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.c
|
||||
@@ -171,84 +171,31 @@ void ath9k_hw_abort_tx_dma(struct ath_hw
|
||||
}
|
||||
EXPORT_SYMBOL(ath9k_hw_abort_tx_dma);
|
||||
|
||||
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q)
|
||||
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q)
|
||||
{
|
||||
-#define ATH9K_TX_STOP_DMA_TIMEOUT 4000 /* usec */
|
||||
+#define ATH9K_TX_STOP_DMA_TIMEOUT 1000 /* usec */
|
||||
#define ATH9K_TIME_QUANTUM 100 /* usec */
|
||||
- struct ath_common *common = ath9k_hw_common(ah);
|
||||
- struct ath9k_hw_capabilities *pCap = &ah->caps;
|
||||
- struct ath9k_tx_queue_info *qi;
|
||||
- u32 tsfLow, j, wait;
|
||||
- u32 wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
|
||||
-
|
||||
- if (q >= pCap->total_queues) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "Stopping TX DMA, invalid queue: %u\n", q);
|
||||
- return false;
|
||||
- }
|
||||
-
|
||||
- qi = &ah->txq[q];
|
||||
- if (qi->tqi_type == ATH9K_TX_QUEUE_INACTIVE) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "Stopping TX DMA, inactive queue: %u\n", q);
|
||||
- return false;
|
||||
- }
|
||||
+ int wait_time = ATH9K_TX_STOP_DMA_TIMEOUT / ATH9K_TIME_QUANTUM;
|
||||
+ int wait;
|
||||
|
||||
REG_WRITE(ah, AR_Q_TXD, 1 << q);
|
||||
|
||||
for (wait = wait_time; wait != 0; wait--) {
|
||||
- if (ath9k_hw_numtxpending(ah, q) == 0)
|
||||
- break;
|
||||
- udelay(ATH9K_TIME_QUANTUM);
|
||||
- }
|
||||
-
|
||||
- if (ath9k_hw_numtxpending(ah, q)) {
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "%s: Num of pending TX Frames %d on Q %d\n",
|
||||
- __func__, ath9k_hw_numtxpending(ah, q), q);
|
||||
-
|
||||
- for (j = 0; j < 2; j++) {
|
||||
- tsfLow = REG_READ(ah, AR_TSF_L32);
|
||||
- REG_WRITE(ah, AR_QUIET2,
|
||||
- SM(10, AR_QUIET2_QUIET_DUR));
|
||||
- REG_WRITE(ah, AR_QUIET_PERIOD, 100);
|
||||
- REG_WRITE(ah, AR_NEXT_QUIET_TIMER, tsfLow >> 10);
|
||||
- REG_SET_BIT(ah, AR_TIMER_MODE,
|
||||
- AR_QUIET_TIMER_EN);
|
||||
-
|
||||
- if ((REG_READ(ah, AR_TSF_L32) >> 10) == (tsfLow >> 10))
|
||||
- break;
|
||||
-
|
||||
- ath_dbg(common, ATH_DBG_QUEUE,
|
||||
- "TSF has moved while trying to set quiet time TSF: 0x%08x\n",
|
||||
- tsfLow);
|
||||
- }
|
||||
-
|
||||
- REG_SET_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
-
|
||||
- udelay(200);
|
||||
- REG_CLR_BIT(ah, AR_TIMER_MODE, AR_QUIET_TIMER_EN);
|
||||
-
|
||||
- wait = wait_time;
|
||||
- while (ath9k_hw_numtxpending(ah, q)) {
|
||||
- if ((--wait) == 0) {
|
||||
- ath_err(common,
|
||||
- "Failed to stop TX DMA in 100 msec after killing last frame\n");
|
||||
- break;
|
||||
- }
|
||||
+ if (wait != wait_time)
|
||||
udelay(ATH9K_TIME_QUANTUM);
|
||||
- }
|
||||
|
||||
- REG_CLR_BIT(ah, AR_DIAG_SW, AR_DIAG_FORCE_CH_IDLE_HIGH);
|
||||
+ if (ath9k_hw_numtxpending(ah, q) == 0)
|
||||
+ break;
|
||||
}
|
||||
|
||||
REG_WRITE(ah, AR_Q_TXD, 0);
|
||||
+
|
||||
return wait != 0;
|
||||
|
||||
#undef ATH9K_TX_STOP_DMA_TIMEOUT
|
||||
#undef ATH9K_TIME_QUANTUM
|
||||
}
|
||||
-EXPORT_SYMBOL(ath9k_hw_stoptxdma);
|
||||
+EXPORT_SYMBOL(ath9k_hw_stop_dma_queue);
|
||||
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs)
|
||||
{
|
||||
--- a/drivers/net/wireless/ath/ath9k/mac.h
|
||||
+++ b/drivers/net/wireless/ath/ath9k/mac.h
|
||||
@@ -675,7 +675,7 @@ void ath9k_hw_txstart(struct ath_hw *ah,
|
||||
void ath9k_hw_cleartxdesc(struct ath_hw *ah, void *ds);
|
||||
u32 ath9k_hw_numtxpending(struct ath_hw *ah, u32 q);
|
||||
bool ath9k_hw_updatetxtriglevel(struct ath_hw *ah, bool bIncTrigLevel);
|
||||
-bool ath9k_hw_stoptxdma(struct ath_hw *ah, u32 q);
|
||||
+bool ath9k_hw_stop_dma_queue(struct ath_hw *ah, u32 q);
|
||||
void ath9k_hw_abort_tx_dma(struct ath_hw *ah);
|
||||
void ath9k_hw_gettxintrtxqs(struct ath_hw *ah, u32 *txqs);
|
||||
bool ath9k_hw_set_txq_props(struct ath_hw *ah, int q,
|
||||
--- 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 da
|
||||
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||
"missed %u consecutive beacons\n",
|
||||
sc->beacon.bmisscnt);
|
||||
+ ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
|
||||
ath9k_hw_bstuck_nfcal(ah);
|
||||
} else if (sc->beacon.bmisscnt >= BSTUCK_THRESH) {
|
||||
ath_dbg(common, ATH_DBG_BSTUCK,
|
||||
@@ -450,16 +451,6 @@ void ath_beacon_tasklet(unsigned long da
|
||||
sc->beacon.updateslot = OK;
|
||||
}
|
||||
if (bfaddr != 0) {
|
||||
- /*
|
||||
- * Stop any current dma and put the new frame(s) on the queue.
|
||||
- * This should never fail since we check above that no frames
|
||||
- * are still pending on the queue.
|
||||
- */
|
||||
- if (!ath9k_hw_stoptxdma(ah, sc->beacon.beaconq)) {
|
||||
- ath_err(common, "beacon queue %u did not stop?\n",
|
||||
- sc->beacon.beaconq);
|
||||
- }
|
||||
-
|
||||
/* NB: cabq traffic should already be queued and primed */
|
||||
ath9k_hw_puttxbuf(ah, sc->beacon.beaconq, bfaddr);
|
||||
ath9k_hw_txstart(ah, sc->beacon.beaconq);
|
||||
@@ -780,7 +771,7 @@ void ath9k_set_beaconing_status(struct a
|
||||
ah->imask &= ~ATH9K_INT_SWBA;
|
||||
ath9k_hw_set_interrupts(ah, ah->imask);
|
||||
tasklet_kill(&sc->bcon_tasklet);
|
||||
- ath9k_hw_stoptxdma(ah, sc->beacon.beaconq);
|
||||
+ ath9k_hw_stop_dma_queue(ah, sc->beacon.beaconq);
|
||||
}
|
||||
ath9k_ps_restore(sc);
|
||||
}
|
|
@ -1,12 +0,0 @@
|
|||
--- a/net/mac80211/chan.c
|
||||
+++ b/net/mac80211/chan.c
|
||||
@@ -77,6 +77,9 @@ bool ieee80211_set_channel_type(struct i
|
||||
switch (tmp->vif.bss_conf.channel_type) {
|
||||
case NL80211_CHAN_NO_HT:
|
||||
case NL80211_CHAN_HT20:
|
||||
+ if (superchan > tmp->vif.bss_conf.channel_type)
|
||||
+ break;
|
||||
+
|
||||
superchan = tmp->vif.bss_conf.channel_type;
|
||||
break;
|
||||
case NL80211_CHAN_HT40PLUS:
|
|
@ -1,11 +0,0 @@
|
|||
--- 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_
|
||||
fi = get_frame_info(bf->bf_mpdu);
|
||||
if (fi->retries) {
|
||||
ath_tx_update_baw(sc, tid, fi->seqno);
|
||||
- ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 0);
|
||||
+ ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, 0, 1);
|
||||
} else {
|
||||
ath_tx_send_normal(sc, txq, NULL, &bf_head);
|
||||
}
|
|
@ -1,6 +1,6 @@
|
|||
--- a/drivers/net/wireless/mwl8k.c
|
||||
+++ b/drivers/net/wireless/mwl8k.c
|
||||
@@ -4502,6 +4502,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
|
||||
@@ -4500,6 +4500,7 @@ MODULE_FIRMWARE("mwl8k/fmimage_8366.fw")
|
||||
MODULE_FIRMWARE(MWL8K_8366_AP_FW(MWL8K_8366_AP_FW_API));
|
||||
|
||||
static DEFINE_PCI_DEVICE_TABLE(mwl8k_pci_id_table) = {
|
||||
|
|
|
@ -1,18 +0,0 @@
|
|||
--- a/drivers/net/wireless/p54/eeprom.c
|
||||
+++ b/drivers/net/wireless/p54/eeprom.c
|
||||
@@ -524,10 +524,13 @@ err_data:
|
||||
|
||||
struct p54_rssi_db_entry *p54_rssi_find(struct p54_common *priv, const u16 freq)
|
||||
{
|
||||
- struct p54_rssi_db_entry *entry = (void *)(priv->rssi_db->data +
|
||||
- priv->rssi_db->offset);
|
||||
+ struct p54_rssi_db_entry *entry;
|
||||
int i, found = -1;
|
||||
|
||||
+ if (!priv->rssi_db)
|
||||
+ return &p54_rssi_default;
|
||||
+
|
||||
+ entry = (void *)(priv->rssi_db->data + priv->rssi_db->offset);
|
||||
for (i = 0; i < priv->rssi_db->entries; i++) {
|
||||
if (!same_band(freq, entry[i].freq))
|
||||
continue;
|
|
@ -1,14 +0,0 @@
|
|||
Index: compat-wireless-2011-02-25/net/mac80211/main.c
|
||||
===================================================================
|
||||
--- compat-wireless-2011-02-25.orig/net/mac80211/main.c 2011-03-07 12:58:14.996968980 +0100
|
||||
+++ compat-wireless-2011-02-25/net/mac80211/main.c 2011-03-07 13:03:26.732273903 +0100
|
||||
@@ -384,6 +384,9 @@ void ieee80211_restart_hw(struct ieee802
|
||||
|
||||
trace_api_restart_hw(local);
|
||||
|
||||
+ wiphy_info(hw->wiphy,
|
||||
+ "Hardware restart was requested\n");
|
||||
+
|
||||
/* use this reason, ieee80211_reconfig will unblock it */
|
||||
ieee80211_stop_queues_by_reason(hw,
|
||||
IEEE80211_QUEUE_STOP_REASON_SUSPEND);
|
|
@ -1,141 +0,0 @@
|
|||
Index: compat-wireless-2011-02-25/net/mac80211/scan.c
|
||||
===================================================================
|
||||
--- compat-wireless-2011-02-25.orig/net/mac80211/scan.c 2011-03-07 14:43:55.695666042 +0100
|
||||
+++ compat-wireless-2011-02-25/net/mac80211/scan.c 2011-03-07 14:43:57.594439631 +0100
|
||||
@@ -258,10 +258,12 @@ static bool ieee80211_prep_hw_scan(struc
|
||||
return true;
|
||||
}
|
||||
|
||||
-static bool __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
|
||||
+static void __ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted,
|
||||
bool was_hw_scan)
|
||||
{
|
||||
struct ieee80211_local *local = hw_to_local(hw);
|
||||
+ bool on_oper_chan;
|
||||
+ bool enable_beacons = false;
|
||||
|
||||
lockdep_assert_held(&local->mtx);
|
||||
|
||||
@@ -275,12 +277,12 @@ static bool __ieee80211_scan_completed(s
|
||||
aborted = true;
|
||||
|
||||
if (WARN_ON(!local->scan_req))
|
||||
- return false;
|
||||
+ return;
|
||||
|
||||
if (was_hw_scan && !aborted && ieee80211_prep_hw_scan(local)) {
|
||||
int rc = drv_hw_scan(local, local->scan_sdata, local->hw_scan_req);
|
||||
if (rc == 0)
|
||||
- return false;
|
||||
+ return;
|
||||
}
|
||||
|
||||
kfree(local->hw_scan_req);
|
||||
@@ -294,26 +296,13 @@ static bool __ieee80211_scan_completed(s
|
||||
local->scanning = 0;
|
||||
local->scan_channel = NULL;
|
||||
|
||||
- return true;
|
||||
-}
|
||||
-
|
||||
-static void __ieee80211_scan_completed_finish(struct ieee80211_hw *hw,
|
||||
- bool was_hw_scan)
|
||||
-{
|
||||
- struct ieee80211_local *local = hw_to_local(hw);
|
||||
- bool on_oper_chan;
|
||||
- bool enable_beacons = false;
|
||||
-
|
||||
- mutex_lock(&local->mtx);
|
||||
on_oper_chan = ieee80211_cfg_on_oper_channel(local);
|
||||
|
||||
WARN_ON(local->scanning & (SCAN_SW_SCANNING | SCAN_HW_SCANNING));
|
||||
|
||||
- if (was_hw_scan || !on_oper_chan) {
|
||||
- if (WARN_ON(local->scan_channel))
|
||||
- local->scan_channel = NULL;
|
||||
+ if (was_hw_scan || !on_oper_chan)
|
||||
ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL);
|
||||
- } else
|
||||
+ else
|
||||
/* Set power back to normal operating levels. */
|
||||
ieee80211_hw_config(local, 0);
|
||||
|
||||
@@ -331,7 +320,6 @@ static void __ieee80211_scan_completed_f
|
||||
}
|
||||
|
||||
ieee80211_recalc_idle(local);
|
||||
- mutex_unlock(&local->mtx);
|
||||
|
||||
ieee80211_mlme_notify_scan_completed(local);
|
||||
ieee80211_ibss_notify_scan_completed(local);
|
||||
@@ -686,12 +674,14 @@ void ieee80211_scan_work(struct work_str
|
||||
{
|
||||
struct ieee80211_local *local =
|
||||
container_of(work, struct ieee80211_local, scan_work.work);
|
||||
- struct ieee80211_sub_if_data *sdata = local->scan_sdata;
|
||||
+ struct ieee80211_sub_if_data *sdata;
|
||||
unsigned long next_delay = 0;
|
||||
- bool aborted, hw_scan, finish;
|
||||
+ bool aborted, hw_scan;
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
|
||||
+ sdata = local->scan_sdata;
|
||||
+
|
||||
if (test_and_clear_bit(SCAN_COMPLETED, &local->scanning)) {
|
||||
aborted = test_and_clear_bit(SCAN_ABORTED, &local->scanning);
|
||||
goto out_complete;
|
||||
@@ -755,17 +745,11 @@ void ieee80211_scan_work(struct work_str
|
||||
} while (next_delay == 0);
|
||||
|
||||
ieee80211_queue_delayed_work(&local->hw, &local->scan_work, next_delay);
|
||||
- mutex_unlock(&local->mtx);
|
||||
- return;
|
||||
+ goto out;
|
||||
|
||||
out_complete:
|
||||
hw_scan = test_bit(SCAN_HW_SCANNING, &local->scanning);
|
||||
- finish = __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
|
||||
- mutex_unlock(&local->mtx);
|
||||
- if (finish)
|
||||
- __ieee80211_scan_completed_finish(&local->hw, hw_scan);
|
||||
- return;
|
||||
-
|
||||
+ __ieee80211_scan_completed(&local->hw, aborted, hw_scan);
|
||||
out:
|
||||
mutex_unlock(&local->mtx);
|
||||
}
|
||||
@@ -835,7 +819,6 @@ int ieee80211_request_internal_scan(stru
|
||||
void ieee80211_scan_cancel(struct ieee80211_local *local)
|
||||
{
|
||||
bool abortscan;
|
||||
- bool finish = false;
|
||||
|
||||
/*
|
||||
* We are only canceling software scan, or deferred scan that was not
|
||||
@@ -855,14 +838,17 @@ void ieee80211_scan_cancel(struct ieee80
|
||||
|
||||
mutex_lock(&local->mtx);
|
||||
abortscan = local->scan_req && !test_bit(SCAN_HW_SCANNING, &local->scanning);
|
||||
- if (abortscan)
|
||||
- finish = __ieee80211_scan_completed(&local->hw, true, false);
|
||||
- mutex_unlock(&local->mtx);
|
||||
-
|
||||
if (abortscan) {
|
||||
- /* The scan is canceled, but stop work from being pending */
|
||||
- cancel_delayed_work_sync(&local->scan_work);
|
||||
+ /*
|
||||
+ * The scan is canceled, but stop work from being pending.
|
||||
+ *
|
||||
+ * If the work is currently running, it must be blocked on
|
||||
+ * the mutex, but we'll set scan_sdata = NULL and it'll
|
||||
+ * simply exit once it acquires the mutex.
|
||||
+ */
|
||||
+ cancel_delayed_work(&local->scan_work);
|
||||
+ /* and clean up */
|
||||
+ __ieee80211_scan_completed(&local->hw, true, false);
|
||||
}
|
||||
- if (finish)
|
||||
- __ieee80211_scan_completed_finish(&local->hw, false);
|
||||
+ mutex_unlock(&local->mtx);
|
||||
}
|
Loading…
Reference in New Issue