PERFORCE change 136005 for review

Sam Leffler sam at FreeBSD.org
Sat Feb 23 01:40:29 UTC 2008


http://perforce.freebsd.org/chv.cgi?CH=136005

Change 136005 by sam at sam_ebb on 2008/02/23 01:39:39

	Update power save support:
	o change iv_set_tim to return an indication whether the TIM state
	  changed for the station so drivers can easily tell if they need to
	  push the change to their device
	o add iv_update_ps callback to notify drivers when the power occupancy
	  of the BSS changed; useful for drivers that want to notify outboard
	  devices when to buffer mcast frames and also should be used to flush
	  any multicast frames being held for xmit at DTIM
	o call if_start on the vap when flushing frames from the ps q
	o reorder operations in ieee80211_node_pwrsave so when a station exits
	  ps the beacon state is updated before the ps q is flushed; this is
	  intended to guard against beacons going out with stale TIM state

Affected files ...

.. //depot/projects/vap/sys/net80211/ieee80211_power.c#10 edit
.. //depot/projects/vap/sys/net80211/ieee80211_var.h#30 edit

Differences ...

==== //depot/projects/vap/sys/net80211/ieee80211_power.c#10 (text+ko) ====

@@ -45,7 +45,8 @@
 
 #include <net/bpf.h>
 
-static void ieee80211_set_tim(struct ieee80211_node *ni, int set);
+static void ieee80211_update_ps(struct ieee80211vap *, int);
+static int ieee80211_set_tim(struct ieee80211_node *, int);
 
 MALLOC_DEFINE(M_80211_POWER, "80211power", "802.11 power save state");
 
@@ -65,6 +66,7 @@
 	if (vap->iv_opmode == IEEE80211_M_HOSTAP ||
 	    vap->iv_opmode == IEEE80211_M_IBSS) {
 		/* NB: driver should override */
+		vap->iv_update_ps = ieee80211_update_ps;
 		vap->iv_set_tim = ieee80211_set_tim;
 	}
 }
@@ -155,14 +157,27 @@
 }
 
 /*
+ * Handle a change in the PS station occupancy.
+ */
+static void
+ieee80211_update_ps(struct ieee80211vap *vap, int nsta)
+{
+
+	KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP ||
+		vap->iv_opmode == IEEE80211_M_IBSS,
+		("operating mode %u", vap->iv_opmode));
+}
+
+/*
  * Indicate whether there are frames queued for a station in power-save mode.
  */
-static void
+static int
 ieee80211_set_tim(struct ieee80211_node *ni, int set)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
 	struct ieee80211com *ic = ni->ni_ic;
 	uint16_t aid;
+	int changed;
 
 	KASSERT(vap->iv_opmode == IEEE80211_M_HOSTAP ||
 		vap->iv_opmode == IEEE80211_M_IBSS,
@@ -173,7 +188,8 @@
 		("bogus aid %u, max %u", aid, vap->iv_max_aid));
 
 	IEEE80211_LOCK(ic);
-	if (set != (isset(vap->iv_tim_bitmap, aid) != 0)) {
+	changed = (set != (isset(vap->iv_tim_bitmap, aid) != 0));
+	if (changed) {
 		if (set) {
 			setbit(vap->iv_tim_bitmap, aid);
 			vap->iv_ps_pending++;
@@ -185,6 +201,8 @@
 		vap->iv_update_beacon(vap, IEEE80211_BEACON_TIM);
 	}
 	IEEE80211_UNLOCK(ic);
+
+	return changed;
 }
 
 /*
@@ -263,9 +281,10 @@
 	IEEE80211_NODE_SAVEQ_UNLOCK(ni);
 	if (mhead != NULL) {
 		/* XXX need different driver interface */
-		/* XXX bypasses q max */
+		/* XXX bypasses q max and OACTIVE */
 		struct ifnet *ifp = ni->ni_vap->iv_ifp;
 		IF_PREPEND_LIST(&ifp->if_snd, mhead, mtail, mcount);
+		if_start(ifp);
 	}
 }
 
@@ -276,26 +295,38 @@
 ieee80211_node_pwrsave(struct ieee80211_node *ni, int enable)
 {
 	struct ieee80211vap *vap = ni->ni_vap;
+	int update;
 
+	update = 0;
 	if (enable) {
-		if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) == 0)
+		if ((ni->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
 			vap->iv_ps_sta++;
+			update = 1;
+		}
 		ni->ni_flags |= IEEE80211_NODE_PWR_MGT;
 		IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
 		    "power save mode on, %u sta's in ps mode", vap->iv_ps_sta);
-		return;
-	}
 
-	if (ni->ni_flags & IEEE80211_NODE_PWR_MGT)
-		vap->iv_ps_sta--;
-	ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
-	IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
-	    "power save mode off, %u sta's in ps mode", vap->iv_ps_sta);
-	/* XXX if no stations in ps mode, flush mc frames */
+		if (update)
+			vap->iv_update_ps(vap, vap->iv_ps_sta);
+	} else {
+		if (ni->ni_flags & IEEE80211_NODE_PWR_MGT) {
+			vap->iv_ps_sta--;
+			update = 1;
+		}
+		ni->ni_flags &= ~IEEE80211_NODE_PWR_MGT;
+		IEEE80211_NOTE(vap, IEEE80211_MSG_POWER, ni,
+		    "power save mode off, %u sta's in ps mode", vap->iv_ps_sta);
 
-	pwrsave_flushq(ni);
-	if (vap->iv_set_tim != NULL)
-		vap->iv_set_tim(ni, 0);
+		/* NB: order here is intentional so TIM is clear before flush */
+		if (vap->iv_set_tim != NULL)
+			vap->iv_set_tim(ni, 0);
+		if (update) {
+			/* NB if no sta's in ps, driver should flush mc q */
+			vap->iv_update_ps(vap, vap->iv_ps_sta);
+		}
+		pwrsave_flushq(ni);
+	}
 }
 
 /*

==== //depot/projects/vap/sys/net80211/ieee80211_var.h#30 (text+ko) ====

@@ -343,7 +343,6 @@
 	uint8_t			iv_dtim_period;	/* DTIM period */
 	uint8_t			iv_dtim_count;	/* DTIM count from last bcn */
 						/* set/unset aid pwrsav state */
-	void			(*iv_set_tim)(struct ieee80211_node *, int);
 	int			iv_csa_count;	/* count for doing CSA */
 
 	struct ieee80211_node	*iv_bss;	/* information for this node */
@@ -401,6 +400,9 @@
 	int			(*iv_reset)(struct ieee80211vap *, u_long);
 	/* [schedule] beacon frame update */
 	void			(*iv_update_beacon)(struct ieee80211vap *, int);
+	/* power save handling */
+	void			(*iv_update_ps)(struct ieee80211vap *, int);
+	int			(*iv_set_tim)(struct ieee80211_node *, int);
 	/* state machine processing */
 	int			(*iv_newstate)(struct ieee80211vap *,
 				    enum ieee80211_state, int);


More information about the p4-projects mailing list