aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/ath/ath9k/xmit.c
diff options
context:
space:
mode:
authorBen Greear <greearb@candelatech.com>2011-01-10 02:11:52 -0500
committerJohn W. Linville <linville@tuxdriver.com>2011-01-21 15:34:17 -0500
commit60f2d1d506195803fa6e1dcf3972637b740fdd60 (patch)
tree583cf2f90cfe193f502c6ad8f4ab0e5135611325 /drivers/net/wireless/ath/ath9k/xmit.c
parent71e025a5a630681ad8b37d4426a994d199976ec9 (diff)
ath9k: Restart xmit logic in xmit watchdog.
The system can get into a state where the xmit queue is stopped, but there are no packets pending, so the queue will not be restarted. Add logic to the xmit watchdog to attempt to restart the xmit logic if this situation is detected. Example 'dmesg' output: ath: txq: f4e723e0 axq_qnum: 2, mac80211_qnum: 2 axq_link: f4e996c8 pending frames: 1 axq_acq empty: 1 stopped: 0 axq_depth: 0 Attempting to restart tx logic. Signed-off-by: Ben Greear <greearb@candelatech.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/ath/ath9k/xmit.c')
-rw-r--r--drivers/net/wireless/ath/ath9k/xmit.c79
1 files changed, 54 insertions, 25 deletions
diff --git a/drivers/net/wireless/ath/ath9k/xmit.c b/drivers/net/wireless/ath/ath9k/xmit.c
index a83f2c54508..2ad732d36f8 100644
--- a/drivers/net/wireless/ath/ath9k/xmit.c
+++ b/drivers/net/wireless/ath/ath9k/xmit.c
@@ -945,7 +945,7 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
945 [WME_AC_VI] = ATH_TXQ_AC_VI, 945 [WME_AC_VI] = ATH_TXQ_AC_VI,
946 [WME_AC_VO] = ATH_TXQ_AC_VO, 946 [WME_AC_VO] = ATH_TXQ_AC_VO,
947 }; 947 };
948 int qnum, i; 948 int axq_qnum, i;
949 949
950 memset(&qi, 0, sizeof(qi)); 950 memset(&qi, 0, sizeof(qi));
951 qi.tqi_subtype = subtype_txq_to_hwq[subtype]; 951 qi.tqi_subtype = subtype_txq_to_hwq[subtype];
@@ -979,24 +979,25 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
979 qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE | 979 qi.tqi_qflags = TXQ_FLAG_TXEOLINT_ENABLE |
980 TXQ_FLAG_TXDESCINT_ENABLE; 980 TXQ_FLAG_TXDESCINT_ENABLE;
981 } 981 }
982 qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi); 982 axq_qnum = ath9k_hw_setuptxqueue(ah, qtype, &qi);
983 if (qnum == -1) { 983 if (axq_qnum == -1) {
984 /* 984 /*
985 * NB: don't print a message, this happens 985 * NB: don't print a message, this happens
986 * normally on parts with too few tx queues 986 * normally on parts with too few tx queues
987 */ 987 */
988 return NULL; 988 return NULL;
989 } 989 }
990 if (qnum >= ARRAY_SIZE(sc->tx.txq)) { 990 if (axq_qnum >= ARRAY_SIZE(sc->tx.txq)) {
991 ath_err(common, "qnum %u out of range, max %zu!\n", 991 ath_err(common, "qnum %u out of range, max %zu!\n",
992 qnum, ARRAY_SIZE(sc->tx.txq)); 992 axq_qnum, ARRAY_SIZE(sc->tx.txq));
993 ath9k_hw_releasetxqueue(ah, qnum); 993 ath9k_hw_releasetxqueue(ah, axq_qnum);
994 return NULL; 994 return NULL;
995 } 995 }
996 if (!ATH_TXQ_SETUP(sc, qnum)) { 996 if (!ATH_TXQ_SETUP(sc, axq_qnum)) {
997 struct ath_txq *txq = &sc->tx.txq[qnum]; 997 struct ath_txq *txq = &sc->tx.txq[axq_qnum];
998 998
999 txq->axq_qnum = qnum; 999 txq->axq_qnum = axq_qnum;
1000 txq->mac80211_qnum = -1;
1000 txq->axq_link = NULL; 1001 txq->axq_link = NULL;
1001 INIT_LIST_HEAD(&txq->axq_q); 1002 INIT_LIST_HEAD(&txq->axq_q);
1002 INIT_LIST_HEAD(&txq->axq_acq); 1003 INIT_LIST_HEAD(&txq->axq_acq);
@@ -1004,14 +1005,14 @@ struct ath_txq *ath_txq_setup(struct ath_softc *sc, int qtype, int subtype)
1004 txq->axq_depth = 0; 1005 txq->axq_depth = 0;
1005 txq->axq_ampdu_depth = 0; 1006 txq->axq_ampdu_depth = 0;
1006 txq->axq_tx_inprogress = false; 1007 txq->axq_tx_inprogress = false;
1007 sc->tx.txqsetup |= 1<<qnum; 1008 sc->tx.txqsetup |= 1<<axq_qnum;
1008 1009
1009 txq->txq_headidx = txq->txq_tailidx = 0; 1010 txq->txq_headidx = txq->txq_tailidx = 0;
1010 for (i = 0; i < ATH_TXFIFO_DEPTH; i++) 1011 for (i = 0; i < ATH_TXFIFO_DEPTH; i++)
1011 INIT_LIST_HEAD(&txq->txq_fifo[i]); 1012 INIT_LIST_HEAD(&txq->txq_fifo[i]);
1012 INIT_LIST_HEAD(&txq->txq_fifo_pending); 1013 INIT_LIST_HEAD(&txq->txq_fifo_pending);
1013 } 1014 }
1014 return &sc->tx.txq[qnum]; 1015 return &sc->tx.txq[axq_qnum];
1015} 1016}
1016 1017
1017int ath_txq_update(struct ath_softc *sc, int qnum, 1018int ath_txq_update(struct ath_softc *sc, int qnum,
@@ -1973,17 +1974,16 @@ static void ath_tx_rc_status(struct ath_buf *bf, struct ath_tx_status *ts,
1973 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1; 1974 tx_info->status.rates[tx_rateindex].count = ts->ts_longretry + 1;
1974} 1975}
1975 1976
1976static void ath_wake_mac80211_queue(struct ath_softc *sc, int qnum) 1977/* Has no locking. Must hold spin_lock_bh(&txq->axq_lock)
1978 * before calling this.
1979 */
1980static void __ath_wake_mac80211_queue(struct ath_softc *sc, struct ath_txq *txq)
1977{ 1981{
1978 struct ath_txq *txq; 1982 if (txq->mac80211_qnum >= 0 &&
1979 1983 txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
1980 txq = sc->tx.txq_map[qnum]; 1984 if (ath_mac80211_start_queue(sc, txq->mac80211_qnum))
1981 spin_lock_bh(&txq->axq_lock);
1982 if (txq->stopped && txq->pending_frames < ATH_MAX_QDEPTH) {
1983 if (ath_mac80211_start_queue(sc, qnum))
1984 txq->stopped = 0; 1985 txq->stopped = 0;
1985 } 1986 }
1986 spin_unlock_bh(&txq->axq_lock);
1987} 1987}
1988 1988
1989static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq) 1989static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
@@ -2086,10 +2086,9 @@ static void ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq)
2086 else 2086 else
2087 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0); 2087 ath_tx_complete_buf(sc, bf, txq, &bf_head, &ts, txok, 0);
2088 2088
2089 if (txq == sc->tx.txq_map[qnum])
2090 ath_wake_mac80211_queue(sc, qnum);
2091
2092 spin_lock_bh(&txq->axq_lock); 2089 spin_lock_bh(&txq->axq_lock);
2090 __ath_wake_mac80211_queue(sc, txq);
2091
2093 if (sc->sc_flags & SC_OP_TXAGGR) 2092 if (sc->sc_flags & SC_OP_TXAGGR)
2094 ath_txq_schedule(sc, txq); 2093 ath_txq_schedule(sc, txq);
2095 spin_unlock_bh(&txq->axq_lock); 2094 spin_unlock_bh(&txq->axq_lock);
@@ -2103,6 +2102,9 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
2103 struct ath_txq *txq; 2102 struct ath_txq *txq;
2104 int i; 2103 int i;
2105 bool needreset = false; 2104 bool needreset = false;
2105#ifdef CONFIG_ATH9K_DEBUGFS
2106 sc->tx_complete_poll_work_seen++;
2107#endif
2106 2108
2107 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++) 2109 for (i = 0; i < ATH9K_NUM_TX_QUEUES; i++)
2108 if (ATH_TXQ_SETUP(sc, i)) { 2110 if (ATH_TXQ_SETUP(sc, i)) {
@@ -2116,6 +2118,34 @@ static void ath_tx_complete_poll_work(struct work_struct *work)
2116 } else { 2118 } else {
2117 txq->axq_tx_inprogress = true; 2119 txq->axq_tx_inprogress = true;
2118 } 2120 }
2121 } else {
2122 /* If the queue has pending buffers, then it
2123 * should be doing tx work (and have axq_depth).
2124 * Shouldn't get to this state I think..but
2125 * we do.
2126 */
2127 if (!(sc->sc_flags & (SC_OP_OFFCHANNEL)) &&
2128 (txq->pending_frames > 0 ||
2129 !list_empty(&txq->axq_acq) ||
2130 txq->stopped)) {
2131 ath_err(ath9k_hw_common(sc->sc_ah),
2132 "txq: %p axq_qnum: %u,"
2133 " mac80211_qnum: %i"
2134 " axq_link: %p"
2135 " pending frames: %i"
2136 " axq_acq empty: %i"
2137 " stopped: %i"
2138 " axq_depth: 0 Attempting to"
2139 " restart tx logic.\n",
2140 txq, txq->axq_qnum,
2141 txq->mac80211_qnum,
2142 txq->axq_link,
2143 txq->pending_frames,
2144 list_empty(&txq->axq_acq),
2145 txq->stopped);
2146 __ath_wake_mac80211_queue(sc, txq);
2147 ath_txq_schedule(sc, txq);
2148 }
2119 } 2149 }
2120 spin_unlock_bh(&txq->axq_lock); 2150 spin_unlock_bh(&txq->axq_lock);
2121 } 2151 }
@@ -2212,10 +2242,9 @@ void ath_tx_edma_tasklet(struct ath_softc *sc)
2212 ath_tx_complete_buf(sc, bf, txq, &bf_head, 2242 ath_tx_complete_buf(sc, bf, txq, &bf_head,
2213 &txs, txok, 0); 2243 &txs, txok, 0);
2214 2244
2215 if (txq == sc->tx.txq_map[qnum])
2216 ath_wake_mac80211_queue(sc, qnum);
2217
2218 spin_lock_bh(&txq->axq_lock); 2245 spin_lock_bh(&txq->axq_lock);
2246 __ath_wake_mac80211_queue(sc, txq);
2247
2219 if (!list_empty(&txq->txq_fifo_pending)) { 2248 if (!list_empty(&txq->txq_fifo_pending)) {
2220 INIT_LIST_HEAD(&bf_head); 2249 INIT_LIST_HEAD(&bf_head);
2221 bf = list_first_entry(&txq->txq_fifo_pending, 2250 bf = list_first_entry(&txq->txq_fifo_pending,