diff options
author | Felix Fietkau <nbd@openwrt.org> | 2014-06-11 06:47:51 -0400 |
---|---|---|
committer | John W. Linville <linville@tuxdriver.com> | 2014-06-19 15:49:16 -0400 |
commit | 0453531e2eae61c5c0a2af7b67cdafd19c0dce68 (patch) | |
tree | 47e1997836b90775ce3ccafa6c2e36d0cac18827 /drivers/net | |
parent | bc7e1be70c9f1c6de622aa14baa62003342034bb (diff) |
ath9k: Move acq to channel context
Add support to maintain per-channel ACs list.
Signed-off-by: Felix Fietkau <nbd@openwrt.org>
Signed-off-by: Rajkumar Manoharan <rmanohar@qti.qualcomm.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net')
-rw-r--r-- | drivers/net/wireless/ath/ath9k/ath9k.h | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/channel.c | 4 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/main.c | 25 | ||||
-rw-r--r-- | drivers/net/wireless/ath/ath9k/xmit.c | 58 |
4 files changed, 63 insertions, 28 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h index b6f6444d109e..198cca38c24b 100644 --- a/drivers/net/wireless/ath/ath9k/ath9k.h +++ b/drivers/net/wireless/ath/ath9k/ath9k.h | |||
@@ -163,7 +163,6 @@ struct ath_txq { | |||
163 | u32 axq_ampdu_depth; | 163 | u32 axq_ampdu_depth; |
164 | bool stopped; | 164 | bool stopped; |
165 | bool axq_tx_inprogress; | 165 | bool axq_tx_inprogress; |
166 | struct list_head axq_acq; | ||
167 | struct list_head txq_fifo[ATH_TXFIFO_DEPTH]; | 166 | struct list_head txq_fifo[ATH_TXFIFO_DEPTH]; |
168 | u8 txq_headidx; | 167 | u8 txq_headidx; |
169 | u8 txq_tailidx; | 168 | u8 txq_tailidx; |
@@ -324,6 +323,8 @@ struct ath_rx { | |||
324 | struct ath_chanctx { | 323 | struct ath_chanctx { |
325 | struct cfg80211_chan_def chandef; | 324 | struct cfg80211_chan_def chandef; |
326 | struct list_head vifs; | 325 | struct list_head vifs; |
326 | struct list_head acq[IEEE80211_NUM_ACS]; | ||
327 | |||
327 | u16 txpower; | 328 | u16 txpower; |
328 | bool offchannel; | 329 | bool offchannel; |
329 | }; | 330 | }; |
@@ -348,6 +349,7 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq); | |||
348 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); | 349 | void ath_tx_node_init(struct ath_softc *sc, struct ath_node *an); |
349 | void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); | 350 | void ath_tx_node_cleanup(struct ath_softc *sc, struct ath_node *an); |
350 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); | 351 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq); |
352 | void ath_txq_schedule_all(struct ath_softc *sc); | ||
351 | int ath_tx_init(struct ath_softc *sc, int nbufs); | 353 | int ath_tx_init(struct ath_softc *sc, int nbufs); |
352 | int ath_txq_update(struct ath_softc *sc, int qnum, | 354 | int ath_txq_update(struct ath_softc *sc, int qnum, |
353 | struct ath9k_tx_queue_info *q); | 355 | struct ath9k_tx_queue_info *q); |
diff --git a/drivers/net/wireless/ath/ath9k/channel.c b/drivers/net/wireless/ath/ath9k/channel.c index 1b40cf5aa955..c8d91dfcb3b9 100644 --- a/drivers/net/wireless/ath/ath9k/channel.c +++ b/drivers/net/wireless/ath/ath9k/channel.c | |||
@@ -107,7 +107,7 @@ void ath_chanctx_init(struct ath_softc *sc) | |||
107 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 107 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
108 | struct ieee80211_supported_band *sband; | 108 | struct ieee80211_supported_band *sband; |
109 | struct ieee80211_channel *chan; | 109 | struct ieee80211_channel *chan; |
110 | int i; | 110 | int i, j; |
111 | 111 | ||
112 | sband = &common->sbands[IEEE80211_BAND_2GHZ]; | 112 | sband = &common->sbands[IEEE80211_BAND_2GHZ]; |
113 | if (!sband->n_channels) | 113 | if (!sband->n_channels) |
@@ -119,6 +119,8 @@ void ath_chanctx_init(struct ath_softc *sc) | |||
119 | cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); | 119 | cfg80211_chandef_create(&ctx->chandef, chan, NL80211_CHAN_HT20); |
120 | INIT_LIST_HEAD(&ctx->vifs); | 120 | INIT_LIST_HEAD(&ctx->vifs); |
121 | ctx->txpower = ATH_TXPOWER_MAX; | 121 | ctx->txpower = ATH_TXPOWER_MAX; |
122 | for (j = 0; j < ARRAY_SIZE(ctx->acq); j++) | ||
123 | INIT_LIST_HEAD(&ctx->acq[j]); | ||
122 | } | 124 | } |
123 | sc->cur_chan = &sc->chanctx[0]; | 125 | sc->cur_chan = &sc->chanctx[0]; |
124 | } | 126 | } |
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c index 5a9cee4a8935..5f7e0bf4c986 100644 --- a/drivers/net/wireless/ath/ath9k/main.c +++ b/drivers/net/wireless/ath/ath9k/main.c | |||
@@ -63,9 +63,16 @@ static bool ath9k_has_pending_frames(struct ath_softc *sc, struct ath_txq *txq) | |||
63 | 63 | ||
64 | spin_lock_bh(&txq->axq_lock); | 64 | spin_lock_bh(&txq->axq_lock); |
65 | 65 | ||
66 | if (txq->axq_depth || !list_empty(&txq->axq_acq)) | 66 | if (txq->axq_depth) |
67 | pending = true; | 67 | pending = true; |
68 | 68 | ||
69 | if (txq->mac80211_qnum >= 0) { | ||
70 | struct list_head *list; | ||
71 | |||
72 | list = &sc->cur_chan->acq[txq->mac80211_qnum]; | ||
73 | if (!list_empty(list)) | ||
74 | pending = true; | ||
75 | } | ||
69 | spin_unlock_bh(&txq->axq_lock); | 76 | spin_unlock_bh(&txq->axq_lock); |
70 | return pending; | 77 | return pending; |
71 | } | 78 | } |
@@ -219,7 +226,6 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
219 | struct ath_hw *ah = sc->sc_ah; | 226 | struct ath_hw *ah = sc->sc_ah; |
220 | struct ath_common *common = ath9k_hw_common(ah); | 227 | struct ath_common *common = ath9k_hw_common(ah); |
221 | unsigned long flags; | 228 | unsigned long flags; |
222 | int i; | ||
223 | 229 | ||
224 | if (ath_startrecv(sc) != 0) { | 230 | if (ath_startrecv(sc) != 0) { |
225 | ath_err(common, "Unable to restart recv logic\n"); | 231 | ath_err(common, "Unable to restart recv logic\n"); |
@@ -247,15 +253,7 @@ static bool ath_complete_reset(struct ath_softc *sc, bool start) | |||
247 | } | 253 | } |
248 | work: | 254 | work: |
249 | ath_restart_work(sc); | 255 | ath_restart_work(sc); |
250 | 256 | ath_txq_schedule_all(sc); | |
251 | for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) { | ||
252 | if (!ATH_TXQ_SETUP(sc, i)) | ||
253 | continue; | ||
254 | |||
255 | spin_lock_bh(&sc->tx.txq[i].axq_lock); | ||
256 | ath_txq_schedule(sc, &sc->tx.txq[i]); | ||
257 | spin_unlock_bh(&sc->tx.txq[i].axq_lock); | ||
258 | } | ||
259 | } | 257 | } |
260 | 258 | ||
261 | sc->gtt_cnt = 0; | 259 | sc->gtt_cnt = 0; |
@@ -1035,6 +1033,10 @@ static int ath9k_add_interface(struct ieee80211_hw *hw, | |||
1035 | 1033 | ||
1036 | avp->vif = vif; | 1034 | avp->vif = vif; |
1037 | 1035 | ||
1036 | /* XXX - will be removed once chanctx ops are added */ | ||
1037 | avp->chanctx = sc->cur_chan; | ||
1038 | list_add_tail(&avp->list, &sc->cur_chan->vifs); | ||
1039 | |||
1038 | an->sc = sc; | 1040 | an->sc = sc; |
1039 | an->sta = NULL; | 1041 | an->sta = NULL; |
1040 | an->vif = vif; | 1042 | an->vif = vif; |
@@ -1120,6 +1122,7 @@ static void ath9k_remove_interface(struct ieee80211_hw *hw, | |||
1120 | } | 1122 | } |
1121 | spin_unlock_bh(&sc->sc_pcu_lock); | 1123 | spin_unlock_bh(&sc->sc_pcu_lock); |
1122 | 1124 | ||
1125 | list_del(&avp->list); | ||
1123 | sc->nvifs--; | 1126 | sc->nvifs--; |
1124 | sc->tx99_vif = NULL; | 1127 | sc->tx99_vif = NULL; |
1125 | 1128 | ||
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c index 66acb2cbd9df..b2e66d21af1c 100644 --- a/drivers/net/wireless/ath/ath9k/xmit.c +++ b/drivers/net/wireless/ath/ath9k/xmit.c | |||
@@ -103,9 +103,16 @@ void ath_txq_unlock_complete(struct ath_softc *sc, struct ath_txq *txq) | |||
103 | ieee80211_tx_status(sc->hw, skb); | 103 | ieee80211_tx_status(sc->hw, skb); |
104 | } | 104 | } |
105 | 105 | ||
106 | static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) | 106 | static void ath_tx_queue_tid(struct ath_softc *sc, struct ath_txq *txq, |
107 | struct ath_atx_tid *tid) | ||
107 | { | 108 | { |
108 | struct ath_atx_ac *ac = tid->ac; | 109 | struct ath_atx_ac *ac = tid->ac; |
110 | struct list_head *list; | ||
111 | struct ath_vif *avp = (struct ath_vif *) tid->an->vif->drv_priv; | ||
112 | struct ath_chanctx *ctx = avp->chanctx; | ||
113 | |||
114 | if (!ctx) | ||
115 | return; | ||
109 | 116 | ||
110 | if (tid->sched) | 117 | if (tid->sched) |
111 | return; | 118 | return; |
@@ -117,7 +124,9 @@ static void ath_tx_queue_tid(struct ath_txq *txq, struct ath_atx_tid *tid) | |||
117 | return; | 124 | return; |
118 | 125 | ||
119 | ac->sched = true; | 126 | ac->sched = true; |
120 | list_add_tail(&ac->list, &txq->axq_acq); | 127 | |
128 | list = &ctx->acq[TID_TO_WME_AC(tid->tidno)]; | ||
129 | list_add_tail(&ac->list, list); | ||
121 | } | 130 | } |
122 | 131 | ||
123 | static struct ath_frame_info *get_frame_info(struct sk_buff *skb) | 132 | static struct ath_frame_info *get_frame_info(struct sk_buff *skb) |
@@ -626,7 +635,7 @@ static void ath_tx_complete_aggr(struct ath_softc *sc, struct ath_txq *txq, | |||
626 | 635 | ||
627 | skb_queue_splice_tail(&bf_pending, &tid->retry_q); | 636 | skb_queue_splice_tail(&bf_pending, &tid->retry_q); |
628 | if (!an->sleeping) { | 637 | if (!an->sleeping) { |
629 | ath_tx_queue_tid(txq, tid); | 638 | ath_tx_queue_tid(sc, txq, tid); |
630 | 639 | ||
631 | if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) | 640 | if (ts->ts_status & (ATH9K_TXERR_FILT | ATH9K_TXERR_XRETRY)) |
632 | tid->ac->clear_ps_filter = true; | 641 | tid->ac->clear_ps_filter = true; |
@@ -1483,7 +1492,7 @@ void ath_tx_aggr_wakeup(struct ath_softc *sc, struct ath_node *an) | |||
1483 | ac->clear_ps_filter = true; | 1492 | ac->clear_ps_filter = true; |
1484 | 1493 | ||
1485 | if (ath_tid_has_buffered(tid)) { | 1494 | if (ath_tid_has_buffered(tid)) { |
1486 | ath_tx_queue_tid(txq, tid); | 1495 | ath_tx_queue_tid(sc, txq, tid); |
1487 | ath_txq_schedule(sc, txq); | 1496 | ath_txq_schedule(sc, txq); |
1488 | } | 1497 | } |
1489 | 1498 | ||
@@ -1507,7 +1516,7 @@ void ath_tx_aggr_resume(struct ath_softc *sc, struct ieee80211_sta *sta, | |||
1507 | tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; | 1516 | tid->baw_size = IEEE80211_MIN_AMPDU_BUF << sta->ht_cap.ampdu_factor; |
1508 | 1517 | ||
1509 | if (ath_tid_has_buffered(tid)) { | 1518 | if (ath_tid_has_buffered(tid)) { |
1510 | ath_tx_queue_tid(txq, tid); | 1519 | ath_tx_queue_tid(sc, txq, tid); |
1511 | ath_txq_schedule(sc, txq); | 1520 | ath_txq_schedule(sc, txq); |
1512 | } | 1521 | } |
1513 | 1522 | ||
@@ -1642,7 +1651,6 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype) | |||
1642 | txq->axq_link = NULL; | 1651 | txq->axq_link = NULL; |
1643 | __skb_queue_head_init(&txq->complete_q); | 1652 | __skb_queue_head_init(&txq->complete_q); |
1644 | INIT_LIST_HEAD(&txq->axq_q); | 1653 | INIT_LIST_HEAD(&txq->axq_q); |
1645 | INIT_LIST_HEAD(&txq->axq_acq); | ||
1646 | spin_lock_init(&txq->axq_lock); | 1654 | spin_lock_init(&txq->axq_lock); |
1647 | txq->axq_depth = 0; | 1655 | txq->axq_depth = 0; |
1648 | txq->axq_ampdu_depth = 0; | 1656 | txq->axq_ampdu_depth = 0; |
@@ -1804,7 +1812,7 @@ void ath_tx_cleanupq(struct ath_softc *sc, struct ath_txq *txq) | |||
1804 | sc->tx.txqsetup &= ~(1<<txq->axq_qnum); | 1812 | sc->tx.txqsetup &= ~(1<<txq->axq_qnum); |
1805 | } | 1813 | } |
1806 | 1814 | ||
1807 | /* For each axq_acq entry, for each tid, try to schedule packets | 1815 | /* For each acq entry, for each tid, try to schedule packets |
1808 | * for transmit until ampdu_depth has reached min Q depth. | 1816 | * for transmit until ampdu_depth has reached min Q depth. |
1809 | */ | 1817 | */ |
1810 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | 1818 | void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) |
@@ -1812,19 +1820,25 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1812 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); | 1820 | struct ath_common *common = ath9k_hw_common(sc->sc_ah); |
1813 | struct ath_atx_ac *ac, *last_ac; | 1821 | struct ath_atx_ac *ac, *last_ac; |
1814 | struct ath_atx_tid *tid, *last_tid; | 1822 | struct ath_atx_tid *tid, *last_tid; |
1823 | struct list_head *ac_list; | ||
1815 | bool sent = false; | 1824 | bool sent = false; |
1816 | 1825 | ||
1826 | if (txq->mac80211_qnum < 0) | ||
1827 | return; | ||
1828 | |||
1829 | ac_list = &sc->cur_chan->acq[txq->mac80211_qnum]; | ||
1830 | |||
1817 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags) || | 1831 | if (test_bit(ATH_OP_HW_RESET, &common->op_flags) || |
1818 | list_empty(&txq->axq_acq)) | 1832 | list_empty(ac_list)) |
1819 | return; | 1833 | return; |
1820 | 1834 | ||
1821 | rcu_read_lock(); | 1835 | rcu_read_lock(); |
1822 | 1836 | ||
1823 | last_ac = list_entry(txq->axq_acq.prev, struct ath_atx_ac, list); | 1837 | last_ac = list_entry(ac_list->prev, struct ath_atx_ac, list); |
1824 | while (!list_empty(&txq->axq_acq)) { | 1838 | while (!list_empty(ac_list)) { |
1825 | bool stop = false; | 1839 | bool stop = false; |
1826 | 1840 | ||
1827 | ac = list_first_entry(&txq->axq_acq, struct ath_atx_ac, list); | 1841 | ac = list_first_entry(ac_list, struct ath_atx_ac, list); |
1828 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); | 1842 | last_tid = list_entry(ac->tid_q.prev, struct ath_atx_tid, list); |
1829 | list_del(&ac->list); | 1843 | list_del(&ac->list); |
1830 | ac->sched = false; | 1844 | ac->sched = false; |
@@ -1844,7 +1858,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1844 | * are pending for the tid | 1858 | * are pending for the tid |
1845 | */ | 1859 | */ |
1846 | if (ath_tid_has_buffered(tid)) | 1860 | if (ath_tid_has_buffered(tid)) |
1847 | ath_tx_queue_tid(txq, tid); | 1861 | ath_tx_queue_tid(sc, txq, tid); |
1848 | 1862 | ||
1849 | if (stop || tid == last_tid) | 1863 | if (stop || tid == last_tid) |
1850 | break; | 1864 | break; |
@@ -1852,7 +1866,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1852 | 1866 | ||
1853 | if (!list_empty(&ac->tid_q) && !ac->sched) { | 1867 | if (!list_empty(&ac->tid_q) && !ac->sched) { |
1854 | ac->sched = true; | 1868 | ac->sched = true; |
1855 | list_add_tail(&ac->list, &txq->axq_acq); | 1869 | list_add_tail(&ac->list, ac_list); |
1856 | } | 1870 | } |
1857 | 1871 | ||
1858 | if (stop) | 1872 | if (stop) |
@@ -1863,7 +1877,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1863 | break; | 1877 | break; |
1864 | 1878 | ||
1865 | sent = false; | 1879 | sent = false; |
1866 | last_ac = list_entry(txq->axq_acq.prev, | 1880 | last_ac = list_entry(ac_list->prev, |
1867 | struct ath_atx_ac, list); | 1881 | struct ath_atx_ac, list); |
1868 | } | 1882 | } |
1869 | } | 1883 | } |
@@ -1871,6 +1885,20 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq) | |||
1871 | rcu_read_unlock(); | 1885 | rcu_read_unlock(); |
1872 | } | 1886 | } |
1873 | 1887 | ||
1888 | void ath_txq_schedule_all(struct ath_softc *sc) | ||
1889 | { | ||
1890 | struct ath_txq *txq; | ||
1891 | int i; | ||
1892 | |||
1893 | for (i = 0; i < IEEE80211_NUM_ACS; i++) { | ||
1894 | txq = sc->tx.txq_map[i]; | ||
1895 | |||
1896 | spin_lock_bh(&txq->axq_lock); | ||
1897 | ath_txq_schedule(sc, txq); | ||
1898 | spin_unlock_bh(&txq->axq_lock); | ||
1899 | } | ||
1900 | } | ||
1901 | |||
1874 | /***********/ | 1902 | /***********/ |
1875 | /* TX, DMA */ | 1903 | /* TX, DMA */ |
1876 | /***********/ | 1904 | /***********/ |
@@ -2198,7 +2226,7 @@ int ath_tx_start(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2198 | TX_STAT_INC(txq->axq_qnum, a_queued_sw); | 2226 | TX_STAT_INC(txq->axq_qnum, a_queued_sw); |
2199 | __skb_queue_tail(&tid->buf_q, skb); | 2227 | __skb_queue_tail(&tid->buf_q, skb); |
2200 | if (!txctl->an->sleeping) | 2228 | if (!txctl->an->sleeping) |
2201 | ath_tx_queue_tid(txq, tid); | 2229 | ath_tx_queue_tid(sc, txq, tid); |
2202 | 2230 | ||
2203 | ath_txq_schedule(sc, txq); | 2231 | ath_txq_schedule(sc, txq); |
2204 | goto out; | 2232 | goto out; |