Add a helper for common boundary check. This is a preliminary patch
to add per bandwidth power control.
Signed-off-by: Ryder Lee <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 12 +++++-------
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h | 12 ++++++++++++
2 files changed, 17 insertions(+), 7 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index f329705c4fa1..8a2546699c3b 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3122,14 +3122,14 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy,
.txpower_max = DIV_ROUND_UP(mphy->txpower_cur, 2),
.wcid = cpu_to_le16(msta->wcid.idx),
};
- int ret, n_chains = hweight8(mphy->antenna_mask);
+ int ret;
s8 txpower_sku[MT7915_SKU_RATE_NUM];
ret = mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku));
if (ret)
return ret;
- txpower = txpower * 2 - mt76_tx_power_nss_delta(n_chains);
+ txpower = mt7915_get_power_bound(phy, txpower);
if (txpower > mphy->txpower_cur || txpower < 0)
return -EINVAL;
@@ -3181,12 +3181,10 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
};
struct mt76_power_limits limits_array;
s8 *la = (s8 *)&limits_array;
- int i, idx, n_chains = hweight8(mphy->antenna_mask);
- int tx_power = hw->conf.power_level * 2;
+ int i, idx;
+ int tx_power;
- tx_power = mt76_get_sar_power(mphy, mphy->chandef.chan,
- tx_power);
- tx_power -= mt76_tx_power_nss_delta(n_chains);
+ tx_power = mt7915_get_power_bound(phy, hw->conf.power_level);
tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
&limits_array, tx_power);
mphy->txpower_cur = tx_power;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 46c517e50ae4..382dcbda50bb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -509,4 +509,16 @@ enum {
sizeof(struct bss_info_bcn_cont) + \
sizeof(struct bss_info_inband_discovery))
+static inline s8
+mt7915_get_power_bound(struct mt7915_phy *phy, s8 txpower)
+{
+ struct mt76_phy *mphy = phy->mt76;
+ int n_chains = hweight8(mphy->antenna_mask);
+
+ txpower = mt76_get_sar_power(mphy, mphy->chandef.chan, txpower * 2);
+ txpower -= mt76_tx_power_nss_delta(n_chains);
+
+ return txpower;
+}
+
#endif
--
2.36.1
This power should override the per bandwidth max power that the
device emits.
Signed-off-by: Ryder Lee <[email protected]>
---
.../wireless/mediatek/mt76/mt7915/debugfs.c | 199 +++++++++++++++---
.../net/wireless/mediatek/mt76/mt7915/mcu.c | 9 +-
.../net/wireless/mediatek/mt76/mt7915/mcu.h | 7 +
3 files changed, 183 insertions(+), 32 deletions(-)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
index fef0ec83185b..197bcacd813e 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c
@@ -957,48 +957,197 @@ mt7915_xmit_queues_show(struct seq_file *file, void *data)
DEFINE_SHOW_ATTRIBUTE(mt7915_xmit_queues);
-static int
-mt7915_rate_txpower_show(struct seq_file *file, void *data)
+#define mt7915_txpower_puts(prefix, rate) \
+({ \
+ len += scnprintf(buf + len, sz - len, "%-16s:", #prefix " (tmac)"); \
+ for (i = 0; i < mt7915_sku_group_len[rate]; i++, offs++) \
+ len += scnprintf(buf + len, sz - len, " %6d", txpwr[offs]); \
+ len += scnprintf(buf + len, sz - len, "\n"); \
+})
+
+#define mt7915_txpower_sets(rate, pwr, flag) \
+({ \
+ offs += len; \
+ len = mt7915_sku_group_len[rate]; \
+ if (mode == flag) { \
+ for (i = 0; i < len; i++) \
+ req.txpower_sku[offs + i] = pwr; \
+ } \
+})
+
+static ssize_t
+mt7915_rate_txpower_get(struct file *file, char __user *user_buf,
+ size_t count, loff_t *ppos)
{
- static const char * const sku_group_name[] = {
- "CCK", "OFDM", "HT20", "HT40",
- "VHT20", "VHT40", "VHT80", "VHT160",
- "RU26", "RU52", "RU106", "RU242/SU20",
- "RU484/SU40", "RU996/SU80", "RU2x996/SU160"
- };
- struct mt7915_phy *phy = file->private;
+ struct mt7915_phy *phy = file->private_data;
struct mt7915_dev *dev = phy->dev;
- s8 txpower[MT7915_SKU_RATE_NUM], *buf;
+ static const size_t sz = 2048;
+ int i, offs = 0, len = 0;
+ ssize_t ret;
+ char *buf;
+ s8 txpwr[MT7915_SKU_RATE_NUM];
u32 reg;
- int i, ret;
- ret = mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower));
+ buf = kzalloc(sz, GFP_KERNEL);
+ if (!buf)
+ return -ENOMEM;
+
+ ret = mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr));
if (ret)
return ret;
/* Txpower propagation path: TMAC -> TXV -> BBP */
- seq_printf(file, "\nPhy %d\n", phy != &dev->phy);
+ len += scnprintf(buf + len, sz - len,
+ "\nPhy%d Tx power table (channel %d)\n",
+ phy != &dev->phy, phy->mt76->chandef.chan->hw_value);
+ len += scnprintf(buf + len, sz - len, "%-16s %6s %6s %6s %6s\n",
+ " ", "1m", "2m", "5m", "11m");
+ mt7915_txpower_puts(CCK, SKU_CCK);
+
+ len += scnprintf(buf + len, sz - len,
+ "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "6m", "9m", "12m", "18m", "24m", "36m", "48m",
+ "54m");
+ mt7915_txpower_puts(OFDM, SKU_OFDM);
+
+ len += scnprintf(buf + len, sz - len,
+ "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4",
+ "mcs5", "mcs6", "mcs7");
+ mt7915_txpower_puts(HT20, SKU_HT_BW20);
+
+ len += scnprintf(buf + len, sz - len,
+ "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
+ "mcs6", "mcs7", "mcs32");
+ mt7915_txpower_puts(HT40, SKU_HT_BW40);
+
+ len += scnprintf(buf + len, sz - len,
+ "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
+ "mcs6", "mcs7", "mcs8", "mcs9", "mcs10", "mcs11");
+ mt7915_txpower_puts(VHT20, SKU_VHT_BW20);
+ mt7915_txpower_puts(VHT40, SKU_VHT_BW40);
+ mt7915_txpower_puts(VHT80, SKU_VHT_BW80);
+ mt7915_txpower_puts(VHT160, SKU_VHT_BW160);
+ mt7915_txpower_puts(HE26, SKU_HE_RU26);
+ mt7915_txpower_puts(HE52, SKU_HE_RU52);
+ mt7915_txpower_puts(HE106, SKU_HE_RU106);
+ mt7915_txpower_puts(HE242, SKU_HE_RU242);
+ mt7915_txpower_puts(HE484, SKU_HE_RU484);
+ mt7915_txpower_puts(HE996, SKU_HE_RU996);
+ mt7915_txpower_puts(HE996x2, SKU_HE_RU2x996);
+
+ reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(phy->band_idx) :
+ MT_WF_PHY_TPC_CTRL_STAT_MT7916(phy->band_idx);
+
+ len += scnprintf(buf + len, sz - len, "\nTx power (bbp) : %6ld\n",
+ mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER));
+
+ ret = simple_read_from_buffer(user_buf, count, ppos, buf, len);
+ kfree(buf);
+ return ret;
+}
+
+static ssize_t
+mt7915_rate_txpower_set(struct file *file, const char __user *user_buf,
+ size_t count, loff_t *ppos)
+{
+ struct mt7915_phy *phy = file->private_data;
+ struct mt7915_dev *dev = phy->dev;
+ struct mt76_phy *mphy = phy->mt76;
+ struct mt7915_mcu_txpower_sku req = {
+ .format_id = TX_POWER_LIMIT_TABLE,
+ .band_idx = phy->band_idx,
+ };
+ char buf[100];
+ int i, ret, pwr160 = 0, pwr80 = 0, pwr40 = 0, pwr20 = 0;
+ enum mac80211_rx_encoding mode;
+ u32 offs = 0, len = 0;
+
+ if (count >= sizeof(buf))
+ return -EINVAL;
- for (i = 0, buf = txpower; i < ARRAY_SIZE(mt7915_sku_group_len); i++) {
- u8 mcs_num = mt7915_sku_group_len[i];
+ if (copy_from_user(buf, user_buf, count))
+ return -EFAULT;
- if (i >= SKU_VHT_BW20 && i <= SKU_VHT_BW160)
- mcs_num = 10;
+ if (count && buf[count - 1] == '\n')
+ buf[count - 1] = '\0';
+ else
+ buf[count] = '\0';
- mt76_seq_puts_array(file, sku_group_name[i], buf, mcs_num);
- buf += mt7915_sku_group_len[i];
+ if (sscanf(buf, "%u %u %u %u %u",
+ &mode, &pwr160, &pwr80, &pwr40, &pwr20) != 5) {
+ dev_warn(dev->mt76.dev,
+ "per bandwidth power limit: Mode BW160 BW80 BW40 BW20");
+ return -EINVAL;
}
- reg = is_mt7915(&dev->mt76) ? MT_WF_PHY_TPC_CTRL_STAT(phy->band_idx) :
- MT_WF_PHY_TPC_CTRL_STAT_MT7916(phy->band_idx);
+ if (mode > RX_ENC_HE)
+ return -EINVAL;
- seq_printf(file, "\nBaseband transmit power %ld\n",
- mt76_get_field(dev, reg, MT_WF_PHY_TPC_POWER));
+ if (pwr160)
+ pwr160 = mt7915_get_power_bound(phy, pwr160);
+ if (pwr80)
+ pwr80 = mt7915_get_power_bound(phy, pwr80);
+ if (pwr40)
+ pwr40 = mt7915_get_power_bound(phy, pwr40);
+ if (pwr20)
+ pwr20 = mt7915_get_power_bound(phy, pwr20);
- return 0;
+ if (pwr160 < 0 || pwr80 < 0 || pwr40 < 0 || pwr20 < 0)
+ return -EINVAL;
+
+ ret = mt7915_mcu_get_txpower_sku(phy, req.txpower_sku,
+ sizeof(req.txpower_sku));
+ if (ret)
+ goto out;
+
+ mt7915_txpower_sets(SKU_CCK, pwr20, RX_ENC_LEGACY);
+ mt7915_txpower_sets(SKU_OFDM, pwr20, RX_ENC_LEGACY);
+ if (mode == RX_ENC_LEGACY)
+ goto skip;
+
+ mt7915_txpower_sets(SKU_HT_BW20, pwr20, RX_ENC_HT);
+ mt7915_txpower_sets(SKU_HT_BW40, pwr40, RX_ENC_HT);
+ if (mode == RX_ENC_HT)
+ goto skip;
+
+ mt7915_txpower_sets(SKU_VHT_BW20, pwr20, RX_ENC_VHT);
+ mt7915_txpower_sets(SKU_VHT_BW40, pwr40, RX_ENC_VHT);
+ mt7915_txpower_sets(SKU_VHT_BW80, pwr80, RX_ENC_VHT);
+ mt7915_txpower_sets(SKU_VHT_BW160, pwr160, RX_ENC_VHT);
+ if (mode == RX_ENC_VHT)
+ goto skip;
+
+ mt7915_txpower_sets(SKU_HE_RU26, pwr20, RX_ENC_HE + 1);
+ mt7915_txpower_sets(SKU_HE_RU52, pwr20, RX_ENC_HE + 1);
+ mt7915_txpower_sets(SKU_HE_RU106, pwr20, RX_ENC_HE + 1);
+ mt7915_txpower_sets(SKU_HE_RU242, pwr20, RX_ENC_HE);
+ mt7915_txpower_sets(SKU_HE_RU484, pwr40, RX_ENC_HE);
+ mt7915_txpower_sets(SKU_HE_RU996, pwr80, RX_ENC_HE);
+ mt7915_txpower_sets(SKU_HE_RU2x996, pwr160, RX_ENC_HE);
+skip:
+ ret = mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TX_POWER_FEATURE_CTRL),
+ &req, sizeof(req), true);
+ if (ret)
+ goto out;
+
+ mphy->txpower_cur = max(mphy->txpower_cur,
+ max(pwr160, max(pwr80, max(pwr40, pwr20))));
+out:
+ mutex_unlock(&dev->mt76.mutex);
+
+ return ret ? ret : count;
}
-DEFINE_SHOW_ATTRIBUTE(mt7915_rate_txpower);
+static const struct file_operations mt7915_rate_txpower_fops = {
+ .write = mt7915_rate_txpower_set,
+ .read = mt7915_rate_txpower_get,
+ .open = simple_open,
+ .owner = THIS_MODULE,
+ .llseek = default_llseek,
+};
static int
mt7915_twt_stats(struct seq_file *s, void *data)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
index 8a2546699c3b..d8389bc8ee82 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
@@ -3170,12 +3170,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
struct mt7915_dev *dev = phy->dev;
struct mt76_phy *mphy = phy->mt76;
struct ieee80211_hw *hw = mphy->hw;
- struct mt7915_sku_val {
- u8 format_id;
- u8 limit_type;
- u8 band_idx;
- s8 val[MT7915_SKU_RATE_NUM];
- } __packed req = {
+ struct mt7915_mcu_txpower_sku req = {
.format_id = TX_POWER_LIMIT_TABLE,
.band_idx = phy->band_idx,
};
@@ -3203,7 +3198,7 @@ int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy)
}
for (j = 0; j < min_t(u8, mcs_num, len); j++)
- req.val[idx + j] = la[j];
+ req.txpower_sku[idx + j] = la[j];
la += mcs_num;
idx += len;
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
index 382dcbda50bb..29b5434bfdb8 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h
@@ -184,6 +184,13 @@ enum mt7915_chan_mib_offs {
MIB_NON_WIFI_TIME_V2
};
+struct mt7915_mcu_txpower_sku {
+ u8 format_id;
+ u8 limit_type;
+ u8 band_idx;
+ s8 txpower_sku[MT7915_SKU_RATE_NUM];
+} __packed;
+
struct edca {
u8 queue;
u8 set;
--
2.36.1
On Thu, 2022-11-24 at 03:37 +0800, Ryder Lee wrote:
> This power should override the per bandwidth max power that the
> device emits.
>
> Signed-off-by: Ryder Lee <[email protected]>
> ---
> .../wireless/mediatek/mt76/mt7915/debugfs.c | 199 +++++++++++++++-
> --
> .../net/wireless/mediatek/mt76/mt7915/mcu.c | 9 +-
> .../net/wireless/mediatek/mt76/mt7915/mcu.h | 7 +
> 3 files changed, 183 insertions(+), 32 deletions(-)
Please ignore this one as I accidentally sent it out. Will post a v2.
Ryder