diff options
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r-- | sys/dev/ath/if_ath.c | 62 |
1 files changed, 61 insertions, 1 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c index ef3db94..210b965 100644 --- a/sys/dev/ath/if_ath.c +++ b/sys/dev/ath/if_ath.c @@ -723,6 +723,19 @@ ath_attach(u_int16_t devid, struct ath_softc *sc) ic->ic_scan_end = ath_scan_end; ic->ic_set_channel = ath_set_channel; + /* 802.11n specific - but just override anyway */ + sc->sc_addba_request = ic->ic_addba_request; + sc->sc_addba_response = ic->ic_addba_response; + sc->sc_addba_stop = ic->ic_addba_stop; + sc->sc_bar_response = ic->ic_bar_response; + sc->sc_addba_response_timeout = ic->ic_addba_response_timeout; + + ic->ic_addba_request = ath_addba_request; + ic->ic_addba_response = ath_addba_response; + ic->ic_addba_response_timeout = ath_addba_response_timeout; + ic->ic_addba_stop = ath_addba_stop; + ic->ic_bar_response = ath_bar_response; + ieee80211_radiotap_attach(ic, &sc->sc_tx_th.wt_ihdr, sizeof(sc->sc_tx_th), ATH_TX_RADIOTAP_PRESENT, @@ -3343,6 +3356,9 @@ ath_node_alloc(struct ieee80211vap *vap, const uint8_t mac[IEEE80211_ADDR_LEN]) device_get_nameunit(sc->sc_dev), an); mtx_init(&an->an_mtx, an->an_name, NULL, MTX_DEF); + /* XXX setup ath_tid */ + ath_tx_tid_init(sc, an); + DPRINTF(sc, ATH_DEBUG_NODE, "%s: an %p\n", __func__, an); return &an->an_node; } @@ -3354,6 +3370,7 @@ ath_node_cleanup(struct ieee80211_node *ni) struct ath_softc *sc = ic->ic_ifp->if_softc; /* Cleanup ath_tid, free unused bufs, unlink bufs in TXQ */ + ath_tx_node_flush(sc, ATH_NODE(ni)); ath_rate_node_cleanup(sc, ATH_NODE(ni)); sc->sc_node_cleanup(ni); } @@ -4364,6 +4381,29 @@ ath_tx_default_comp(struct ath_softc *sc, struct ath_buf *bf, int fail) } /* + * Update rate control with the given completion status. + */ +void +ath_tx_update_ratectrl(struct ath_softc *sc, struct ieee80211_node *ni, + struct ath_rc_series *rc, struct ath_tx_status *ts, int frmlen, + int nframes, int nbad) +{ + struct ath_node *an; + + /* Only for unicast frames */ + if (ni == NULL) + return; + + an = ATH_NODE(ni); + + if ((ts->ts_status & HAL_TXERR_FILT) == 0) { + ATH_NODE_LOCK(an); + ath_rate_tx_complete(sc, an, rc, ts, frmlen, nframes, nbad); + ATH_NODE_UNLOCK(an); + } +} + +/* * Update the busy status of the last frame on the free list. * When doing TDMA, the busy flag tracks whether the hardware * currently points to this buffer or not, and thus gated DMA @@ -4396,6 +4436,8 @@ ath_tx_update_busy(struct ath_softc *sc) /* * Process completed xmit descriptors from the specified queue. + * Kick the packet scheduler if needed. This can occur from this + * particular task. */ static int ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) @@ -4405,6 +4447,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) struct ath_desc *ds; struct ath_tx_status *ts; struct ieee80211_node *ni; + struct ath_node *an; int nacked; HAL_STATUS status; @@ -4471,6 +4514,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) /* If unicast frame, update general statistics */ if (ni != NULL) { + an = ATH_NODE(ni); /* update statistics */ ath_tx_update_stats(sc, ts, bf); } @@ -4490,7 +4534,10 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) * XXX assume this isn't an aggregate * frame. */ - ath_rate_tx_complete(sc, ATH_NODE(ni), bf); + ath_tx_update_ratectrl(sc, ni, + bf->bf_state.bfs_rc, ts, + bf->bf_state.bfs_pktlen, 1, + (ts->ts_status == 0 ? 0 : 1)); } ath_tx_default_comp(sc, bf, 0); } else @@ -4503,6 +4550,14 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched) if (txq->axq_depth <= 1) ieee80211_ff_flush(ic, txq->axq_ac); #endif + + /* Kick the TXQ scheduler */ + if (dosched) { + ATH_TXQ_LOCK(txq); + ath_txq_sched(sc, txq); + ATH_TXQ_UNLOCK(txq); + } + return nacked; } @@ -4736,6 +4791,11 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq) ath_tx_default_comp(sc, bf, 1); } + /* + * Drain software queued frames which are on + * active TIDs. + */ + ath_tx_txq_drain(sc, txq); } static void |