mac80211: per interface idle notification

Sometimes we don't just need to know whether or
not the device is idle, but also per interface.
This adds that reporting capability to mac80211.

Signed-off-by: Johannes Berg <johannes.berg@intel.com>
Signed-off-by: John W. Linville <linville@tuxdriver.com>
This commit is contained in:
Johannes Berg
2010-08-05 17:02:38 +02:00
committed by John W. Linville
parent 1fdaa46e9f
commit 7da7cc1d42
7 changed files with 81 additions and 16 deletions

View File

@@ -309,7 +309,9 @@ static int ieee80211_open(struct net_device *dev)
if (sdata->flags & IEEE80211_SDATA_PROMISC)
atomic_inc(&local->iff_promiscs);
mutex_lock(&local->mtx);
hw_reconf_flags |= __ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
local->open_count++;
if (hw_reconf_flags) {
@@ -516,7 +518,9 @@ static int ieee80211_stop(struct net_device *dev)
sdata->bss = NULL;
mutex_lock(&local->mtx);
hw_reconf_flags |= __ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
ieee80211_recalc_ps(local, -1);
@@ -1199,28 +1203,61 @@ u32 __ieee80211_recalc_idle(struct ieee80211_local *local)
{
struct ieee80211_sub_if_data *sdata;
int count = 0;
bool working = false, scanning = false;
struct ieee80211_work *wk;
if (!list_empty(&local->work_list))
return ieee80211_idle_off(local, "working");
if (local->scanning)
return ieee80211_idle_off(local, "scanning");
#ifdef CONFIG_PROVE_LOCKING
WARN_ON(debug_locks && !lockdep_rtnl_is_held() &&
!lockdep_is_held(&local->iflist_mtx));
#endif
lockdep_assert_held(&local->mtx);
list_for_each_entry(sdata, &local->interfaces, list) {
if (!ieee80211_sdata_running(sdata))
if (!ieee80211_sdata_running(sdata)) {
sdata->vif.bss_conf.idle = true;
continue;
}
sdata->old_idle = sdata->vif.bss_conf.idle;
/* do not count disabled managed interfaces */
if (sdata->vif.type == NL80211_IFTYPE_STATION &&
!sdata->u.mgd.associated)
!sdata->u.mgd.associated) {
sdata->vif.bss_conf.idle = true;
continue;
}
/* do not count unused IBSS interfaces */
if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
!sdata->u.ibss.ssid_len)
!sdata->u.ibss.ssid_len) {
sdata->vif.bss_conf.idle = true;
continue;
}
/* count everything else */
count++;
}
list_for_each_entry(wk, &local->work_list, list) {
working = true;
wk->sdata->vif.bss_conf.idle = false;
}
if (local->scan_sdata) {
scanning = true;
local->scan_sdata->vif.bss_conf.idle = false;
}
list_for_each_entry(sdata, &local->interfaces, list) {
if (sdata->old_idle == sdata->vif.bss_conf.idle)
continue;
if (!ieee80211_sdata_running(sdata))
continue;
ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_IDLE);
}
if (working)
return ieee80211_idle_off(local, "working");
if (scanning)
return ieee80211_idle_off(local, "scanning");
if (!count)
return ieee80211_idle_on(local);
else