diff options
Diffstat (limited to 'net/wireless/scan.c')
| -rw-r--r-- | net/wireless/scan.c | 24 | 
1 files changed, 16 insertions, 8 deletions
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 674aadca007..fd99ea495b7 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -169,7 +169,7 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, bool leak)  	union iwreq_data wrqu;  #endif -	ASSERT_RDEV_LOCK(rdev); +	lockdep_assert_held(&rdev->sched_scan_mtx);  	request = rdev->scan_req; @@ -230,9 +230,9 @@ void __cfg80211_scan_done(struct work_struct *wk)  	rdev = container_of(wk, struct cfg80211_registered_device,  			    scan_done_wk); -	cfg80211_lock_rdev(rdev); +	mutex_lock(&rdev->sched_scan_mtx);  	___cfg80211_scan_done(rdev, false); -	cfg80211_unlock_rdev(rdev); +	mutex_unlock(&rdev->sched_scan_mtx);  }  void cfg80211_scan_done(struct cfg80211_scan_request *request, bool aborted) @@ -698,11 +698,6 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,  	found = rb_find_bss(dev, tmp, BSS_CMP_REGULAR);  	if (found) { -		found->pub.beacon_interval = tmp->pub.beacon_interval; -		found->pub.signal = tmp->pub.signal; -		found->pub.capability = tmp->pub.capability; -		found->ts = tmp->ts; -  		/* Update IEs */  		if (rcu_access_pointer(tmp->pub.proberesp_ies)) {  			const struct cfg80211_bss_ies *old; @@ -723,6 +718,8 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,  			if (found->pub.hidden_beacon_bss &&  			    !list_empty(&found->hidden_list)) { +				const struct cfg80211_bss_ies *f; +  				/*  				 * The found BSS struct is one of the probe  				 * response members of a group, but we're @@ -732,6 +729,10 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,  				 * SSID to showing it, which is confusing so  				 * drop this information.  				 */ + +				f = rcu_access_pointer(tmp->pub.beacon_ies); +				kfree_rcu((struct cfg80211_bss_ies *)f, +					  rcu_head);  				goto drop;  			} @@ -761,6 +762,11 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,  				kfree_rcu((struct cfg80211_bss_ies *)old,  					  rcu_head);  		} + +		found->pub.beacon_interval = tmp->pub.beacon_interval; +		found->pub.signal = tmp->pub.signal; +		found->pub.capability = tmp->pub.capability; +		found->ts = tmp->ts;  	} else {  		struct cfg80211_internal_bss *new;  		struct cfg80211_internal_bss *hidden; @@ -1056,6 +1062,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,  	if (IS_ERR(rdev))  		return PTR_ERR(rdev); +	mutex_lock(&rdev->sched_scan_mtx);  	if (rdev->scan_req) {  		err = -EBUSY;  		goto out; @@ -1162,6 +1169,7 @@ int cfg80211_wext_siwscan(struct net_device *dev,  		dev_hold(dev);  	}   out: +	mutex_unlock(&rdev->sched_scan_mtx);  	kfree(creq);  	cfg80211_unlock_rdev(rdev);  	return err;  |