svn commit: r244051 - head/sys/net80211

Adrian Chadd adrian at FreeBSD.org
Sun Dec 9 19:20:29 UTC 2012


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)


More information about the svn-src-all mailing list