svn commit: r315583 - head/sys/net80211

Andriy Voskoboinyk avos at FreeBSD.org
Sun Mar 19 20:05:22 UTC 2017


Author: avos
Date: Sun Mar 19 20:05:21 2017
New Revision: 315583
URL: https://svnweb.freebsd.org/changeset/base/315583

Log:
  net80211: add a timer to flush fast-frames queues.
  
  This should allow to drop 'ieee80211_ff_[age/flush]' calls from drivers
  (an additional call can be made from ieee80211_tx_complete()
  for non-default ieee80211_ffagemax values to prevent stalls -
  but it will require an additional counter for transmitted frames).
  
  Tested with RTL8821AU, STA mode (A-MSDU part only).
  
  Reviewed by:	adrian
  Differential Revision:	https://reviews.freebsd.org/D9984

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 Mar 19 20:04:57 2017	(r315582)
+++ head/sys/net80211/ieee80211_superg.c	Sun Mar 19 20:05:21 2017	(r315583)
@@ -94,6 +94,33 @@ SYSCTL_PROC(_net_wlan, OID_AUTO, ffagema
 	&ieee80211_ffagemax, 0, ieee80211_sysctl_msecs_ticks, "I",
 	"max hold time for fast-frame staging (ms)");
 
+static void
+ff_age_all(void *arg, int npending)
+{
+	struct ieee80211com *ic = arg;
+
+	/* XXX cache timer value somewhere (racy) */
+	ieee80211_ff_age_all(ic, ieee80211_ffagemax + 1);
+}
+
+static void
+ff_check_cancel_age_timer(struct ieee80211com *ic)
+{
+	struct ieee80211_superg *sg = ic->ic_superg;
+
+	IEEE80211_FF_LOCK_ASSERT(ic);
+
+	if (sg->ff_stageq[WME_AC_VO].depth == 0 &&
+	    sg->ff_stageq[WME_AC_VI].depth == 0 &&
+	    sg->ff_stageq[WME_AC_BE].depth == 0 &&
+	    sg->ff_stageq[WME_AC_BK].depth == 0) {
+		struct timeout_task *qtask = &sg->ff_qtimer;
+
+		/* NB: may be called from the task itself */
+		(void) taskqueue_cancel_timeout(ic->ic_tq, qtask, NULL);
+	}
+}
+
 void
 ieee80211_superg_attach(struct ieee80211com *ic)
 {
@@ -109,6 +136,7 @@ ieee80211_superg_attach(struct ieee80211
 		    __func__);
 		return;
 	}
+	TIMEOUT_TASK_INIT(ic->ic_tq, &sg->ff_qtimer, 0, ff_age_all, ic);
 	ic->ic_superg = sg;
 
 	/*
@@ -122,12 +150,16 @@ ieee80211_superg_attach(struct ieee80211
 void
 ieee80211_superg_detach(struct ieee80211com *ic)
 {
-	IEEE80211_FF_LOCK_DESTROY(ic);
 
 	if (ic->ic_superg != NULL) {
+		struct timeout_task *qtask = &ic->ic_superg->ff_qtimer;
+
+		while (taskqueue_cancel_timeout(ic->ic_tq, qtask, NULL) != 0)
+			taskqueue_drain_timeout(ic->ic_tq, qtask);
 		IEEE80211_FREE(ic->ic_superg, M_80211_VAP);
 		ic->ic_superg = NULL;
 	}
+	IEEE80211_FF_LOCK_DESTROY(ic);
 }
 
 void
@@ -647,9 +679,10 @@ ieee80211_ff_age(struct ieee80211com *ic
 		sq->head = m->m_nextpkt;
 		sq->depth--;
 	}
-	if (m == NULL)
+	if (m == NULL) {
 		sq->tail = NULL;
-	else
+		ff_check_cancel_age_timer(ic);
+	} else
 		M_AGE_SUB(m, quanta);
 	IEEE80211_FF_UNLOCK(ic);
 
@@ -668,8 +701,13 @@ stageq_add(struct ieee80211com *ic, stru
 	if (sq->tail != NULL) {
 		sq->tail->m_nextpkt = m;
 		age -= M_AGE_GET(sq->head);
-	} else
+	} else {
 		sq->head = m;
+
+		/* Do not restart the timer if task was already scheduled. */
+		struct timeout_task *qtask = &ic->ic_superg->ff_qtimer;
+		taskqueue_enqueue_timeout(ic->ic_tq, qtask, -age);
+	}
 	KASSERT(age >= 0, ("age %d", age));
 	M_AGE_SET(m, age);
 	m->m_nextpkt = NULL;
@@ -694,6 +732,7 @@ stageq_remove(struct ieee80211com *ic, s
 			if (sq->tail == m)
 				sq->tail = mprev;
 			sq->depth--;
+			ff_check_cancel_age_timer(ic);
 			return;
 		}
 		mprev = m;

Modified: head/sys/net80211/ieee80211_superg.h
==============================================================================
--- head/sys/net80211/ieee80211_superg.h	Sun Mar 19 20:04:57 2017	(r315582)
+++ head/sys/net80211/ieee80211_superg.h	Sun Mar 19 20:05:21 2017	(r315583)
@@ -66,6 +66,8 @@ struct ieee80211_stageq {
 struct ieee80211_superg {
 	/* fast-frames staging q */
 	struct ieee80211_stageq	ff_stageq[WME_NUM_AC];
+	/* flush queues automatically */
+	struct timeout_task	ff_qtimer;
 };
 
 void	ieee80211_superg_attach(struct ieee80211com *);


More information about the svn-src-head mailing list