forked from mirrors/linux
		
	wifi: mac80211: Support disabled links during association
When the association is complete, do not configure disabled links, and track them as part of the interface data. Signed-off-by: Ilan Peer <ilan.peer@intel.com> Signed-off-by: Gregory Greenman <gregory.greenman@intel.com> Link: https://lore.kernel.org/r/20230608163202.c194fabeb81a.Iaefdef5ba0492afe9a5ede14c68060a4af36e444@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									d5a17cfb98
								
							
						
					
					
						commit
						6d543b34db
					
				
					 5 changed files with 53 additions and 32 deletions
				
			
		| 
						 | 
					@ -1846,6 +1846,8 @@ struct ieee80211_vif_cfg {
 | 
				
			||||||
 * @active_links: The bitmap of active links, or 0 for non-MLO.
 | 
					 * @active_links: The bitmap of active links, or 0 for non-MLO.
 | 
				
			||||||
 *	The driver shouldn't change this directly, but use the
 | 
					 *	The driver shouldn't change this directly, but use the
 | 
				
			||||||
 *	API calls meant for that purpose.
 | 
					 *	API calls meant for that purpose.
 | 
				
			||||||
 | 
					 * @dormant_links: bitmap of valid but disabled links, or 0 for non-MLO.
 | 
				
			||||||
 | 
					 *	Must be a subset of valid_links.
 | 
				
			||||||
 * @addr: address of this interface
 | 
					 * @addr: address of this interface
 | 
				
			||||||
 * @p2p: indicates whether this AP or STA interface is a p2p
 | 
					 * @p2p: indicates whether this AP or STA interface is a p2p
 | 
				
			||||||
 *	interface, i.e. a GO or p2p-sta respectively
 | 
					 *	interface, i.e. a GO or p2p-sta respectively
 | 
				
			||||||
| 
						 | 
					@ -1883,7 +1885,7 @@ struct ieee80211_vif {
 | 
				
			||||||
	struct ieee80211_vif_cfg cfg;
 | 
						struct ieee80211_vif_cfg cfg;
 | 
				
			||||||
	struct ieee80211_bss_conf bss_conf;
 | 
						struct ieee80211_bss_conf bss_conf;
 | 
				
			||||||
	struct ieee80211_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
						struct ieee80211_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
				
			||||||
	u16 valid_links, active_links;
 | 
						u16 valid_links, active_links, dormant_links;
 | 
				
			||||||
	u8 addr[ETH_ALEN] __aligned(2);
 | 
						u8 addr[ETH_ALEN] __aligned(2);
 | 
				
			||||||
	bool p2p;
 | 
						bool p2p;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1916,7 +1918,7 @@ struct ieee80211_vif {
 | 
				
			||||||
 */
 | 
					 */
 | 
				
			||||||
static inline u16 ieee80211_vif_usable_links(const struct ieee80211_vif *vif)
 | 
					static inline u16 ieee80211_vif_usable_links(const struct ieee80211_vif *vif)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	return vif->valid_links;
 | 
						return vif->valid_links & ~vif->dormant_links;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/**
 | 
					/**
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4868,7 +4868,7 @@ static int ieee80211_add_intf_link(struct wiphy *wiphy,
 | 
				
			||||||
		return -EOPNOTSUPP;
 | 
							return -EOPNOTSUPP;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&sdata->local->mtx);
 | 
						mutex_lock(&sdata->local->mtx);
 | 
				
			||||||
	res = ieee80211_vif_set_links(sdata, wdev->valid_links);
 | 
						res = ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
 | 
				
			||||||
	mutex_unlock(&sdata->local->mtx);
 | 
						mutex_unlock(&sdata->local->mtx);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return res;
 | 
						return res;
 | 
				
			||||||
| 
						 | 
					@ -4881,7 +4881,7 @@ static void ieee80211_del_intf_link(struct wiphy *wiphy,
 | 
				
			||||||
	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 | 
						struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&sdata->local->mtx);
 | 
						mutex_lock(&sdata->local->mtx);
 | 
				
			||||||
	ieee80211_vif_set_links(sdata, wdev->valid_links);
 | 
						ieee80211_vif_set_links(sdata, wdev->valid_links, 0);
 | 
				
			||||||
	mutex_unlock(&sdata->local->mtx);
 | 
						mutex_unlock(&sdata->local->mtx);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -410,6 +410,8 @@ struct ieee80211_mgd_assoc_data {
 | 
				
			||||||
		ieee80211_conn_flags_t conn_flags;
 | 
							ieee80211_conn_flags_t conn_flags;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		u16 status;
 | 
							u16 status;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bool disabled;
 | 
				
			||||||
	} link[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
						} link[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	u8 ap_addr[ETH_ALEN] __aligned(2);
 | 
						u8 ap_addr[ETH_ALEN] __aligned(2);
 | 
				
			||||||
| 
						 | 
					@ -2019,7 +2021,7 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			 struct ieee80211_bss_conf *link_conf);
 | 
								 struct ieee80211_bss_conf *link_conf);
 | 
				
			||||||
void ieee80211_link_stop(struct ieee80211_link_data *link);
 | 
					void ieee80211_link_stop(struct ieee80211_link_data *link);
 | 
				
			||||||
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
 | 
					int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			    u16 new_links);
 | 
								    u16 new_links, u16 dormant_links);
 | 
				
			||||||
void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata);
 | 
					void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
/* tx handling */
 | 
					/* tx handling */
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -142,25 +142,34 @@ static int ieee80211_check_dup_link_addrs(struct ieee80211_sub_if_data *sdata)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata,
 | 
					static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
					    u16 links)
 | 
										    u16 valid_links, u16 dormant_links)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	sdata->vif.valid_links = links;
 | 
						sdata->vif.valid_links = valid_links;
 | 
				
			||||||
 | 
						sdata->vif.dormant_links = dormant_links;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (!links) {
 | 
						if (!valid_links ||
 | 
				
			||||||
 | 
						    WARN((~valid_links & dormant_links) ||
 | 
				
			||||||
 | 
							 !(valid_links & ~dormant_links),
 | 
				
			||||||
 | 
							 "Invalid links: valid=0x%x, dormant=0x%x",
 | 
				
			||||||
 | 
							 valid_links, dormant_links)) {
 | 
				
			||||||
		sdata->vif.active_links = 0;
 | 
							sdata->vif.active_links = 0;
 | 
				
			||||||
 | 
							sdata->vif.dormant_links = 0;
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (sdata->vif.type) {
 | 
						switch (sdata->vif.type) {
 | 
				
			||||||
	case NL80211_IFTYPE_AP:
 | 
						case NL80211_IFTYPE_AP:
 | 
				
			||||||
		/* in an AP all links are always active */
 | 
							/* in an AP all links are always active */
 | 
				
			||||||
		sdata->vif.active_links = links;
 | 
							sdata->vif.active_links = valid_links;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/* AP links are not expected to be disabled */
 | 
				
			||||||
 | 
							WARN_ON(dormant_links);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	case NL80211_IFTYPE_STATION:
 | 
						case NL80211_IFTYPE_STATION:
 | 
				
			||||||
		if (sdata->vif.active_links)
 | 
							if (sdata->vif.active_links)
 | 
				
			||||||
			break;
 | 
								break;
 | 
				
			||||||
		WARN_ON(hweight16(links) > 1);
 | 
							sdata->vif.active_links = valid_links & ~dormant_links;
 | 
				
			||||||
		sdata->vif.active_links = links;
 | 
							WARN_ON(hweight16(sdata->vif.active_links) > 1);
 | 
				
			||||||
		break;
 | 
							break;
 | 
				
			||||||
	default:
 | 
						default:
 | 
				
			||||||
		WARN_ON(1);
 | 
							WARN_ON(1);
 | 
				
			||||||
| 
						 | 
					@ -169,7 +178,7 @@ static void ieee80211_set_vif_links_bitmaps(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
 | 
					static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
				      struct link_container **to_free,
 | 
									      struct link_container **to_free,
 | 
				
			||||||
				      u16 new_links)
 | 
									      u16 new_links, u16 dormant_links)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	u16 old_links = sdata->vif.valid_links;
 | 
						u16 old_links = sdata->vif.valid_links;
 | 
				
			||||||
	u16 old_active = sdata->vif.active_links;
 | 
						u16 old_active = sdata->vif.active_links;
 | 
				
			||||||
| 
						 | 
					@ -245,7 +254,7 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		/* for keys we will not be able to undo this */
 | 
							/* for keys we will not be able to undo this */
 | 
				
			||||||
		ieee80211_tear_down_links(sdata, to_free, rem);
 | 
							ieee80211_tear_down_links(sdata, to_free, rem);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ieee80211_set_vif_links_bitmaps(sdata, new_links);
 | 
							ieee80211_set_vif_links_bitmaps(sdata, new_links, dormant_links);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* tell the driver */
 | 
							/* tell the driver */
 | 
				
			||||||
		ret = drv_change_vif_links(sdata->local, sdata,
 | 
							ret = drv_change_vif_links(sdata->local, sdata,
 | 
				
			||||||
| 
						 | 
					@ -258,7 +267,7 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		/* restore config */
 | 
							/* restore config */
 | 
				
			||||||
		memcpy(sdata->link, old_data, sizeof(old_data));
 | 
							memcpy(sdata->link, old_data, sizeof(old_data));
 | 
				
			||||||
		memcpy(sdata->vif.link_conf, old, sizeof(old));
 | 
							memcpy(sdata->vif.link_conf, old, sizeof(old));
 | 
				
			||||||
		ieee80211_set_vif_links_bitmaps(sdata, old_links);
 | 
							ieee80211_set_vif_links_bitmaps(sdata, old_links, dormant_links);
 | 
				
			||||||
		/* and free (only) the newly allocated links */
 | 
							/* and free (only) the newly allocated links */
 | 
				
			||||||
		memset(to_free, 0, sizeof(links));
 | 
							memset(to_free, 0, sizeof(links));
 | 
				
			||||||
		goto free;
 | 
							goto free;
 | 
				
			||||||
| 
						 | 
					@ -282,12 +291,13 @@ static int ieee80211_vif_update_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
 | 
					int ieee80211_vif_set_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			    u16 new_links)
 | 
								    u16 new_links, u16 dormant_links)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
						struct link_container *links[IEEE80211_MLD_MAX_NUM_LINKS];
 | 
				
			||||||
	int ret;
 | 
						int ret;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ret = ieee80211_vif_update_links(sdata, links, new_links);
 | 
						ret = ieee80211_vif_update_links(sdata, links, new_links,
 | 
				
			||||||
 | 
										 dormant_links);
 | 
				
			||||||
	ieee80211_free_links(sdata, links);
 | 
						ieee80211_free_links(sdata, links);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return ret;
 | 
						return ret;
 | 
				
			||||||
| 
						 | 
					@ -304,7 +314,7 @@ void ieee80211_vif_clear_links(struct ieee80211_sub_if_data *sdata)
 | 
				
			||||||
	 */
 | 
						 */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sdata_lock(sdata);
 | 
						sdata_lock(sdata);
 | 
				
			||||||
	ieee80211_vif_update_links(sdata, links, 0);
 | 
						ieee80211_vif_update_links(sdata, links, 0, 0);
 | 
				
			||||||
	sdata_unlock(sdata);
 | 
						sdata_unlock(sdata);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ieee80211_free_links(sdata, links);
 | 
						ieee80211_free_links(sdata, links);
 | 
				
			||||||
| 
						 | 
					@ -328,7 +338,6 @@ static int _ieee80211_set_active_links(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 | 
						if (sdata->vif.type != NL80211_IFTYPE_STATION)
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* cannot activate links that don't exist */
 | 
					 | 
				
			||||||
	if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
 | 
						if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -484,7 +493,6 @@ void ieee80211_set_active_links_async(struct ieee80211_vif *vif,
 | 
				
			||||||
	if (sdata->vif.type != NL80211_IFTYPE_STATION)
 | 
						if (sdata->vif.type != NL80211_IFTYPE_STATION)
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* cannot activate links that don't exist */
 | 
					 | 
				
			||||||
	if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
 | 
						if (active_links & ~ieee80211_vif_usable_links(&sdata->vif))
 | 
				
			||||||
		return;
 | 
							return;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2818,6 +2818,10 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		    assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
 | 
							    assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if (ieee80211_vif_is_mld(&sdata->vif) &&
 | 
				
			||||||
 | 
							    !(ieee80211_vif_usable_links(&sdata->vif) & BIT(link_id)))
 | 
				
			||||||
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		link = sdata_dereference(sdata->link[link_id], sdata);
 | 
							link = sdata_dereference(sdata->link[link_id], sdata);
 | 
				
			||||||
		if (WARN_ON(!link))
 | 
							if (WARN_ON(!link))
 | 
				
			||||||
			return;
 | 
								return;
 | 
				
			||||||
| 
						 | 
					@ -2844,6 +2848,8 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
			struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
 | 
								struct cfg80211_bss *cbss = assoc_data->link[link_id].bss;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (!cbss ||
 | 
								if (!cbss ||
 | 
				
			||||||
 | 
								    !(BIT(link_id) &
 | 
				
			||||||
 | 
								      ieee80211_vif_usable_links(&sdata->vif)) ||
 | 
				
			||||||
			    assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
 | 
								    assoc_data->link[link_id].status != WLAN_STATUS_SUCCESS)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3058,7 +3064,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	memset(sdata->vif.bss_conf.tx_pwr_env, 0,
 | 
						memset(sdata->vif.bss_conf.tx_pwr_env, 0,
 | 
				
			||||||
	       sizeof(sdata->vif.bss_conf.tx_pwr_env));
 | 
						       sizeof(sdata->vif.bss_conf.tx_pwr_env));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ieee80211_vif_set_links(sdata, 0);
 | 
						ieee80211_vif_set_links(sdata, 0, 0);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
 | 
					static void ieee80211_reset_ap_probe(struct ieee80211_sub_if_data *sdata)
 | 
				
			||||||
| 
						 | 
					@ -3511,7 +3517,7 @@ static void ieee80211_destroy_auth_data(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mutex_lock(&sdata->local->mtx);
 | 
							mutex_lock(&sdata->local->mtx);
 | 
				
			||||||
		ieee80211_link_release_channel(&sdata->deflink);
 | 
							ieee80211_link_release_channel(&sdata->deflink);
 | 
				
			||||||
		ieee80211_vif_set_links(sdata, 0);
 | 
							ieee80211_vif_set_links(sdata, 0, 0);
 | 
				
			||||||
		mutex_unlock(&sdata->local->mtx);
 | 
							mutex_unlock(&sdata->local->mtx);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3570,7 +3576,7 @@ static void ieee80211_destroy_assoc_data(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		mutex_lock(&sdata->local->mtx);
 | 
							mutex_lock(&sdata->local->mtx);
 | 
				
			||||||
		ieee80211_link_release_channel(&sdata->deflink);
 | 
							ieee80211_link_release_channel(&sdata->deflink);
 | 
				
			||||||
		ieee80211_vif_set_links(sdata, 0);
 | 
							ieee80211_vif_set_links(sdata, 0, 0);
 | 
				
			||||||
		mutex_unlock(&sdata->local->mtx);
 | 
							mutex_unlock(&sdata->local->mtx);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4979,7 +4985,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	unsigned int link_id;
 | 
						unsigned int link_id;
 | 
				
			||||||
	struct sta_info *sta;
 | 
						struct sta_info *sta;
 | 
				
			||||||
	u64 changed[IEEE80211_MLD_MAX_NUM_LINKS] = {};
 | 
						u64 changed[IEEE80211_MLD_MAX_NUM_LINKS] = {};
 | 
				
			||||||
	u16 valid_links = 0;
 | 
						u16 valid_links = 0, dormant_links = 0;
 | 
				
			||||||
	int err;
 | 
						int err;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	mutex_lock(&sdata->local->sta_mtx);
 | 
						mutex_lock(&sdata->local->sta_mtx);
 | 
				
			||||||
| 
						 | 
					@ -4995,16 +5001,18 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
 | 
							for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
 | 
				
			||||||
			if (!assoc_data->link[link_id].bss)
 | 
								if (!assoc_data->link[link_id].bss)
 | 
				
			||||||
				continue;
 | 
									continue;
 | 
				
			||||||
			valid_links |= BIT(link_id);
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
			if (link_id != assoc_data->assoc_link_id) {
 | 
								valid_links |= BIT(link_id);
 | 
				
			||||||
 | 
								if (assoc_data->link[link_id].disabled) {
 | 
				
			||||||
 | 
									dormant_links |= BIT(link_id);
 | 
				
			||||||
 | 
								} else if (link_id != assoc_data->assoc_link_id) {
 | 
				
			||||||
				err = ieee80211_sta_allocate_link(sta, link_id);
 | 
									err = ieee80211_sta_allocate_link(sta, link_id);
 | 
				
			||||||
				if (err)
 | 
									if (err)
 | 
				
			||||||
					goto out_err;
 | 
										goto out_err;
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ieee80211_vif_set_links(sdata, valid_links);
 | 
							ieee80211_vif_set_links(sdata, valid_links, dormant_links);
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
 | 
						for (link_id = 0; link_id < IEEE80211_MLD_MAX_NUM_LINKS; link_id++) {
 | 
				
			||||||
| 
						 | 
					@ -5012,7 +5020,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		struct ieee80211_link_data *link;
 | 
							struct ieee80211_link_data *link;
 | 
				
			||||||
		struct link_sta_info *link_sta;
 | 
							struct link_sta_info *link_sta;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if (!cbss)
 | 
							if (!cbss || assoc_data->link[link_id].disabled)
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		link = sdata_dereference(sdata->link[link_id], sdata);
 | 
							link = sdata_dereference(sdata->link[link_id], sdata);
 | 
				
			||||||
| 
						 | 
					@ -5084,7 +5092,7 @@ static bool ieee80211_assoc_success(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/* links might have changed due to rejected ones, set them again */
 | 
						/* links might have changed due to rejected ones, set them again */
 | 
				
			||||||
	ieee80211_vif_set_links(sdata, valid_links);
 | 
						ieee80211_vif_set_links(sdata, valid_links, dormant_links);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rate_control_rate_init(sta);
 | 
						rate_control_rate_init(sta);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6627,12 +6635,12 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		mlo = true;
 | 
							mlo = true;
 | 
				
			||||||
		if (WARN_ON(!ap_mld_addr))
 | 
							if (WARN_ON(!ap_mld_addr))
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		err = ieee80211_vif_set_links(sdata, BIT(link_id));
 | 
							err = ieee80211_vif_set_links(sdata, BIT(link_id), 0);
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		if (WARN_ON(ap_mld_addr))
 | 
							if (WARN_ON(ap_mld_addr))
 | 
				
			||||||
			return -EINVAL;
 | 
								return -EINVAL;
 | 
				
			||||||
		ap_mld_addr = cbss->bssid;
 | 
							ap_mld_addr = cbss->bssid;
 | 
				
			||||||
		err = ieee80211_vif_set_links(sdata, 0);
 | 
							err = ieee80211_vif_set_links(sdata, 0, 0);
 | 
				
			||||||
		link_id = 0;
 | 
							link_id = 0;
 | 
				
			||||||
		mlo = false;
 | 
							mlo = false;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -6784,7 +6792,7 @@ static int ieee80211_prep_connection(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
out_err:
 | 
					out_err:
 | 
				
			||||||
	ieee80211_link_release_channel(&sdata->deflink);
 | 
						ieee80211_link_release_channel(&sdata->deflink);
 | 
				
			||||||
	ieee80211_vif_set_links(sdata, 0);
 | 
						ieee80211_vif_set_links(sdata, 0, 0);
 | 
				
			||||||
	return err;
 | 
						return err;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7324,10 +7332,11 @@ int ieee80211_mgd_assoc(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
		for (i = 0; i < ARRAY_SIZE(assoc_data->link); i++) {
 | 
							for (i = 0; i < ARRAY_SIZE(assoc_data->link); i++) {
 | 
				
			||||||
			assoc_data->link[i].conn_flags = conn_flags;
 | 
								assoc_data->link[i].conn_flags = conn_flags;
 | 
				
			||||||
			assoc_data->link[i].bss = req->links[i].bss;
 | 
								assoc_data->link[i].bss = req->links[i].bss;
 | 
				
			||||||
 | 
								assoc_data->link[i].disabled = req->links[i].disabled;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		/* if there was no authentication, set up the link */
 | 
							/* if there was no authentication, set up the link */
 | 
				
			||||||
		err = ieee80211_vif_set_links(sdata, BIT(assoc_link_id));
 | 
							err = ieee80211_vif_set_links(sdata, BIT(assoc_link_id), 0);
 | 
				
			||||||
		if (err)
 | 
							if (err)
 | 
				
			||||||
			goto err_clear;
 | 
								goto err_clear;
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue