2021-04-05 18:16:26

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 0/8] introduce single-sku support for mt7663/mt7921 drivers

Add per-rate power limitations for 802.11n/802.11ac/802.11ax rates to
mt7663/mt7921 drivers.
Introduce per-rate power limit dts parsing/binding.

Felix Fietkau (2):
mt76: add functions for parsing rate power limits from DT
mt76: mt7615: implement support for using DT rate power limits

Lorenzo Bianconi (4):
dt-bindings:net:wireless:ieee80211: introduce regdomain property
dt-bindings:net:wireless:mediatek,mt76: introduce power-limits node
mt76: mt7615: do not use mt7615 single-sku values for mt7663
mt76: introduce single-sku support for mt7663/mt7921

Sean Wang (1):
mt76: mt7921: add dumping Tx power table

Shayne Chen (1):
mt76: extend DT rate power limits to support 11ax devices

.../bindings/net/wireless/ieee80211.yaml | 9 +
.../bindings/net/wireless/mediatek,mt76.yaml | 79 +++++++
drivers/net/wireless/mediatek/mt76/eeprom.c | 219 ++++++++++++++++++
drivers/net/wireless/mediatek/mt76/mt76.h | 13 ++
.../net/wireless/mediatek/mt76/mt7615/init.c | 15 +-
.../net/wireless/mediatek/mt76/mt7615/main.c | 4 +
.../net/wireless/mediatek/mt76/mt7615/mcu.c | 66 +++++-
.../wireless/mediatek/mt76/mt76_connac_mcu.c | 133 +++++++++++
.../wireless/mediatek/mt76/mt76_connac_mcu.h | 24 ++
.../wireless/mediatek/mt76/mt7921/debugfs.c | 79 +++++++
.../net/wireless/mediatek/mt76/mt7921/init.c | 2 +
.../net/wireless/mediatek/mt76/mt7921/main.c | 4 +
.../net/wireless/mediatek/mt76/mt7921/mcu.c | 23 ++
.../net/wireless/mediatek/mt76/mt7921/mcu.h | 17 ++
.../wireless/mediatek/mt76/mt7921/mt7921.h | 31 +++
15 files changed, 715 insertions(+), 3 deletions(-)

--
2.30.2


2021-04-05 18:16:26

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 1/8] dt-bindings:net:wireless:ieee80211: introduce regdomain property

Add regdomain property to ieee80211 binding

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../devicetree/bindings/net/wireless/ieee80211.yaml | 9 +++++++++
1 file changed, 9 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
index d58e1571df9b..6557c6348cac 100644
--- a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
@@ -30,6 +30,15 @@ properties:
different 5 GHz subbands. Using them incorrectly could not work or
decrease performance noticeably

+ regdomain:
+ minItems: 1
+ maxItems: 1
+ contains:
+ enum:
+ - FCC
+ - ETSI
+ - JP
+
additionalProperties: true

examples:
--
2.30.2

2021-04-05 18:16:36

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 2/8] dt-bindings:net:wireless:mediatek,mt76: introduce power-limits node

Introduce power-limits node in mt76 binding in order to specify
per-rate power limit values for each 802.11n/802.11ac rate

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../bindings/net/wireless/mediatek,mt76.yaml | 79 +++++++++++++++++++
1 file changed, 79 insertions(+)

diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
index d6f835d17d66..6ede331e3e52 100644
--- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
+++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
@@ -72,6 +72,62 @@ properties:
led-sources:
maxItems: 1

+ power-limits:
+ type: object
+ properties:
+ regdomain: true
+
+ patternProperties:
+ "^r[0-9]+":
+ type: object
+ patternProperties:
+ "^txpower-[256]g$":
+ type: object
+ patternProperties:
+ "^b[0-9]+$":
+ type: object
+ properties:
+ channels:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 2
+ maxItems: 2
+ description:
+ Pairs of first and last channel number of the selected
+ band
+
+ cck:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ minItems: 4
+ maxItems: 4
+ description:
+ 4 half-dBm per-rate power limit values
+
+ mcs:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ description:
+ Sets of per-rate power limit values for 802.11n/802.11ac
+ rates for multiple channel bandwidth settings.
+ Each set starts with the number of channel bandwidth
+ settings for which the rate set applies, followed by
+ either 8 or 10 power limit values. The order of the
+ channel bandwidth settings is 20, 40, 80 and 160 MHz.
+
+ ru:
+ $ref: /schemas/types.yaml#/definitions/uint32-matrix
+ description:
+ Sets of per-rate power limit values for 802.11ax rates
+ for multiple channel bandwidth or resource unit settings.
+ Each set starts with the number of channel bandwidth or
+ resource unit settings for which the rate set applies,
+ followed by 12 power limit values. The order of the
+ channel resource unit settings is RU26, RU52, RU106,
+ RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.
+
+ txs-delta:
+ $ref: /schemas/types.yaml#/definitions/uint32-array
+ description:
+ Half-dBm power delta for different numbers of antennas
+
required:
- compatible
- reg
@@ -93,6 +149,29 @@ examples:
led {
led-sources = <2>;
};
+
+ power-limits {
+ r0 {
+ txpower-5g {
+ regdomain = "FCC";
+ b0 {
+ channels = <36 48>;
+ ofdm = <23 23 23 23 23 23 23 23>;
+ mcs = <1 23 23 23 23 23 23 23 23 23 23>,
+ <3 22 22 22 22 22 22 22 22 22 22>;
+ ru = <3 22 22 22 22 22 22 22 22 22 22 22 22>,
+ <4 20 20 20 20 20 20 20 20 20 20 20 20>;
+ };
+ b1 {
+ channels = <100 181>;
+ ofdm = <14 14 14 14 14 14 14 14>;
+ mcs = <4 14 14 14 14 14 14 14 14 14 14>;
+ txs-delta = <12 9 6>;
+ ru = <7 14 14 14 14 14 14 14 14 14 14 14 14>;
+ };
+ };
+ };
+ };
};
};

--
2.30.2

2021-04-05 18:16:37

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 3/8] mt76: add functions for parsing rate power limits from DT

From: Felix Fietkau <[email protected]>

This subnode can be used to set per-rate tx power limits either per
country code / regdomain or globally.
These limits are typically provided by the device manufacturers and are
used to limit sideband emissions and stay within regulatory limits

Signed-off-by: Felix Fietkau <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
drivers/net/wireless/mediatek/mt76/eeprom.c | 203 ++++++++++++++++++++
drivers/net/wireless/mediatek/mt76/mt76.h | 12 ++
2 files changed, 215 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c
index 665b54c5c8ae..9e2f4a11493b 100644
--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
@@ -111,6 +111,209 @@ mt76_eeprom_override(struct mt76_phy *phy)
}
EXPORT_SYMBOL_GPL(mt76_eeprom_override);

+static bool mt76_string_prop_find(struct property *prop, const char *str)
+{
+ const char *cp = NULL;
+
+ if (!prop || !str || !str[0])
+ return false;
+
+ while ((cp = of_prop_next_string(prop, cp)) != NULL)
+ if (!strcasecmp(cp, str))
+ return true;
+
+ return false;
+}
+
+static struct device_node *
+mt76_find_power_limits_node(struct mt76_dev *dev)
+{
+ struct device_node *np = dev->dev->of_node;
+ const char *const region_names[] = {
+ [NL80211_DFS_ETSI] = "etsi",
+ [NL80211_DFS_FCC] = "fcc",
+ [NL80211_DFS_JP] = "jp",
+ };
+ struct device_node *cur, *fallback = NULL;
+ const char *region_name = NULL;
+
+ if (dev->region < ARRAY_SIZE(region_names))
+ region_name = region_names[dev->region];
+
+ np = of_get_child_by_name(np, "power-limits");
+ if (!np)
+ return NULL;
+
+ for_each_child_of_node(np, cur) {
+ struct property *country = of_find_property(cur, "country", NULL);
+ struct property *regd = of_find_property(cur, "regdomain", NULL);
+
+ if (!country && !regd) {
+ fallback = cur;
+ continue;
+ }
+
+ if (mt76_string_prop_find(country, dev->alpha2) ||
+ mt76_string_prop_find(regd, region_name))
+ return cur;
+ }
+
+ return fallback;
+}
+
+static const __be32 *
+mt76_get_of_array(struct device_node *np, char *name, size_t *len, int min)
+{
+ struct property *prop = of_find_property(np, name, NULL);
+
+ if (!prop || !prop->value || prop->length < min * 4)
+ return NULL;
+
+ *len = prop->length;
+
+ return prop->value;
+}
+
+static struct device_node *
+mt76_find_channel_node(struct device_node *np, struct ieee80211_channel *chan)
+{
+ struct device_node *cur;
+ const __be32 *val;
+ size_t len;
+
+ for_each_child_of_node(np, cur) {
+ val = mt76_get_of_array(cur, "channels", &len, 2);
+ if (!val)
+ continue;
+
+ while (len >= 2 * sizeof(*val)) {
+ if (chan->hw_value >= be32_to_cpu(val[0]) &&
+ chan->hw_value <= be32_to_cpu(val[1]))
+ return cur;
+
+ val += 2;
+ len -= 2 * sizeof(*val);
+ }
+ }
+
+ return NULL;
+}
+
+static s8
+mt76_get_txs_delta(struct device_node *np, u8 nss)
+{
+ const __be32 *val;
+ size_t len;
+
+ val = mt76_get_of_array(np, "txs-delta", &len, nss);
+ if (!val)
+ return 0;
+
+ return be32_to_cpu(val[nss - 1]);
+}
+
+static void
+mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data,
+ s8 target_power, s8 nss_delta, s8 *max_power)
+{
+ int i;
+
+ if (!data)
+ return;
+
+ for (i = 0; i < pwr_len; i++) {
+ pwr[i] = min_t(s8, target_power,
+ be32_to_cpu(data[i]) + nss_delta);
+ *max_power = max(*max_power, pwr[i]);
+ }
+}
+
+s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ struct ieee80211_channel *chan,
+ struct mt76_power_limits *dest,
+ s8 target_power)
+{
+ struct mt76_dev *dev = phy->dev;
+ struct device_node *np;
+ const __be32 *val;
+ char name[16];
+ u32 mcs_rates = dev->drv->mcs_rates;
+ char band;
+ size_t len;
+ int i, cur;
+ s8 max_power = 0;
+ s8 txs_delta;
+
+ if (!mcs_rates)
+ mcs_rates = 10;
+
+ memset(dest, target_power, sizeof(*dest));
+
+ if (!IS_ENABLED(CONFIG_OF))
+ return target_power;
+
+ np = mt76_find_power_limits_node(dev);
+ if (!np)
+ return target_power;
+
+ switch (chan->band) {
+ case NL80211_BAND_2GHZ:
+ band = '2';
+ break;
+ case NL80211_BAND_5GHZ:
+ band = '5';
+ break;
+ default:
+ return target_power;
+ }
+
+ snprintf(name, sizeof(name), "txpower-%cg", band);
+ np = of_get_child_by_name(np, name);
+ if (!np)
+ return target_power;
+
+ np = mt76_find_channel_node(np, chan);
+ if (!np)
+ return target_power;
+
+ txs_delta = mt76_get_txs_delta(np, hweight8(phy->antenna_mask));
+
+ val = mt76_get_of_array(np, "cck", &len, ARRAY_SIZE(dest->cck));
+ mt76_apply_array_limit(dest->cck, ARRAY_SIZE(dest->cck), val,
+ target_power, txs_delta, &max_power);
+
+ val = mt76_get_of_array(np, "ofdm", &len, ARRAY_SIZE(dest->ofdm));
+ mt76_apply_array_limit(dest->ofdm, ARRAY_SIZE(dest->ofdm), val,
+ target_power, txs_delta, &max_power);
+
+ val = mt76_get_of_array(np, "mcs", &len, mcs_rates + 1);
+ if (!val)
+ return max_power;
+
+ len /= 4;
+ cur = be32_to_cpu(val[0]);
+ for (i = 0; i < ARRAY_SIZE(dest->mcs); i++) {
+ if (len < mcs_rates + 1)
+ break;
+
+ mt76_apply_array_limit(dest->mcs[i], ARRAY_SIZE(dest->mcs[i]),
+ val + 1, target_power, txs_delta,
+ &max_power);
+ if (--cur > 0)
+ continue;
+
+ val += mcs_rates + 1;
+ len -= mcs_rates + 1;
+ if (!len)
+ break;
+
+ cur = be32_to_cpu(val[0]);
+ }
+
+ return max_power;
+}
+EXPORT_SYMBOL_GPL(mt76_get_rate_power_limits);
+
int
mt76_eeprom_init(struct mt76_dev *dev, int len)
{
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index b09b0f5ffd6d..0d2eeb37129c 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -331,6 +331,7 @@ struct mt76_driver_ops {
u32 drv_flags;
u32 survey_flags;
u16 txwi_size;
+ u8 mcs_rates;

void (*update_survey)(struct mt76_dev *dev);

@@ -710,6 +711,12 @@ struct mt76_dev {
};
};

+struct mt76_power_limits {
+ s8 cck[4];
+ s8 ofdm[8];
+ s8 mcs[4][10];
+};
+
enum mt76_phy_type {
MT_PHY_TYPE_CCK,
MT_PHY_TYPE_OFDM,
@@ -1193,4 +1200,9 @@ mt76_mcu_skb_send_msg(struct mt76_dev *dev, struct sk_buff *skb, int cmd,

void mt76_set_irq_mask(struct mt76_dev *dev, u32 addr, u32 clear, u32 set);

+s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
+ struct ieee80211_channel *chan,
+ struct mt76_power_limits *dest,
+ s8 target_power);
+
#endif
--
2.30.2

2021-04-05 18:16:43

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 4/8] mt76: extend DT rate power limits to support 11ax devices

From: Shayne Chen <[email protected]>

Enable parsing per-rate txpower limits from DT for 11ax chipsets.

Co-developed-by: Felix Fietkau <[email protected]>
Signed-off-by: Felix Fietkau <[email protected]>
Tested-by: Evelyn Tsai <[email protected]>
Signed-off-by: Shayne Chen <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
drivers/net/wireless/mediatek/mt76/eeprom.c | 62 +++++++++++++--------
drivers/net/wireless/mediatek/mt76/mt76.h | 1 +
2 files changed, 40 insertions(+), 23 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c
index 9e2f4a11493b..65813f19e2ee 100644
--- a/drivers/net/wireless/mediatek/mt76/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/eeprom.c
@@ -228,6 +228,36 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const __be32 *data,
}
}

+static void
+mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num,
+ const __be32 *data, size_t len, s8 target_power,
+ s8 nss_delta, s8 *max_power)
+{
+ int i, cur;
+
+ if (!data)
+ return;
+
+ len /= 4;
+ cur = be32_to_cpu(data[0]);
+ for (i = 0; i < pwr_num; i++) {
+ if (len < pwr_len + 1)
+ break;
+
+ mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1,
+ target_power, nss_delta, max_power);
+ if (--cur > 0)
+ continue;
+
+ data += pwr_len + 1;
+ len -= pwr_len + 1;
+ if (!len)
+ break;
+
+ cur = be32_to_cpu(data[0]);
+ }
+}
+
s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
struct ieee80211_channel *chan,
struct mt76_power_limits *dest,
@@ -238,9 +268,9 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
const __be32 *val;
char name[16];
u32 mcs_rates = dev->drv->mcs_rates;
+ u32 ru_rates = ARRAY_SIZE(dest->ru[0]);
char band;
size_t len;
- int i, cur;
s8 max_power = 0;
s8 txs_delta;

@@ -287,28 +317,14 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy,
target_power, txs_delta, &max_power);

val = mt76_get_of_array(np, "mcs", &len, mcs_rates + 1);
- if (!val)
- return max_power;
-
- len /= 4;
- cur = be32_to_cpu(val[0]);
- for (i = 0; i < ARRAY_SIZE(dest->mcs); i++) {
- if (len < mcs_rates + 1)
- break;
-
- mt76_apply_array_limit(dest->mcs[i], ARRAY_SIZE(dest->mcs[i]),
- val + 1, target_power, txs_delta,
- &max_power);
- if (--cur > 0)
- continue;
-
- val += mcs_rates + 1;
- len -= mcs_rates + 1;
- if (!len)
- break;
-
- cur = be32_to_cpu(val[0]);
- }
+ mt76_apply_multi_array_limit(dest->mcs[0], ARRAY_SIZE(dest->mcs[0]),
+ ARRAY_SIZE(dest->mcs), val, len,
+ target_power, txs_delta, &max_power);
+
+ val = mt76_get_of_array(np, "ru", &len, ru_rates + 1);
+ mt76_apply_multi_array_limit(dest->ru[0], ARRAY_SIZE(dest->ru[0]),
+ ARRAY_SIZE(dest->ru), val, len,
+ target_power, txs_delta, &max_power);

return max_power;
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h
index 0d2eeb37129c..2cfe5584f33f 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76.h
@@ -715,6 +715,7 @@ struct mt76_power_limits {
s8 cck[4];
s8 ofdm[8];
s8 mcs[4][10];
+ s8 ru[7][12];
};

enum mt76_phy_type {
--
2.30.2

2021-04-05 18:17:16

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 5/8] mt76: mt7615: implement support for using DT rate power limits

From: Felix Fietkau <[email protected]>

Limits are used to update the channel max_power settings and also passed
to the firmware on channel changes

Signed-off-by: Felix Fietkau <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../net/wireless/mediatek/mt76/mt7615/init.c | 10 ++-
.../net/wireless/mediatek/mt76/mt7615/mcu.c | 61 ++++++++++++++++++-
2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index 857fb4918975..e23898365166 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -252,6 +252,7 @@ void mt7615_init_txpower(struct mt7615_dev *dev,
int delta_idx, delta = mt76_tx_power_nss_delta(n_chains);
u8 *eep = (u8 *)dev->mt76.eeprom.data;
enum nl80211_band band = sband->band;
+ struct mt76_power_limits limits;
u8 rate_val;

delta_idx = mt7615_eeprom_get_power_delta_index(dev, band);
@@ -280,7 +281,11 @@ void mt7615_init_txpower(struct mt7615_dev *dev,
target_power = max(target_power, eep[index]);
}

- target_power = DIV_ROUND_UP(target_power + delta, 2);
+ target_power = mt76_get_rate_power_limits(&dev->mphy, chan,
+ &limits,
+ target_power);
+ target_power += 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;
@@ -311,6 +316,9 @@ mt7615_regd_notifier(struct wiphy *wiphy,
memcpy(dev->mt76.alpha2, request->alpha2, sizeof(dev->mt76.alpha2));
dev->mt76.region = request->dfs_region;

+ mt7615_init_txpower(dev, &mphy->sband_2g.sband);
+ mt7615_init_txpower(dev, &mphy->sband_5g.sband);
+
mt7615_mutex_acquire(dev);

if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 600c5366c099..7ca7d239b53d 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -2127,16 +2127,75 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
{
struct mt76_phy *mphy = phy->mt76;
struct ieee80211_hw *hw = mphy->hw;
+ struct mt76_power_limits limits;
+ s8 *limits_array = (s8 *)&limits;
int n_chains = hweight8(mphy->antenna_mask);
int tx_power;
int i;
+ static const u8 sku_mapping[] = {
+#define SKU_FIELD(_type, _field) \
+ [MT_SKU_##_type] = offsetof(struct mt76_power_limits, _field)
+ SKU_FIELD(CCK_1_2, cck[0]),
+ SKU_FIELD(CCK_55_11, cck[2]),
+ SKU_FIELD(OFDM_6_9, ofdm[0]),
+ SKU_FIELD(OFDM_12_18, ofdm[2]),
+ SKU_FIELD(OFDM_24_36, ofdm[4]),
+ SKU_FIELD(OFDM_48, ofdm[6]),
+ SKU_FIELD(OFDM_54, ofdm[7]),
+ SKU_FIELD(HT20_0_8, mcs[0][0]),
+ SKU_FIELD(HT20_32, ofdm[0]),
+ SKU_FIELD(HT20_1_2_9_10, mcs[0][1]),
+ SKU_FIELD(HT20_3_4_11_12, mcs[0][3]),
+ SKU_FIELD(HT20_5_13, mcs[0][5]),
+ SKU_FIELD(HT20_6_14, mcs[0][6]),
+ SKU_FIELD(HT20_7_15, mcs[0][7]),
+ SKU_FIELD(HT40_0_8, mcs[1][0]),
+ SKU_FIELD(HT40_32, ofdm[0]),
+ SKU_FIELD(HT40_1_2_9_10, mcs[1][1]),
+ SKU_FIELD(HT40_3_4_11_12, mcs[1][3]),
+ SKU_FIELD(HT40_5_13, mcs[1][5]),
+ SKU_FIELD(HT40_6_14, mcs[1][6]),
+ SKU_FIELD(HT40_7_15, mcs[1][7]),
+ SKU_FIELD(VHT20_0, mcs[0][0]),
+ SKU_FIELD(VHT20_1_2, mcs[0][1]),
+ SKU_FIELD(VHT20_3_4, mcs[0][3]),
+ SKU_FIELD(VHT20_5_6, mcs[0][5]),
+ SKU_FIELD(VHT20_7, mcs[0][7]),
+ SKU_FIELD(VHT20_8, mcs[0][8]),
+ SKU_FIELD(VHT20_9, mcs[0][9]),
+ SKU_FIELD(VHT40_0, mcs[1][0]),
+ SKU_FIELD(VHT40_1_2, mcs[1][1]),
+ SKU_FIELD(VHT40_3_4, mcs[1][3]),
+ SKU_FIELD(VHT40_5_6, mcs[1][5]),
+ SKU_FIELD(VHT40_7, mcs[1][7]),
+ SKU_FIELD(VHT40_8, mcs[1][8]),
+ SKU_FIELD(VHT40_9, mcs[1][9]),
+ SKU_FIELD(VHT80_0, mcs[2][0]),
+ SKU_FIELD(VHT80_1_2, mcs[2][1]),
+ SKU_FIELD(VHT80_3_4, mcs[2][3]),
+ SKU_FIELD(VHT80_5_6, mcs[2][5]),
+ SKU_FIELD(VHT80_7, mcs[2][7]),
+ SKU_FIELD(VHT80_8, mcs[2][8]),
+ SKU_FIELD(VHT80_9, mcs[2][9]),
+ SKU_FIELD(VHT160_0, mcs[3][0]),
+ SKU_FIELD(VHT160_1_2, mcs[3][1]),
+ SKU_FIELD(VHT160_3_4, mcs[3][3]),
+ SKU_FIELD(VHT160_5_6, mcs[3][5]),
+ SKU_FIELD(VHT160_7, mcs[3][7]),
+ SKU_FIELD(VHT160_8, mcs[3][8]),
+ SKU_FIELD(VHT160_9, mcs[3][9]),
+#undef SKU_FIELD
+ };

tx_power = hw->conf.power_level * 2 -
mt76_tx_power_nss_delta(n_chains);
+
+ tx_power = mt76_get_rate_power_limits(mphy, mphy->chandef.chan,
+ &limits, tx_power);
mphy->txpower_cur = tx_power;

for (i = 0; i < MT_SKU_1SS_DELTA; i++)
- sku[i] = tx_power;
+ sku[i] = limits_array[sku_mapping[i]];

for (i = 0; i < 4; i++) {
int delta = 0;
--
2.30.2

2021-04-05 18:17:26

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 6/8] mt76: mt7615: do not use mt7615 single-sku values for mt7663

mt7663 mcu relies on different APIs to configure APIs per-rate power limit
respect to mt7615 driver.

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
drivers/net/wireless/mediatek/mt76/mt7615/mcu.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
index 7ca7d239b53d..19b408b6badb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c
@@ -2194,6 +2194,11 @@ static void mt7615_mcu_set_txpower_sku(struct mt7615_phy *phy, u8 *sku)
&limits, tx_power);
mphy->txpower_cur = tx_power;

+ if (is_mt7663(mphy->dev)) {
+ memset(sku, tx_power, MT_SKU_4SS_DELTA + 1);
+ return;
+ }
+
for (i = 0; i < MT_SKU_1SS_DELTA; i++)
sku[i] = limits_array[sku_mapping[i]];

--
2.30.2

2021-04-05 18:17:28

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 7/8] mt76: introduce single-sku support for mt7663/mt7921

Introduce support for rate-txpower compensation for mt7663/mt7921 chipsets.
Rate-txpower limit is specified through dts

Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../net/wireless/mediatek/mt76/mt7615/init.c | 5 +-
.../net/wireless/mediatek/mt76/mt7615/main.c | 4 +
.../wireless/mediatek/mt76/mt76_connac_mcu.c | 133 ++++++++++++++++++
.../wireless/mediatek/mt76/mt76_connac_mcu.h | 23 +++
.../net/wireless/mediatek/mt76/mt7921/init.c | 2 +
.../net/wireless/mediatek/mt76/mt7921/main.c | 4 +
6 files changed, 170 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/init.c b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
index e23898365166..d2eb8e9fb7f1 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/init.c
@@ -323,8 +323,11 @@ mt7615_regd_notifier(struct wiphy *wiphy,

if (chandef->chan->flags & IEEE80211_CHAN_RADAR)
mt7615_dfs_init_radar_detector(phy);
- if (mt7615_firmware_offload(phy->dev))
+
+ if (mt7615_firmware_offload(phy->dev)) {
mt76_connac_mcu_set_channel_domain(mphy);
+ mt76_connac_mcu_set_rate_txpower(mphy);
+ }

mt7615_mutex_release(dev);
}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
index e30b256784e0..62d9df47a1f6 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c
@@ -66,6 +66,10 @@ static int mt7615_start(struct ieee80211_hw *hw)
ret = mt76_connac_mcu_set_channel_domain(phy->mt76);
if (ret)
goto out;
+
+ ret = mt76_connac_mcu_set_rate_txpower(phy->mt76);
+ if (ret)
+ goto out;
}

ret = mt7615_mcu_set_chan_info(phy, MCU_EXT_CMD_SET_RX_PATH);
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
index bafe95210807..2b62d2a0fd67 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c
@@ -1560,6 +1560,139 @@ void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
}
EXPORT_SYMBOL_GPL(mt76_connac_mcu_coredump_event);

+static void
+mt76_connac_mcu_build_sku(struct mt76_dev *dev, s8 *sku,
+ struct mt76_power_limits *limits,
+ enum nl80211_band band)
+{
+ int max_power = is_mt7921(dev) ? 127 : 63;
+ int i, offset = sizeof(limits->cck);
+
+ memset(sku, max_power, MT_SKU_POWER_LIMIT);
+
+ if (band == NL80211_BAND_2GHZ) {
+ /* cck */
+ memcpy(sku, limits->cck, sizeof(limits->cck));
+ }
+
+ /* ofdm */
+ memcpy(&sku[offset], limits->ofdm, sizeof(limits->ofdm));
+ offset += sizeof(limits->ofdm);
+
+ /* ht */
+ for (i = 0; i < 2; i++) {
+ memcpy(&sku[offset], limits->mcs[i], 8);
+ offset += 8;
+ }
+ sku[offset++] = limits->mcs[0][0];
+
+ /* vht */
+ for (i = 0; i < ARRAY_SIZE(limits->mcs); i++) {
+ memcpy(&sku[offset], limits->mcs[i],
+ ARRAY_SIZE(limits->mcs[i]));
+ offset += 12;
+ }
+
+ if (!is_mt7921(dev))
+ return;
+
+ /* he */
+ for (i = 0; i < ARRAY_SIZE(limits->ru); i++) {
+ memcpy(&sku[offset], limits->ru[i], ARRAY_SIZE(limits->ru[i]));
+ offset += ARRAY_SIZE(limits->ru[i]);
+ }
+}
+
+static int
+mt76_connac_mcu_rate_txpower_band(struct mt76_phy *phy,
+ enum nl80211_band band)
+{
+ struct mt76_dev *dev = phy->dev;
+ int sku_len, batch_len = is_mt7921(dev) ? 8 : 16;
+ static const u8 chan_list_2ghz[] = {
+ 1, 2, 3, 4, 5, 6, 7,
+ 8, 9, 10, 11, 12, 13, 14
+ };
+ static const u8 chan_list_5ghz[] = {
+ 36, 38, 40, 42, 44, 46, 48,
+ 50, 52, 54, 56, 58, 60, 62,
+ 64, 100, 102, 104, 106, 108, 110,
+ 112, 114, 116, 118, 120, 122, 124,
+ 126, 128, 132, 134, 136, 138, 140,
+ 142, 144, 149, 151, 153, 155, 157,
+ 159, 161, 165
+ };
+ struct mt76_connac_sku_tlv sku_tlbv;
+ int i, n_chan, batch_size, idx = 0;
+ struct mt76_power_limits limits;
+ const u8 *ch_list;
+
+ sku_len = is_mt7921(dev) ? sizeof(sku_tlbv) : sizeof(sku_tlbv) - 92;
+
+ if (band == NL80211_BAND_2GHZ) {
+ n_chan = ARRAY_SIZE(chan_list_2ghz);
+ ch_list = chan_list_2ghz;
+ } else {
+ n_chan = ARRAY_SIZE(chan_list_5ghz);
+ ch_list = chan_list_5ghz;
+ }
+ batch_size = DIV_ROUND_UP(n_chan, batch_len);
+
+ for (i = 0; i < batch_size; i++) {
+ bool last_msg = i == batch_size - 1;
+ int num_ch = last_msg ? n_chan % batch_len : batch_len;
+ struct mt76_connac_tx_power_limit_tlv tx_power_tlv = {
+ .band = band == NL80211_BAND_2GHZ ? 1 : 2,
+ .n_chan = num_ch,
+ .last_msg = last_msg,
+ };
+ struct sk_buff *skb;
+ int j, err, msg_len;
+
+ msg_len = sizeof(tx_power_tlv) + num_ch * sizeof(sku_tlbv);
+ skb = mt76_mcu_msg_alloc(dev, NULL, msg_len);
+ if (!skb)
+ return -ENOMEM;
+
+ BUILD_BUG_ON(sizeof(dev->alpha2) > sizeof(tx_power_tlv.alpha2));
+ memcpy(tx_power_tlv.alpha2, dev->alpha2, sizeof(dev->alpha2));
+
+ skb_put_data(skb, &tx_power_tlv, sizeof(tx_power_tlv));
+ for (j = 0; j < num_ch; j++, idx++) {
+ struct ieee80211_channel chan = {
+ .hw_value = ch_list[idx],
+ .band = band,
+ };
+
+ mt76_get_rate_power_limits(phy, &chan, &limits, 127);
+
+ sku_tlbv.channel = ch_list[idx];
+ mt76_connac_mcu_build_sku(dev, sku_tlbv.pwr_limit,
+ &limits, band);
+ skb_put_data(skb, &sku_tlbv, sku_len);
+ }
+
+ err = mt76_mcu_skb_send_msg(dev, skb,
+ MCU_CMD_SET_RATE_TX_POWER, false);
+ if (err < 0)
+ return err;
+ }
+
+ return 0;
+}
+
+int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy)
+{
+ int err;
+
+ err = mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_2GHZ);
+ if (err < 0)
+ return err;
+
+ return mt76_connac_mcu_rate_txpower_band(phy, NL80211_BAND_5GHZ);
+}
+EXPORT_SYMBOL_GPL(mt76_connac_mcu_set_rate_txpower);
+
#ifdef CONFIG_PM

const struct wiphy_wowlan_support mt76_connac_wowlan_support = {
diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index 5a3efd744546..c397adb817f2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -892,6 +892,28 @@ struct mt76_sta_cmd_info {
u8 rcpi;
};

+#define MT_SKU_POWER_LIMIT 161
+
+struct mt76_connac_sku_tlv {
+ u8 channel;
+ s8 pwr_limit[MT_SKU_POWER_LIMIT];
+} __packed;
+
+struct mt76_connac_tx_power_limit_tlv {
+ /* DW0 - common info*/
+ u8 ver;
+ u8 pad0;
+ __le16 len;
+ /* DW1 - cmd hint */
+ u8 n_chan; /* # channel */
+ u8 band; /* 2.4GHz - 5GHz */
+ u8 last_msg;
+ u8 pad1;
+ /* DW3 */
+ u8 alpha2[4]; /* regulatory_request.alpha2 */
+ u8 pad2[32];
+} __packed;
+
#define to_wcid_lo(id) FIELD_GET(GENMASK(7, 0), (u16)id)
#define to_wcid_hi(id) FIELD_GET(GENMASK(9, 8), (u16)id)

@@ -994,4 +1016,5 @@ void mt76_connac_mcu_set_suspend_iter(void *priv, u8 *mac,
int mt76_connac_mcu_chip_config(struct mt76_dev *dev);
void mt76_connac_mcu_coredump_event(struct mt76_dev *dev, struct sk_buff *skb,
struct mt76_connac_coredump *coredump);
+int mt76_connac_mcu_set_rate_txpower(struct mt76_phy *phy);
#endif /* __MT76_CONNAC_MCU_H */
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/init.c b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
index 262c9d150bf0..82ef6c6c6cd2 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/init.c
@@ -58,12 +58,14 @@ mt7921_regd_notifier(struct wiphy *wiphy,
{
struct ieee80211_hw *hw = wiphy_to_ieee80211_hw(wiphy);
struct mt7921_dev *dev = mt7921_hw_dev(hw);
+ struct mt7921_phy *phy = mt7921_hw_phy(hw);

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

mt7921_mutex_acquire(dev);
mt76_connac_mcu_set_channel_domain(hw->priv);
+ mt76_connac_mcu_set_rate_txpower(phy->mt76);
mt7921_mutex_release(dev);
}

diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/main.c b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
index 06a47cab494e..be7e314023bd 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c
@@ -186,6 +186,10 @@ int __mt7921_start(struct mt7921_phy *phy)
if (err)
return err;

+ err = mt76_connac_mcu_set_rate_txpower(phy->mt76);
+ if (err)
+ return err;
+
mt7921_mac_reset_counters(phy);
set_bit(MT76_STATE_RUNNING, &mphy->state);

--
2.30.2

2021-04-05 18:19:55

by Lorenzo Bianconi

[permalink] [raw]
Subject: [PATCH 8/8] mt76: mt7921: add dumping Tx power table

From: Sean Wang <[email protected]>

Dump the tx power table saved in offload firmware.

Signed-off-by: Sean Wang <[email protected]>
Signed-off-by: Lorenzo Bianconi <[email protected]>
---
.../wireless/mediatek/mt76/mt76_connac_mcu.h | 1 +
.../wireless/mediatek/mt76/mt7921/debugfs.c | 79 +++++++++++++++++++
.../net/wireless/mediatek/mt76/mt7921/mcu.c | 23 ++++++
.../net/wireless/mediatek/mt76/mt7921/mcu.h | 17 ++++
.../wireless/mediatek/mt76/mt7921/mt7921.h | 31 ++++++++
5 files changed, 151 insertions(+)

diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
index c397adb817f2..11bee1972534 100644
--- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h
@@ -561,6 +561,7 @@ enum {
MCU_CMD_CHIP_CONFIG = MCU_CE_PREFIX | 0xca,
MCU_CMD_FWLOG_2_HOST = MCU_CE_PREFIX | 0xc5,
MCU_CMD_GET_WTBL = MCU_CE_PREFIX | 0xcd,
+ MCU_CMD_GET_TXPWR = MCU_CE_PREFIX | 0xd0,
};

enum {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
index b2e8d698e019..024524173115 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/debugfs.c
@@ -158,6 +158,83 @@ mt7921_queues_read(struct seq_file *s, void *data)
return 0;
}

+static void
+mt7921_seq_puts_array(struct seq_file *file, const char *str,
+ s8 *val, int len)
+{
+ int i;
+
+ seq_printf(file, "%-16s:", str);
+ for (i = 0; i < len; i++)
+ if (val[i] == 127)
+ seq_printf(file, " %6s", "N.A");
+ else
+ seq_printf(file, " %6d", val[i]);
+ seq_puts(file, "\n");
+}
+
+#define mt7921_print_txpwr_entry(prefix, rate) \
+({ \
+ mt7921_seq_puts_array(s, #prefix " (user)", \
+ txpwr.data[TXPWR_USER].rate, \
+ ARRAY_SIZE(txpwr.data[TXPWR_USER].rate)); \
+ mt7921_seq_puts_array(s, #prefix " (eeprom)", \
+ txpwr.data[TXPWR_EEPROM].rate, \
+ ARRAY_SIZE(txpwr.data[TXPWR_EEPROM].rate)); \
+ mt7921_seq_puts_array(s, #prefix " (tmac)", \
+ txpwr.data[TXPWR_MAC].rate, \
+ ARRAY_SIZE(txpwr.data[TXPWR_MAC].rate)); \
+})
+
+static int
+mt7921_txpwr(struct seq_file *s, void *data)
+{
+ struct mt7921_dev *dev = dev_get_drvdata(s->private);
+ struct mt7921_txpwr txpwr;
+ int ret;
+
+ ret = mt7921_get_txpwr_info(dev, &txpwr);
+ if (ret)
+ return ret;
+
+ seq_printf(s, "Tx power table (channel %d)\n", txpwr.ch);
+ seq_printf(s, "%-16s %6s %6s %6s %6s\n",
+ " ", "1m", "2m", "5m", "11m");
+ mt7921_print_txpwr_entry(CCK, cck);
+
+ seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "6m", "9m", "12m", "18m", "24m", "36m",
+ "48m", "54m");
+ mt7921_print_txpwr_entry(OFDM, ofdm);
+
+ seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
+ "mcs6", "mcs7");
+ mt7921_print_txpwr_entry(HT20, ht20);
+
+ seq_printf(s, "%-16s %6s %6s %6s %6s %6s %6s %6s %6s %6s\n",
+ " ", "mcs0", "mcs1", "mcs2", "mcs3", "mcs4", "mcs5",
+ "mcs6", "mcs7", "mcs32");
+ mt7921_print_txpwr_entry(HT40, ht40);
+
+ seq_printf(s, "%-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");
+ mt7921_print_txpwr_entry(VHT20, vht20);
+ mt7921_print_txpwr_entry(VHT40, vht40);
+ mt7921_print_txpwr_entry(VHT80, vht80);
+ mt7921_print_txpwr_entry(VHT160, vht160);
+ mt7921_print_txpwr_entry(HE26, he26);
+ mt7921_print_txpwr_entry(HE52, he52);
+ mt7921_print_txpwr_entry(HE106, he106);
+ mt7921_print_txpwr_entry(HE242, he242);
+ mt7921_print_txpwr_entry(HE484, he484);
+ mt7921_print_txpwr_entry(HE996, he996);
+ mt7921_print_txpwr_entry(HE996x2, he996x2);
+
+ return 0;
+}
+
static int
mt7921_pm_set(void *data, u64 val)
{
@@ -237,6 +314,8 @@ int mt7921_init_debugfs(struct mt7921_dev *dev)
mt7921_queues_read);
debugfs_create_devm_seqfile(dev->mt76.dev, "acq", dir,
mt7921_queues_acq);
+ debugfs_create_devm_seqfile(dev->mt76.dev, "txpower_sku", dir,
+ mt7921_txpwr);
debugfs_create_file("tx_stats", 0400, dir, dev, &fops_tx_stats);
debugfs_create_file("fw_debug", 0600, dir, dev, &fops_fw_debug);
debugfs_create_file("runtime-pm", 0600, dir, dev, &fops_pm);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
index 9283f9865ad5..0ae0a22ca966 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c
@@ -1325,3 +1325,26 @@ mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif)
mt76_clear(dev, MT_WF_RFCR(0), MT_WF_RFCR_DROP_OTHER_BEACON);
}
}
+
+int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr)
+{
+ struct mt7921_txpwr_event *event;
+ struct mt7921_txpwr_req req = {
+ .dbdc_idx = 0,
+ };
+ struct sk_buff *skb;
+ int ret;
+
+ ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_CMD_GET_TXPWR,
+ &req, sizeof(req), true, &skb);
+ if (ret)
+ return ret;
+
+ event = (struct mt7921_txpwr_event *)skb->data;
+ WARN_ON(skb->len != le16_to_cpu(event->len));
+ memcpy(txpwr, &event->txpwr, sizeof(event->txpwr));
+
+ dev_kfree_skb(skb);
+
+ return 0;
+}
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
index af8b42983a00..d980e92028ba 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.h
@@ -85,6 +85,7 @@ enum {
MCU_EVENT_CH_PRIVILEGE = 0x18,
MCU_EVENT_SCHED_SCAN_DONE = 0x23,
MCU_EVENT_DBG_MSG = 0x27,
+ MCU_EVENT_TXPWR = 0xd0,
MCU_EVENT_COREDUMP = 0xf0,
};

@@ -389,4 +390,20 @@ struct mt7921_mcu_wlan_info {
__le32 wlan_idx;
struct mt7921_mcu_wlan_info_event event;
} __packed;
+
+struct mt7921_txpwr_req {
+ u8 ver;
+ u8 action;
+ __le16 len;
+ u8 dbdc_idx;
+ u8 rsv[3];
+} __packed;
+
+struct mt7921_txpwr_event {
+ u8 ver;
+ u8 action;
+ __le16 len;
+ struct mt7921_txpwr txpwr;
+} __packed;
+
#endif
diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
index 5cedefc41416..ad5c5f51ee19 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7921/mt7921.h
@@ -172,6 +172,36 @@ struct mt7921_dev {
struct mt76_connac_coredump coredump;
};

+enum {
+ TXPWR_USER,
+ TXPWR_EEPROM,
+ TXPWR_MAC,
+ TXPWR_MAX_NUM,
+};
+
+struct mt7921_txpwr {
+ u8 ch;
+ u8 rsv[3];
+ struct {
+ u8 ch;
+ u8 cck[4];
+ u8 ofdm[8];
+ u8 ht20[8];
+ u8 ht40[9];
+ u8 vht20[12];
+ u8 vht40[12];
+ u8 vht80[12];
+ u8 vht160[12];
+ u8 he26[12];
+ u8 he52[12];
+ u8 he106[12];
+ u8 he242[12];
+ u8 he484[12];
+ u8 he996[12];
+ u8 he996x2[12];
+ } data[TXPWR_MAX_NUM];
+};
+
enum {
MT_LMAC_AC00,
MT_LMAC_AC01,
@@ -348,4 +378,5 @@ int mt7921_mac_set_beacon_filter(struct mt7921_phy *phy,
bool enable);
void mt7921_pm_interface_iter(void *priv, u8 *mac, struct ieee80211_vif *vif);
void mt7921_coredump_work(struct work_struct *work);
+int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr);
#endif
--
2.30.2

2021-04-09 15:14:27

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH 1/8] dt-bindings:net:wireless:ieee80211: introduce regdomain property

On Mon, Apr 05, 2021 at 02:40:25PM +0200, Lorenzo Bianconi wrote:
> Add regdomain property to ieee80211 binding
>
> Signed-off-by: Lorenzo Bianconi <[email protected]>
> ---
> .../devicetree/bindings/net/wireless/ieee80211.yaml | 9 +++++++++
> 1 file changed, 9 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
> index d58e1571df9b..6557c6348cac 100644
> --- a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
> +++ b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
> @@ -30,6 +30,15 @@ properties:
> different 5 GHz subbands. Using them incorrectly could not work or
> decrease performance noticeably
>
> + regdomain:
> + minItems: 1
> + maxItems: 1
> + contains:

If only 1 entry, then 'contains' is pointless. Just 'enum' is enough.
You also need a 'description'.

> + enum:
> + - FCC
> + - ETSI
> + - JP
> +
> additionalProperties: true
>
> examples:
> --
> 2.30.2
>

2021-04-09 15:23:02

by Rob Herring

[permalink] [raw]
Subject: Re: [PATCH 2/8] dt-bindings:net:wireless:mediatek,mt76: introduce power-limits node

On Mon, Apr 05, 2021 at 02:40:26PM +0200, Lorenzo Bianconi wrote:
> Introduce power-limits node in mt76 binding in order to specify
> per-rate power limit values for each 802.11n/802.11ac rate
>
> Signed-off-by: Lorenzo Bianconi <[email protected]>
> ---
> .../bindings/net/wireless/mediatek,mt76.yaml | 79 +++++++++++++++++++
> 1 file changed, 79 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
> index d6f835d17d66..6ede331e3e52 100644
> --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
> +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
> @@ -72,6 +72,62 @@ properties:
> led-sources:
> maxItems: 1
>
> + power-limits:
> + type: object
> + properties:
> + regdomain: true

This shouldn't really be in ieee80211.yaml if it belongs under
'power-limits' node. You may need a 2nd power limits schema if this
something that should/can be common.

> +
> + patternProperties:
> + "^r[0-9]+":
> + type: object
> + patternProperties:
> + "^txpower-[256]g$":
> + type: object
> + patternProperties:
> + "^b[0-9]+$":
> + type: object
> + properties:
> + channels:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + minItems: 2
> + maxItems: 2
> + description:
> + Pairs of first and last channel number of the selected
> + band
> +
> + cck:
> + $ref: /schemas/types.yaml#/definitions/uint32-array

What's the range of values? Could be 8-bit?

> + minItems: 4
> + maxItems: 4
> + description:
> + 4 half-dBm per-rate power limit values
> +
> + mcs:
> + $ref: /schemas/types.yaml#/definitions/uint32-matrix
> + description:
> + Sets of per-rate power limit values for 802.11n/802.11ac
> + rates for multiple channel bandwidth settings.
> + Each set starts with the number of channel bandwidth
> + settings for which the rate set applies, followed by
> + either 8 or 10 power limit values. The order of the
> + channel bandwidth settings is 20, 40, 80 and 160 MHz.
> +
> + ru:
> + $ref: /schemas/types.yaml#/definitions/uint32-matrix
> + description:
> + Sets of per-rate power limit values for 802.11ax rates
> + for multiple channel bandwidth or resource unit settings.
> + Each set starts with the number of channel bandwidth or
> + resource unit settings for which the rate set applies,
> + followed by 12 power limit values. The order of the
> + channel resource unit settings is RU26, RU52, RU106,
> + RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.

These short property names bother me because we don't want 2 property
names with different meanings. A 2-3 letter name seems more likely to
collide. Also, the names aren't really self describing either.

> +
> + txs-delta:
> + $ref: /schemas/types.yaml#/definitions/uint32-array
> + description:
> + Half-dBm power delta for different numbers of antennas
> +
> required:
> - compatible
> - reg
> @@ -93,6 +149,29 @@ examples:
> led {
> led-sources = <2>;
> };
> +
> + power-limits {
> + r0 {
> + txpower-5g {
> + regdomain = "FCC";

Not the right location for what you've defined.

> + b0 {
> + channels = <36 48>;
> + ofdm = <23 23 23 23 23 23 23 23>;
> + mcs = <1 23 23 23 23 23 23 23 23 23 23>,
> + <3 22 22 22 22 22 22 22 22 22 22>;
> + ru = <3 22 22 22 22 22 22 22 22 22 22 22 22>,
> + <4 20 20 20 20 20 20 20 20 20 20 20 20>;
> + };
> + b1 {
> + channels = <100 181>;
> + ofdm = <14 14 14 14 14 14 14 14>;
> + mcs = <4 14 14 14 14 14 14 14 14 14 14>;
> + txs-delta = <12 9 6>;
> + ru = <7 14 14 14 14 14 14 14 14 14 14 14 14>;
> + };
> + };
> + };
> + };
> };
> };
>
> --
> 2.30.2
>

2021-04-09 21:28:07

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 1/8] dt-bindings:net:wireless:ieee80211: introduce regdomain property

> On Mon, Apr 05, 2021 at 02:40:25PM +0200, Lorenzo Bianconi wrote:
> > Add regdomain property to ieee80211 binding
> >
> > Signed-off-by: Lorenzo Bianconi <[email protected]>
> > ---
> > .../devicetree/bindings/net/wireless/ieee80211.yaml | 9 +++++++++
> > 1 file changed, 9 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
> > index d58e1571df9b..6557c6348cac 100644
> > --- a/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
> > +++ b/Documentation/devicetree/bindings/net/wireless/ieee80211.yaml
> > @@ -30,6 +30,15 @@ properties:
> > different 5 GHz subbands. Using them incorrectly could not work or
> > decrease performance noticeably
> >
> > + regdomain:
> > + minItems: 1
> > + maxItems: 1
> > + contains:
>
> If only 1 entry, then 'contains' is pointless. Just 'enum' is enough.
> You also need a 'description'.

ack, I will fix it in v2 moving it in mt76.yaml patch

Regards,
Lorenzo

>
> > + enum:
> > + - FCC
> > + - ETSI
> > + - JP
> > +
> > additionalProperties: true
> >
> > examples:
> > --
> > 2.30.2
> >


Attachments:
(No filename) (1.23 kB)
signature.asc (235.00 B)
Download all attachments

2021-04-09 22:54:42

by Lorenzo Bianconi

[permalink] [raw]
Subject: Re: [PATCH 2/8] dt-bindings:net:wireless:mediatek,mt76: introduce power-limits node

> On Mon, Apr 05, 2021 at 02:40:26PM +0200, Lorenzo Bianconi wrote:
> > Introduce power-limits node in mt76 binding in order to specify
> > per-rate power limit values for each 802.11n/802.11ac rate
> >
> > Signed-off-by: Lorenzo Bianconi <[email protected]>
> > ---
> > .../bindings/net/wireless/mediatek,mt76.yaml | 79 +++++++++++++++++++
> > 1 file changed, 79 insertions(+)
> >
> > diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
> > index d6f835d17d66..6ede331e3e52 100644
> > --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
> > +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml
> > @@ -72,6 +72,62 @@ properties:
> > led-sources:
> > maxItems: 1
> >
> > + power-limits:
> > + type: object
> > + properties:
> > + regdomain: true
>
> This shouldn't really be in ieee80211.yaml if it belongs under
> 'power-limits' node. You may need a 2nd power limits schema if this
> something that should/can be common.

ack, I will fix it in v2

>
> > +
> > + patternProperties:
> > + "^r[0-9]+":
> > + type: object
> > + patternProperties:
> > + "^txpower-[256]g$":
> > + type: object
> > + patternProperties:
> > + "^b[0-9]+$":
> > + type: object
> > + properties:
> > + channels:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > + minItems: 2
> > + maxItems: 2
> > + description:
> > + Pairs of first and last channel number of the selected
> > + band
> > +
> > + cck:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
>
> What's the range of values? Could be 8-bit?

yes, I will fix it in v2

>
> > + minItems: 4
> > + maxItems: 4
> > + description:
> > + 4 half-dBm per-rate power limit values
> > +
> > + mcs:
> > + $ref: /schemas/types.yaml#/definitions/uint32-matrix
> > + description:
> > + Sets of per-rate power limit values for 802.11n/802.11ac
> > + rates for multiple channel bandwidth settings.
> > + Each set starts with the number of channel bandwidth
> > + settings for which the rate set applies, followed by
> > + either 8 or 10 power limit values. The order of the
> > + channel bandwidth settings is 20, 40, 80 and 160 MHz.
> > +
> > + ru:
> > + $ref: /schemas/types.yaml#/definitions/uint32-matrix
> > + description:
> > + Sets of per-rate power limit values for 802.11ax rates
> > + for multiple channel bandwidth or resource unit settings.
> > + Each set starts with the number of channel bandwidth or
> > + resource unit settings for which the rate set applies,
> > + followed by 12 power limit values. The order of the
> > + channel resource unit settings is RU26, RU52, RU106,
> > + RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160.
>
> These short property names bother me because we don't want 2 property
> names with different meanings. A 2-3 letter name seems more likely to
> collide. Also, the names aren't really self describing either.
>
> > +
> > + txs-delta:
> > + $ref: /schemas/types.yaml#/definitions/uint32-array
> > + description:
> > + Half-dBm power delta for different numbers of antennas
> > +
> > required:
> > - compatible
> > - reg
> > @@ -93,6 +149,29 @@ examples:
> > led {
> > led-sources = <2>;
> > };
> > +
> > + power-limits {
> > + r0 {
> > + txpower-5g {
> > + regdomain = "FCC";
>
> Not the right location for what you've defined.

ack, I will fix it in v2

Regards,
Lorenzo

>
> > + b0 {
> > + channels = <36 48>;
> > + ofdm = <23 23 23 23 23 23 23 23>;
> > + mcs = <1 23 23 23 23 23 23 23 23 23 23>,
> > + <3 22 22 22 22 22 22 22 22 22 22>;
> > + ru = <3 22 22 22 22 22 22 22 22 22 22 22 22>,
> > + <4 20 20 20 20 20 20 20 20 20 20 20 20>;
> > + };
> > + b1 {
> > + channels = <100 181>;
> > + ofdm = <14 14 14 14 14 14 14 14>;
> > + mcs = <4 14 14 14 14 14 14 14 14 14 14>;
> > + txs-delta = <12 9 6>;
> > + ru = <7 14 14 14 14 14 14 14 14 14 14 14 14>;
> > + };
> > + };
> > + };
> > + };
> > };
> > };
> >
> > --
> > 2.30.2
> >


Attachments:
(No filename) (5.20 kB)
signature.asc (235.00 B)
Download all attachments