/* * Timer check on whether the VAP has had any transmit activity. * * This may schedule a transition from _RUN -> _SLEEP if it's appropriate. */ void ieee80211_sta_ps_timer_check(struct ieee80211vap *vap) { struct ieee80211com *ic = vap->iv_ic; /* XXX lock assert */ /* For no, only do this in STA mode */ if (! (vap->iv_caps & IEEE80211_C_SWSLEEP)) goto out; if (vap->iv_opmode != IEEE80211_M_STA) goto out; /* If we're not at run state, bail */ if (vap->iv_state != IEEE80211_S_RUN) goto out; IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, "%s: lastdata=%llu, ticks=%llu\n", __func__, (unsigned long long) ic->ic_lastdata, (unsigned long long) ticks); /* If powersave is disabled on the VAP, don't bother */ if (! (vap->iv_flags & IEEE80211_F_PMGTON)) goto out; /* If we've done any data within our idle interval, bail */ /* XXX hard-coded to one second for now, ew! */ if (ieee80211_time_after(ic->ic_lastdata + 500, ticks)) goto out; /* * Signify we're going into power save and transition the * node to powersave. */ if ((vap->iv_bss->ni_flags & IEEE80211_NODE_PWR_MGT) == 0) vap->iv_sta_ps(vap, 1); /* * XXX The driver has to handle the fact that we're going * to sleep but frames may still be transmitted; * hopefully it and/or us will do the right thing and mark any * transmitted frames with PWRMGT set to 1. */ ieee80211_new_state_locked(vap, IEEE80211_S_SLEEP, 0); IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, "%s: time delta=%d msec\n", __func__, (int) ticks_to_msecs(ticks - ic->ic_lastdata)); out: return; }
/* * Handle being notified that we have data available for us in a TIM/ATIM. * * This may schedule a transition from _SLEEP -> _RUN if it's appropriate. */ void ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set) { /* * Schedule the driver state change. It'll happen at some point soon. * Since the hardware shouldn't know that we're running just yet * (and thus tell the peer that we're awake before we actually wake * up said hardware), we leave the actual node state transition * up to the transition to RUN. * * XXX TODO: verify that the transition to RUN will wake up the * BSS node! */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, "%s: TIM=%d\n", __func__, set); if (set == 1 && vap->iv_state == IEEE80211_S_SLEEP) { ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0); } }
/* * Handle being notified that we have data available for us in a TIM/ATIM. * * This may schedule a transition from _SLEEP -> _RUN if it's appropriate. * * In STA mode, we may have put to sleep during scan and need to be dragged * back out of powersave mode. */ void ieee80211_sta_tim_notify(struct ieee80211vap *vap, int set) { struct ieee80211com *ic = vap->iv_ic; /* * Schedule the driver state change. It'll happen at some point soon. * Since the hardware shouldn't know that we're running just yet * (and thus tell the peer that we're awake before we actually wake * up said hardware), we leave the actual node state transition * up to the transition to RUN. * * XXX TODO: verify that the transition to RUN will wake up the * BSS node! */ IEEE80211_LOCK(vap->iv_ic); if (set == 1 && vap->iv_state == IEEE80211_S_SLEEP) { ieee80211_new_state_locked(vap, IEEE80211_S_RUN, 0); IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, "%s: TIM=%d; wakeup\n", __func__, set); } else if ((set == 1) && (ic->ic_flags_ext & IEEE80211_FEXT_BGSCAN)) { /* * XXX only do this if we're in RUN state? */ IEEE80211_DPRINTF(vap, IEEE80211_MSG_POWER, "%s: wake up from bgscan vap sleep\n", __func__); /* * We may be in BGSCAN mode - this means the VAP is is in STA * mode powersave. If it is, we need to wake it up so we * can process outbound traffic. */ vap->iv_sta_ps(vap, 0); } IEEE80211_UNLOCK(vap->iv_ic); }