Date: Wed, 22 Jun 2011 14:27:30 +0000 (UTC) From: Adrian Chadd <adrian@FreeBSD.org> To: src-committers@freebsd.org, svn-src-user@freebsd.org Subject: svn commit: r223422 - user/adrian/if_ath_tx/sys/dev/ath Message-ID: <201106221427.p5MERUvT053039@svn.freebsd.org>
next in thread | raw e-mail | index | archive | help
Author: adrian Date: Wed Jun 22 14:27:30 2011 New Revision: 223422 URL: http://svn.freebsd.org/changeset/base/223422 Log: Begin fleshing out the aggregate session handling code. Document what I see as currently missing, so I don't forget to fill in the gaps and implement this stuff. Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c Wed Jun 22 09:55:28 2011 (r223421) +++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.c Wed Jun 22 14:27:30 2011 (r223422) @@ -939,6 +939,12 @@ ath_tx_start(struct ath_softc *sc, struc ismcast = IEEE80211_IS_MULTICAST(wh->i_addr1); /* A-MPDU TX */ + /* + * XXX This doesn't hold the node lock! + * XXX So it's possible that another TX process can change + * XXX the AMPDU status from underneath us. This needs to be + * XXX further investigated! + */ is_ampdu_tx = ath_tx_ampdu_running(sc, ATH_NODE(ni), tid); is_ampdu_pending = ath_tx_ampdu_pending(sc, ATH_NODE(ni), tid); is_ampdu = is_ampdu_tx | is_ampdu_pending; @@ -1646,15 +1652,90 @@ ath_tx_tid_cleanup(struct ath_softc *sc, } /* + * Handle completion of aggregate frames. + */ +static void +ath_tx_aggr_comp(struct ath_softc *sc, struct ath_buf *bf) +{ + /* Success? Complete */ + ath_tx_default_comp(sc, bf); + + /* + * Not success and have retries left? + * + * Mark as retry, requeue at head of queue + */ + + /* + * Not success and out of retries? + * + * Need to wait for the hardware TXQ to finish draining, + * then once we know what was successfully TXed and what + * wasn't, we send a BAR to advance the pointer to that + * place. + */ +} + +/* * Schedule some packets from the given node/TID to the hardware. * - * For non-aggregate packets, all packets can just be queued. - * Aggregate destinations will end up having limitations on - * what can actually be queued here (ie, not more than the - * block-ack window.) + * This is the aggregate version. + */ +void +ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an, int tid) +{ + struct ath_buf *bf; + struct ath_txq *txq; + struct ath_tid *atid = &an->an_tid[tid]; + + for (;;) { + ATH_TXQ_LOCK(atid); + bf = STAILQ_FIRST(&atid->axq_q); + if (bf == NULL) { + ATH_TXQ_UNLOCK(atid); + break; + } + + /* XXX check if seqno is outside of BAW, if so don't queue it */ + + /* + * XXX If the seqno is out of BAW, then we should pause this TID + * XXX until a completion for this TID allows the BAW to be advanced. + * XXX Otherwise it's possible that we'll simply keep getting called + * XXX for this node/TID until some TX completion has occured + * XXX and progress can be made. + */ + ATH_TXQ_REMOVE_HEAD(atid, bf_list); + ATH_TXQ_UNLOCK(atid); + + /* Remove from queue */ + ATH_NODE_LOCK(an); + an->an_qdepth--; + ATH_NODE_UNLOCK(an); + + txq = bf->bf_state.bfs_txq; + /* Sanity check! */ + if (tid != bf->bf_state.bfs_tid) { + device_printf(sc->sc_dev, "%s: bfs_tid %d !=" + " tid %d\n", + __func__, bf->bf_state.bfs_tid, tid); + } + + /* Set completion handler */ + bf->bf_comp = ath_tx_aggr_comp; + + /* Punt to hardware or software txq */ + ath_tx_handoff(sc, txq, bf); + } +} + + + +/* + * Schedule some packets from the given node/TID to the hardware. */ void -ath_tx_tid_hw_queue(struct ath_softc *sc, struct ath_node *an, int tid) +ath_tx_tid_hw_queue_norm(struct ath_softc *sc, struct ath_node *an, int tid) { struct ath_buf *bf; struct ath_txq *txq; @@ -1695,29 +1776,28 @@ void ath_tx_hw_queue(struct ath_softc *sc, struct ath_node *an) { struct ath_tid *atid; - int i; + int tid; /* * For now, just queue from all TIDs in order. * This is very likely absolutely wrong from a QoS * perspective but it'll do for now. */ - for (i = 0; i < IEEE80211_TID_SIZE; i++) { - atid = &an->an_tid[i]; + for (tid = 0; tid < IEEE80211_TID_SIZE; tid++) { + atid = &an->an_tid[tid]; ATH_NODE_LOCK(an); - if (ath_tx_ampdu_pending(sc, an, i)) { + if (ath_tx_ampdu_pending(sc, an, tid)) { ATH_NODE_UNLOCK(an); continue; } ATH_NODE_UNLOCK(an); - ath_tx_tid_hw_queue(sc, an, i); + if (ath_tx_ampdu_running(sc, an, tid)) + ath_tx_tid_hw_queue_aggr(sc, an, tid); + else + ath_tx_tid_hw_queue_norm(sc, an, tid); } } -/* - * XXX this needs to be atomic or ath_node locked - * XXX This is currently serialised behind the ATH lock - */ static int ath_txq_node_qlen(struct ath_softc *sc, struct ath_node *an) { @@ -1783,7 +1863,7 @@ ath_tx_ampdu_running(struct ath_softc *s { struct ieee80211_tx_ampdu *tap; - //ATH_NODE_LOCK_ASSERT(an); + ATH_NODE_LOCK_ASSERT(an); tap = ath_tx_get_tx_tid(an, tid); if (tap == NULL) @@ -1802,7 +1882,7 @@ ath_tx_ampdu_pending(struct ath_softc *s { struct ieee80211_tx_ampdu *tap; - //ATH_NODE_LOCK_ASSERT(an); + ATH_NODE_LOCK_ASSERT(an); tap = ath_tx_get_tx_tid(an, tid); if (tap == NULL) Modified: user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h ============================================================================== --- user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h Wed Jun 22 09:55:28 2011 (r223421) +++ user/adrian/if_ath_tx/sys/dev/ath/if_ath_tx.h Wed Jun 22 14:27:30 2011 (r223422) @@ -47,7 +47,9 @@ extern void ath_tx_swq(struct ath_softc struct ath_txq *txq, struct ath_buf *bf, struct mbuf *m0); extern void ath_tx_tid_init(struct ath_softc *sc, struct ath_node *an); extern void ath_tx_tid_cleanup(struct ath_softc *sc, struct ath_node *an); -extern void ath_tx_tid_hw_queue(struct ath_softc *sc, struct ath_node *an, +extern void ath_tx_tid_hw_queue_aggr(struct ath_softc *sc, struct ath_node *an, + int tid); +extern void ath_tx_tid_hw_queue_norm(struct ath_softc *sc, struct ath_node *an, int tid); extern void ath_tx_hw_queue(struct ath_softc *sc, struct ath_node *an); extern void ath_txq_sched(struct ath_softc *sc);
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201106221427.p5MERUvT053039>