|
|
|
@ -1013,13 +1013,13 @@
|
|
|
|
|
+
|
|
|
|
|
+ if (!ath_tid_has_buffered(tid))
|
|
|
|
|
+ return false;
|
|
|
|
|
+
|
|
|
|
|
+ INIT_LIST_HEAD(&bf_q);
|
|
|
|
|
|
|
|
|
|
- ath_tx_fill_desc(sc, bf, txq, aggr_len);
|
|
|
|
|
- ath_tx_txqaddbuf(sc, txq, &bf_q, false);
|
|
|
|
|
- } while (txq->axq_ampdu_depth < ATH_AGGR_MIN_QDEPTH &&
|
|
|
|
|
- status != ATH_AGGR_BAW_CLOSED);
|
|
|
|
|
+ INIT_LIST_HEAD(&bf_q);
|
|
|
|
|
+
|
|
|
|
|
+ bf = ath_tx_get_tid_subframe(sc, txq, tid, &tid_q);
|
|
|
|
|
+ if (!bf)
|
|
|
|
|
+ return false;
|
|
|
|
@ -1193,7 +1193,17 @@
|
|
|
|
|
list_del(&bf->list);
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
@ -1226,7 +1236,7 @@
|
|
|
|
|
tid = list_first_entry(&ac->tid_q, struct ath_atx_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)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
@ -1248,7 +1258,7 @@
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1268,7 +1278,7 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
txq->axq_ampdu_depth++;
|
|
|
|
|
|
|
|
|
@ -1352,7 +1362,7 @@
|
|
|
|
|
|
|
|
|
|
bf->bf_next = NULL;
|
|
|
|
|
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 ath9k_channel *curchan = ah->curchan;
|
|
|
|
|
|
|
|
|
@ -1362,7 +1372,7 @@
|
|
|
|
|
(chainmask == 0x7) && (rate < 0x90))
|
|
|
|
|
return 0x3;
|
|
|
|
|
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_sta *sta = txctl->sta;
|
|
|
|
|
struct ieee80211_vif *vif = info->control.vif;
|
|
|
|
@ -1370,7 +1380,7 @@
|
|
|
|
|
struct ath_softc *sc = hw->priv;
|
|
|
|
|
int frmlen = skb->len + FCS_LEN;
|
|
|
|
|
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 */
|
|
|
|
|
if (sta)
|
|
|
|
|
txctl->an = (struct ath_node *)sta->drv_priv;
|
|
|
|
@ -1381,7 +1391,7 @@
|
|
|
|
|
|
|
|
|
|
if (info->control.hw_key)
|
|
|
|
|
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_atx_tid *tid = NULL;
|
|
|
|
|
struct ath_buf *bf;
|
|
|
|
@ -1389,7 +1399,7 @@
|
|
|
|
|
int q;
|
|
|
|
|
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);
|
|
|
|
|
txq = sc->tx.uapsdq;
|
|
|
|
|
ath_txq_lock(sc, txq);
|
|
|
|
@ -1432,7 +1442,7 @@
|
|
|
|
|
if (txctl->paprd)
|
|
|
|
|
dev_kfree_skb_any(skb);
|
|
|
|
|
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;
|
|
|
|
|
ath_set_rates(vif, NULL, bf);
|
|
|
|
@ -1441,7 +1451,7 @@
|
|
|
|
|
duration += info.rates[0].PktDuration;
|
|
|
|
|
if (bf_tail)
|
|
|
|
|
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 ath_common *common = ath9k_hw_common(sc->sc_ah);
|
|
|
|
|
struct ieee80211_hdr * hdr = (struct ieee80211_hdr *)skb->data;
|
|
|
|
@ -1450,7 +1460,7 @@
|
|
|
|
|
unsigned long flags;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
__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,
|
|
|
|
|
@@ -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)) {
|
|
|
|
|
txq->axq_link = NULL;
|
|
|
|
@ -1483,7 +1493,7 @@
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
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.
|
|
|
|
|
*/
|
|
|
|
|
bf_held = NULL;
|
|
|
|
@ -1492,7 +1502,7 @@
|
|
|
|
|
bf_held = bf;
|
|
|
|
|
if (list_is_last(&bf_held->list, &txq->axq_q))
|
|
|
|
|
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
|
|
|
|
|
* descriptor for hw.
|
|
|
|
|
*/
|
|
|
|
@ -1501,7 +1511,7 @@
|
|
|
|
|
INIT_LIST_HEAD(&bf_head);
|
|
|
|
|
if (!list_is_singular(&lastbf->list))
|
|
|
|
|
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);
|
|
|
|
@ -1510,7 +1520,7 @@
|
|
|
|
|
list_del(&bf->list);
|
|
|
|
|
ath_tx_return_buffer(sc, bf);
|
|
|
|
|
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);
|
|
|
|
|
}
|
|
|
|
|
} else {
|
|
|
|
@ -1519,7 +1529,7 @@
|
|
|
|
|
if (bf != lastbf)
|
|
|
|
|
list_cut_position(&bf_head, fifo_list,
|
|
|
|
|
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->active = false;
|
|
|
|
|
__skb_queue_head_init(&tid->buf_q);
|
|
|
|
@ -1527,7 +1537,7 @@
|
|
|
|
|
acno = TID_TO_WME_AC(tidno);
|
|
|
|
|
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];
|
|
|
|
|
acno < IEEE80211_NUM_ACS; acno++, ac++) {
|
|
|
|
|
ac->sched = false;
|
|
|
|
@ -1537,7 +1547,61 @@
|
|
|
|
|
}
|
|
|
|
|
--- a/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);
|
|
|
|
|
|
|
|
|
@ -1547,7 +1611,7 @@
|
|
|
|
|
ieee80211_queue_delayed_work(sc->hw, &sc->hw_pll_work,
|
|
|
|
|
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_common *common = ath9k_hw_common(ah);
|
|
|
|
|
unsigned long flags;
|
|
|
|
@ -1555,7 +1619,7 @@
|
|
|
|
|
|
|
|
|
|
if (ath_startrecv(sc) != 0) {
|
|
|
|
|
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:
|
|
|
|
|
ath_restart_work(sc);
|
|
|
|
@ -1575,7 +1639,7 @@
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
* DMA, then restart stuff.
|
|
|
|
|
*/
|
|
|
|
@ -1670,7 +1734,16 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
@ -1693,7 +1766,7 @@
|
|
|
|
|
ath9k_ps_restore(sc);
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
mutex_lock(&sc->mutex);
|
|
|
|
|
|
|
|
|
@ -1702,7 +1775,7 @@
|
|
|
|
|
|
|
|
|
|
/* Reset SERDES registers */
|
|
|
|
|
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)
|
|
|
|
@ -1711,7 +1784,7 @@
|
|
|
|
|
|
|
|
|
|
ath9k_hw_reset(ah, ah->curchan, ah->caldata, false);
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
@ -1720,7 +1793,7 @@
|
|
|
|
|
{
|
|
|
|
|
switch (type) {
|
|
|
|
|
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_hw *ah = sc->sc_ah;
|
|
|
|
|
struct ath_common *common = ath9k_hw_common(ah);
|
|
|
|
@ -1729,7 +1802,7 @@
|
|
|
|
|
|
|
|
|
|
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))
|
|
|
|
|
ath9k_beacon_assign_slot(sc, vif);
|
|
|
|
|
|
|
|
|
@ -1742,7 +1815,7 @@
|
|
|
|
|
mutex_unlock(&sc->mutex);
|
|
|
|
|
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_common *common = ath9k_hw_common(sc->sc_ah);
|
|
|
|
@ -1750,7 +1823,7 @@
|
|
|
|
|
|
|
|
|
|
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_ps_restore(sc);
|
|
|
|
|
|
|
|
|
@ -1759,7 +1832,7 @@
|
|
|
|
|
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) {
|
|
|
|
@ -1844,7 +1917,7 @@
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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_node *an = (struct ath_node *) sta->drv_priv;
|
|
|
|
|
|
|
|
|
@ -1854,7 +1927,70 @@
|
|
|
|
|
switch (cmd) {
|
|
|
|
|
case STA_NOTIFY_SLEEP:
|
|
|
|
|
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 ath9k_wow_pattern *wow_pattern = NULL;
|
|
|
|
@ -3517,7 +3653,15 @@
|
|
|
|
|
int av_bslot;
|
|
|
|
|
bool primary_sta_vif;
|
|
|
|
|
__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_ALT_ANT_RATIO 30
|
|
|
|
|
#define ATH_ANT_DIV_COMB_ALT_ANT_RATIO2 20
|
|
|
|
@ -3539,7 +3683,7 @@
|
|
|
|
|
struct ath_ant_comb {
|
|
|
|
|
u16 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_second;
|
|
|
|
|
int rssi_third;
|
|
|
|
@ -3582,7 +3726,23 @@
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* 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_reload_chainmask_settings(struct ath_softc *sc);
|
|
|
|
|
|
|
|
|
@ -5453,15 +5613,18 @@
|
|
|
|
|
struct ath_common *common;
|
|
|
|
|
int ret = 0, i;
|
|
|
|
|
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;
|
|
|
|
|
atomic_set(&ah->intr_ref_cnt, -1);
|
|
|
|
|
sc->sc_ah = ah;
|
|
|
|
|
+ pCap = &ah->caps;
|
|
|
|
|
|
|
|
|
|
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);
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
@ -5481,7 +5644,15 @@
|
|
|
|
|
|
|
|
|
|
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_channel *chan;
|
|
|
|
|
struct ath_hw *ah = sc->sc_ah;
|
|
|
|
@ -5498,7 +5669,7 @@
|
|
|
|
|
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_SPECTRUM_MGMT |
|
|
|
|
|
IEEE80211_HW_REPORTS_TX_ACK_STATUS |
|
|
|
|
@ -5508,6 +5679,14 @@
|
|
|
|
|
|
|
|
|
|
if (sc->sc_ah->caps.hw_caps & ATH9K_HW_CAP_HT) {
|
|
|
|
|
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
|
|
|
|
|
+++ b/drivers/net/wireless/ath/carl9170/main.c
|
|
|
|
|
@@ -1878,7 +1878,8 @@ void *carl9170_alloc(size_t priv_size)
|
|
|
|
|