From 42f52da0d189dd01767d36d907e5af512d5ba3f5 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Wed, 11 Jul 2012 16:38:09 +0200 Subject: [PATCH] --- yaml --- r: 315547 b: refs/heads/master c: 685fb72b63faf09a767cc28332545f5830b91be8 h: refs/heads/master i: 315545: 46f2ff05639249f2b677e7314adf52675c4d6152 315543: 7ee5085a9815d59673646bf30780f0ae0c24b053 v: v3 --- [refs] | 2 +- trunk/net/mac80211/iface.c | 29 +++++++++++++++++++---------- trunk/net/mac80211/util.c | 9 +++++++++ 3 files changed, 29 insertions(+), 11 deletions(-) diff --git a/[refs] b/[refs] index 137c3736f988..8f69874f0269 100644 --- a/[refs] +++ b/[refs] @@ -1,2 +1,2 @@ --- -refs/heads/master: 8e95ea49c94908cb10e698c5637d57f0fbdc796d +refs/heads/master: 685fb72b63faf09a767cc28332545f5830b91be8 diff --git a/trunk/net/mac80211/iface.c b/trunk/net/mac80211/iface.c index e3c49748ce8f..334ee0fb18ca 100644 --- a/trunk/net/mac80211/iface.c +++ b/trunk/net/mac80211/iface.c @@ -334,17 +334,21 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata) int ieee80211_add_virtual_monitor(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; - int ret; + int ret = 0; if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) return 0; + mutex_lock(&local->iflist_mtx); + if (local->monitor_sdata) - return 0; + goto out_unlock; sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); - if (!sdata) - return -ENOMEM; + if (!sdata) { + ret = -ENOMEM; + goto out_unlock; + } /* set up data */ sdata->local = local; @@ -358,18 +362,19 @@ int ieee80211_add_virtual_monitor(struct ieee80211_local *local) if (WARN_ON(ret)) { /* ok .. stupid driver, it asked for this! */ kfree(sdata); - return ret; + goto out_unlock; } ret = ieee80211_check_queues(sdata); if (ret) { kfree(sdata); - return ret; + goto out_unlock; } rcu_assign_pointer(local->monitor_sdata, sdata); - - return 0; + out_unlock: + mutex_unlock(&local->iflist_mtx); + return ret; } void ieee80211_del_virtual_monitor(struct ieee80211_local *local) @@ -379,10 +384,12 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF)) return; - sdata = rtnl_dereference(local->monitor_sdata); + mutex_lock(&local->iflist_mtx); + sdata = rcu_dereference_protected(local->monitor_sdata, + lockdep_is_held(&local->iflist_mtx)); if (!sdata) - return; + goto out_unlock; rcu_assign_pointer(local->monitor_sdata, NULL); synchronize_net(); @@ -390,6 +397,8 @@ void ieee80211_del_virtual_monitor(struct ieee80211_local *local) drv_remove_interface(local, sdata); kfree(sdata); + out_unlock: + mutex_unlock(&local->iflist_mtx); } /* diff --git a/trunk/net/mac80211/util.c b/trunk/net/mac80211/util.c index 596db0c2a113..39b82fee4904 100644 --- a/trunk/net/mac80211/util.c +++ b/trunk/net/mac80211/util.c @@ -529,6 +529,11 @@ void ieee80211_iterate_active_interfaces( &sdata->vif); } + sdata = rcu_dereference_protected(local->monitor_sdata, + lockdep_is_held(&local->iflist_mtx)); + if (sdata) + iterator(data, sdata->vif.addr, &sdata->vif); + mutex_unlock(&local->iflist_mtx); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces); @@ -557,6 +562,10 @@ void ieee80211_iterate_active_interfaces_atomic( &sdata->vif); } + sdata = rcu_dereference(local->monitor_sdata); + if (sdata) + iterator(data, sdata->vif.addr, &sdata->vif); + rcu_read_unlock(); } EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);