Migrate the power-save functions to be overridable VAP methods.
This turns ieee80211_node_pwrsave(), ieee80211_sta_pwrsave() and ieee80211_recv_pspoll() into methods. The intent is to let drivers override these and tie into the power save management pathway. For ath(4), this is the beginning of forcing a node software queue to stop and start as needed, as well as supporting "leaking" single frames from the software queue to the hardware. Right now, ieee80211_recv_pspoll() will attempt to transmit a single frame to the hardware (whether it be a data frame on the power-save queue or a NULL data frame) but the driver may have hardware/software queued frames queued up. This initial work is an attempt at providing the hooks required to implement correct behaviour. Allowing ieee80211_node_pwrsave() to be overridden allows the ath(4) driver to pause and unpause the entire software queue for a given node. It doesn't make sense to transmit anything whilst the node is asleep. Please note that there are other corner cases to correctly handle - specifically, setting the MORE data bit correctly on frames to a station, as well as keeping the TIM updated. Those particular issues can be addressed later.
This commit is contained in:
parent
001794b735
commit
b7889929b9
@ -242,7 +242,7 @@ adhoc_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
ic->ic_newassoc(ni, ostate != IEEE80211_S_RUN);
|
ic->ic_newassoc(ni, ostate != IEEE80211_S_RUN);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_S_SLEEP:
|
case IEEE80211_S_SLEEP:
|
||||||
ieee80211_sta_pwrsave(vap, 0);
|
vap->iv_sta_ps(vap, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
invalid:
|
invalid:
|
||||||
|
@ -73,7 +73,6 @@ static void hostap_deliver_data(struct ieee80211vap *,
|
|||||||
static void hostap_recv_mgmt(struct ieee80211_node *, struct mbuf *,
|
static void hostap_recv_mgmt(struct ieee80211_node *, struct mbuf *,
|
||||||
int subtype, int rssi, int nf);
|
int subtype, int rssi, int nf);
|
||||||
static void hostap_recv_ctl(struct ieee80211_node *, struct mbuf *, int);
|
static void hostap_recv_ctl(struct ieee80211_node *, struct mbuf *, int);
|
||||||
static void hostap_recv_pspoll(struct ieee80211_node *, struct mbuf *);
|
|
||||||
|
|
||||||
void
|
void
|
||||||
ieee80211_hostap_attach(struct ieee80211com *ic)
|
ieee80211_hostap_attach(struct ieee80211com *ic)
|
||||||
@ -100,6 +99,7 @@ hostap_vattach(struct ieee80211vap *vap)
|
|||||||
vap->iv_recv_ctl = hostap_recv_ctl;
|
vap->iv_recv_ctl = hostap_recv_ctl;
|
||||||
vap->iv_opdetach = hostap_vdetach;
|
vap->iv_opdetach = hostap_vdetach;
|
||||||
vap->iv_deliver_data = hostap_deliver_data;
|
vap->iv_deliver_data = hostap_deliver_data;
|
||||||
|
vap->iv_recv_pspoll = ieee80211_recv_pspoll;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -645,7 +645,7 @@ hostap_input(struct ieee80211_node *ni, struct mbuf *m, int rssi, int nf)
|
|||||||
*/
|
*/
|
||||||
if (((wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) ^
|
if (((wh->i_fc[1] & IEEE80211_FC1_PWR_MGT) ^
|
||||||
(ni->ni_flags & IEEE80211_NODE_PWR_MGT)))
|
(ni->ni_flags & IEEE80211_NODE_PWR_MGT)))
|
||||||
ieee80211_node_pwrsave(ni,
|
vap->iv_node_ps(ni,
|
||||||
wh->i_fc[1] & IEEE80211_FC1_PWR_MGT);
|
wh->i_fc[1] & IEEE80211_FC1_PWR_MGT);
|
||||||
/*
|
/*
|
||||||
* For 4-address packets handle WDS discovery
|
* For 4-address packets handle WDS discovery
|
||||||
@ -2240,7 +2240,7 @@ hostap_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
|
|||||||
{
|
{
|
||||||
switch (subtype) {
|
switch (subtype) {
|
||||||
case IEEE80211_FC0_SUBTYPE_PS_POLL:
|
case IEEE80211_FC0_SUBTYPE_PS_POLL:
|
||||||
hostap_recv_pspoll(ni, m);
|
ni->ni_vap->iv_recv_pspoll(ni, m);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_FC0_SUBTYPE_BAR:
|
case IEEE80211_FC0_SUBTYPE_BAR:
|
||||||
ieee80211_recv_bar(ni, m);
|
ieee80211_recv_bar(ni, m);
|
||||||
@ -2251,8 +2251,8 @@ hostap_recv_ctl(struct ieee80211_node *ni, struct mbuf *m, int subtype)
|
|||||||
/*
|
/*
|
||||||
* Process a received ps-poll frame.
|
* Process a received ps-poll frame.
|
||||||
*/
|
*/
|
||||||
static void
|
void
|
||||||
hostap_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0)
|
ieee80211_recv_pspoll(struct ieee80211_node *ni, struct mbuf *m0)
|
||||||
{
|
{
|
||||||
struct ieee80211vap *vap = ni->ni_vap;
|
struct ieee80211vap *vap = ni->ni_vap;
|
||||||
struct ieee80211_frame_min *wh;
|
struct ieee80211_frame_min *wh;
|
||||||
|
@ -32,4 +32,10 @@
|
|||||||
*/
|
*/
|
||||||
void ieee80211_hostap_attach(struct ieee80211com *);
|
void ieee80211_hostap_attach(struct ieee80211com *);
|
||||||
void ieee80211_hostap_detach(struct ieee80211com *);
|
void ieee80211_hostap_detach(struct ieee80211com *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This method can be overridden
|
||||||
|
*/
|
||||||
|
void ieee80211_recv_pspoll(struct ieee80211_node *, struct mbuf *);
|
||||||
|
|
||||||
#endif /* !_NET80211_IEEE80211_HOSTAP_H_ */
|
#endif /* !_NET80211_IEEE80211_HOSTAP_H_ */
|
||||||
|
@ -69,6 +69,8 @@ ieee80211_power_vattach(struct ieee80211vap *vap)
|
|||||||
vap->iv_update_ps = ieee80211_update_ps;
|
vap->iv_update_ps = ieee80211_update_ps;
|
||||||
vap->iv_set_tim = ieee80211_set_tim;
|
vap->iv_set_tim = ieee80211_set_tim;
|
||||||
}
|
}
|
||||||
|
vap->iv_node_ps = ieee80211_node_pwrsave;
|
||||||
|
vap->iv_sta_ps = ieee80211_sta_pwrsave;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
|
@ -71,6 +71,11 @@ void ieee80211_power_latevattach(struct ieee80211vap *);
|
|||||||
struct mbuf *ieee80211_node_psq_dequeue(struct ieee80211_node *ni, int *qlen);
|
struct mbuf *ieee80211_node_psq_dequeue(struct ieee80211_node *ni, int *qlen);
|
||||||
int ieee80211_node_psq_drain(struct ieee80211_node *);
|
int ieee80211_node_psq_drain(struct ieee80211_node *);
|
||||||
int ieee80211_node_psq_age(struct ieee80211_node *);
|
int ieee80211_node_psq_age(struct ieee80211_node *);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Don't call these directly from the stack; they are vap methods
|
||||||
|
* that should be overridden.
|
||||||
|
*/
|
||||||
int ieee80211_pwrsave(struct ieee80211_node *, struct mbuf *);
|
int ieee80211_pwrsave(struct ieee80211_node *, struct mbuf *);
|
||||||
void ieee80211_node_pwrsave(struct ieee80211_node *, int enable);
|
void ieee80211_node_pwrsave(struct ieee80211_node *, int enable);
|
||||||
void ieee80211_sta_pwrsave(struct ieee80211vap *, int enable);
|
void ieee80211_sta_pwrsave(struct ieee80211vap *, int enable);
|
||||||
|
@ -866,7 +866,7 @@ scan_task(void *arg, int pending)
|
|||||||
vap->iv_state == IEEE80211_S_RUN) {
|
vap->iv_state == IEEE80211_S_RUN) {
|
||||||
if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
|
if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) {
|
||||||
/* Enable station power save mode */
|
/* Enable station power save mode */
|
||||||
ieee80211_sta_pwrsave(vap, 1);
|
vap->iv_sta_ps(vap, 1);
|
||||||
/*
|
/*
|
||||||
* Use an 1ms delay so the null data frame has a chance
|
* Use an 1ms delay so the null data frame has a chance
|
||||||
* to go out.
|
* to go out.
|
||||||
@ -1047,7 +1047,7 @@ done:
|
|||||||
* waiting for us.
|
* waiting for us.
|
||||||
*/
|
*/
|
||||||
if (scandone) {
|
if (scandone) {
|
||||||
ieee80211_sta_pwrsave(vap, 0);
|
vap->iv_sta_ps(vap, 0);
|
||||||
if (ss->ss_next >= ss->ss_last) {
|
if (ss->ss_next >= ss->ss_last) {
|
||||||
ieee80211_notify_scan_done(vap);
|
ieee80211_notify_scan_done(vap);
|
||||||
ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
|
ic->ic_flags_ext &= ~IEEE80211_FEXT_BGSCAN;
|
||||||
|
@ -402,7 +402,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
|
arg == IEEE80211_FC0_SUBTYPE_ASSOC_RESP);
|
||||||
break;
|
break;
|
||||||
case IEEE80211_S_SLEEP:
|
case IEEE80211_S_SLEEP:
|
||||||
ieee80211_sta_pwrsave(vap, 0);
|
vap->iv_sta_ps(vap, 0);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
goto invalid;
|
goto invalid;
|
||||||
@ -438,7 +438,7 @@ sta_newstate(struct ieee80211vap *vap, enum ieee80211_state nstate, int arg)
|
|||||||
goto invalid;
|
goto invalid;
|
||||||
break;
|
break;
|
||||||
case IEEE80211_S_SLEEP:
|
case IEEE80211_S_SLEEP:
|
||||||
ieee80211_sta_pwrsave(vap, 1);
|
vap->iv_sta_ps(vap, 1);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
invalid:
|
invalid:
|
||||||
@ -1396,7 +1396,7 @@ sta_recv_mgmt(struct ieee80211_node *ni, struct mbuf *m0,
|
|||||||
* we are expecting data.
|
* we are expecting data.
|
||||||
*/
|
*/
|
||||||
ic->ic_lastdata = ticks;
|
ic->ic_lastdata = ticks;
|
||||||
ieee80211_sta_pwrsave(vap, 0);
|
vap->iv_sta_ps(vap, 0);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
ni->ni_dtim_count = tim->tim_count;
|
ni->ni_dtim_count = tim->tim_count;
|
||||||
|
@ -486,6 +486,11 @@ struct ieee80211vap {
|
|||||||
/* power save handling */
|
/* power save handling */
|
||||||
void (*iv_update_ps)(struct ieee80211vap *, int);
|
void (*iv_update_ps)(struct ieee80211vap *, int);
|
||||||
int (*iv_set_tim)(struct ieee80211_node *, int);
|
int (*iv_set_tim)(struct ieee80211_node *, int);
|
||||||
|
void (*iv_node_ps)(struct ieee80211_node *, int);
|
||||||
|
void (*iv_sta_ps)(struct ieee80211vap *, int);
|
||||||
|
void (*iv_recv_pspoll)(struct ieee80211_node *,
|
||||||
|
struct mbuf *);
|
||||||
|
|
||||||
/* state machine processing */
|
/* state machine processing */
|
||||||
int (*iv_newstate)(struct ieee80211vap *,
|
int (*iv_newstate)(struct ieee80211vap *,
|
||||||
enum ieee80211_state, int);
|
enum ieee80211_state, int);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user