mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	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: Emmanuel Grumbach <emmanuel.grumbach@intel.com> Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com> Link: https://patch.msgid.link/20241007144851.2685dab8e1ab.I1d82cbdb2dda020aee4a225bd9a134f7d82dd810@changeid Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
		
							parent
							
								
									0b7392ee3b
								
							
						
					
					
						commit
						c4382d5ca1
					
				
					 4 changed files with 74 additions and 51 deletions
				
			
		| 
						 | 
					@ -3061,9 +3061,25 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 | 
				
			||||||
	enum nl80211_tx_power_setting txp_type = type;
 | 
						enum nl80211_tx_power_setting txp_type = type;
 | 
				
			||||||
	bool update_txp_type = false;
 | 
						bool update_txp_type = false;
 | 
				
			||||||
	bool has_monitor = false;
 | 
						bool has_monitor = false;
 | 
				
			||||||
 | 
						int user_power_level;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	lockdep_assert_wiphy(local->hw.wiphy);
 | 
						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) {
 | 
						if (wdev) {
 | 
				
			||||||
		sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 | 
							sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3077,57 +3093,65 @@ static int ieee80211_set_tx_power(struct wiphy *wiphy,
 | 
				
			||||||
				return -EOPNOTSUPP;
 | 
									return -EOPNOTSUPP;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		switch (type) {
 | 
							for (int link_id = 0;
 | 
				
			||||||
		case NL80211_TX_POWER_AUTOMATIC:
 | 
							     link_id < ARRAY_SIZE(sdata->link);
 | 
				
			||||||
			sdata->deflink.user_power_level =
 | 
							     link_id++) {
 | 
				
			||||||
				IEEE80211_UNSET_POWER_LEVEL;
 | 
								struct ieee80211_link_data *link =
 | 
				
			||||||
			txp_type = NL80211_TX_POWER_LIMITED;
 | 
									wiphy_dereference(wiphy, sdata->link[link_id]);
 | 
				
			||||||
			break;
 | 
					
 | 
				
			||||||
		case NL80211_TX_POWER_LIMITED:
 | 
								if (!link)
 | 
				
			||||||
		case NL80211_TX_POWER_FIXED:
 | 
									continue;
 | 
				
			||||||
			if (mbm < 0 || (mbm % 100))
 | 
					
 | 
				
			||||||
				return -EOPNOTSUPP;
 | 
								link->user_power_level = user_power_level;
 | 
				
			||||||
			sdata->deflink.user_power_level = MBM_TO_DBM(mbm);
 | 
					
 | 
				
			||||||
			break;
 | 
								if (txp_type != link->conf->txpower_type) {
 | 
				
			||||||
 | 
									update_txp_type = true;
 | 
				
			||||||
 | 
									link->conf->txpower_type = txp_type;
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								ieee80211_recalc_txpower(link, update_txp_type);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					 | 
				
			||||||
		if (txp_type != sdata->vif.bss_conf.txpower_type) {
 | 
					 | 
				
			||||||
			update_txp_type = true;
 | 
					 | 
				
			||||||
			sdata->vif.bss_conf.txpower_type = txp_type;
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		ieee80211_recalc_txpower(&sdata->deflink, update_txp_type);
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
		return 0;
 | 
							return 0;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	switch (type) {
 | 
						local->user_power_level = user_power_level;
 | 
				
			||||||
	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;
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
						list_for_each_entry(sdata, &local->interfaces, list) {
 | 
				
			||||||
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
							if (sdata->vif.type == NL80211_IFTYPE_MONITOR) {
 | 
				
			||||||
			has_monitor = true;
 | 
								has_monitor = true;
 | 
				
			||||||
			continue;
 | 
								continue;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		sdata->deflink.user_power_level = local->user_power_level;
 | 
					
 | 
				
			||||||
		if (txp_type != sdata->vif.bss_conf.txpower_type)
 | 
							for (int link_id = 0;
 | 
				
			||||||
			update_txp_type = true;
 | 
							     link_id < ARRAY_SIZE(sdata->link);
 | 
				
			||||||
		sdata->vif.bss_conf.txpower_type = txp_type;
 | 
							     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;
 | 
				
			||||||
 | 
								link->conf->txpower_type = txp_type;
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	list_for_each_entry(sdata, &local->interfaces, list) {
 | 
						list_for_each_entry(sdata, &local->interfaces, list) {
 | 
				
			||||||
		if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
 | 
							if (sdata->vif.type == NL80211_IFTYPE_MONITOR)
 | 
				
			||||||
			continue;
 | 
								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) {
 | 
						if (has_monitor) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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) {
 | 
						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);
 | 
							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,
 | 
													  link,
 | 
				
			||||||
								  changed);
 | 
													  changed);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
			ieee80211_recalc_txpower(&sdata->deflink, false);
 | 
								ieee80211_recalc_txpower(link, false);
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		ieee80211_recalc_chanctx_chantype(local, ctx);
 | 
							ieee80211_recalc_chanctx_chantype(local, ctx);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -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)
 | 
					bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct ieee80211_sub_if_data *sdata = link->sdata;
 | 
					 | 
				
			||||||
	struct ieee80211_chanctx_conf *chanctx_conf;
 | 
						struct ieee80211_chanctx_conf *chanctx_conf;
 | 
				
			||||||
	int power;
 | 
						int power;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	rcu_read_lock();
 | 
						rcu_read_lock();
 | 
				
			||||||
	chanctx_conf = rcu_dereference(sdata->vif.bss_conf.chanctx_conf);
 | 
						chanctx_conf = rcu_dereference(link->conf->chanctx_conf);
 | 
				
			||||||
	if (!chanctx_conf) {
 | 
						if (!chanctx_conf) {
 | 
				
			||||||
		rcu_read_unlock();
 | 
							rcu_read_unlock();
 | 
				
			||||||
		return false;
 | 
							return false;
 | 
				
			||||||
| 
						 | 
					@ -60,15 +59,15 @@ bool __ieee80211_recalc_txpower(struct ieee80211_link_data *link)
 | 
				
			||||||
	power = ieee80211_chandef_max_power(&chanctx_conf->def);
 | 
						power = ieee80211_chandef_max_power(&chanctx_conf->def);
 | 
				
			||||||
	rcu_read_unlock();
 | 
						rcu_read_unlock();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdata->deflink.user_power_level != IEEE80211_UNSET_POWER_LEVEL)
 | 
						if (link->user_power_level != IEEE80211_UNSET_POWER_LEVEL)
 | 
				
			||||||
		power = min(power, sdata->deflink.user_power_level);
 | 
							power = min(power, link->user_power_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (sdata->deflink.ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
 | 
						if (link->ap_power_level != IEEE80211_UNSET_POWER_LEVEL)
 | 
				
			||||||
		power = min(power, sdata->deflink.ap_power_level);
 | 
							power = min(power, link->ap_power_level);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (power != sdata->vif.bss_conf.txpower) {
 | 
						if (power != link->conf->txpower) {
 | 
				
			||||||
		sdata->vif.bss_conf.txpower = power;
 | 
							link->conf->txpower = power;
 | 
				
			||||||
		ieee80211_hw_config(sdata->local, 0);
 | 
							ieee80211_hw_config(link->sdata->local, 0);
 | 
				
			||||||
		return true;
 | 
							return true;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2177,9 +2176,6 @@ int ieee80211_if_add(struct ieee80211_local *local, const char *name,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	ieee80211_set_default_queues(sdata);
 | 
						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 */
 | 
						/* setup type-dependent data */
 | 
				
			||||||
	ieee80211_setup_sdata(sdata, type);
 | 
						ieee80211_setup_sdata(sdata, type);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,9 @@ void ieee80211_link_init(struct ieee80211_sub_if_data *sdata,
 | 
				
			||||||
	link->conf = link_conf;
 | 
						link->conf = link_conf;
 | 
				
			||||||
	link_conf->link_id = link_id;
 | 
						link_conf->link_id = link_id;
 | 
				
			||||||
	link_conf->vif = &sdata->vif;
 | 
						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,
 | 
						wiphy_work_init(&link->csa.finalize_work,
 | 
				
			||||||
			ieee80211_csa_finalize_work);
 | 
								ieee80211_csa_finalize_work);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in a new issue