Commit c4382d5c authored by Emmanuel Grumbach's avatar Emmanuel Grumbach Committed by Johannes Berg
Browse files

wifi: mac80211: update the right link for tx power



Stop looking at deflink and start using the actual link.
Initialize the power settings upon link init.

Signed-off-by: default avatarEmmanuel Grumbach <emmanuel.grumbach@intel.com>
Signed-off-by: default avatarMiri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20241007144851.2685dab8e1ab.I1d82cbdb2dda020aee4a225bd9a134f7d82dd810@changeid


Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 0b7392ee
Loading
Loading
Loading
Loading
+59 −35
Original line number Diff line number Diff line
@@ -3061,9 +3061,25 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
	enum nl80211_tx_power_setting txp_type = type;
	bool update_txp_type = false;
	bool has_monitor = false;
	int user_power_level;

	lockdep_assert_wiphy(local->hw.wiphy);

	switch (type) {
	case NL80211_TX_POWER_AUTOMATIC:
		user_power_level = IEEE80211_UNSET_POWER_LEVEL;
		txp_type = NL80211_TX_POWER_LIMITED;
		break;
	case NL80211_TX_POWER_LIMITED:
	case NL80211_TX_POWER_FIXED:
		if (mbm < 0 || (mbm % 100))
			return -EOPNOTSUPP;
		user_power_level = MBM_TO_DBM(mbm);
		break;
	default:
		return -EINVAL;
	}

	if (wdev) {
		sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);

@@ -3077,57 +3093,65 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
				return -EOPNOTSUPP;
		}

		switch (type) {
		case NL80211_TX_POWER_AUTOMATIC:
			sdata->deflink.user_power_level =
				IEEE80211_UNSET_POWER_LEVEL;
			txp_type = NL80211_TX_POWER_LIMITED;
			break;
		case NL80211_TX_POWER_LIMITED:
		case NL80211_TX_POWER_FIXED:
			if (mbm < 0 || (mbm % 100))
				return -EOPNOTSUPP;
			sdata->deflink.user_power_level = MBM_TO_DBM(mbm);
			break;
		}
		for (int link_id = 0;
		     link_id < ARRAY_SIZE(sdata->link);
		     link_id++) {
			struct ieee80211_link_data *link =
				wiphy_dereference(wiphy, sdata->link[link_id]);

		if (txp_type != sdata->vif.bss_conf.txpower_type) {
			if (!link)
				continue;

			link->user_power_level = user_power_level;

			if (txp_type != link->conf->txpower_type) {
				update_txp_type = true;
			sdata->vif.bss_conf.txpower_type = txp_type;
				link->conf->txpower_type = txp_type;
			}

		ieee80211_recalc_txpower(&sdata->deflink, update_txp_type);

			ieee80211_recalc_txpower(link, update_txp_type);
		}
		return 0;
	}

	switch (type) {
	case NL80211_TX_POWER_AUTOMATIC:
		local->user_power_level = IEEE80211_UNSET_POWER_LEVEL;
		txp_type = NL80211_TX_POWER_LIMITED;
		break;
	case NL80211_TX_POWER_LIMITED:
	case NL80211_TX_POWER_FIXED:
		if (mbm < 0 || (mbm % 100))
			return -EOPNOTSUPP;
		local->user_power_level = MBM_TO_DBM(mbm);
		break;
	}
	local->user_power_level = user_power_level;

	list_for_each_entry(sdata, &local->interfaces, list) {
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
			has_monitor = true;
			continue;
		}
		sdata->deflink.user_power_level = local->user_power_level;
		if (txp_type != sdata->vif.bss_conf.txpower_type)

		for (int link_id = 0;
		     link_id < ARRAY_SIZE(sdata->link);
		     link_id++) {
			struct ieee80211_link_data *link =
				wiphy_dereference(wiphy, sdata->link[link_id]);

			if (!link)
				continue;

			link->user_power_level = local->user_power_level;
			if (txp_type != link->conf->txpower_type)
				update_txp_type = true;
		sdata->vif.bss_conf.txpower_type = txp_type;
			link->conf->txpower_type = txp_type;
		}
	}
	list_for_each_entry(sdata, &local->interfaces, list) {
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
			continue;
		ieee80211_recalc_txpower(&sdata->deflink, update_txp_type);

		for (int link_id = 0;
		     link_id < ARRAY_SIZE(sdata->link);
		     link_id++) {
			struct ieee80211_link_data *link =
				wiphy_dereference(wiphy, sdata->link[link_id]);

			if (!link)
				continue;

			ieee80211_recalc_txpower(link, update_txp_type);
		}
	}

	if (has_monitor) {
+2 −2
Original line number Diff line number Diff line
@@ -905,7 +905,7 @@ static int ieee80211_assign_link_chanctx(struct ieee80211_link_data *link,
	}

	if (new_ctx && ieee80211_chanctx_num_assigned(local, new_ctx) > 0) {
		ieee80211_recalc_txpower(&sdata->deflink, false);
		ieee80211_recalc_txpower(link, false);
		ieee80211_recalc_chanctx_min_def(local, new_ctx, NULL, false);
	}

@@ -1712,7 +1712,7 @@ static int ieee80211_vif_use_reserved_switch(struct ieee80211_local *local)
								  link,
								  changed);

			ieee80211_recalc_txpower(&sdata->deflink, false);
			ieee80211_recalc_txpower(link, false);
		}

		ieee80211_recalc_chanctx_chantype(local, ctx);
+8 −12
Original line number Diff line number Diff line
@@ -46,12 +46,11 @@ static void ieee80211_iface_work(struct wiphy *wiphy, struct wiphy_work *work);

bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link)
{
	struct ieee80211_sub_if_data *sdata = link->sdata;
	struct ieee80211_chanctx_conf *chanctx_conf;
	int power;

	rcu_read_lock();
	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
	chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
	if (!chanctx_conf) {
		rcu_read_unlock();
		return false;
@@ -60,15 +59,15 @@ bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link)
	power = ieee80211_chandef_max_power(&chanctx_conf->def);
	rcu_read_unlock();

	if (sdata->deflink.user_power_level != IEEE80211_UNSET_POWER_LEVEL)
		power = min(power, sdata->deflink.user_power_level);
	if (link->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
		power = min(power, link->user_power_level);

	if (sdata->deflink.ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
		power = min(power, sdata->deflink.ap_power_level);
	if (link->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
		power = min(power, link->ap_power_level);

	if (power != sdata->vif.bss_conf.txpower) {
		sdata->vif.bss_conf.txpower = power;
		ieee80211_hw_config(sdata->local, 0);
	if (power != link->conf->txpower) {
		link->conf->txpower = power;
		ieee80211_hw_config(link->sdata->local, 0);
		return true;
	}

@@ -2177,9 +2176,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,

	ieee80211_set_default_queues(sdata);

	sdata->deflink.ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
	sdata->deflink.user_power_level = local->user_power_level;

	/* setup type-dependent data */
	ieee80211_setup_sdata(sdata, type);

+3 −0
Original line number Diff line number Diff line
@@ -36,6 +36,9 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
	link->conf = link_conf;
	link_conf->link_id = link_id;
	link_conf->vif = &sdata->vif;
	link->ap_power_level = IEEE80211_UNSET_POWER_LEVEL;
	link->user_power_level = sdata->local->user_power_level;
	link_conf->txpower = INT_MIN;

	wiphy_work_init(&link->csa.finalize_work,
			ieee80211_csa_finalize_work);