diff options
Diffstat (limited to 'net/wireless/util.c')
| -rw-r--r-- | net/wireless/util.c | 21 | 
1 files changed, 19 insertions, 2 deletions
| diff --git a/net/wireless/util.c b/net/wireless/util.c index 55d99466babb..316cfd00914f 100644 --- a/net/wireless/util.c +++ b/net/wireless/util.c @@ -804,7 +804,7 @@ int cfg80211_change_iface(struct cfg80211_registered_device *rdev,  	     ntype == NL80211_IFTYPE_P2P_CLIENT))  		return -EBUSY; -	if (ntype != otype) { +	if (ntype != otype && netif_running(dev)) {  		err = cfg80211_can_change_interface(rdev, dev->ieee80211_ptr,  						    ntype);  		if (err) @@ -935,6 +935,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,  				  enum nl80211_iftype iftype)  {  	struct wireless_dev *wdev_iter; +	u32 used_iftypes = BIT(iftype);  	int num[NUM_NL80211_IFTYPES];  	int total = 1;  	int i, j; @@ -961,6 +962,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,  		num[wdev_iter->iftype]++;  		total++; +		used_iftypes |= BIT(wdev_iter->iftype);  	}  	mutex_unlock(&rdev->devlist_mtx); @@ -970,6 +972,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,  	for (i = 0; i < rdev->wiphy.n_iface_combinations; i++) {  		const struct ieee80211_iface_combination *c;  		struct ieee80211_iface_limit *limits; +		u32 all_iftypes = 0;  		c = &rdev->wiphy.iface_combinations[i]; @@ -984,6 +987,7 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,  			if (rdev->wiphy.software_iftypes & BIT(iftype))  				continue;  			for (j = 0; j < c->n_limits; j++) { +				all_iftypes |= limits[j].types;  				if (!(limits[j].types & BIT(iftype)))  					continue;  				if (limits[j].max < num[iftype]) @@ -991,7 +995,20 @@ int cfg80211_can_change_interface(struct cfg80211_registered_device *rdev,  				limits[j].max -= num[iftype];  			}  		} -		/* yay, it fits */ + +		/* +		 * Finally check that all iftypes that we're currently +		 * using are actually part of this combination. If they +		 * aren't then we can't use this combination and have +		 * to continue to the next. +		 */ +		if ((all_iftypes & used_iftypes) != used_iftypes) +			goto cont; + +		/* +		 * This combination covered all interface types and +		 * supported the requested numbers, so we're good. +		 */  		kfree(limits);  		return 0;   cont: | 
