summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r--sys/dev/ath/if_ath.c62
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
OpenPOWER on IntegriCloud