Commit ecb187a7 authored by Shayne Chen's avatar Shayne Chen Committed by Felix Fietkau
Browse files

mt76: mt7915: rework the flow of txpower setting



Clean up the flow of per-rate txpower limit setting to get rid of
duplicate work since it has already been handled by firmware, and set
proper max_power based on different channels and regdomains.

Signed-off-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 790d228a
Loading
Loading
Loading
Loading
+12 −22
Original line number Diff line number Diff line
@@ -299,8 +299,7 @@ mt7915_queues_read(struct seq_file *s, void *data)
}

static void
mt7915_puts_rate_txpower(struct seq_file *s, s8 *delta,
			 s8 txpower_cur, int band)
mt7915_puts_rate_txpower(struct seq_file *s, s8 txpower_cur, int band)
{
	static const char * const sku_group_name[] = {
		"CCK", "OFDM", "HT20", "HT40",
@@ -308,24 +307,18 @@ mt7915_puts_rate_txpower(struct seq_file *s, s8 *delta,
		"RU26", "RU52", "RU106", "RU242/SU20",
		"RU484/SU40", "RU996/SU80", "RU2x996/SU160"
	};
	s8 txpower[MT7915_SKU_RATE_NUM];
	s8 txpower[161];
	int i, idx = 0;

	for (i = 0; i < MT7915_SKU_RATE_NUM; i++)
		txpower[i] = DIV_ROUND_UP(txpower_cur + delta[i], 2);
	for (i = 0; i < ARRAY_SIZE(txpower); i++)
		txpower[i] = DIV_ROUND_UP(txpower_cur, 2);

	for (i = 0; i < MAX_SKU_RATE_GROUP_NUM; i++) {
		const struct sku_group *sku = &mt7915_sku_groups[i];
		u32 offset = sku->offset[band];

		if (!offset) {
			idx += sku->len;
			continue;
		}
	for (i = 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
		u8 len = mt7915_sku_group_len[i];

		mt76_seq_puts_array(s, sku_group_name[i],
				    txpower + idx, sku->len);
		idx += sku->len;
				    txpower + idx, len);
		idx += len;
	}
}

@@ -335,21 +328,18 @@ mt7915_read_rate_txpower(struct seq_file *s, void *data)
	struct mt7915_dev *dev = dev_get_drvdata(s->private);
	struct mt76_phy *mphy = &dev->mphy;
	enum nl80211_band band = mphy->chandef.chan->band;
	s8 *delta = dev->rate_power[band];
	s8 txpower_base = mphy->txpower_cur - delta[MT7915_SKU_MAX_DELTA_IDX];
	s8 txpower = mphy->txpower_cur;

	seq_puts(s, "Band 0:\n");
	mt7915_puts_rate_txpower(s, delta, txpower_base, band);
	mt7915_puts_rate_txpower(s, txpower, band);

	if (dev->mt76.phy2) {
		mphy = dev->mt76.phy2;
		band = mphy->chandef.chan->band;
		delta = dev->rate_power[band];
		txpower_base = mphy->txpower_cur -
			       delta[MT7915_SKU_MAX_DELTA_IDX];
		txpower = mphy->txpower_cur;

		seq_puts(s, "Band 1:\n");
		mt7915_puts_rate_txpower(s, delta, txpower_base, band);
		mt7915_puts_rate_txpower(s, txpower, band);
	}

	return 0;
+28 −110
Original line number Diff line number Diff line
@@ -170,120 +170,38 @@ int mt7915_eeprom_get_target_power(struct mt7915_dev *dev,
	return target_power;
}

static const u8 sku_cck_delta_map[] = {
	SKU_CCK_GROUP0,
	SKU_CCK_GROUP0,
	SKU_CCK_GROUP1,
	SKU_CCK_GROUP1,
};

static const u8 sku_ofdm_delta_map[] = {
	SKU_OFDM_GROUP0,
	SKU_OFDM_GROUP0,
	SKU_OFDM_GROUP1,
	SKU_OFDM_GROUP1,
	SKU_OFDM_GROUP2,
	SKU_OFDM_GROUP2,
	SKU_OFDM_GROUP3,
	SKU_OFDM_GROUP4,
};

static const u8 sku_mcs_delta_map[] = {
	SKU_MCS_GROUP0,
	SKU_MCS_GROUP1,
	SKU_MCS_GROUP1,
	SKU_MCS_GROUP2,
	SKU_MCS_GROUP2,
	SKU_MCS_GROUP3,
	SKU_MCS_GROUP4,
	SKU_MCS_GROUP5,
	SKU_MCS_GROUP6,
	SKU_MCS_GROUP7,
	SKU_MCS_GROUP8,
	SKU_MCS_GROUP9,
};

#define SKU_GROUP(_mode, _len, _ofs_2g, _ofs_5g, _map)	\
	[_mode] = {					\
	.len = _len,					\
	.offset = {					\
		_ofs_2g,				\
		_ofs_5g,				\
	},						\
	.delta_map = _map				\
}

const struct sku_group mt7915_sku_groups[] = {
	SKU_GROUP(SKU_CCK, 4, 0x252, 0, sku_cck_delta_map),
	SKU_GROUP(SKU_OFDM, 8, 0x254, 0x29d, sku_ofdm_delta_map),

	SKU_GROUP(SKU_HT_BW20, 8, 0x259, 0x2a2, sku_mcs_delta_map),
	SKU_GROUP(SKU_HT_BW40, 9, 0x262, 0x2ab, sku_mcs_delta_map),
	SKU_GROUP(SKU_VHT_BW20, 12, 0x259, 0x2a2, sku_mcs_delta_map),
	SKU_GROUP(SKU_VHT_BW40, 12, 0x262, 0x2ab, sku_mcs_delta_map),
	SKU_GROUP(SKU_VHT_BW80, 12, 0, 0x2b4, sku_mcs_delta_map),
	SKU_GROUP(SKU_VHT_BW160, 12, 0, 0, sku_mcs_delta_map),

	SKU_GROUP(SKU_HE_RU26, 12, 0x27f, 0x2dd, sku_mcs_delta_map),
	SKU_GROUP(SKU_HE_RU52, 12, 0x289, 0x2e7, sku_mcs_delta_map),
	SKU_GROUP(SKU_HE_RU106, 12, 0x293, 0x2f1, sku_mcs_delta_map),
	SKU_GROUP(SKU_HE_RU242, 12, 0x26b, 0x2bf, sku_mcs_delta_map),
	SKU_GROUP(SKU_HE_RU484, 12, 0x275, 0x2c9, sku_mcs_delta_map),
	SKU_GROUP(SKU_HE_RU996, 12, 0, 0x2d3, sku_mcs_delta_map),
	SKU_GROUP(SKU_HE_RU2x996, 12, 0, 0, sku_mcs_delta_map),
};

static s8
mt7915_get_sku_delta(struct mt7915_dev *dev, u32 addr)
{
	u32 val = mt7915_eeprom_read(dev, addr);
	s8 delta = FIELD_GET(SKU_DELTA_VAL, val);

	if (!(val & SKU_DELTA_EN))
		return 0;

	return val & SKU_DELTA_ADD ? delta : -delta;
}

static void
mt7915_eeprom_init_sku_band(struct mt7915_dev *dev,
			    struct ieee80211_supported_band *sband)
s8 mt7915_eeprom_get_power_delta(struct mt7915_dev *dev, int band)
{
	int i, band = sband->band;
	s8 *rate_power = dev->rate_power[band], max_delta = 0;
	u8 idx = 0;

	for (i = 0; i < ARRAY_SIZE(mt7915_sku_groups); i++) {
		const struct sku_group *sku = &mt7915_sku_groups[i];
		u32 offset = sku->offset[band];
		int j;

		if (!offset) {
			idx += sku->len;
			continue;
		}

		rate_power[idx++] = mt7915_get_sku_delta(dev, offset);
		if (rate_power[idx - 1] > max_delta)
			max_delta = rate_power[idx - 1];

		if (i == SKU_HT_BW20 || i == SKU_VHT_BW20)
			offset += 1;

		for (j = 1; j < sku->len; j++) {
			u32 addr = offset + sku->delta_map[j];
	u32 val;
	s8 delta;

			rate_power[idx++] = mt7915_get_sku_delta(dev, addr);
			if (rate_power[idx - 1] > max_delta)
				max_delta = rate_power[idx - 1];
		}
	}
	if (band == NL80211_BAND_2GHZ)
		val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_2G);
	else
		val = mt7915_eeprom_read(dev, MT_EE_RATE_DELTA_5G);

	rate_power[idx] = max_delta;
}
	if (!(val & MT_EE_RATE_DELTA_EN))
		return 0;

void mt7915_eeprom_init_sku(struct mt7915_dev *dev)
{
	mt7915_eeprom_init_sku_band(dev, &dev->mphy.sband_2g.sband);
	mt7915_eeprom_init_sku_band(dev, &dev->mphy.sband_5g.sband);
}
	delta = FIELD_GET(MT_EE_RATE_DELTA_MASK, val);

	return val & MT_EE_RATE_DELTA_SIGN ? delta : -delta;
}

const u8 mt7915_sku_group_len[] = {
	[SKU_CCK] = 4,
	[SKU_OFDM] = 8,
	[SKU_HT_BW20] = 8,
	[SKU_HT_BW40] = 9,
	[SKU_VHT_BW20] = 12,
	[SKU_VHT_BW40] = 12,
	[SKU_VHT_BW80] = 12,
	[SKU_VHT_BW160] = 12,
	[SKU_HE_RU26] = 12,
	[SKU_HE_RU52] = 12,
	[SKU_HE_RU106] = 12,
	[SKU_HE_RU242] = 12,
	[SKU_HE_RU484] = 12,
	[SKU_HE_RU996] = 12,
	[SKU_HE_RU2x996] = 12
};
+7 −33
Original line number Diff line number Diff line
@@ -19,6 +19,8 @@ enum mt7915_eeprom_field {
	MT_EE_DDIE_FT_VERSION =	0x050,
	MT_EE_DO_PRE_CAL =	0x062,
	MT_EE_WIFI_CONF =	0x190,
	MT_EE_RATE_DELTA_2G =	0x252,
	MT_EE_RATE_DELTA_5G =	0x29d,
	MT_EE_TX0_POWER_2G =	0x2fc,
	MT_EE_TX0_POWER_5G =	0x34b,
	MT_EE_ADIE_FT_VERSION =	0x9a0,
@@ -43,6 +45,10 @@ enum mt7915_eeprom_field {
#define MT_EE_WIFI_CONF7_TSSI0_5G		BIT(2)
#define MT_EE_WIFI_CONF7_TSSI1_5G		BIT(4)

#define MT_EE_RATE_DELTA_MASK			GENMASK(5, 0)
#define MT_EE_RATE_DELTA_SIGN			BIT(6)
#define MT_EE_RATE_DELTA_EN			BIT(7)

enum mt7915_eeprom_band {
	MT_EE_BAND_SEL_DEFAULT,
	MT_EE_BAND_SEL_5GHZ,
@@ -50,32 +56,6 @@ enum mt7915_eeprom_band {
	MT_EE_BAND_SEL_DUAL,
};

#define SKU_DELTA_VAL		GENMASK(5, 0)
#define SKU_DELTA_ADD		BIT(6)
#define SKU_DELTA_EN		BIT(7)

enum mt7915_sku_delta_group {
	SKU_CCK_GROUP0,
	SKU_CCK_GROUP1,

	SKU_OFDM_GROUP0 = 0,
	SKU_OFDM_GROUP1,
	SKU_OFDM_GROUP2,
	SKU_OFDM_GROUP3,
	SKU_OFDM_GROUP4,

	SKU_MCS_GROUP0 = 0,
	SKU_MCS_GROUP1,
	SKU_MCS_GROUP2,
	SKU_MCS_GROUP3,
	SKU_MCS_GROUP4,
	SKU_MCS_GROUP5,
	SKU_MCS_GROUP6,
	SKU_MCS_GROUP7,
	SKU_MCS_GROUP8,
	SKU_MCS_GROUP9,
};

enum mt7915_sku_rate_group {
	SKU_CCK,
	SKU_OFDM,
@@ -95,12 +75,6 @@ enum mt7915_sku_rate_group {
	MAX_SKU_RATE_GROUP_NUM,
};

struct sku_group {
	u8 len;
	u16 offset[2];
	const u8 *delta_map;
};

static inline int
mt7915_get_channel_group(int channel)
{
@@ -133,6 +107,6 @@ mt7915_tssi_enabled(struct mt7915_dev *dev, enum nl80211_band band)
		return eep[MT_EE_WIFI_CONF + 7] & MT_EE_WIFI_CONF7_TSSI0_2G;
}

extern const struct sku_group mt7915_sku_groups[];
extern const u8 mt7915_sku_group_len[MAX_SKU_RATE_GROUP_NUM];

#endif
+39 −33
Original line number Diff line number Diff line
@@ -67,6 +67,39 @@ static const struct ieee80211_iface_combination if_comb[] = {
	}
};

static void
mt7915_init_txpower(struct mt7915_dev *dev,
		    struct ieee80211_supported_band *sband)
{
	int i, n_chains = hweight8(dev->mphy.antenna_mask);
	int nss_delta = mt76_tx_power_nss_delta(n_chains);
	int pwr_delta = mt7915_eeprom_get_power_delta(dev, sband->band);
	struct mt76_power_limits limits;

	for (i = 0; i < sband->n_channels; i++) {
		struct ieee80211_channel *chan = &sband->channels[i];
		u32 target_power = 0;
		int j;

		for (j = 0; j < n_chains; j++) {
			u32 val;

			val = mt7915_eeprom_get_target_power(dev, chan, j);
			target_power = max(target_power, val);
		}

		target_power += pwr_delta;
		target_power = mt76_get_rate_power_limits(&dev->mphy, chan,
							  &limits,
							  target_power);
		target_power += nss_delta;
		target_power = DIV_ROUND_UP(target_power, 2);
		chan->max_power = min_t(int, chan->max_reg_power,
					target_power);
		chan->orig_mpwr = target_power;
	}
}

static void
mt7915_regd_notifier(struct wiphy *wiphy,
		     struct regulatory_request *request)
@@ -77,8 +110,12 @@ mt7915_regd_notifier(struct wiphy *wiphy,
	struct mt7915_phy *phy = mphy->priv;
	struct cfg80211_chan_def *chandef = &mphy->chandef;

	memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
	dev->mt76.region = request->dfs_region;

	mt7915_init_txpower(dev, &mphy->sband_2g.sband);
	mt7915_init_txpower(dev, &mphy->sband_5g.sband);

	if (!(chandef->chan->flags & IEEE80211_CHAN_RADAR))
		return;

@@ -207,38 +244,6 @@ static int mt7915_txbf_init(struct mt7915_dev *dev)
	return mt7915_mcu_set_txbf_type(dev);
}

static void
mt7915_init_txpower_band(struct mt7915_dev *dev,
			 struct ieee80211_supported_band *sband)
{
	int i, n_chains = hweight8(dev->mphy.antenna_mask);

	for (i = 0; i < sband->n_channels; i++) {
		struct ieee80211_channel *chan = &sband->channels[i];
		u32 target_power = 0;
		int j;

		for (j = 0; j < n_chains; j++) {
			u32 val;

			val = mt7915_eeprom_get_target_power(dev, chan, j);
			target_power = max(target_power, val);
		}

		chan->max_power = min_t(int, chan->max_reg_power,
					target_power / 2);
		chan->orig_mpwr = target_power / 2;
	}
}

static void mt7915_init_txpower(struct mt7915_dev *dev)
{
	mt7915_init_txpower_band(dev, &dev->mphy.sband_2g.sband);
	mt7915_init_txpower_band(dev, &dev->mphy.sband_5g.sband);

	mt7915_eeprom_init_sku(dev);
}

static int mt7915_register_ext_phy(struct mt7915_dev *dev)
{
	struct mt7915_phy *phy = mt7915_ext_phy(dev);
@@ -295,7 +300,8 @@ static void mt7915_init_work(struct work_struct *work)

	mt7915_mcu_set_eeprom(dev);
	mt7915_mac_init(dev);
	mt7915_init_txpower(dev);
	mt7915_init_txpower(dev, &dev->mphy.sband_2g.sband);
	mt7915_init_txpower(dev, &dev->mphy.sband_5g.sband);
	mt7915_txbf_init(dev);
}

+1 −1
Original line number Diff line number Diff line
@@ -429,7 +429,7 @@ static int mt7915_config(struct ieee80211_hw *hw, u32 changed)
	}

	if (changed & IEEE80211_CONF_CHANGE_POWER) {
		ret = mt7915_mcu_set_sku(phy);
		ret = mt7915_mcu_set_txpower_sku(phy);
		if (ret)
			return ret;
	}
Loading