Commit d8675a63 authored by Johannes Berg's avatar Johannes Berg
Browse files

wifi: mac80211: RCU-ify link/link_conf pointers



Since links can be added and removed dynamically, we need to
somehow protect the sdata->link[] and vif->link_conf[] array
pointers from disappearing when accessing them without locks.
RCU-ify the pointers to achieve this, which requires quite a
bit of rework.

Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 3d1cc7cd
Loading
Loading
Loading
Loading
+9 −5
Original line number Diff line number Diff line
@@ -1477,9 +1477,10 @@ static void mac80211_hwsim_tx_iter(void *_data, u8 *addr,
	int i;

	for (i = 0; i < ARRAY_SIZE(vif->link_conf); i++) {
		struct ieee80211_bss_conf *conf = vif->link_conf[i];
		struct ieee80211_bss_conf *conf;
		struct ieee80211_chanctx_conf *chanctx;

		conf = rcu_dereference(vif->link_conf[i]);
		if (!conf)
			continue;

@@ -1917,7 +1918,7 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,
{
	struct mac80211_hwsim_link_data *link_data = arg;
	u32 link_id = link_data->link_id;
	struct ieee80211_bss_conf *link_conf = vif->link_conf[link_id];
	struct ieee80211_bss_conf *link_conf;
	struct mac80211_hwsim_data *data =
		container_of(link_data, struct mac80211_hwsim_data,
			     link_data[link_id]);
@@ -1931,6 +1932,10 @@ static void mac80211_hwsim_beacon_tx(void *arg, u8 *mac,

	hwsim_check_magic(vif);

	link_conf = rcu_dereference(vif->link_conf[link_id]);
	if (!link_conf)
		return;

	if (vif->type != NL80211_IFTYPE_AP &&
	    vif->type != NL80211_IFTYPE_MESH_POINT &&
	    vif->type != NL80211_IFTYPE_ADHOC &&
@@ -2155,12 +2160,11 @@ static void mac80211_hwsim_vif_info_changed(struct ieee80211_hw *hw,

static void mac80211_hwsim_link_info_changed(struct ieee80211_hw *hw,
					     struct ieee80211_vif *vif,
					     u32 link_id,
					     u64 changed)
					     struct ieee80211_bss_conf *info,
					     u32 link_id, u64 changed)
{
	struct hwsim_vif_priv *vp = (void *)vif->drv_priv;
	struct mac80211_hwsim_data *data = hw->priv;
	struct ieee80211_bss_conf *info = vif->link_conf[link_id];
	struct mac80211_hwsim_link_data *link_data = &data->link_data[link_id];

	hwsim_check_magic(vif);
+4 −2
Original line number Diff line number Diff line
@@ -1789,7 +1789,7 @@ struct ieee80211_vif {
	enum nl80211_iftype type;
	struct ieee80211_vif_cfg cfg;
	struct ieee80211_bss_conf bss_conf;
	struct ieee80211_bss_conf *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
	struct ieee80211_bss_conf __rcu *link_conf[IEEE80211_MLD_MAX_NUM_LINKS];
	u16 valid_links;
	u8 addr[ETH_ALEN] __aligned(2);
	bool p2p;
@@ -4082,7 +4082,9 @@ struct ieee80211_ops {
				u64 changed);
	void (*link_info_changed)(struct ieee80211_hw *hw,
				  struct ieee80211_vif *vif,
				  unsigned int link_id, u64 changed);
				  struct ieee80211_bss_conf *info,
				  unsigned int link_id,
				  u64 changed);

	int (*start_ap)(struct ieee80211_hw *hw, struct ieee80211_vif *vif,
			unsigned int link_id);
+109 −60
Original line number Diff line number Diff line
@@ -39,7 +39,7 @@ static void ieee80211_set_mu_mimo_follow(struct ieee80211_sub_if_data *sdata,
		memcpy(sdata->vif.bss_conf.mu_group.position,
		       params->vht_mumimo_groups + WLAN_MEMBERSHIP_LEN,
		       WLAN_USER_POSITION_LEN);
		ieee80211_link_info_change_notify(sdata, 0,
		ieee80211_link_info_change_notify(sdata, &sdata->deflink,
						  BSS_CHANGED_MU_GROUPS);
		/* don't care about endianness - just check for 0 */
		memcpy(&membership, params->vht_mumimo_groups,
@@ -841,8 +841,8 @@ static int ieee80211_set_monitor_channel(struct wiphy *wiphy,
		sdata = wiphy_dereference(local->hw.wiphy,
					  local->monitor_sdata);
		if (sdata) {
			ieee80211_link_release_channel(sdata->link[0]);
			ret = ieee80211_link_use_channel(sdata->link[0],
			ieee80211_link_release_channel(&sdata->deflink);
			ret = ieee80211_link_use_channel(&sdata->deflink,
							 chandef,
							 IEEE80211_CHANCTX_EXCLUSIVE);
		}
@@ -1008,6 +1008,7 @@ ieee80211_copy_mbssid_beacon(u8 *pos, struct cfg80211_mbssid_elems *dst,
}

static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
				   struct ieee80211_link_data *link,
				   struct cfg80211_beacon_data *params,
				   const struct ieee80211_csa_settings *csa,
				   const struct ieee80211_color_change_settings *cca)
@@ -1017,9 +1018,7 @@ static int ieee80211_assign_beacon(struct ieee80211_sub_if_data *sdata,
	int new_head_len, new_tail_len;
	int size, err;
	u32 changed = BSS_CHANGED_BEACON;
	struct ieee80211_link_data *link = sdata->link[params->link_id];
	struct ieee80211_bss_conf *link_conf =
		sdata->vif.link_conf[params->link_id];
	struct ieee80211_bss_conf *link_conf = link->conf;

	old = sdata_dereference(link->u.ap.beacon, sdata);

@@ -1153,8 +1152,14 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
	int i, err;
	int prev_beacon_int;
	unsigned int link_id = params->beacon.link_id;
	struct ieee80211_link_data *link = sdata->link[link_id];
	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
	struct ieee80211_link_data *link;
	struct ieee80211_bss_conf *link_conf;

	link = sdata_dereference(sdata->link[link_id], sdata);
	if (!link)
		return -ENOLINK;

	link_conf = link->conf;

	old = sdata_dereference(link->u.ap.beacon, sdata);
	if (old)
@@ -1264,7 +1269,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
	if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL))
		link_conf->beacon_tx_rate = params->beacon_rate;

	err = ieee80211_assign_beacon(sdata, &params->beacon, NULL, NULL);
	err = ieee80211_assign_beacon(sdata, link, &params->beacon, NULL, NULL);
	if (err < 0)
		goto error;
	changed |= err;
@@ -1300,7 +1305,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,

	ieee80211_recalc_dtim(local, sdata);
	ieee80211_vif_cfg_change_notify(sdata, BSS_CHANGED_SSID);
	ieee80211_link_info_change_notify(sdata, link_id, changed);
	ieee80211_link_info_change_notify(sdata, link, changed);

	netif_carrier_on(dev);
	list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
@@ -1320,25 +1325,30 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
				   struct cfg80211_beacon_data *params)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link;
	struct beacon_data *old;
	int err;
	struct ieee80211_bss_conf *link_conf =
		sdata->vif.link_conf[params->link_id];
	struct ieee80211_bss_conf *link_conf;

	sdata_assert_lock(sdata);

	link = sdata_dereference(sdata->link[params->link_id], sdata);
	if (!link)
		return -ENOLINK;

	link_conf = link->conf;

	/* don't allow changing the beacon while a countdown is in place - offset
	 * of channel switch counter may change
	 */
	if (link_conf->csa_active || link_conf->color_change_active)
		return -EBUSY;

	old = sdata_dereference(sdata->link[params->link_id]->u.ap.beacon,
				sdata);
	old = sdata_dereference(link->u.ap.beacon, sdata);
	if (!old)
		return -ENOENT;

	err = ieee80211_assign_beacon(sdata, params, NULL, NULL);
	err = ieee80211_assign_beacon(sdata, link, params, NULL, NULL);
	if (err < 0)
		return err;

@@ -1348,7 +1358,7 @@ static int ieee80211_change_beacon(struct wiphy *wiphy, struct net_device *dev,
		err |= BSS_CHANGED_HE_BSS_COLOR;
	}

	ieee80211_link_info_change_notify(sdata, params->link_id, err);
	ieee80211_link_info_change_notify(sdata, link, err);
	return 0;
}

@@ -1373,8 +1383,9 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
	struct fils_discovery_data *old_fils_discovery;
	struct unsol_bcast_probe_resp_data *old_unsol_bcast_probe_resp;
	struct cfg80211_chan_def chandef;
	struct ieee80211_link_data *link = sdata->link[link_id];
	struct ieee80211_bss_conf *link_conf = sdata->vif.link_conf[link_id];
	struct ieee80211_link_data *link =
		sdata_dereference(sdata->link[link_id], sdata);
	struct ieee80211_bss_conf *link_conf = link->conf;

	sdata_assert_lock(sdata);

@@ -1431,7 +1442,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev,
	sdata->beacon_rate_set = false;
	sdata->vif.cfg.ssid_len = 0;
	clear_bit(SDATA_STATE_OFFCHANNEL_BEACON_STOPPED, &sdata->state);
	ieee80211_link_info_change_notify(sdata, link_id,
	ieee80211_link_info_change_notify(sdata, link,
					  BSS_CHANGED_BEACON_ENABLED);

	if (sdata->wdev.cac_started) {
@@ -1589,14 +1600,16 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,
	struct ieee80211_supported_band *sband;
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	u32 link_id = params->link_id < 0 ? 0 : params->link_id;
	struct ieee80211_link_data *link =
		sdata_dereference(sdata->link[link_id], sdata);
	struct link_sta_info *link_sta =
		rcu_dereference_protected(sta->link[link_id],
					  lockdep_is_held(&local->sta_mtx));

	if (!link_sta)
	if (!link || !link_sta)
		return -EINVAL;

	sband = ieee80211_get_link_sband(sdata, link_id);
	sband = ieee80211_get_link_sband(link);
	if (!sband)
		return -EINVAL;

@@ -1616,7 +1629,7 @@ static int sta_link_apply_parameters(struct ieee80211_local *local,

	if (params->supported_rates &&
	    params->supported_rates_len) {
		ieee80211_parse_bitrates(&sdata->vif.link_conf[link_id]->chandef,
		ieee80211_parse_bitrates(&link->conf->chandef,
					 sband, params->supported_rates,
					 params->supported_rates_len,
					 &link_sta->pub->supp_rates[sband->band]);
@@ -1667,9 +1680,14 @@ static int sta_apply_parameters(struct ieee80211_local *local,
	struct ieee80211_sub_if_data *sdata = sta->sdata;
	u32 link_id = params->link_sta_params.link_id < 0 ?
		      0 : params->link_sta_params.link_id;
	struct ieee80211_link_data *link;
	u32 mask, set;

	sband = ieee80211_get_link_sband(sdata, link_id);
	link = sdata_dereference(sdata->link[link_id], sdata);
	if (!link)
		return -ENOLINK;

	sband = ieee80211_get_link_sband(link);
	if (!sband)
		return -EINVAL;

@@ -1987,7 +2005,14 @@ static int ieee80211_change_station(struct wiphy *wiphy,
		}
	}

	/* we use sta_info_get_bss() so this might be different */
	if (sdata != sta->sdata) {
		mutex_lock_nested(&sta->sdata->wdev.mtx, 1);
		err = sta_apply_parameters(local, sta, params);
		mutex_unlock(&sta->sdata->wdev.mtx);
	} else {
		err = sta_apply_parameters(local, sta, params);
	}
	if (err)
		goto out_err;

@@ -2374,7 +2399,8 @@ static int ieee80211_update_mesh_config(struct wiphy *wiphy,
	if (_chg_mesh_attr(NL80211_MESHCONF_HT_OPMODE, mask)) {
		conf->ht_opmode = nconf->ht_opmode;
		sdata->vif.bss_conf.ht_operation_mode = nconf->ht_opmode;
		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_HT);
		ieee80211_link_info_change_notify(sdata, &sdata->deflink,
						  BSS_CHANGED_HT);
	}
	if (_chg_mesh_attr(NL80211_MESHCONF_HWMP_PATH_TO_ROOT_TIMEOUT, mask))
		conf->dot11MeshHWMPactivePathToRootTimeout =
@@ -2426,7 +2452,7 @@ static int ieee80211_join_mesh(struct wiphy *wiphy, struct net_device *dev,
	sdata->deflink.needed_rx_chains = sdata->local->rx_chains;

	mutex_lock(&sdata->local->mtx);
	err = ieee80211_link_use_channel(sdata->link[0], &setup->chandef,
	err = ieee80211_link_use_channel(&sdata->deflink, &setup->chandef,
					 IEEE80211_CHANCTX_SHARED);
	mutex_unlock(&sdata->local->mtx);
	if (err)
@@ -2441,7 +2467,7 @@ static int ieee80211_leave_mesh(struct wiphy *wiphy, struct net_device *dev)

	ieee80211_stop_mesh(sdata);
	mutex_lock(&sdata->local->mtx);
	ieee80211_link_release_channel(sdata->link[0]);
	ieee80211_link_release_channel(&sdata->deflink);
	kfree(sdata->u.mesh.ie);
	mutex_unlock(&sdata->local->mtx);

@@ -2529,7 +2555,7 @@ static int ieee80211_change_bss(struct wiphy *wiphy,
		changed |= BSS_CHANGED_P2P_PS;
	}

	ieee80211_link_info_change_notify(sdata, 0, changed);
	ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);

	return 0;
}
@@ -2570,7 +2596,8 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy,
		return -EINVAL;
	}

	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_QOS);
	ieee80211_link_info_change_notify(sdata, &sdata->deflink,
					  BSS_CHANGED_QOS);

	return 0;
}
@@ -2719,7 +2746,8 @@ static int ieee80211_set_mcast_rate(struct wiphy *wiphy, struct net_device *dev,
	memcpy(sdata->vif.bss_conf.mcast_rate, rate,
	       sizeof(int) * NUM_NL80211_BANDS);

	ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_MCAST_RATE);
	ieee80211_link_info_change_notify(sdata, &sdata->deflink,
					  BSS_CHANGED_MCAST_RATE);

	return 0;
}
@@ -2934,7 +2962,7 @@ static int ieee80211_testmode_dump(struct wiphy *wiphy,
#endif

int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
				 unsigned int link_id,
				 struct ieee80211_link_data *link,
				 enum ieee80211_smps_mode smps_mode)
{
	const u8 *ap;
@@ -2948,8 +2976,8 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
	if (WARN_ON_ONCE(sdata->vif.type != NL80211_IFTYPE_STATION))
		return -EINVAL;

	old_req = sdata->link[link_id]->u.mgd.req_smps;
	sdata->link[link_id]->u.mgd.req_smps = smps_mode;
	old_req = link->u.mgd.req_smps;
	link->u.mgd.req_smps = smps_mode;

	if (old_req == smps_mode &&
	    smps_mode != IEEE80211_SMPS_AUTOMATIC)
@@ -2961,10 +2989,10 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
	 * the new value until we associate.
	 */
	if (!sdata->u.mgd.associated ||
	    sdata->vif.link_conf[link_id]->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
	    link->conf->chandef.width == NL80211_CHAN_WIDTH_20_NOHT)
		return 0;

	ap = sdata->link[link_id]->u.mgd.bssid;
	ap = link->u.mgd.bssid;

	rcu_read_lock();
	list_for_each_entry_rcu(sta, &sdata->local->sta_list, list) {
@@ -2988,7 +3016,7 @@ int __ieee80211_request_smps_mgd(struct ieee80211_sub_if_data *sdata,
	err = ieee80211_send_smps_action(sdata, smps_mode,
					 ap, ap);
	if (err)
		sdata->link[link_id]->u.mgd.req_smps = old_req;
		link->u.mgd.req_smps = old_req;
	else if (smps_mode != IEEE80211_SMPS_OFF && tdls_peer_found)
		ieee80211_teardown_tdls_peers(sdata);

@@ -3018,10 +3046,14 @@ static int ieee80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
	/* no change, but if automatic follow powersave */
	sdata_lock(sdata);
	for (link_id = 0; link_id < ARRAY_SIZE(sdata->link); link_id++) {
		if (!sdata->link[link_id])
		struct ieee80211_link_data *link;

		link = sdata_dereference(sdata->link[link_id], sdata);

		if (!link)
			continue;
		__ieee80211_request_smps_mgd(sdata, link_id,
					     sdata->link[link_id]->u.mgd.req_smps);
		__ieee80211_request_smps_mgd(sdata, link,
					     link->u.mgd.req_smps);
	}
	sdata_unlock(sdata);

@@ -3060,7 +3092,8 @@ static int ieee80211_set_cqm_rssi_config(struct wiphy *wiphy,
	/* tell the driver upon association, unless already associated */
	if (sdata->u.mgd.associated &&
	    sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_CQM);
		ieee80211_link_info_change_notify(sdata, &sdata->deflink,
						  BSS_CHANGED_CQM);

	return 0;
}
@@ -3085,7 +3118,8 @@ static int ieee80211_set_cqm_rssi_range_config(struct wiphy *wiphy,
	/* tell the driver upon association, unless already associated */
	if (sdata->u.mgd.associated &&
	    sdata->vif.driver_flags & IEEE80211_VIF_SUPPORTS_CQM_RSSI)
		ieee80211_link_info_change_notify(sdata, 0, BSS_CHANGED_CQM);
		ieee80211_link_info_change_notify(sdata, &sdata->deflink,
						  BSS_CHANGED_CQM);

	return 0;
}
@@ -3177,7 +3211,7 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
	sdata->deflink.smps_mode = IEEE80211_SMPS_OFF;
	sdata->deflink.needed_rx_chains = local->rx_chains;

	err = ieee80211_link_use_channel(sdata->link[0], chandef,
	err = ieee80211_link_use_channel(&sdata->deflink, chandef,
					 IEEE80211_CHANCTX_SHARED);
	if (err)
		goto out_unlock;
@@ -3206,7 +3240,7 @@ static void ieee80211_end_cac(struct wiphy *wiphy,
		cancel_delayed_work(&sdata->deflink.dfs_cac_timer_work);

		if (sdata->wdev.cac_started) {
			ieee80211_link_release_channel(sdata->link[0]);
			ieee80211_link_release_channel(&sdata->deflink);
			sdata->wdev.cac_started = false;
		}
	}
@@ -3353,7 +3387,7 @@ static int ieee80211_set_after_csa_beacon(struct ieee80211_sub_if_data *sdata,
		if (!sdata->deflink.u.ap.next_beacon)
			return -EINVAL;

		err = ieee80211_assign_beacon(sdata,
		err = ieee80211_assign_beacon(sdata, &sdata->deflink,
					      sdata->deflink.u.ap.next_beacon,
					      NULL, NULL);
		ieee80211_free_next_beacon(&sdata->deflink);
@@ -3410,7 +3444,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
		if (sdata->deflink.reserved_ready)
			return 0;

		return ieee80211_link_use_reserved_context(sdata->link[0]);
		return ieee80211_link_use_reserved_context(&sdata->deflink);
	}

	if (!cfg80211_chandef_identical(&sdata->vif.bss_conf.chandef,
@@ -3423,7 +3457,7 @@ static int __ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
	if (err)
		return err;

	ieee80211_link_info_change_notify(sdata, 0, changed);
	ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);

	if (sdata->deflink.csa_block_tx) {
		ieee80211_wake_vif_queues(local, sdata,
@@ -3522,7 +3556,9 @@ static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
		csa.n_counter_offsets_presp = params->n_counter_offsets_presp;
		csa.count = params->count;

		err = ieee80211_assign_beacon(sdata, &params->beacon_csa, &csa, NULL);
		err = ieee80211_assign_beacon(sdata, &sdata->deflink,
					      &params->beacon_csa, &csa,
					      NULL);
		if (err < 0) {
			ieee80211_free_next_beacon(&sdata->deflink);
			return err;
@@ -3675,7 +3711,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
	if (err)
		goto out;

	err = ieee80211_link_reserve_chanctx(sdata->link[0], &params->chandef,
	err = ieee80211_link_reserve_chanctx(&sdata->deflink, &params->chandef,
					     chanctx->mode,
					     params->radar_required);
	if (err)
@@ -3684,7 +3720,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
	/* if reservation is invalid then this will fail */
	err = ieee80211_check_combinations(sdata, NULL, chanctx->mode, 0);
	if (err) {
		ieee80211_link_unreserve_chanctx(sdata->link[0]);
		ieee80211_link_unreserve_chanctx(&sdata->deflink);
		goto out;
	}

@@ -3694,7 +3730,7 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,

	err = ieee80211_set_csa_beacon(sdata, params, &changed);
	if (err) {
		ieee80211_link_unreserve_chanctx(sdata->link[0]);
		ieee80211_link_unreserve_chanctx(&sdata->deflink);
		goto out;
	}

@@ -3711,7 +3747,8 @@ __ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
					  params->count, params->block_tx);

	if (changed) {
		ieee80211_link_info_change_notify(sdata, 0, changed);
		ieee80211_link_info_change_notify(sdata, &sdata->deflink,
						  changed);
		drv_channel_switch_beacon(sdata, &params->chandef);
	} else {
		/* if the beacon didn't change, we can finalize immediately */
@@ -3950,12 +3987,19 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
	struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
	struct ieee80211_local *local = wiphy_priv(wiphy);
	struct ieee80211_chanctx_conf *chanctx_conf;
	struct ieee80211_link_data *link;
	int ret = -ENODATA;

	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.link_conf[link_id]->chanctx_conf);
	link = rcu_dereference(sdata->link[link_id]);
	if (!link) {
		ret = -ENOLINK;
		goto out;
	}

	chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
	if (chanctx_conf) {
		*chandef = sdata->vif.link_conf[link_id]->chandef;
		*chandef = link->conf->chandef;
		ret = 0;
	} else if (local->open_count > 0 &&
		   local->open_count == local->monitors &&
@@ -3966,6 +4010,7 @@ static int ieee80211_cfg_get_channel(struct wiphy *wiphy,
			*chandef = local->_oper_chandef;
		ret = 0;
	}
out:
	rcu_read_unlock();

	return ret;
@@ -4009,13 +4054,15 @@ static int ieee80211_set_ap_chanwidth(struct wiphy *wiphy,
				      struct cfg80211_chan_def *chandef)
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	struct ieee80211_link_data *link;
	int ret;
	u32 changed = 0;

	ret = ieee80211_link_change_bandwidth(sdata->link[link_id], chandef,
					      &changed);
	link = sdata_dereference(sdata->link[link_id], sdata);

	ret = ieee80211_link_change_bandwidth(link, chandef, &changed);
	if (ret == 0)
		ieee80211_link_info_change_notify(sdata, link_id, changed);
		ieee80211_link_info_change_notify(sdata, link, changed);

	return ret;
}
@@ -4358,7 +4405,7 @@ ieee80211_set_after_color_change_beacon(struct ieee80211_sub_if_data *sdata,
		if (!sdata->deflink.u.ap.next_beacon)
			return -EINVAL;

		ret = ieee80211_assign_beacon(sdata,
		ret = ieee80211_assign_beacon(sdata, &sdata->deflink,
					      sdata->deflink.u.ap.next_beacon,
					      NULL, NULL);
		ieee80211_free_next_beacon(&sdata->deflink);
@@ -4401,7 +4448,8 @@ ieee80211_set_color_change_beacon(struct ieee80211_sub_if_data *sdata,
			params->counter_offset_presp;
		color_change.count = params->count;

		err = ieee80211_assign_beacon(sdata, &params->beacon_color_change,
		err = ieee80211_assign_beacon(sdata, &sdata->deflink,
					      &params->beacon_color_change,
					      NULL, &color_change);
		if (err < 0) {
			ieee80211_free_next_beacon(&sdata->deflink);
@@ -4424,7 +4472,7 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
	sdata->vif.bss_conf.he_bss_color.enabled = enable;
	changed |= BSS_CHANGED_HE_BSS_COLOR;

	ieee80211_link_info_change_notify(sdata, 0, changed);
	ieee80211_link_info_change_notify(sdata, &sdata->deflink, changed);

	if (!sdata->vif.bss_conf.nontransmitted && sdata->vif.mbssid_tx_vif) {
		struct ieee80211_sub_if_data *child;
@@ -4434,7 +4482,8 @@ ieee80211_color_change_bss_config_notify(struct ieee80211_sub_if_data *sdata,
			if (child != sdata && child->vif.mbssid_tx_vif == &sdata->vif) {
				child->vif.bss_conf.he_bss_color.color = color;
				child->vif.bss_conf.he_bss_color.enabled = enable;
				ieee80211_link_info_change_notify(child, 0,
				ieee80211_link_info_change_notify(child,
								  &child->deflink,
								  BSS_CHANGED_HE_BSS_COLOR);
			}
		}
+66 −57

File changed.

Preview size limit exceeded, changes collapsed.

+1 −1
Original line number Diff line number Diff line
@@ -256,7 +256,7 @@ static int ieee80211_set_smps(struct ieee80211_sub_if_data *sdata,
		return -EOPNOTSUPP;

	sdata_lock(sdata);
	err = __ieee80211_request_smps_mgd(sdata, 0, smps_mode);
	err = __ieee80211_request_smps_mgd(sdata, &sdata->deflink, smps_mode);
	sdata_unlock(sdata);

	return err;
Loading