summaryrefslogtreecommitdiffstats
path: root/sys/dev/ath/if_ath.c
diff options
context:
space:
mode:
authoradrian <adrian@FreeBSD.org>2011-11-08 21:25:36 +0000
committeradrian <adrian@FreeBSD.org>2011-11-08 21:25:36 +0000
commit49cbf8b5e40871381fdef6d3da5c3512df7457f8 (patch)
tree725fe13b0ac4ba3696e0e03ddcaabee4c22f6983 /sys/dev/ath/if_ath.c
parent7bcb6d191ceb59e6fe9be8a24eac8b2f5e90ae40 (diff)
downloadFreeBSD-src-49cbf8b5e40871381fdef6d3da5c3512df7457f8.zip
FreeBSD-src-49cbf8b5e40871381fdef6d3da5c3512df7457f8.tar.gz
Change the descriptor logic to use bf_lastds to point to the last
descriptor, rather than using the maths involving bf_desc[bf_nseg - 1]. When doing TX aggregation, the status will be updated in the -final- descriptor of the -final- subframe in an aggregate. Thus bf_lastds may point to the last descriptor in a completely different ath_buf. Sponsored by: Hobnob, Inc.
Diffstat (limited to 'sys/dev/ath/if_ath.c')
-rw-r--r--sys/dev/ath/if_ath.c24
1 files changed, 18 insertions, 6 deletions
diff --git a/sys/dev/ath/if_ath.c b/sys/dev/ath/if_ath.c
index 8be0293..3aa1a12 100644
--- a/sys/dev/ath/if_ath.c
+++ b/sys/dev/ath/if_ath.c
@@ -2503,6 +2503,8 @@ ath_beacon_setup(struct ath_softc *sc, struct ath_buf *bf)
/* setup descriptors */
ds = bf->bf_desc;
+ bf->bf_last = bf;
+ bf->bf_lastds = ds;
flags = HAL_TXDESC_NOACK;
if (ic->ic_opmode == IEEE80211_M_IBSS && sc->sc_hasveol) {
@@ -2582,7 +2584,9 @@ ath_txqmove(struct ath_txq *dst, struct ath_txq *src)
dst->axq_link = src->axq_link;
src->axq_link = NULL;
dst->axq_depth += src->axq_depth;
+ dst->axq_aggr_depth += src->axq_aggr_depth;
src->axq_depth = 0;
+ src->axq_aggr_depth = 0;
}
/*
@@ -3227,6 +3231,7 @@ ath_descdma_setup(struct ath_softc *sc,
ath_descdma_cleanup(sc, dd, head);
return error;
}
+ bf->bf_lastds = bf->bf_desc; /* Just an initial value */
TAILQ_INSERT_TAIL(head, bf, bf_list);
}
return 0;
@@ -4284,7 +4289,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched)
struct ifnet *ifp = sc->sc_ifp;
struct ieee80211com *ic = ifp->if_l2com;
struct ath_buf *bf, *last;
- struct ath_desc *ds, *ds0;
+ struct ath_desc *ds;
struct ath_tx_status *ts;
struct ieee80211_node *ni;
struct ath_node *an;
@@ -4304,8 +4309,7 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched)
ATH_TXQ_UNLOCK(txq);
break;
}
- ds0 = &bf->bf_desc[0];
- ds = &bf->bf_desc[bf->bf_nseg - 1];
+ ds = bf->bf_lastds; /* XXX must be setup correctly! */
ts = &bf->bf_status.ds_txstat;
status = ath_hal_txprocdesc(ah, ds, ts);
#ifdef ATH_DEBUG
@@ -4324,13 +4328,19 @@ ath_tx_processq(struct ath_softc *sc, struct ath_txq *txq, int dosched)
* 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_flags |= ATH_BUF_BUSY;
+ bf->bf_last->bf_flags |= ATH_BUF_BUSY;
} else
#else
if (txq->axq_depth == 0)
#endif
txq->axq_link = NULL;
+ if (bf->bf_state.bfs_aggr)
+ txq->axq_aggr_depth--;
ATH_TXQ_UNLOCK(txq);
ni = bf->bf_node;
@@ -4565,13 +4575,15 @@ ath_tx_draintxq(struct ath_softc *sc, struct ath_txq *txq)
break;
}
ATH_TXQ_REMOVE(txq, bf, bf_list);
+ if (bf->bf_state.bfs_aggr)
+ txq->axq_aggr_depth--;
ATH_TXQ_UNLOCK(txq);
#ifdef ATH_DEBUG
if (sc->sc_debug & ATH_DEBUG_RESET) {
struct ieee80211com *ic = sc->sc_ifp->if_l2com;
ath_printtxbuf(sc, bf, txq->axq_qnum, ix,
- ath_hal_txprocdesc(ah, bf->bf_desc,
+ ath_hal_txprocdesc(ah, bf->bf_lastds,
&bf->bf_status.ds_txstat) == HAL_OK);
ieee80211_dump_pkt(ic, mtod(bf->bf_m, const uint8_t *),
bf->bf_m->m_len, 0, -1);
@@ -4657,7 +4669,7 @@ ath_draintxq(struct ath_softc *sc, ATH_RESET_TYPE reset_type)
struct ath_buf *bf = TAILQ_FIRST(&sc->sc_bbuf);
if (bf != NULL && bf->bf_m != NULL) {
ath_printtxbuf(sc, bf, sc->sc_bhalq, 0,
- ath_hal_txprocdesc(ah, bf->bf_desc,
+ ath_hal_txprocdesc(ah, bf->bf_lastds,
&bf->bf_status.ds_txstat) == HAL_OK);
ieee80211_dump_pkt(ifp->if_l2com,
mtod(bf->bf_m, const uint8_t *), bf->bf_m->m_len,
OpenPOWER on IntegriCloud