ath9k: add some more pending fixes / optimizations

Signed-off-by: Felix Fietkau <nbd@openwrt.org>

git-svn-id: svn://svn.openwrt.org/openwrt/trunk@38398 3c298f89-4303-0410-b956-a3cf2f4a3e73
master
Felix Fietkau 2013-10-14 19:38:42 +00:00
parent 01e1878a8a
commit 8184099eab
9 changed files with 234 additions and 55 deletions

View File

@ -1013,13 +1013,13 @@
+ +
+ if (!ath_tid_has_buffered(tid)) + if (!ath_tid_has_buffered(tid))
+ return false; + return false;
+
+ INIT_LIST_HEAD(&bf_q);
- ath_tx_fill_desc(sc, bf, txq, aggr_len); - ath_tx_fill_desc(sc, bf, txq, aggr_len);
- ath_tx_txqaddbuf(sc, txq, &bf_q, false); - ath_tx_txqaddbuf(sc, txq, &bf_q, false);
- } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH && - } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
- status != ATH_AGGR_BAW_CLOSED); - status != ATH_AGGR_BAW_CLOSED);
+ INIT_LIST_HEAD(&bf_q);
+
+ bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q); + bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
+ if (!bf) + if (!bf)
+ return false; + return false;
@ -1193,7 +1193,17 @@
list_del(&bf->list); list_del(&bf->list);
ath_tx_return_buffer(sc, bf); ath_tx_return_buffer(sc, bf);
@@ -1665,25 +1820,27 @@ void ath_tx_cleanupq(struct ath_softc *s @@ -1630,6 +1785,9 @@ bool ath_drain_all_txq(struct ath_softc
if (!ATH_TXQ_SETUP(sc, i))
continue;
+ if (!sc->tx.txq[i].axq_depth)
+ continue;
+
if (ath9k_hw_numtxpending(ah, sc->tx.txq[i].axq_qnum))
npend |= BIT(i);
}
@@ -1665,25 +1823,27 @@ void ath_tx_cleanupq(struct ath_softc *s
*/ */
void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
{ {
@ -1226,7 +1236,7 @@
tid = list_first_entry(&ac->tid_q, struct ath_atx_tid, tid = list_first_entry(&ac->tid_q, struct ath_atx_tid,
list); list);
list_del(&tid->list); list_del(&tid->list);
@@ -1692,17 +1849,17 @@ void ath_txq_schedule(struct ath_softc * @@ -1692,17 +1852,17 @@ void ath_txq_schedule(struct ath_softc *
if (tid->paused) if (tid->paused)
continue; continue;
@ -1248,7 +1258,7 @@
break; break;
} }
@@ -1711,9 +1868,17 @@ void ath_txq_schedule(struct ath_softc * @@ -1711,9 +1871,17 @@ void ath_txq_schedule(struct ath_softc *
list_add_tail(&ac->list, &txq->axq_acq); list_add_tail(&ac->list, &txq->axq_acq);
} }
@ -1268,7 +1278,7 @@
} }
rcu_read_unlock(); rcu_read_unlock();
@@ -1787,74 +1952,28 @@ static void ath_tx_txqaddbuf(struct ath_ @@ -1787,74 +1955,28 @@ static void ath_tx_txqaddbuf(struct ath_
if (bf_is_ampdu_not_probing(bf)) if (bf_is_ampdu_not_probing(bf))
txq->axq_ampdu_depth++; txq->axq_ampdu_depth++;
@ -1352,7 +1362,7 @@
bf->bf_next = NULL; bf->bf_next = NULL;
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
@@ -1911,8 +2030,7 @@ u8 ath_txchainmask_reduction(struct ath_ @@ -1911,8 +2033,7 @@ u8 ath_txchainmask_reduction(struct ath_
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath9k_channel *curchan = ah->curchan; struct ath9k_channel *curchan = ah->curchan;
@ -1362,7 +1372,7 @@
(chainmask == 0x7) && (rate < 0x90)) (chainmask == 0x7) && (rate < 0x90))
return 0x3; return 0x3;
else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) && else if (AR_SREV_9462(ah) && ath9k_hw_btcoex_is_enabled(ah) &&
@@ -1985,6 +2103,7 @@ static int ath_tx_prepare(struct ieee802 @@ -1985,6 +2106,7 @@ static int ath_tx_prepare(struct ieee802
struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
struct ieee80211_sta *sta = txctl->sta; struct ieee80211_sta *sta = txctl->sta;
struct ieee80211_vif *vif = info->control.vif; struct ieee80211_vif *vif = info->control.vif;
@ -1370,7 +1380,7 @@
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
int frmlen = skb->len + FCS_LEN; int frmlen = skb->len + FCS_LEN;
int padpos, padsize; int padpos, padsize;
@@ -1992,6 +2111,10 @@ static int ath_tx_prepare(struct ieee802 @@ -1992,6 +2114,10 @@ static int ath_tx_prepare(struct ieee802
/* NOTE: sta can be NULL according to net/mac80211.h */ /* NOTE: sta can be NULL according to net/mac80211.h */
if (sta) if (sta)
txctl->an = (struct ath_node *)sta->drv_priv; txctl->an = (struct ath_node *)sta->drv_priv;
@ -1381,7 +1391,7 @@
if (info->control.hw_key) if (info->control.hw_key)
frmlen += info->control.hw_key->icv_len; frmlen += info->control.hw_key->icv_len;
@@ -2041,7 +2164,6 @@ int ath_tx_start(struct ieee80211_hw *hw @@ -2041,7 +2167,6 @@ int ath_tx_start(struct ieee80211_hw *hw
struct ath_txq *txq = txctl->txq; struct ath_txq *txq = txctl->txq;
struct ath_atx_tid *tid = NULL; struct ath_atx_tid *tid = NULL;
struct ath_buf *bf; struct ath_buf *bf;
@ -1389,7 +1399,7 @@
int q; int q;
int ret; int ret;
@@ -2069,27 +2191,31 @@ int ath_tx_start(struct ieee80211_hw *hw @@ -2069,27 +2194,31 @@ int ath_tx_start(struct ieee80211_hw *hw
ath_txq_unlock(sc, txq); ath_txq_unlock(sc, txq);
txq = sc->tx.uapsdq; txq = sc->tx.uapsdq;
ath_txq_lock(sc, txq); ath_txq_lock(sc, txq);
@ -1432,7 +1442,7 @@
if (txctl->paprd) if (txctl->paprd)
dev_kfree_skb_any(skb); dev_kfree_skb_any(skb);
else else
@@ -2142,7 +2268,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw @@ -2142,7 +2271,7 @@ void ath_tx_cabq(struct ieee80211_hw *hw
bf->bf_lastbf = bf; bf->bf_lastbf = bf;
ath_set_rates(vif, NULL, bf); ath_set_rates(vif, NULL, bf);
@ -1441,7 +1451,7 @@
duration += info.rates[0].PktDuration; duration += info.rates[0].PktDuration;
if (bf_tail) if (bf_tail)
bf_tail->bf_next = bf; bf_tail->bf_next = bf;
@@ -2189,7 +2315,7 @@ static void ath_tx_complete(struct ath_s @@ -2189,7 +2318,7 @@ static void ath_tx_complete(struct ath_s
struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb);
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data; struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
@ -1450,7 +1460,7 @@
unsigned long flags; unsigned long flags;
ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb); ath_dbg(common, XMIT, "TX complete: skb: %p\n", skb);
@@ -2225,21 +2351,7 @@ static void ath_tx_complete(struct ath_s @@ -2225,21 +2354,7 @@ static void ath_tx_complete(struct ath_s
spin_unlock_irqrestore(&sc->sc_pm_lock, flags); spin_unlock_irqrestore(&sc->sc_pm_lock, flags);
__skb_queue_tail(&txq->complete_q, skb); __skb_queue_tail(&txq->complete_q, skb);
@ -1473,7 +1483,7 @@
} }
static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf, static void ath_tx_complete_buf(struct ath_softc *sc, struct ath_buf *bf,
@@ -2360,8 +2472,7 @@ static void ath_tx_processq(struct ath_s @@ -2360,8 +2475,7 @@ static void ath_tx_processq(struct ath_s
if (list_empty(&txq->axq_q)) { if (list_empty(&txq->axq_q)) {
txq->axq_link = NULL; txq->axq_link = NULL;
@ -1483,7 +1493,7 @@
break; break;
} }
bf = list_first_entry(&txq->axq_q, struct ath_buf, list); bf = list_first_entry(&txq->axq_q, struct ath_buf, list);
@@ -2375,7 +2486,7 @@ static void ath_tx_processq(struct ath_s @@ -2375,7 +2489,7 @@ static void ath_tx_processq(struct ath_s
* it with the STALE flag. * it with the STALE flag.
*/ */
bf_held = NULL; bf_held = NULL;
@ -1492,7 +1502,7 @@
bf_held = bf; bf_held = bf;
if (list_is_last(&bf_held->list, &txq->axq_q)) if (list_is_last(&bf_held->list, &txq->axq_q))
break; break;
@@ -2399,7 +2510,7 @@ static void ath_tx_processq(struct ath_s @@ -2399,7 +2513,7 @@ static void ath_tx_processq(struct ath_s
* however leave the last descriptor back as the holding * however leave the last descriptor back as the holding
* descriptor for hw. * descriptor for hw.
*/ */
@ -1501,7 +1511,7 @@
INIT_LIST_HEAD(&bf_head); INIT_LIST_HEAD(&bf_head);
if (!list_is_singular(&lastbf->list)) if (!list_is_singular(&lastbf->list))
list_cut_position(&bf_head, list_cut_position(&bf_head,
@@ -2470,7 +2581,7 @@ void ath_tx_edma_tasklet(struct ath_soft @@ -2470,7 +2584,7 @@ void ath_tx_edma_tasklet(struct ath_soft
} }
bf = list_first_entry(fifo_list, struct ath_buf, list); bf = list_first_entry(fifo_list, struct ath_buf, list);
@ -1510,7 +1520,7 @@
list_del(&bf->list); list_del(&bf->list);
ath_tx_return_buffer(sc, bf); ath_tx_return_buffer(sc, bf);
bf = list_first_entry(fifo_list, struct ath_buf, list); bf = list_first_entry(fifo_list, struct ath_buf, list);
@@ -2492,7 +2603,7 @@ void ath_tx_edma_tasklet(struct ath_soft @@ -2492,7 +2606,7 @@ void ath_tx_edma_tasklet(struct ath_soft
ath_tx_txqaddbuf(sc, txq, &bf_q, true); ath_tx_txqaddbuf(sc, txq, &bf_q, true);
} }
} else { } else {
@ -1519,7 +1529,7 @@
if (bf != lastbf) if (bf != lastbf)
list_cut_position(&bf_head, fifo_list, list_cut_position(&bf_head, fifo_list,
lastbf->list.prev); lastbf->list.prev);
@@ -2583,6 +2694,7 @@ void ath_tx_node_init(struct ath_softc * @@ -2583,6 +2697,7 @@ void ath_tx_node_init(struct ath_softc *
tid->paused = false; tid->paused = false;
tid->active = false; tid->active = false;
__skb_queue_head_init(&tid->buf_q); __skb_queue_head_init(&tid->buf_q);
@ -1527,7 +1537,7 @@
acno = TID_TO_WME_AC(tidno); acno = TID_TO_WME_AC(tidno);
tid->ac = &an->ac[acno]; tid->ac = &an->ac[acno];
} }
@@ -2590,6 +2702,7 @@ void ath_tx_node_init(struct ath_softc * @@ -2590,6 +2705,7 @@ void ath_tx_node_init(struct ath_softc *
for (acno = 0, ac = &an->ac[acno]; for (acno = 0, ac = &an->ac[acno];
acno < IEEE80211_NUM_ACS; acno++, ac++) { acno < IEEE80211_NUM_ACS; acno++, ac++) {
ac->sched = false; ac->sched = false;
@ -1537,7 +1547,61 @@
} }
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -173,8 +173,7 @@ static void ath_restart_work(struct ath_ @@ -82,6 +82,22 @@ static bool ath9k_setpower(struct ath_so
return ret;
}
+void ath_ps_full_sleep(unsigned long data)
+{
+ struct ath_softc *sc = (struct ath_softc *) data;
+ struct ath_common *common = ath9k_hw_common(sc->sc_ah);
+ bool reset;
+
+ spin_lock(&common->cc_lock);
+ ath_hw_cycle_counters_update(common);
+ spin_unlock(&common->cc_lock);
+
+ ath9k_hw_setrxabort(sc->sc_ah, 1);
+ ath9k_hw_stopdmarecv(sc->sc_ah, &reset);
+
+ ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_FULL_SLEEP);
+}
+
void ath9k_ps_wakeup(struct ath_softc *sc)
{
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@@ -92,6 +108,7 @@ void ath9k_ps_wakeup(struct ath_softc *s
if (++sc->ps_usecount != 1)
goto unlock;
+ del_timer_sync(&sc->sleep_timer);
power_mode = sc->sc_ah->power_mode;
ath9k_hw_setpower(sc->sc_ah, ATH9K_PM_AWAKE);
@@ -117,17 +134,17 @@ void ath9k_ps_restore(struct ath_softc *
struct ath_common *common = ath9k_hw_common(sc->sc_ah);
enum ath9k_power_mode mode;
unsigned long flags;
- bool reset;
spin_lock_irqsave(&sc->sc_pm_lock, flags);
if (--sc->ps_usecount != 0)
goto unlock;
if (sc->ps_idle) {
- ath9k_hw_setrxabort(sc->sc_ah, 1);
- ath9k_hw_stopdmarecv(sc->sc_ah, &reset);
- mode = ATH9K_PM_FULL_SLEEP;
- } else if (sc->ps_enabled &&
+ mod_timer(&sc->sleep_timer, jiffies + HZ / 10);
+ goto unlock;
+ }
+
+ if (sc->ps_enabled &&
!(sc->ps_flags & (PS_WAIT_FOR_BEACON |
PS_WAIT_FOR_CAB |
PS_WAIT_FOR_PSPOLL_DATA |
@@ -173,8 +190,7 @@ static void ath_restart_work(struct ath_
{ {
ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0); ieee80211_queue_delayed_work(sc->hw, &sc->tx_complete_work, 0);
@ -1547,7 +1611,7 @@
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work, ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
msecs_to_jiffies(ATH_PLL_WORK_INTERVAL)); msecs_to_jiffies(ATH_PLL_WORK_INTERVAL));
@@ -209,6 +208,7 @@ static bool ath_complete_reset(struct at @@ -209,6 +225,7 @@ static bool ath_complete_reset(struct at
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
unsigned long flags; unsigned long flags;
@ -1555,7 +1619,7 @@
if (ath_startrecv(sc) != 0) { if (ath_startrecv(sc) != 0) {
ath_err(common, "Unable to restart recv logic\n"); ath_err(common, "Unable to restart recv logic\n");
@@ -236,10 +236,16 @@ static bool ath_complete_reset(struct at @@ -236,10 +253,16 @@ static bool ath_complete_reset(struct at
} }
work: work:
ath_restart_work(sc); ath_restart_work(sc);
@ -1575,7 +1639,7 @@
ieee80211_wake_queues(sc->hw); ieee80211_wake_queues(sc->hw);
@@ -306,17 +312,91 @@ out: @@ -306,17 +329,91 @@ out:
* by reseting the chip. To accomplish this we must first cleanup any pending * by reseting the chip. To accomplish this we must first cleanup any pending
* DMA, then restart stuff. * DMA, then restart stuff.
*/ */
@ -1670,7 +1734,16 @@
} }
static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta, static void ath_node_attach(struct ath_softc *sc, struct ieee80211_sta *sta,
@@ -543,21 +623,10 @@ chip_reset: @@ -400,6 +497,8 @@ void ath9k_tasklet(unsigned long data)
ath_tx_edma_tasklet(sc);
else
ath_tx_tasklet(sc);
+
+ wake_up(&sc->tx_wait);
}
ath9k_btcoex_handle_interrupt(sc, status);
@@ -543,21 +642,10 @@ chip_reset:
static int ath_reset(struct ath_softc *sc) static int ath_reset(struct ath_softc *sc)
{ {
@ -1693,7 +1766,7 @@
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
return r; return r;
@@ -599,7 +668,7 @@ static int ath9k_start(struct ieee80211_ @@ -599,7 +687,7 @@ static int ath9k_start(struct ieee80211_
ath9k_ps_wakeup(sc); ath9k_ps_wakeup(sc);
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
@ -1702,7 +1775,7 @@
/* Reset SERDES registers */ /* Reset SERDES registers */
ath9k_hw_configpcipowersave(ah, false); ath9k_hw_configpcipowersave(ah, false);
@@ -802,7 +871,7 @@ static void ath9k_stop(struct ieee80211_ @@ -802,7 +890,7 @@ static void ath9k_stop(struct ieee80211_
} }
if (!ah->curchan) if (!ah->curchan)
@ -1711,7 +1784,7 @@
ath9k_hw_reset(ah, ah->curchan, ah->caldata, false); ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
ath9k_hw_phy_disable(ah); ath9k_hw_phy_disable(ah);
@@ -821,7 +890,7 @@ static void ath9k_stop(struct ieee80211_ @@ -821,7 +909,7 @@ static void ath9k_stop(struct ieee80211_
ath_dbg(common, CONFIG, "Driver halt\n"); ath_dbg(common, CONFIG, "Driver halt\n");
} }
@ -1720,7 +1793,7 @@
{ {
switch (type) { switch (type) {
case NL80211_IFTYPE_AP: case NL80211_IFTYPE_AP:
@@ -966,6 +1035,8 @@ static int ath9k_add_interface(struct ie @@ -966,6 +1054,8 @@ static int ath9k_add_interface(struct ie
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah); struct ath_common *common = ath9k_hw_common(ah);
@ -1729,7 +1802,7 @@
mutex_lock(&sc->mutex); mutex_lock(&sc->mutex);
@@ -979,6 +1050,12 @@ static int ath9k_add_interface(struct ie @@ -979,6 +1069,12 @@ static int ath9k_add_interface(struct ie
if (ath9k_uses_beacons(vif->type)) if (ath9k_uses_beacons(vif->type))
ath9k_beacon_assign_slot(sc, vif); ath9k_beacon_assign_slot(sc, vif);
@ -1742,7 +1815,7 @@
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
return 0; return 0;
} }
@@ -1016,6 +1093,7 @@ static void ath9k_remove_interface(struc @@ -1016,6 +1112,7 @@ static void ath9k_remove_interface(struc
{ {
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_common *common = ath9k_hw_common(sc->sc_ah); struct ath_common *common = ath9k_hw_common(sc->sc_ah);
@ -1750,7 +1823,7 @@
ath_dbg(common, CONFIG, "Detach Interface\n"); ath_dbg(common, CONFIG, "Detach Interface\n");
@@ -1030,6 +1108,8 @@ static void ath9k_remove_interface(struc @@ -1030,6 +1127,8 @@ static void ath9k_remove_interface(struc
ath9k_calculate_summary_state(hw, NULL); ath9k_calculate_summary_state(hw, NULL);
ath9k_ps_restore(sc); ath9k_ps_restore(sc);
@ -1759,7 +1832,7 @@
mutex_unlock(&sc->mutex); mutex_unlock(&sc->mutex);
} }
@@ -1192,83 +1272,12 @@ static int ath9k_config(struct ieee80211 @@ -1192,83 +1291,12 @@ static int ath9k_config(struct ieee80211
} }
if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) { if ((changed & IEEE80211_CONF_CHANGE_CHANNEL) || reset_channel) {
@ -1844,7 +1917,7 @@
} }
if (changed & IEEE80211_CONF_CHANGE_POWER) { if (changed & IEEE80211_CONF_CHANGE_POWER) {
@@ -1374,9 +1383,6 @@ static void ath9k_sta_notify(struct ieee @@ -1374,9 +1402,6 @@ static void ath9k_sta_notify(struct ieee
struct ath_softc *sc = hw->priv; struct ath_softc *sc = hw->priv;
struct ath_node *an = (struct ath_node *) sta->drv_priv; struct ath_node *an = (struct ath_node *) sta->drv_priv;
@ -1854,7 +1927,70 @@
switch (cmd) { switch (cmd) {
case STA_NOTIFY_SLEEP: case STA_NOTIFY_SLEEP:
an->sleeping = true; an->sleeping = true;
@@ -2094,7 +2100,7 @@ static void ath9k_wow_add_pattern(struct @@ -1772,13 +1797,31 @@ static void ath9k_set_coverage_class(str
mutex_unlock(&sc->mutex);
}
+static bool ath9k_has_tx_pending(struct ath_softc *sc)
+{
+ int i, npend;
+
+ for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
+ if (!ATH_TXQ_SETUP(sc, i))
+ continue;
+
+ if (!sc->tx.txq[i].axq_depth)
+ continue;
+
+ npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
+ if (npend)
+ break;
+ }
+
+ return !!npend;
+}
+
static void ath9k_flush(struct ieee80211_hw *hw, u32 queues, bool drop)
{
struct ath_softc *sc = hw->priv;
struct ath_hw *ah = sc->sc_ah;
struct ath_common *common = ath9k_hw_common(ah);
- int timeout = 200; /* ms */
- int i, j;
+ int timeout = HZ / 5; /* 200 ms */
bool drain_txq;
mutex_lock(&sc->mutex);
@@ -1796,25 +1839,9 @@ static void ath9k_flush(struct ieee80211
return;
}
- for (j = 0; j < timeout; j++) {
- bool npend = false;
-
- if (j)
- usleep_range(1000, 2000);
-
- for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) {
- if (!ATH_TXQ_SETUP(sc, i))
- continue;
-
- npend = ath9k_has_pending_frames(sc, &sc->tx.txq[i]);
-
- if (npend)
- break;
- }
-
- if (!npend)
- break;
- }
+ if (wait_event_timeout(sc->tx_wait, !ath9k_has_tx_pending(sc),
+ timeout) > 0)
+ drop = false;
if (drop) {
ath9k_ps_wakeup(sc);
@@ -2094,7 +2121,7 @@ static void ath9k_wow_add_pattern(struct
{ {
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
struct ath9k_wow_pattern *wow_pattern = NULL; struct ath9k_wow_pattern *wow_pattern = NULL;
@ -3517,7 +3653,15 @@
int av_bslot; int av_bslot;
bool primary_sta_vif; bool primary_sta_vif;
__le64 tsf_adjust; /* TSF adjustment for staggered beacons */ __le64 tsf_adjust; /* TSF adjustment for staggered beacons */
@@ -585,19 +588,14 @@ static inline void ath_fill_led_pin(stru @@ -459,6 +462,7 @@ void ath_check_ani(struct ath_softc *sc)
int ath_update_survey_stats(struct ath_softc *sc);
void ath_update_survey_nf(struct ath_softc *sc, int channel);
void ath9k_queue_reset(struct ath_softc *sc, enum ath_reset_type type);
+void ath_ps_full_sleep(unsigned long data);
/**********/
/* BTCOEX */
@@ -585,19 +589,14 @@ static inline void ath_fill_led_pin(stru
#define ATH_ANT_DIV_COMB_MAX_COUNT 100 #define ATH_ANT_DIV_COMB_MAX_COUNT 100
#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO 30
#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20 #define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
@ -3539,7 +3683,7 @@
struct ath_ant_comb { struct ath_ant_comb {
u16 count; u16 count;
u16 total_pkt_count; u16 total_pkt_count;
@@ -614,27 +612,36 @@ struct ath_ant_comb { @@ -614,27 +613,36 @@ struct ath_ant_comb {
int rssi_first; int rssi_first;
int rssi_second; int rssi_second;
int rssi_third; int rssi_third;
@ -3582,7 +3726,23 @@
/* /*
* Default cache line size, in bytes. * Default cache line size, in bytes.
@@ -926,7 +933,6 @@ void ath9k_deinit_device(struct ath_soft @@ -717,6 +725,7 @@ struct ath_softc {
struct work_struct hw_check_work;
struct work_struct hw_reset_work;
struct completion paprd_complete;
+ wait_queue_head_t tx_wait;
unsigned int hw_busy_count;
unsigned long sc_flags;
@@ -753,6 +762,7 @@ struct ath_softc {
struct delayed_work tx_complete_work;
struct delayed_work hw_pll_work;
struct timer_list rx_poll_timer;
+ struct timer_list sleep_timer;
#ifdef CPTCFG_ATH9K_BTCOEX_SUPPORT
struct ath_btcoex btcoex;
@@ -926,7 +936,6 @@ void ath9k_deinit_device(struct ath_soft
void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw); void ath9k_set_hw_capab(struct ath_softc *sc, struct ieee80211_hw *hw);
void ath9k_reload_chainmask_settings(struct ath_softc *sc); void ath9k_reload_chainmask_settings(struct ath_softc *sc);
@ -5453,15 +5613,18 @@
struct ath_common *common; struct ath_common *common;
int ret = 0, i; int ret = 0, i;
int csz = 0; int csz = 0;
@@ -600,6 +650,7 @@ static int ath9k_init_softc(u16 devid, s @@ -600,8 +650,10 @@ static int ath9k_init_softc(u16 devid, s
ah->reg_ops.rmw = ath9k_reg_rmw; ah->reg_ops.rmw = ath9k_reg_rmw;
atomic_set(&ah->intr_ref_cnt, -1); atomic_set(&ah->intr_ref_cnt, -1);
sc->sc_ah = ah; sc->sc_ah = ah;
+ pCap = &ah->caps; + pCap = &ah->caps;
sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET); sc->dfs_detector = dfs_pattern_detector_init(ah, NL80211_DFS_UNSET);
+ init_waitqueue_head(&sc->tx_wait);
@@ -631,11 +682,15 @@ static int ath9k_init_softc(u16 devid, s if (!pdata) {
ah->ah_flags |= AH_USE_EEPROM;
@@ -631,11 +683,15 @@ static int ath9k_init_softc(u16 devid, s
ath9k_init_platform(sc); ath9k_init_platform(sc);
/* /*
@ -5481,7 +5644,15 @@
spin_lock_init(&common->cc_lock); spin_lock_init(&common->cc_lock);
@@ -710,13 +765,15 @@ static void ath9k_init_band_txpower(stru @@ -646,6 +702,7 @@ static int ath9k_init_softc(u16 devid, s
tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet,
(unsigned long)sc);
+ setup_timer(&sc->sleep_timer, ath_ps_full_sleep, (unsigned long)sc);
INIT_WORK(&sc->hw_reset_work, ath_reset_work);
INIT_WORK(&sc->hw_check_work, ath_hw_check);
INIT_WORK(&sc->paprd_work, ath_paprd_calibrate);
@@ -710,13 +767,15 @@ static void ath9k_init_band_txpower(stru
struct ieee80211_supported_band *sband; struct ieee80211_supported_band *sband;
struct ieee80211_channel *chan; struct ieee80211_channel *chan;
struct ath_hw *ah = sc->sc_ah; struct ath_hw *ah = sc->sc_ah;
@ -5498,7 +5669,7 @@
ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true); ath9k_hw_set_txpowerlimit(ah, MAX_RATE_POWER, true);
} }
} }
@@ -802,7 +859,8 @@ void ath9k_set_hw_capab(struct ath_softc @@ -802,7 +861,8 @@ void ath9k_set_hw_capab(struct ath_softc
IEEE80211_HW_PS_NULLFUNC_STACK | IEEE80211_HW_PS_NULLFUNC_STACK |
IEEE80211_HW_SPECTRUM_MGMT | IEEE80211_HW_SPECTRUM_MGMT |
IEEE80211_HW_REPORTS_TX_ACK_STATUS | IEEE80211_HW_REPORTS_TX_ACK_STATUS |
@ -5508,6 +5679,14 @@
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) { if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION; hw->flags |= IEEE80211_HW_AMPDU_AGGREGATION;
@@ -968,6 +1028,7 @@ static void ath9k_deinit_softc(struct at
if (ATH_TXQ_SETUP(sc, i))
ath_tx_cleanupq(sc, &sc->tx.txq[i]);
+ del_timer_sync(&sc->sleep_timer);
ath9k_hw_deinit(sc->sc_ah);
if (sc->dfs_detector != NULL)
sc->dfs_detector->exit(sc->dfs_detector);
--- a/drivers/net/wireless/ath/carl9170/main.c --- a/drivers/net/wireless/ath/carl9170/main.c
+++ b/drivers/net/wireless/ath/carl9170/main.c +++ b/drivers/net/wireless/ath/carl9170/main.c
@@ -1878,7 +1878,8 @@ void *carl9170_alloc(size_t priv_size) @@ -1878,7 +1878,8 @@ void *carl9170_alloc(size_t priv_size)

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/init.c --- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -812,6 +812,7 @@ static const struct ieee80211_iface_limi @@ -814,6 +814,7 @@ static const struct ieee80211_iface_limi
#endif #endif
BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_AP) |
BIT(NL80211_IFTYPE_P2P_GO) }, BIT(NL80211_IFTYPE_P2P_GO) },

View File

@ -81,7 +81,7 @@
struct ath_ops reg_ops; struct ath_ops reg_ops;
--- a/drivers/net/wireless/ath/ath9k/init.c --- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -664,6 +664,8 @@ static int ath9k_init_softc(u16 devid, s @@ -665,6 +665,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz; ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision; ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset; ah->external_reset = pdata->external_reset;

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/init.c --- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -1069,23 +1069,23 @@ static int __init ath9k_init(void) @@ -1072,23 +1072,23 @@ static int __init ath9k_init(void)
goto err_out; goto err_out;
} }

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -296,8 +296,12 @@ static int ath_reset_internal(struct ath @@ -313,8 +313,12 @@ static int ath_reset_internal(struct ath
(sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL)) (sc->hw->conf.flags & IEEE80211_CONF_OFFCHANNEL))
ath9k_mci_set_txpower(sc, true, false); ath9k_mci_set_txpower(sc, true, false);
@ -14,7 +14,7 @@
out: out:
spin_unlock_bh(&sc->sc_pcu_lock); spin_unlock_bh(&sc->sc_pcu_lock);
@@ -1285,6 +1289,7 @@ static int ath9k_config(struct ieee80211 @@ -1304,6 +1308,7 @@ static int ath9k_config(struct ieee80211
sc->config.txpowlimit = 2 * conf->power_level; sc->config.txpowlimit = 2 * conf->power_level;
ath9k_cmn_update_txpow(ah, sc->curtxpow, ath9k_cmn_update_txpow(ah, sc->curtxpow,
sc->config.txpowlimit, &sc->curtxpow); sc->config.txpowlimit, &sc->curtxpow);

View File

@ -21,7 +21,7 @@
if (ant_gain > max_gain) if (ant_gain > max_gain)
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1285,7 +1285,10 @@ static int ath9k_config(struct ieee80211 @@ -1304,7 +1304,10 @@ static int ath9k_config(struct ieee80211
} }
if (changed & IEEE80211_CONF_CHANGE_POWER) { if (changed & IEEE80211_CONF_CHANGE_POWER) {

View File

@ -1,6 +1,6 @@
--- a/drivers/net/wireless/ath/ath9k/ath9k.h --- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -560,6 +560,9 @@ struct ath9k_wow_pattern { @@ -561,6 +561,9 @@ struct ath9k_wow_pattern {
void ath_init_leds(struct ath_softc *sc); void ath_init_leds(struct ath_softc *sc);
void ath_deinit_leds(struct ath_softc *sc); void ath_deinit_leds(struct ath_softc *sc);
void ath_fill_led_pin(struct ath_softc *sc); void ath_fill_led_pin(struct ath_softc *sc);
@ -10,7 +10,7 @@
#else #else
static inline void ath_init_leds(struct ath_softc *sc) static inline void ath_init_leds(struct ath_softc *sc)
{ {
@@ -704,6 +707,13 @@ enum spectral_mode { @@ -705,6 +708,13 @@ enum spectral_mode {
SPECTRAL_CHANSCAN, SPECTRAL_CHANSCAN,
}; };
@ -24,7 +24,7 @@
struct ath_softc { struct ath_softc {
struct ieee80211_hw *hw; struct ieee80211_hw *hw;
struct device *dev; struct device *dev;
@@ -745,9 +755,8 @@ struct ath_softc { @@ -747,9 +757,8 @@ struct ath_softc {
struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS]; struct ieee80211_supported_band sbands[IEEE80211_NUM_BANDS];
#ifdef CPTCFG_MAC80211_LEDS #ifdef CPTCFG_MAC80211_LEDS
@ -162,7 +162,7 @@
void ath_fill_led_pin(struct ath_softc *sc) void ath_fill_led_pin(struct ath_softc *sc)
--- a/drivers/net/wireless/ath/ath9k/init.c --- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -976,7 +976,7 @@ int ath9k_init_device(u16 devid, struct @@ -978,7 +978,7 @@ int ath9k_init_device(u16 devid, struct
#ifdef CPTCFG_MAC80211_LEDS #ifdef CPTCFG_MAC80211_LEDS
/* must be initialized before ieee80211_register_hw */ /* must be initialized before ieee80211_register_hw */

View File

@ -125,7 +125,7 @@
REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON); REG_SET_BIT(ah, AR_BTCOEX_WL_LNADIV, AR_BTCOEX_WL_LNADIV_FORCE_ON);
--- a/drivers/net/wireless/ath/ath9k/main.c --- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -546,6 +546,11 @@ irqreturn_t ath_isr(int irq, void *dev) @@ -565,6 +565,11 @@ irqreturn_t ath_isr(int irq, void *dev)
ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */ ath9k_hw_getisr(ah, &status); /* NB: clears ISR too */
status &= ah->imask; /* discard unasked-for bits */ status &= ah->imask; /* discard unasked-for bits */

View File

@ -59,7 +59,7 @@
}; };
--- a/drivers/net/wireless/ath/ath9k/init.c --- a/drivers/net/wireless/ath/ath9k/init.c
+++ b/drivers/net/wireless/ath/ath9k/init.c +++ b/drivers/net/wireless/ath/ath9k/init.c
@@ -664,6 +664,8 @@ static int ath9k_init_softc(u16 devid, s @@ -665,6 +665,8 @@ static int ath9k_init_softc(u16 devid, s
ah->is_clk_25mhz = pdata->is_clk_25mhz; ah->is_clk_25mhz = pdata->is_clk_25mhz;
ah->get_mac_revision = pdata->get_mac_revision; ah->get_mac_revision = pdata->get_mac_revision;
ah->external_reset = pdata->external_reset; ah->external_reset = pdata->external_reset;