- sc->sc_tx_start = 0;
- }
-@@ -2221,12 +2233,13 @@
- * Insert the frame on the outbound list and
- * pass it on to the hardware.
- */
-- ATH_TXQ_LOCK(txq);
-+ ATH_TXQ_LOCK_IRQ(txq);
- if (ni && ni->ni_vap && txq == &ATH_VAP(ni->ni_vap)->av_mcastq) {
- /*
- * The CAB queue is started from the SWBA handler since
- * frames only go out on DTIM and to avoid possible races.
- */
-+ sc->sc_imask &= ~HAL_INT_SWBA;
- ath_hal_intrset(ah, sc->sc_imask & ~HAL_INT_SWBA);
- ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
- DPRINTF(sc, ATH_DEBUG_TX_PROC, "%s: txq depth = %d\n", __func__, txq->axq_depth);
-@@ -2242,6 +2255,7 @@
- ito64(bf->bf_daddr), bf->bf_desc);
- }
- txq->axq_link = &lastds->ds_link;
-+ sc->sc_imask |= HAL_INT_SWBA;
- ath_hal_intrset(ah, sc->sc_imask);
- } else {
- ATH_TXQ_INSERT_TAIL(txq, bf, bf_list);
-@@ -2275,7 +2289,7 @@
- sc->sc_tx_start = jiffies;
- }
- }
-- ATH_TXQ_UNLOCK(txq);
-+ ATH_TXQ_UNLOCK_IRQ(txq);
-
- sc->sc_devstats.tx_packets++;
- sc->sc_devstats.tx_bytes += framelen;
-@@ -2426,8 +2440,14 @@
- unsigned int pktlen;
- int framecnt;
-
-+ /*
-+ * NB: using _BH style locking even though this function may be called
-+ * at interrupt time (within tasklet or bh). This should be harmless
-+ * and this function calls others (i.e., ath_tx_start()) which do
-+ * the same.
-+ */
- for (;;) {
-- ATH_TXQ_LOCK(txq);
-+ ATH_TXQ_LOCK_BH(txq);
-
- bf_ff = TAILQ_LAST(&txq->axq_stageq, axq_headtype);
- if ((!bf_ff) || ath_ff_flushdonetest(txq, bf_ff)) {
-@@ -2441,7 +2461,7 @@
- ATH_NODE(ni)->an_tx_ffbuf[bf_ff->bf_skb->priority] = NULL;
- TAILQ_REMOVE(&txq->axq_stageq, bf_ff, bf_stagelist);
-
-- ATH_TXQ_UNLOCK(txq);
-+ ATH_TXQ_UNLOCK_BH(txq);
-
- /* encap and xmit */
- bf_ff->bf_skb = ieee80211_encap(ni, bf_ff->bf_skb, &framecnt);
-@@ -2462,15 +2482,16 @@
- }
- bf_ff->bf_node = NULL;
-
-- ATH_TXBUF_LOCK_IRQ(sc);
-+ ATH_TXBUF_LOCK_BH(sc);
- STAILQ_INSERT_TAIL(&sc->sc_txbuf, bf_ff, bf_list);
-- ATH_TXBUF_UNLOCK_IRQ(sc);
-+ ATH_TXBUF_UNLOCK_BH(sc);
- }
-+ ATH_TXQ_UNLOCK_BH(txq);
- }
- #endif
-
- #define ATH_HARDSTART_GET_TX_BUF_WITH_LOCK \
-- ATH_TXBUF_LOCK_IRQ(sc); \
-+ ATH_TXBUF_LOCK_BH(sc); \
- bf = STAILQ_FIRST(&sc->sc_txbuf); \
- if (bf != NULL) { \
- STAILQ_REMOVE_HEAD(&sc->sc_txbuf, bf_list); \
-@@ -2485,10 +2506,21 @@
- sc->sc_devstopped = 1; \
- ATH_SCHEDULE_TQUEUE(&sc->sc_txtq, NULL); \
- } \
-- ATH_TXBUF_UNLOCK_IRQ(sc); \
-+
-+#define ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_OFF \
-+ ATH_TXBUF_UNLOCK_BH(sc); \
-+ if (bf == NULL) { /* NB: should not happen */ \
-+ DPRINTF(sc,ATH_DEBUG_XMIT,"%s: discard, no xmit buf\n", __func__); \
-+ sc->sc_stats.ast_tx_nobuf++; \
-+ goto hardstart_fail; \
-+ }
-+
-+#define ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_ON \
-+ ATH_TXBUF_UNLOCK_BH(sc); \
- if (bf == NULL) { /* NB: should not happen */ \
- DPRINTF(sc,ATH_DEBUG_XMIT, \
- "%s: discard, no xmit buf\n", __func__); \
-+ ATH_TXQ_UNLOCK_BH(txq); \
- sc->sc_stats.ast_tx_nobuf++; \
- goto hardstart_fail; \
- }
-@@ -2490,6 +2490,7 @@
- DPRINTF(sc,ATH_DEBUG_XMIT, \
- "%s: discard, no xmit buf\n", __func__); \
- sc->sc_stats.ast_tx_nobuf++; \
-+ goto hardstart_fail; \
- }
-
- /*
-@@ -2552,6 +2584,7 @@
- if (M_FLAG_GET(skb, M_UAPSD)) {
- /* bypass FF handling */
- ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
-+ ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_OFF;
- if (bf == NULL)
- goto hardstart_fail;
- goto ff_bypass;
-@@ -2573,7 +2606,7 @@
- /* NB: use this lock to protect an->an_ff_txbuf in athff_can_aggregate()
- * call too.
- */
-- ATH_TXQ_LOCK(txq);
-+ ATH_TXQ_LOCK_BH(txq);
- if (athff_can_aggregate(sc, eh, an, skb, vap->iv_fragthreshold, &ff_flush)) {
-
- if (an->an_tx_ffbuf[skb->priority]) { /* i.e., frame on the staging queue */
-@@ -2583,7 +2616,7 @@
- TAILQ_REMOVE(&txq->axq_stageq, bf, bf_stagelist);
- an->an_tx_ffbuf[skb->priority] = NULL;
-
-- ATH_TXQ_UNLOCK(txq);
-+ ATH_TXQ_UNLOCK_BH(txq);
-
- /*
- * chain skbs and add FF magic
-@@ -2610,6 +2643,7 @@
- * to give the buffer back.
- */
- ATH_HARDSTART_GET_TX_BUF_WITH_LOCK;
-+ ATH_HARDSTART_REL_TX_BUF_WITH_TXQLOCK_ON;
- if (bf == NULL) {
- ATH_TXQ_UNLOCK(txq);
- goto hardstart_fail;
-@@ -2624,7 +2658,7 @@
-
- TAILQ_INSERT_HEAD(&txq->axq_stageq, bf, bf_stagelist);
-
-- ATH_TXQ_UNLOCK(txq);
-+ ATH_TXQ_UNLOCK_BH(txq);
-
- return 0;