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