Author: adrian Date: Sun Dec 9 19:20:28 2012 New Revision: 244051 URL: http://svnweb.freebsd.org/changeset/base/244051
Log: Atheros SuperG bug fixes, as part of hunting down kern/174283. The stageqdepth (global, over all staging queues) was being kept incorrectly. It was being incremented whenever things were added, but only decremented during a flush. During active fast frames activity it wasn't being decremented, resulting in it always having a non-zero value during normal fast-frames operation. It was only used when checking if the aging queue should be checked; we may as well just defer to each of those staging queue counters (which look correct, thankfully.) Whilst I'm here, add locking assertions in the staging queue add/remove functions. The current crash shows that the staging queue has one frame, but only has a tail pointer set (the head pointer being set to NULL.) I'd like to grab a few more crashes where these locking assertions are in place so I can narrow down the issue between "somehow locking is messed up and things are racy" and "the stage queue head/tail pointer manipulation logic is subtly wrong." Tested: * AR5416 STA, AR5413 AP; with FastFrames enabled in the AR5416 HAL. PR: kern/174283 Modified: head/sys/net80211/ieee80211_superg.c head/sys/net80211/ieee80211_superg.h Modified: head/sys/net80211/ieee80211_superg.c ============================================================================== --- head/sys/net80211/ieee80211_superg.c Sun Dec 9 18:45:59 2012 (r244050) +++ head/sys/net80211/ieee80211_superg.c Sun Dec 9 19:20:28 2012 (r244051) @@ -560,7 +560,6 @@ void ieee80211_ff_age(struct ieee80211com *ic, struct ieee80211_stageq *sq, int quanta) { - struct ieee80211_superg *sg = ic->ic_superg; struct mbuf *m, *head; struct ieee80211_node *ni; struct ieee80211_tx_ampdu *tap; @@ -582,7 +581,6 @@ ieee80211_ff_age(struct ieee80211com *ic sq->head = m->m_nextpkt; sq->depth--; - sg->ff_stageqdepth--; } if (m == NULL) sq->tail = NULL; @@ -594,9 +592,12 @@ ieee80211_ff_age(struct ieee80211com *ic } static void -stageq_add(struct ieee80211_stageq *sq, struct mbuf *m) +stageq_add(struct ieee80211com *ic, struct ieee80211_stageq *sq, struct mbuf *m) { int age = ieee80211_ffagemax; + + IEEE80211_LOCK_ASSERT(ic); + if (sq->tail != NULL) { sq->tail->m_nextpkt = m; age -= M_AGE_GET(sq->head); @@ -610,10 +611,12 @@ stageq_add(struct ieee80211_stageq *sq, } static void -stageq_remove(struct ieee80211_stageq *sq, struct mbuf *mstaged) +stageq_remove(struct ieee80211com *ic, struct ieee80211_stageq *sq, struct mbuf *mstaged) { struct mbuf *m, *mprev; + IEEE80211_LOCK_ASSERT(ic); + mprev = NULL; for (m = sq->head; m != NULL; m = m->m_nextpkt) { if (m == mstaged) { @@ -725,7 +728,7 @@ ieee80211_ff_check(struct ieee80211_node tap->txa_private = NULL; if (mstaged != NULL) - stageq_remove(sq, mstaged); + stageq_remove(ic, sq, mstaged); IEEE80211_UNLOCK(ic); if (mstaged != NULL) { @@ -745,7 +748,7 @@ ieee80211_ff_check(struct ieee80211_node */ if (mstaged != NULL) { tap->txa_private = NULL; - stageq_remove(sq, mstaged); + stageq_remove(ic, sq, mstaged); IEEE80211_UNLOCK(ic); IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni, @@ -766,8 +769,7 @@ ieee80211_ff_check(struct ieee80211_node ("txa_private %p", tap->txa_private)); tap->txa_private = m; - stageq_add(sq, m); - sg->ff_stageqdepth++; + stageq_add(ic, sq, m); IEEE80211_UNLOCK(ic); IEEE80211_NOTE(vap, IEEE80211_MSG_SUPERG, ni, @@ -806,7 +808,7 @@ ieee80211_ff_node_cleanup(struct ieee802 m = tap->txa_private; if (m != NULL) { tap->txa_private = NULL; - stageq_remove(&sg->ff_stageq[ac], m); + stageq_remove(ic, &sg->ff_stageq[ac], m); m->m_nextpkt = head; head = m; } Modified: head/sys/net80211/ieee80211_superg.h ============================================================================== --- head/sys/net80211/ieee80211_superg.h Sun Dec 9 18:45:59 2012 (r244050) +++ head/sys/net80211/ieee80211_superg.h Sun Dec 9 19:20:28 2012 (r244051) @@ -66,7 +66,6 @@ struct ieee80211_stageq { struct ieee80211_superg { /* fast-frames staging q */ struct ieee80211_stageq ff_stageq[WME_NUM_AC]; - int ff_stageqdepth; /* cumulative depth */ }; void ieee80211_superg_attach(struct ieee80211com *); @@ -109,7 +108,7 @@ ieee80211_ff_age_all(struct ieee80211com { struct ieee80211_superg *sg = ic->ic_superg; - if (sg != NULL && sg->ff_stageqdepth) { + if (sg != NULL) { if (sg->ff_stageq[WME_AC_VO].depth) ieee80211_ff_age(ic, &sg->ff_stageq[WME_AC_VO], quanta); if (sg->ff_stageq[WME_AC_VI].depth) _______________________________________________ svn-src-all@freebsd.org mailing list http://lists.freebsd.org/mailman/listinfo/svn-src-all To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"