From patchwork Tue Apr 13 09:08:35 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 421301 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id BC2D1C43461 for ; Tue, 13 Apr 2021 09:08:57 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 8D5AA613B2 for ; Tue, 13 Apr 2021 09:08:57 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236867AbhDMJJP (ORCPT ); Tue, 13 Apr 2021 05:09:15 -0400 Received: from mail.kernel.org ([198.145.29.99]:44452 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244888AbhDMJJO (ORCPT ); Tue, 13 Apr 2021 05:09:14 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id BC6D5613B6; Tue, 13 Apr 2021 09:08:53 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304935; bh=dIj/syPx4ZkxNuw3pcl689EUkLrvQUELkhg2rQgTKoI=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=bf8Fh2UXOr5jQul7LPkl9/oxsK8UR1/7BzjXuXb7tHFn9aERvVDJXk8xOymMkRjdu LiwzjXOMdOqUlnbzJDs6bEWlTEg+KGuMpFxJx7+uRTDpvwR9Hj9W7+Gt7LnDX/Zmkl fM3sJiiZ8wM6aFyL7R2XAyzvOThKGokQrCWaXyoBmlFQab+YM8rzyvnxGmlXEid1pT w++33iSEglpXZgUXQeBiMHmXUSLgkc3HCQXF2UHvATgwgw8HdZcL/p9HVs9S/N1rgp N9yz0HJ0g4maHJFNEOgJbfJqm3Xu4rf/MurnEKndgB7MxcEg3BFL8k9iNw9MQUNTvS Oe4Cqe3UVjxKg== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 1/7] dt-bindings:net:wireless:mediatek, mt76: introduce power-limits node Date: Tue, 13 Apr 2021 11:08:35 +0200 Message-Id: <9f3720a402e8741553a3dbb26f81018008442ef1.1618304559.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org 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 --- .../bindings/net/wireless/mediatek,mt76.yaml | 107 ++++++++++++++++++ 1 file changed, 107 insertions(+) diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml index d6f835d17d66..3e2c2e43175e 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml @@ -72,6 +72,90 @@ properties: led-sources: maxItems: 1 + power-limits: + type: object + additionalProperties: false + patternProperties: + "^r[0-9]+": + type: object + additionalProperties: false + properties: + regdomain: + $ref: /schemas/types.yaml#/definitions/string + description: + Regdomain refers to a legal regulatory region. Different + countries define different levels of allowable transmitter + power, time that a channel can be occupied, and different + available channels + enum: + - FCC + - ETSI + - JP + + patternProperties: + "^txpower-[256]g$": + type: object + additionalProperties: false + patternProperties: + "^b[0-9]+$": + type: object + additionalProperties: false + 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 + + rates-cck: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 4 + maxItems: 4 + description: + 4 half-dBm per-rate power limit values + + rates-ofdm: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 8 + maxItems: 8 + description: + 8 half-dBm per-rate power limit values + + rates-mcs: + $ref: /schemas/types.yaml#/definitions/uint8-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. + maxItems: 4 + items: + minItems: 9 + maxItems: 11 + + rates-ru: + $ref: /schemas/types.yaml#/definitions/uint8-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. + items: + minItems: 13 + maxItems: 13 + + txs-delta: + $ref: /schemas/types.yaml#/definitions/uint32-array + description: + Half-dBm power delta for different numbers of antennas + required: - compatible - reg @@ -93,6 +177,29 @@ examples: led { led-sources = <2>; }; + + power-limits { + r0 { + regdomain = "FCC"; + txpower-5g { + b0 { + channels = <36 48>; + rates-ofdm = /bits/ 8 <23 23 23 23 23 23 23 23>; + rates-mcs = /bits/ 8 <1 23 23 23 23 23 23 23 23 23 23>, + <3 22 22 22 22 22 22 22 22 22 22>; + rates-ru = /bits/ 8 <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>; + rates-ofdm = /bits/ 8 <14 14 14 14 14 14 14 14>; + rates-mcs = /bits/ 8 <4 14 14 14 14 14 14 14 14 14 14>; + txs-delta = <12 9 6>; + rates-ru = /bits/ 8 <7 14 14 14 14 14 14 14 14 14 14 14 14>; + }; + }; + }; + }; }; }; From patchwork Tue Apr 13 09:08:36 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 420355 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C8E86C433ED for ; Tue, 13 Apr 2021 09:09:00 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id A6DA3613B8 for ; Tue, 13 Apr 2021 09:09:00 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S241119AbhDMJJS (ORCPT ); Tue, 13 Apr 2021 05:09:18 -0400 Received: from mail.kernel.org ([198.145.29.99]:44500 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236908AbhDMJJR (ORCPT ); Tue, 13 Apr 2021 05:09:17 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id DAE9A60FEF; Tue, 13 Apr 2021 09:08:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304938; bh=2W5DzsIkPbyTP6BAsOxaDthMOXAUKeVxYI1G2wJSsxs=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=CkOmJYzZpPbAnjdanaZ3H/Gl7WFM1+3HHsqa7NTEGVVgiXBXJ2iPQdNrFKeXdMSAI 72AWI8i3Pk+MeoYASZtHQ4GfnPyJmIExk8ATM79oql1Tv35Tlst3q24hjNQFK4A97r 9WZNLYxTEJWzmlONhcV8i4gYKz2GXHPRvJtJfdwMZe2CqZD314ZfqZMGy4V0YOfqcT rAWc7JNEab24NRe3nsxrJTiM0PvDi+bK6rx2OTEq3acn5OfTgKAkIhndm4M9kb5WIU wyjatMA/E9SyODqFQOHhKU+th28I0FcOp2GbMfcyvPkGy3LIK+EtAklM3KHeHEswsA Ta7MEDNS3LnEg== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 2/7] mt76: add functions for parsing rate power limits from DT Date: Tue, 13 Apr 2021 11:08:36 +0200 Message-Id: <4dceab9e4a94915eeefde34e6e23945bc18f72c0.1618304559.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Felix Fietkau 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 Signed-off-by: Lorenzo Bianconi --- drivers/net/wireless/mediatek/mt76/eeprom.c | 204 ++++++++++++++++++++ drivers/net/wireless/mediatek/mt76/mt76.h | 12 ++ 2 files changed, 216 insertions(+) diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wireless/mediatek/mt76/eeprom.c index 665b54c5c8ae..874a6d869e5b 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -111,6 +111,210 @@ 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, "rates-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, "rates-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, "rates-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 d121c176c37c..ece5b79a50e2 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); @@ -711,6 +712,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, @@ -1194,4 +1201,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 From patchwork Tue Apr 13 09:08:37 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 421300 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 50FC4C43460 for ; Tue, 13 Apr 2021 09:09:02 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 34F7E613B8 for ; Tue, 13 Apr 2021 09:09:02 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S243668AbhDMJJU (ORCPT ); Tue, 13 Apr 2021 05:09:20 -0400 Received: from mail.kernel.org ([198.145.29.99]:44528 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S236908AbhDMJJU (ORCPT ); Tue, 13 Apr 2021 05:09:20 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 12119613B7; Tue, 13 Apr 2021 09:08:58 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304940; bh=02geVXL34+1q4r/XQW3qNz2g9/t9UyAWHZ/lLPdb03M=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=PiX8TPHsxcT+7MNPjA0YcBN8GvUPTfpAW40x/0qe88a8/Pe4GNYMRWzilhk1pqblt eJVrPrDdx5yjhvNGGD2NtH+jhSW+9cCT2QhxC12BEh2hpW+IzdIUqPeF0Jd4UVphrN 374sbcCWKSYjOYpV7rY9ZJNXvb/5oOmrtI4EVItA8GcsjKuaSrU7W9JbDQbpd7YSX2 ON7+pvHSdxY0OhAs98PCwbni7MMfBgrbONwRIMPCBru9kFp0QJ3TgfCoPwG3288fuD 52IVfO+dAMjY5zly8yfB1f70EK0OF6Qyd18+kbT786i55t4fjarFvXW7TH1gsZBuVQ qv5A4LY60NmrA== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 3/7] mt76: extend DT rate power limits to support 11ax devices Date: Tue, 13 Apr 2021 11:08:37 +0200 Message-Id: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Shayne Chen Enable parsing per-rate txpower limits from DT for 11ax chipsets. Co-developed-by: Felix Fietkau Signed-off-by: Felix Fietkau Tested-by: Evelyn Tsai Signed-off-by: Shayne Chen Signed-off-by: Lorenzo Bianconi --- 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 874a6d869e5b..e20aa6998e4d 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; @@ -288,28 +318,14 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, target_power, txs_delta, &max_power); val = mt76_get_of_array(np, "rates-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, "rates-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 ece5b79a50e2..4571f0ed352c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -716,6 +716,7 @@ struct mt76_power_limits { s8 cck[4]; s8 ofdm[8]; s8 mcs[4][10]; + s8 ru[7][12]; }; enum mt76_phy_type { From patchwork Tue Apr 13 09:08:38 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 420354 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 1DEC4C433ED for ; Tue, 13 Apr 2021 09:09:04 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 01B0F613B7 for ; Tue, 13 Apr 2021 09:09:03 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S245141AbhDMJJW (ORCPT ); Tue, 13 Apr 2021 05:09:22 -0400 Received: from mail.kernel.org ([198.145.29.99]:44552 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244505AbhDMJJW (ORCPT ); Tue, 13 Apr 2021 05:09:22 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 29A9660FEF; Tue, 13 Apr 2021 09:09:01 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304942; bh=fg+pIbsJUB+YMYTv/ScJd67E6j7+p8pMIQkbn/7H6AA=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=dbLZyNbYW7BMDHOXOGW3/g5sTV/xO4dZb0Xsx4GYkpYFPodqcWU4TOx+5T92ZhHyV Hl/3lFW3ktOh6z7i8cMhlUjDrkrllVO9O81Y5RKWVzrqP+Ujz2Hi02/ZwR9qDDEBPv NyQ8zgEjmm+tIgeLxKi6fN0tsUKUR1PPoF+jGAIFuaxerlNQj/KwIFKTOF6Zpgzug5 9Q5dWsJsy1OqW4DSjn3qv8j53+1HWzkPWlKIRWjA/jvGKw9B/sIgCbu+aOa1OSF0Wn gJkeJovhN56nUESVLktUS4Ee47c5qCsQVUPAbQLrMkUezlzme7BY6+HYQ0+OBTfvLY Uq05VHWa21PJg== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 4/7] mt76: mt7615: implement support for using DT rate power limits Date: Tue, 13 Apr 2021 11:08:38 +0200 Message-Id: <0bb56c92100ae4364f5c8a7627b513a9143c28ff.1618304559.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Felix Fietkau Limits are used to update the channel max_power settings and also passed to the firmware on channel changes Signed-off-by: Felix Fietkau Signed-off-by: Lorenzo Bianconi --- .../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 1e418740c17b..e58f46d6a85b 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 6ca9e9840399..8c0a21e243db 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -2135,16 +2135,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; From patchwork Tue Apr 13 09:08:39 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 421299 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 634D4C433ED for ; Tue, 13 Apr 2021 09:09:06 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 45EE3613B8 for ; Tue, 13 Apr 2021 09:09:06 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S236914AbhDMJJY (ORCPT ); Tue, 13 Apr 2021 05:09:24 -0400 Received: from mail.kernel.org ([198.145.29.99]:44574 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S230229AbhDMJJY (ORCPT ); Tue, 13 Apr 2021 05:09:24 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 35511613B6; Tue, 13 Apr 2021 09:09:03 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304944; bh=WeRIurobnQ3/hlMp5vMAM6xs6GS+WI9TFRpl83nl4/s=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=XGtGlKCcru51WCqxCt6g7uJ+qckuZZsbzJzFfo8+L46nsk/vq1pyDJ2soaj5UofrB H5hR27iRQczfYo/AY5zEISK5L0vQwiJi9nBgN6VUo/tCLLwVir9A6Ug+//dWRy5hNG DeG0mM9AoWsNlbI7RE6TzWskvJ9Jx5cyW5ZVHNxmQWsr3afz0NvAQcYmyHxUy/rY5D wlPaLqzz/BvmajwckYj1l8qsHhwZNuSa2YQ0dMtt61onQ8VaP68knH+67aGBa9+k1c 6YwZBxDxPSxrA1aVQwG+57LGuHNjDRpLY3aJkTN3dBqhyZdz2MjEOVqJdvUaEUDTcQ K5bCmaZmcD9wA== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 5/7] mt76: mt7615: do not use mt7615 single-sku values for mt7663 Date: Tue, 13 Apr 2021 11:08:39 +0200 Message-Id: <512d1c4c0ee8894ce133968c7e26b47b825b50e3.1618304559.git.lorenzo@kernel.org> X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org mt7663 mcu relies on different APIs to configure APIs per-rate power limit respect to mt7615 driver. Signed-off-by: Lorenzo Bianconi --- 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 8c0a21e243db..195596194b51 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mcu.c @@ -2202,6 +2202,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]]; From patchwork Tue Apr 13 09:08:40 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 421298 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI,SPF_HELO_NONE,SPF_PASS,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 413BBC43461 for ; Tue, 13 Apr 2021 09:09:20 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 227CA613B7 for ; Tue, 13 Apr 2021 09:09:20 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S237134AbhDMJJh (ORCPT ); Tue, 13 Apr 2021 05:09:37 -0400 Received: from mail.kernel.org ([198.145.29.99]:44598 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S237040AbhDMJJ2 (ORCPT ); Tue, 13 Apr 2021 05:09:28 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 43EDE613B2; Tue, 13 Apr 2021 09:09:05 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304946; bh=PAXBzfBndjV0ZQWa/TUzbkaiuUpRIr2YL/WTsKU+hJw=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=jywPRalwyUHMf69CN82QGqn1TfrmCWhGqb3liKQYwrY8d8oWwS3NNhFQysf9mATXL IOF1SxITcoux+qdOg5A5VpsQIfZxC+IeCaSL+b5oKh/7yW77kHgWUhf0KGbyY3rql3 qVhAb7pxTBq6NxsOAW2gfTNwLOAVZhGVPloUaEHv/Qs29HDWoaCYgMaSR6NkQHoBtU scjmfBLKtKEu/13l/YFOCiYNTtDwvCjQpTXvmPzfXBqOXCN94NB205KIftzsih7Ce/ NrNp/mDKZprzoG0LsS7VY0rnfbjRoZI3FlBnxDXJ8lI1e+q/WntwgX3fAusEL0lI+G +4yGKcP+5Vukw== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 6/7] mt76: introduce single-sku support for mt7663/mt7921 Date: Tue, 13 Apr 2021 11:08:40 +0200 Message-Id: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org Introduce support for rate-txpower compensation for mt7663/mt7921 chipsets. Rate-txpower limit is specified through dts Signed-off-by: Lorenzo Bianconi --- .../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 e58f46d6a85b..d84662fb0304 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 4892728ad9bb..fdc64993e531 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.c @@ -1564,6 +1564,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 6f9b7807305a..01c458e14dc7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -895,6 +895,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) @@ -997,4 +1019,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 7344cdfb5e47..6dc96dd4651c 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 d9ec7d9bb1c4..8e1891da5c6a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/main.c @@ -182,6 +182,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); From patchwork Tue Apr 13 09:08:41 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Lorenzo Bianconi X-Patchwork-Id: 420353 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-19.0 required=3.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, INCLUDES_CR_TRAILER, INCLUDES_PATCH, MAILING_LIST_MULTI, SPF_HELO_NONE, SPF_PASS, URIBL_BLOCKED, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id 5ABC5C433ED for ; Tue, 13 Apr 2021 09:09:19 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by mail.kernel.org (Postfix) with ESMTP id 3B3DF613B6 for ; Tue, 13 Apr 2021 09:09:19 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S244036AbhDMJJg (ORCPT ); Tue, 13 Apr 2021 05:09:36 -0400 Received: from mail.kernel.org ([198.145.29.99]:44620 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S244480AbhDMJJ2 (ORCPT ); Tue, 13 Apr 2021 05:09:28 -0400 Received: by mail.kernel.org (Postfix) with ESMTPSA id 54217613B6; Tue, 13 Apr 2021 09:09:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=k20201202; t=1618304949; bh=qsz0wGM2ihjdhhrpX6OJ+KFengIv2Q1WFB8f/HKAsW0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=kXTmLFi9/ACdyVhTqXIQ6U0fUXt9hRxHx7SaFfDtFTAzc6zjbQKZXVmwejvdU0kh3 NxSxxwt/eAIxO1PcEZyk3tOEmQnxSPl2xLlcT72xn90bUHoGfTKwZLqRsoeX6TGJiv OnWk079Z28Fp3XcH+E5S4SfhiYAa7yFcrqPsCy4AoH5S20fFIrsVyJTrJEZ532kmwe l0u+uxjgZMXtgOKqmGQFJhjiP7Zwp4QqYQoz5X+fEIjTXRLS3vuaqOaQOY6pOZDPyf rgZLcrrgYVrZ4Oda/62lU1o1wz1hkMd1FrV6YMzUm93GlTPyqFuJpH71gxN/1F/eUY CnhoFFPIL1N0w== From: Lorenzo Bianconi To: nbd@nbd.name Cc: linux-wireless@vger.kernel.org, lorenzo.bianconi@redhat.com, sean.wang@mediatek.com, ryder.lee@mediatek.com, shayne.chen@mediatek.com, devicetree@vger.kernel.org, robh@kernel.org Subject: [PATCH v3 7/7] mt76: mt7921: add dumping Tx power table Date: Tue, 13 Apr 2021 11:08:41 +0200 Message-Id: X-Mailer: git-send-email 2.30.2 In-Reply-To: References: MIME-Version: 1.0 Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Sean Wang Dump the tx power table saved in offload firmware. Signed-off-by: Sean Wang Signed-off-by: Lorenzo Bianconi --- .../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 01c458e14dc7..c056eca6816a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac_mcu.h @@ -564,6 +564,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 b233b12860ef..b5cee20c5f27 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7921/mcu.c @@ -1358,3 +1358,26 @@ int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, return mt76_mcu_skb_send_msg(&dev->mt76, skb, MCU_UNI_CMD_OFFLOAD, true); } + +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 e3d83d3d954c..5cc01efee989 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, @@ -352,4 +382,5 @@ int mt7921_mcu_update_arp_filter(struct ieee80211_hw *hw, struct ieee80211_vif *vif, struct ieee80211_bss_conf *info); int mt7921_wfsys_reset(struct mt7921_dev *dev); +int mt7921_get_txpwr_info(struct mt7921_dev *dev, struct mt7921_txpwr *txpwr); #endif