Skip to content

Commit

Permalink
mac80211: per interface idle notification
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Johannes Berg authored and John W. Linville committed Aug 16, 2010
1 parent 1fdaa46 commit 7da7cc1
Show file tree
Hide file tree
Showing 7 changed files with 81 additions and 16 deletions.
6 changes: 6 additions & 0 deletions include/net/mac80211.h
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,7 @@ struct ieee80211_low_level_stats {
* @BSS_CHANGED_ARP_FILTER: Hardware ARP filter address list or state changed.
* @BSS_CHANGED_QOS: QoS for this association was enabled/disabled. Note
* that it is only ever disabled for station mode.
* @BSS_CHANGED_IDLE: Idle changed for this BSS/interface.
*/
enum ieee80211_bss_change {
BSS_CHANGED_ASSOC = 1<<0,
Expand All @@ -165,6 +166,7 @@ enum ieee80211_bss_change {
BSS_CHANGED_IBSS = 1<<11,
BSS_CHANGED_ARP_FILTER = 1<<12,
BSS_CHANGED_QOS = 1<<13,
BSS_CHANGED_IDLE = 1<<14,

/* when adding here, make sure to change ieee80211_reconfig */
};
Expand Down Expand Up @@ -223,6 +225,9 @@ enum ieee80211_bss_change {
* hardware must not perform any ARP filtering. Note, that the filter will
* be enabled also in promiscuous mode.
* @qos: This is a QoS-enabled BSS.
* @idle: This interface is idle. There's also a global idle flag in the
* hardware config which may be more appropriate depending on what
* your driver/device needs to do.
*/
struct ieee80211_bss_conf {
const u8 *bssid;
Expand All @@ -247,6 +252,7 @@ struct ieee80211_bss_conf {
u8 arp_addr_cnt;
bool arp_filter_enabled;
bool qos;
bool idle;
};

/**
Expand Down
8 changes: 6 additions & 2 deletions net/mac80211/ibss.c
Original file line number Diff line number Diff line change
Expand Up @@ -920,12 +920,14 @@ int ieee80211_ibss_join(struct ieee80211_sub_if_data *sdata,
memcpy(sdata->u.ibss.ssid, params->ssid, IEEE80211_MAX_SSID_LEN);
sdata->u.ibss.ssid_len = params->ssid_len;

mutex_unlock(&sdata->u.ibss.mtx);

mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&sdata->local->mtx);

ieee80211_queue_work(&sdata->local->hw, &sdata->work);

mutex_unlock(&sdata->u.ibss.mtx);

return 0;
}

Expand Down Expand Up @@ -980,7 +982,9 @@ int ieee80211_ibss_leave(struct ieee80211_sub_if_data *sdata)

mutex_unlock(&sdata->u.ibss.mtx);

mutex_lock(&local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&local->mtx);

return 0;
}
3 changes: 3 additions & 0 deletions net/mac80211/ieee80211_i.h
Original file line number Diff line number Diff line change
Expand Up @@ -497,6 +497,9 @@ struct ieee80211_sub_if_data {
*/
bool ht_opmode_valid;

/* to detect idle changes */
bool old_idle;

/* Fragment table for host-based reassembly */
struct ieee80211_fragment_entry fragments[IEEE80211_FRAGMENT_MAX];
unsigned int fragment_next;
Expand Down
53 changes: 45 additions & 8 deletions net/mac80211/iface.c
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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
Expand Down
17 changes: 15 additions & 2 deletions net/mac80211/mlme.c
Original file line number Diff line number Diff line change
Expand Up @@ -1103,8 +1103,11 @@ static void __ieee80211_connection_loss(struct ieee80211_sub_if_data *sdata)
printk(KERN_DEBUG "Connection to AP %pM lost.\n", bssid);

ieee80211_set_disassoc(sdata, true);
ieee80211_recalc_idle(local);
mutex_unlock(&ifmgd->mtx);

mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
/*
* must be outside lock due to cfg80211,
* but that's not a problem.
Expand Down Expand Up @@ -1173,7 +1176,9 @@ ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata,
sdata->name, bssid, reason_code);

ieee80211_set_disassoc(sdata, true);
mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&sdata->local->mtx);

return RX_MGMT_CFG80211_DEAUTH;
}
Expand Down Expand Up @@ -1203,7 +1208,9 @@ ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata,
sdata->name, mgmt->sa, reason_code);

ieee80211_set_disassoc(sdata, true);
mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&sdata->local->mtx);
return RX_MGMT_CFG80211_DISASSOC;
}

Expand Down Expand Up @@ -1840,8 +1847,10 @@ void ieee80211_sta_work(struct ieee80211_sub_if_data *sdata)
" after %dms, disconnecting.\n",
bssid, (1000 * IEEE80211_PROBE_WAIT)/HZ);
ieee80211_set_disassoc(sdata, true);
ieee80211_recalc_idle(local);
mutex_unlock(&ifmgd->mtx);
mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
/*
* must be outside lock due to cfg80211,
* but that's not a problem.
Expand Down Expand Up @@ -2319,7 +2328,9 @@ int ieee80211_mgd_deauth(struct ieee80211_sub_if_data *sdata,
if (assoc_bss)
sta_info_destroy_addr(sdata, bssid);

mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&sdata->local->mtx);

return 0;
}
Expand Down Expand Up @@ -2357,7 +2368,9 @@ int ieee80211_mgd_disassoc(struct ieee80211_sub_if_data *sdata,
cookie, !req->local_state_change);
sta_info_destroy_addr(sdata, bssid);

mutex_lock(&sdata->local->mtx);
ieee80211_recalc_idle(sdata->local);
mutex_unlock(&sdata->local->mtx);

return 0;
}
Expand Down
2 changes: 2 additions & 0 deletions net/mac80211/scan.c
Original file line number Diff line number Diff line change
Expand Up @@ -304,7 +304,9 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw, bool aborted)
ieee80211_offchannel_return(local, true);

done:
mutex_lock(&local->mtx);
ieee80211_recalc_idle(local);
mutex_unlock(&local->mtx);
ieee80211_mlme_notify_scan_completed(local);
ieee80211_ibss_notify_scan_completed(local);
ieee80211_mesh_notify_scan_completed(local);
Expand Down
8 changes: 4 additions & 4 deletions net/mac80211/work.c
Original file line number Diff line number Diff line change
Expand Up @@ -888,10 +888,10 @@ static void ieee80211_work_work(struct work_struct *work)
while ((skb = skb_dequeue(&local->work_skb_queue)))
ieee80211_work_rx_queued_mgmt(local, skb);

ieee80211_recalc_idle(local);

mutex_lock(&local->mtx);

ieee80211_recalc_idle(local);

list_for_each_entry_safe(wk, tmp, &local->work_list, list) {
bool started = wk->started;

Expand Down Expand Up @@ -1001,10 +1001,10 @@ static void ieee80211_work_work(struct work_struct *work)
&local->scan_work,
round_jiffies_relative(0));

mutex_unlock(&local->mtx);

ieee80211_recalc_idle(local);

mutex_unlock(&local->mtx);

list_for_each_entry_safe(wk, tmp, &free_work, list) {
wk->done(wk, NULL);
list_del(&wk->list);
Expand Down

0 comments on commit 7da7cc1

Please sign in to comment.