diff options
Diffstat (limited to 'net/mac80211/link.c')
| -rw-r--r-- | net/mac80211/link.c | 28 | 
1 files changed, 23 insertions, 5 deletions
diff --git a/net/mac80211/link.c b/net/mac80211/link.c index 685ec66b4264..af0321408a97 100644 --- a/net/mac80211/link.c +++ b/net/mac80211/link.c @@ -358,7 +358,7 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,  		ieee80211_teardown_tdls_peers(link); -		ieee80211_link_release_channel(link); +		__ieee80211_link_release_channel(link, true);  	}  	list_for_each_entry(sta, &local->sta_list, list) { @@ -404,9 +404,24 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,  		link = sdata_dereference(sdata->link[link_id], sdata); -		ret = ieee80211_link_use_channel(link, -						 &link->conf->chanreq, -						 IEEE80211_CHANCTX_SHARED); +		/* +		 * This call really should not fail. Unfortunately, it appears +		 * that this may happen occasionally with some drivers. Should +		 * it happen, we are stuck in a bad place as going backwards is +		 * not really feasible. +		 * +		 * So lets just tell link_use_channel that it must not fail to +		 * assign the channel context (from mac80211's perspective) and +		 * assume the driver is going to trigger a recovery flow if it +		 * had a failure. +		 * That really is not great nor guaranteed to work. But at least +		 * the internal mac80211 state remains consistent and there is +		 * a chance that we can recover. +		 */ +		ret = _ieee80211_link_use_channel(link, +						  &link->conf->chanreq, +						  IEEE80211_CHANCTX_SHARED, +						  true);  		WARN_ON_ONCE(ret);  		ieee80211_mgd_set_link_qos_params(link); @@ -450,10 +465,13 @@ int ieee80211_set_active_links(struct ieee80211_vif *vif, u16 active_links)  	if (WARN_ON(!active_links))  		return -EINVAL; +	old_active = sdata->vif.active_links; +	if (old_active == active_links) +		return 0; +  	if (!drv_can_activate_links(local, sdata, active_links))  		return -EINVAL; -	old_active = sdata->vif.active_links;  	if (old_active & active_links) {  		/*  		 * if there's at least one link that stays active across  |