svn commit: r237917 - stable/9/sys/dev/iwn
Bernhard Schmidt
bschmidt at FreeBSD.org
Sun Jul 1 09:30:38 UTC 2012
Author: bschmidt
Date: Sun Jul 1 09:30:37 2012
New Revision: 237917
URL: http://svn.freebsd.org/changeset/base/237917
Log:
MFC BA/DELBA fixes:
- r234321:
Use the M_AMPDU_MPDU flag to determine when to manually set the seqno and
use a BA queue.
- r235686:
Discard frames after a DELBA which where queued during an active BA
session.
- r235687:
remove unused vap variable
- r237647:
Fix a TX aggregation issue, if after the last compressed BA notification
the TX queue is empty, there won't be a TX done notification, effectly
resulting in an mbuf leak. The correct way to handle this is to free
up mbufs on both BA and TX done notifications up to the last sent seqno.
- r237649 (1):
We need to defer passing the DELBA request to the firmware until the aggr
queue is empty or the firmware will go nuts.
PR: kern/167806 (1)
Modified:
stable/9/sys/dev/iwn/if_iwn.c
Directory Properties:
stable/9/sys/ (props changed)
stable/9/sys/dev/ (props changed)
Modified: stable/9/sys/dev/iwn/if_iwn.c
==============================================================================
--- stable/9/sys/dev/iwn/if_iwn.c Sun Jul 1 09:17:55 2012 (r237916)
+++ stable/9/sys/dev/iwn/if_iwn.c Sun Jul 1 09:30:37 2012 (r237917)
@@ -2432,23 +2432,66 @@ static void
iwn_rx_compressed_ba(struct iwn_softc *sc, struct iwn_rx_desc *desc,
struct iwn_rx_data *data)
{
+ struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct iwn_node *wn;
struct ieee80211_node *ni;
struct iwn_compressed_ba *ba = (struct iwn_compressed_ba *)(desc + 1);
struct iwn_tx_ring *txq;
+ struct iwn_tx_data *txdata;
struct ieee80211_tx_ampdu *tap;
+ struct mbuf *m;
uint64_t bitmap;
+ uint16_t ssn;
uint8_t tid;
- int ackfailcnt = 0, i, shift;
+ int ackfailcnt = 0, i, lastidx, qid, *res, shift;
bus_dmamap_sync(sc->rxq.data_dmat, data->map, BUS_DMASYNC_POSTREAD);
- txq = &sc->txq[le16toh(ba->qid)];
- tap = sc->qid2tap[le16toh(ba->qid)];
+ qid = le16toh(ba->qid);
+ txq = &sc->txq[ba->qid];
+ tap = sc->qid2tap[ba->qid];
tid = WME_AC_TO_TID(tap->txa_ac);
- ni = tap->txa_ni;
- wn = (void *)ni;
+ wn = (void *)tap->txa_ni;
+
+ res = NULL;
+ ssn = 0;
+ if (!IEEE80211_AMPDU_RUNNING(tap)) {
+ res = tap->txa_private;
+ ssn = tap->txa_start & 0xfff;
+ }
+
+ for (lastidx = le16toh(ba->ssn) & 0xff; txq->read != lastidx;) {
+ txdata = &txq->data[txq->read];
+
+ /* Unmap and free mbuf. */
+ bus_dmamap_sync(txq->data_dmat, txdata->map,
+ BUS_DMASYNC_POSTWRITE);
+ bus_dmamap_unload(txq->data_dmat, txdata->map);
+ m = txdata->m, txdata->m = NULL;
+ ni = txdata->ni, txdata->ni = NULL;
+
+ KASSERT(ni != NULL, ("no node"));
+ KASSERT(m != NULL, ("no mbuf"));
+
+ if (m->m_flags & M_TXCB)
+ ieee80211_process_callback(ni, m, 1);
+
+ m_freem(m);
+ ieee80211_free_node(ni);
+
+ txq->queued--;
+ txq->read = (txq->read + 1) % IWN_TX_RING_COUNT;
+ }
+
+ if (txq->queued == 0 && res != NULL) {
+ iwn_nic_lock(sc);
+ ops->ampdu_tx_stop(sc, qid, tid, ssn);
+ iwn_nic_unlock(sc);
+ sc->qid2tap[qid] = NULL;
+ free(res, M_DEVBUF);
+ return;
+ }
if (wn->agg[tid].bitmap == 0)
return;
@@ -2460,6 +2503,7 @@ iwn_rx_compressed_ba(struct iwn_softc *s
if (wn->agg[tid].nframes > (64 - shift))
return;
+ ni = tap->txa_ni;
bitmap = (le64toh(ba->bitmap) >> shift) & wn->agg[tid].bitmap;
for (i = 0; bitmap; i++) {
if ((bitmap & 1) == 0) {
@@ -2759,19 +2803,20 @@ static void
iwn_ampdu_tx_done(struct iwn_softc *sc, int qid, int idx, int nframes,
void *stat)
{
+ struct iwn_ops *ops = &sc->ops;
struct ifnet *ifp = sc->sc_ifp;
struct iwn_tx_ring *ring = &sc->txq[qid];
struct iwn_tx_data *data;
struct mbuf *m;
struct iwn_node *wn;
struct ieee80211_node *ni;
- struct ieee80211vap *vap;
struct ieee80211_tx_ampdu *tap;
uint64_t bitmap;
uint32_t *status = stat;
uint16_t *aggstatus = stat;
+ uint16_t ssn;
uint8_t tid;
- int bit, i, lastidx, seqno, shift, start;
+ int bit, i, lastidx, *res, seqno, shift, start;
#ifdef NOT_YET
if (nframes == 1) {
@@ -2804,27 +2849,32 @@ iwn_ampdu_tx_done(struct iwn_softc *sc,
bitmap |= 1ULL << bit;
}
tap = sc->qid2tap[qid];
- if (tap != NULL) {
- tid = WME_AC_TO_TID(tap->txa_ac);
- wn = (void *)tap->txa_ni;
- wn->agg[tid].bitmap = bitmap;
- wn->agg[tid].startidx = start;
- wn->agg[tid].nframes = nframes;
+ tid = WME_AC_TO_TID(tap->txa_ac);
+ wn = (void *)tap->txa_ni;
+ wn->agg[tid].bitmap = bitmap;
+ wn->agg[tid].startidx = start;
+ wn->agg[tid].nframes = nframes;
+
+ res = NULL;
+ ssn = 0;
+ if (!IEEE80211_AMPDU_RUNNING(tap)) {
+ res = tap->txa_private;
+ ssn = tap->txa_start & 0xfff;
}
seqno = le32toh(*(status + nframes)) & 0xfff;
for (lastidx = (seqno & 0xff); ring->read != lastidx;) {
data = &ring->data[ring->read];
- KASSERT(data->ni != NULL, ("no node"));
-
/* Unmap and free mbuf. */
bus_dmamap_sync(ring->data_dmat, data->map,
BUS_DMASYNC_POSTWRITE);
bus_dmamap_unload(ring->data_dmat, data->map);
m = data->m, data->m = NULL;
ni = data->ni, data->ni = NULL;
- vap = ni->ni_vap;
+
+ KASSERT(ni != NULL, ("no node"));
+ KASSERT(m != NULL, ("no mbuf"));
if (m->m_flags & M_TXCB)
ieee80211_process_callback(ni, m, 1);
@@ -2836,6 +2886,15 @@ iwn_ampdu_tx_done(struct iwn_softc *sc,
ring->read = (ring->read + 1) % IWN_TX_RING_COUNT;
}
+ if (ring->queued == 0 && res != NULL) {
+ iwn_nic_lock(sc);
+ ops->ampdu_tx_stop(sc, qid, tid, ssn);
+ iwn_nic_unlock(sc);
+ sc->qid2tap[qid] = NULL;
+ free(res, M_DEVBUF);
+ return;
+ }
+
sc->sc_tx_timer = 0;
if (ring->queued < IWN_TX_RING_LOMARK) {
sc->qfullmsk &= ~(1 << ring->qid);
@@ -3309,18 +3368,20 @@ iwn_tx_data(struct iwn_softc *sc, struct
tid = 0;
}
ac = M_WME_GETAC(m);
-
- if (IEEE80211_QOS_HAS_SEQ(wh) &&
- IEEE80211_AMPDU_RUNNING(&ni->ni_tx_ampdu[ac])) {
+ if (m->m_flags & M_AMPDU_MPDU) {
struct ieee80211_tx_ampdu *tap = &ni->ni_tx_ampdu[ac];
- ring = &sc->txq[*(int *)tap->txa_private];
+ if (!IEEE80211_AMPDU_RUNNING(tap)) {
+ m_freem(m);
+ return EINVAL;
+ }
+
+ ac = *(int *)tap->txa_private;
*(uint16_t *)wh->i_seq =
htole16(ni->ni_txseqs[tid] << IEEE80211_SEQ_SEQ_SHIFT);
ni->ni_txseqs[tid]++;
- } else {
- ring = &sc->txq[ac];
}
+ ring = &sc->txq[ac];
desc = &ring->desc[ring->cur];
data = &ring->data[ring->cur];
@@ -5634,6 +5695,8 @@ iwn_ampdu_tx_start(struct ieee80211com *
if ((error = iwn_nic_lock(sc)) != 0)
return 0;
qid = *(int *)tap->txa_private;
+ DPRINTF(sc, IWN_DEBUG_XMIT, "%s: ra=%d tid=%d ssn=%d qid=%d\n",
+ __func__, wn->id, tid, tap->txa_start, qid);
ops->ampdu_tx_start(sc, ni, qid, tid, tap->txa_start & 0xfff);
iwn_nic_unlock(sc);
@@ -5649,10 +5712,14 @@ iwn_ampdu_tx_stop(struct ieee80211_node
uint8_t tid = WME_AC_TO_TID(tap->txa_ac);
int qid;
+ sc->sc_addba_stop(ni, tap);
+
if (tap->txa_private == NULL)
return;
qid = *(int *)tap->txa_private;
+ if (sc->txq[qid].queued != 0)
+ return;
if (iwn_nic_lock(sc) != 0)
return;
ops->ampdu_tx_stop(sc, qid, tid, tap->txa_start & 0xfff);
@@ -5660,7 +5727,6 @@ iwn_ampdu_tx_stop(struct ieee80211_node
sc->qid2tap[qid] = NULL;
free(tap->txa_private, M_DEVBUF);
tap->txa_private = NULL;
- sc->sc_addba_stop(ni, tap);
}
static void
More information about the svn-src-stable-9
mailing list