diff options
Diffstat (limited to 'net/mac80211/iface.c')
| -rw-r--r-- | net/mac80211/iface.c | 35 | 
1 files changed, 19 insertions, 16 deletions
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c index baaa8608e52..3bfe2612c8c 100644 --- a/net/mac80211/iface.c +++ b/net/mac80211/iface.c @@ -349,21 +349,19 @@ static void ieee80211_set_default_queues(struct ieee80211_sub_if_data *sdata)  static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)  {  	struct ieee80211_sub_if_data *sdata; -	int ret = 0; +	int ret;  	if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))  		return 0; -	mutex_lock(&local->iflist_mtx); +	ASSERT_RTNL();  	if (local->monitor_sdata) -		goto out_unlock; +		return 0;  	sdata = kzalloc(sizeof(*sdata) + local->hw.vif_data_size, GFP_KERNEL); -	if (!sdata) { -		ret = -ENOMEM; -		goto out_unlock; -	} +	if (!sdata) +		return -ENOMEM;  	/* set up data */  	sdata->local = local; @@ -377,13 +375,13 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)  	if (WARN_ON(ret)) {  		/* ok .. stupid driver, it asked for this! */  		kfree(sdata); -		goto out_unlock; +		return ret;  	}  	ret = ieee80211_check_queues(sdata);  	if (ret) {  		kfree(sdata); -		goto out_unlock; +		return ret;  	}  	ret = ieee80211_vif_use_channel(sdata, &local->monitor_chandef, @@ -391,13 +389,14 @@ static int ieee80211_add_virtual_monitor(struct ieee80211_local *local)  	if (ret) {  		drv_remove_interface(local, sdata);  		kfree(sdata); -		goto out_unlock; +		return ret;  	} +	mutex_lock(&local->iflist_mtx);  	rcu_assign_pointer(local->monitor_sdata, sdata); - out_unlock:  	mutex_unlock(&local->iflist_mtx); -	return ret; + +	return 0;  }  static void ieee80211_del_virtual_monitor(struct ieee80211_local *local) @@ -407,14 +406,20 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)  	if (!(local->hw.flags & IEEE80211_HW_WANT_MONITOR_VIF))  		return; +	ASSERT_RTNL(); +  	mutex_lock(&local->iflist_mtx);  	sdata = rcu_dereference_protected(local->monitor_sdata,  					  lockdep_is_held(&local->iflist_mtx)); -	if (!sdata) -		goto out_unlock; +	if (!sdata) { +		mutex_unlock(&local->iflist_mtx); +		return; +	}  	rcu_assign_pointer(local->monitor_sdata, NULL); +	mutex_unlock(&local->iflist_mtx); +  	synchronize_net();  	ieee80211_vif_release_channel(sdata); @@ -422,8 +427,6 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)  	drv_remove_interface(local, sdata);  	kfree(sdata); - out_unlock: -	mutex_unlock(&local->iflist_mtx);  }  /*  |