aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net')
-rw-r--r--drivers/net/wireless/ath/ath9k/ath9k.h4
-rw-r--r--drivers/net/wireless/ath/ath9k/main.c3
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c57
3 files changed, 50 insertions, 14 deletions
diff --git a/drivers/net/wireless/ath/ath9k/ath9k.h b/drivers/net/wireless/ath/ath9k/ath9k.h
index 544599b826c1..20bf4a7f896d 100644
--- a/drivers/net/wireless/ath/ath9k/ath9k.h
+++ b/drivers/net/wireless/ath/ath9k/ath9k.h
@@ -225,6 +225,8 @@ void ath_descdma_cleanup(struct ath_softc *sc, struct ath_descdma *dd,
225#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA) 225#define ATH_DS_TX_BA(_ds) ((_ds)->ds_us.tx.ts_flags & ATH9K_TX_BA)
226#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)]) 226#define ATH_AN_2_TID(_an, _tidno) (&(_an)->tid[(_tidno)])
227 227
228#define ATH_TX_COMPLETE_POLL_INT 1000
229
228enum ATH_AGGR_STATUS { 230enum ATH_AGGR_STATUS {
229 ATH_AGGR_DONE, 231 ATH_AGGR_DONE,
230 ATH_AGGR_BAW_CLOSED, 232 ATH_AGGR_BAW_CLOSED,
@@ -240,6 +242,7 @@ struct ath_txq {
240 u8 axq_aggr_depth; 242 u8 axq_aggr_depth;
241 u32 axq_totalqueued; 243 u32 axq_totalqueued;
242 bool stopped; 244 bool stopped;
245 bool axq_tx_inprogress;
243 struct ath_buf *axq_linkbuf; 246 struct ath_buf *axq_linkbuf;
244 247
245 /* first desc of the last descriptor that contains CTS */ 248 /* first desc of the last descriptor that contains CTS */
@@ -605,6 +608,7 @@ struct ath_softc {
605#endif 608#endif
606 struct ath_bus_ops *bus_ops; 609 struct ath_bus_ops *bus_ops;
607 struct ath_beacon_config cur_beacon_conf; 610 struct ath_beacon_config cur_beacon_conf;
611 struct delayed_work tx_complete_work;
608}; 612};
609 613
610struct ath_wiphy { 614struct ath_wiphy {
diff --git a/drivers/net/wireless/ath/ath9k/main.c b/drivers/net/wireless/ath/ath9k/main.c
index 2ad718489c0d..46f4a692c8d1 100644
--- a/drivers/net/wireless/ath/ath9k/main.c
+++ b/drivers/net/wireless/ath/ath9k/main.c
@@ -1259,6 +1259,7 @@ void ath_detach(struct ath_softc *sc)
1259 ath_deinit_leds(sc); 1259 ath_deinit_leds(sc);
1260 cancel_work_sync(&sc->chan_work); 1260 cancel_work_sync(&sc->chan_work);
1261 cancel_delayed_work_sync(&sc->wiphy_work); 1261 cancel_delayed_work_sync(&sc->wiphy_work);
1262 cancel_delayed_work_sync(&sc->tx_complete_work);
1262 1263
1263 for (i = 0; i < sc->num_sec_wiphy; i++) { 1264 for (i = 0; i < sc->num_sec_wiphy; i++) {
1264 struct ath_wiphy *aphy = sc->sec_wiphy[i]; 1265 struct ath_wiphy *aphy = sc->sec_wiphy[i];
@@ -1979,6 +1980,8 @@ static int ath9k_start(struct ieee80211_hw *hw)
1979 1980
1980 ieee80211_wake_queues(hw); 1981 ieee80211_wake_queues(hw);
1981 1982
1983 queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work, 0);
1984
1982mutex_unlock: 1985mutex_unlock:
1983 mutex_unlock(&sc->mutex); 1986 mutex_unlock(&sc->mutex);
1984 1987
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index 5de9878d2c12..a3bc4310a67c 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -857,6 +857,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
857 txq->axq_aggr_depth = 0; 857 txq->axq_aggr_depth = 0;
858 txq->axq_totalqueued = 0; 858 txq->axq_totalqueued = 0;
859 txq->axq_linkbuf = NULL; 859 txq->axq_linkbuf = NULL;
860 txq->axq_tx_inprogress = false;
860 sc->tx.txqsetup |= 1<<qnum; 861 sc->tx.txqsetup |= 1<<qnum;
861 } 862 }
862 return &sc->tx.txq[qnum]; 863 return &sc->tx.txq[qnum];
@@ -1023,6 +1024,10 @@ void ath_draintxq(struct ath_softc *sc, struct ath_txq *txq, bool retry_tx)
1023 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0); 1024 ath_tx_complete_buf(sc, bf, &bf_head, 0, 0);
1024 } 1025 }
1025 1026
1027 spin_lock_bh(&txq->axq_lock);
1028 txq->axq_tx_inprogress = false;
1029 spin_unlock_bh(&txq->axq_lock);
1030
1026 /* flush any pending frames if aggregation is enabled */ 1031 /* flush any pending frames if aggregation is enabled */
1027 if (sc->sc_flags & SC_OP_TXAGGR) { 1032 if (sc->sc_flags & SC_OP_TXAGGR) {
1028 if (!retry_tx) { 1033 if (!retry_tx) {
@@ -1103,8 +1108,7 @@ void ath_txq_schedule(struct ath_softc *sc, struct ath_txq *txq)
1103 if (tid->paused) 1108 if (tid->paused)
1104 continue; 1109 continue;
1105 1110
1106 if ((txq->axq_depth % 2) == 0) 1111 ath_tx_sched_aggr(sc, txq, tid);
1107 ath_tx_sched_aggr(sc, txq, tid);
1108 1112
1109 /* 1113 /*
1110 * add tid to round-robin queue if more frames 1114 * add tid to round-robin queue if more frames
@@ -1947,19 +1951,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
1947 if (bf->bf_stale) { 1951 if (bf->bf_stale) {
1948 bf_held = bf; 1952 bf_held = bf;
1949 if (list_is_last(&bf_held->list, &txq->axq_q)) { 1953 if (list_is_last(&bf_held->list, &txq->axq_q)) {
1950 txq->axq_link = NULL;
1951 txq->axq_linkbuf = NULL;
1952 spin_unlock_bh(&txq->axq_lock); 1954 spin_unlock_bh(&txq->axq_lock);
1953
1954 /*
1955 * The holding descriptor is the last
1956 * descriptor in queue. It's safe to remove
1957 * the last holding descriptor in BH context.
1958 */
1959 spin_lock_bh(&sc->tx.txbuflock);
1960 list_move_tail(&bf_held->list, &sc->tx.txbuf);
1961 spin_unlock_bh(&sc->tx.txbuflock);
1962
1963 break; 1955 break;
1964 } else { 1956 } else {
1965 bf = list_entry(bf_held->list.next, 1957 bf = list_entry(bf_held->list.next,
@@ -1996,6 +1988,7 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
1996 txq->axq_aggr_depth--; 1988 txq->axq_aggr_depth--;
1997 1989
1998 txok = (ds->ds_txstat.ts_status == 0); 1990 txok = (ds->ds_txstat.ts_status == 0);
1991 txq->axq_tx_inprogress = false;
1999 spin_unlock_bh(&txq->axq_lock); 1992 spin_unlock_bh(&txq->axq_lock);
2000 1993
2001 if (bf_held) { 1994 if (bf_held) {
@@ -2029,6 +2022,40 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2029 } 2022 }
2030} 2023}
2031 2024
2025void ath_tx_complete_poll_work(struct work_struct *work)
2026{
2027 struct ath_softc *sc = container_of(work, struct ath_softc,
2028 tx_complete_work.work);
2029 struct ath_txq *txq;
2030 int i;
2031 bool needreset = false;
2032
2033 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
2034 if (ATH_TXQ_SETUP(sc, i)) {
2035 txq = &sc->tx.txq[i];
2036 spin_lock_bh(&txq->axq_lock);
2037 if (txq->axq_depth) {
2038 if (txq->axq_tx_inprogress) {
2039 needreset = true;
2040 spin_unlock_bh(&txq->axq_lock);
2041 break;
2042 } else {
2043 txq->axq_tx_inprogress = true;
2044 }
2045 }
2046 spin_unlock_bh(&txq->axq_lock);
2047 }
2048
2049 if (needreset) {
2050 DPRINTF(sc, ATH_DBG_RESET, "tx hung, resetting the chip\n");
2051 ath_reset(sc, false);
2052 }
2053
2054 queue_delayed_work(sc->hw->workqueue, &sc->tx_complete_work,
2055 msecs_to_jiffies(ATH_TX_COMPLETE_POLL_INT));
2056}
2057
2058
2032 2059
2033void ath_tx_tasklet(struct ath_softc *sc) 2060void ath_tx_tasklet(struct ath_softc *sc)
2034{ 2061{
@@ -2069,6 +2096,8 @@ int ath_tx_init(struct ath_softc *sc, int nbufs)
2069 goto err; 2096 goto err;
2070 } 2097 }
2071 2098
2099 INIT_DELAYED_WORK(&sc->tx_complete_work, ath_tx_complete_poll_work);
2100
2072err: 2101err:
2073 if (error != 0) 2102 if (error != 0)
2074 ath_tx_cleanup(sc); 2103 ath_tx_cleanup(sc);