diff options
-rw-r--r-- | sys/dev/ath/if_ath.c | 27 | ||||
-rw-r--r-- | sys/dev/ath/if_ath_misc.h | 6 |
2 files changed, 19 insertions, 14 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index f0b5328c9820..a71b3f813556 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -4000,20 +4000,19 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) break; } ATH_TXQ_REMOVE(txq, bf, bf_list); - - /* - * Always mark the last buffer in this list as busy. - * - * The hardware may re-read the holding descriptor - * even if we hit the end of the list and try writing - * a new TxDP. - * - * If there's no holding descriptor then this is the - * last buffer in the list of buffers after a fresh - * reset; it'll soon become the holding buffer. - */ - bf->bf_last->bf_flags |= ATH_BUF_BUSY; - + if (txq->axq_depth > 0) { + /* + * More frames follow. Mark the buffer busy + * so it's not re-used while the hardware may + * still re-read the link field in the descriptor. + * + * Use the last buffer in an aggregate as that + * is where the hardware may be - intermediate + * descriptors won't be "busy". + */ + bf->bf_last->bf_flags |= ATH_BUF_BUSY; + } else + txq->axq_link = NULL; if (bf->bf_state.bfs_aggr) txq->axq_aggr_depth--; diff --git a/sys/dev/ath/if_ath_misc.h b/sys/dev/ath/if_ath_misc.h index 965ab9f41cce..404d073f7107 100644 --- a/sys/dev/ath/if_ath_misc.h +++ b/sys/dev/ath/if_ath_misc.h @@ -131,10 +131,16 @@ extern void ath_start_task(void *arg, int npending); static inline void ath_tx_kick(struct ath_softc *sc) { + struct ieee80211com *ic = sc->sc_ifp->if_l2com; + IEEE80211_TX_UNLOCK_ASSERT(ic); + ATH_TX_UNLOCK_ASSERT(sc); + + IEEE80211_TX_LOCK(ic); ATH_TX_LOCK(sc); ath_start(sc->sc_ifp); ATH_TX_UNLOCK(sc); + IEEE80211_TX_UNLOCK(ic); } /* |