From nobody Wed Dec 17 08:52:28 2025 Received: from mail.simonwunderlich.de (mail.simonwunderlich.de [23.88.38.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B21C82550AF; Tue, 7 Oct 2025 08:11:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.38.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759824696; cv=none; b=V5+MGVqb1kZJaA1GNVqjeJpPCOhXpRBAc6qN8svvtE5DcsJv6OXqua3IgOtwNjpRqL8VDwfvLD2JrJGW9yTOefXVaB6U4bETr13Z2KyuFVgHMOszUBXHEzGrrbxEWkQDYtmdO/LmIwYYBXIhUzsGIW6bHAz/Fsrskb6HAkd6yCk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759824696; c=relaxed/simple; bh=Zgzq1p3L1CDxfbkdFz0MtUhMwlBzhL5HCmT/wDBTlB0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=JCvWl9kExJQC0uRgrPXBELsMPnvC8VfEEgCc0qSyZyYhq8w37Z2L1J46tpKCtsYRH1mPN0KvIiDVvthxPEFhvm1ZMynswOvTM00Zg0r08TMzgPx9ZNx+l6wISfPFhQZFFvOZz6/J6j/zINBwF4Vej0nhyyajUvvpWWkPw5BBLzs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de; spf=pass smtp.mailfrom=simonwunderlich.de; arc=none smtp.client-ip=23.88.38.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=simonwunderlich.de Received: from sven-desktop.home.narfation.org (p200300c597021aE00000000000000C00.dip0.t-ipconnect.de [IPv6:2003:c5:9702:1ae0::c00]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (prime256v1) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.simonwunderlich.de (Postfix) with ESMTPSA id EEDE0FA130; Tue, 7 Oct 2025 10:11:32 +0200 (CEST) From: "Sven Eckelmann (Plasma Cloud)" Date: Tue, 07 Oct 2025 10:11:14 +0200 Subject: [PATCH mt76 v3 1/3] dt-bindings: net: wireless: mt76: Document power-limits country property Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251007-backoff-table-support-v3-1-fd6e2684988f@simonwunderlich.de> References: <20251007-backoff-table-support-v3-0-fd6e2684988f@simonwunderlich.de> In-Reply-To: <20251007-backoff-table-support-v3-0-fd6e2684988f@simonwunderlich.de> To: Felix Fietkau , Lorenzo Bianconi , Ryder Lee , Shayne Chen , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Maxime Coquelin , Alexandre Torgue , Johannes Berg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, devicetree@vger.kernel.org, "Sven Eckelmann (Plasma Cloud)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=1732; i=se@simonwunderlich.de; h=from:subject:message-id; bh=Zgzq1p3L1CDxfbkdFz0MtUhMwlBzhL5HCmT/wDBTlB0=; b=owGbwMvMwCXmy1+ufVnk62nG02pJDBlPTuuuL2D80DAl4bZujOTXE2xvT79bf/3NN8fGo2eFG iUSZyUUd5SyMIhxMciKKbLsuZJ/fjP7W/nP0z4ehZnDygQyhIGLUwAm8pyP4Sfjdda7jx7NUuwV f7WkIThrful8sSlhTNfq/998Xazwsj2HkeEFe/aKzy+2f9lencT3izNB45Y0V4+LSv3NvRvSpMV alnMDAA== X-Developer-Key: i=se@simonwunderlich.de; a=openpgp; fpr=522D7163831C73A635D12FE5EC371482956781AF The commit 22b980badc0f ("mt76: add functions for parsing rate power limits from DT") added filtering of the power limits based on two properties: * regdomain * country If either the country or the regdomain matches, the power limits are applied and the search is aborted. If none of the two is defined for the power limit, it is a global (or "fallback") power limit. The last "fallback" power limit in the list will be returned when not matching regdomain or country was found. The idea is here to allow to specify "overwriting" country limits in front of the list - just in case a regdomain is shared but a country has additional limitations. But this property was forgotten to be defined in commit 2de6ccebe0e7 ("dt-bindings:net:wireless:mediatek,mt76: introduce power-limits node"). Signed-off-by: Sven Eckelmann (Plasma Cloud) Reviewed-by: Rob Herring (Arm) --- Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml | 6 ++++= ++ 1 file changed, 6 insertions(+) diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.y= aml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml index eabceb849537..82b224c2f6f7 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml @@ -151,6 +151,12 @@ properties: - ETSI - JP =20 + country: + $ref: /schemas/types.yaml#/definitions/string + pattern: '^[A-Z]{2}$' + description: + ISO 3166-1 alpha-2 country code for power limits + patternProperties: "^txpower-[256]g$": type: object --=20 2.47.3 From nobody Wed Dec 17 08:52:28 2025 Received: from mail.simonwunderlich.de (mail.simonwunderlich.de [23.88.38.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 16EF2258CED; Tue, 7 Oct 2025 08:11:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.38.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759824697; cv=none; b=iVM1SEErAPqa2jBiiShYomxDnBhAcAKv5OoBlOPH2qdlEFlZfKeQPVYHeILxlLHKbrVvfQBlhhf93mCrv0bRov3IuBwWZ/sZvGAmUVM0XK+Tlf5OVkAZtHpcf1HhGR+Ob21AWLPzGy2yvNh4a2Dt6yH03t+8GmvIRyNeGmtCtGU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759824697; c=relaxed/simple; bh=JmHhqGG89jO2WbYbTgMaIlIgIBZxFYzyAwDnCRUHBlo=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=mjgq0fngIPyUyOEyb/ri4/DeQ9Jo3DAuU9q8cUstnBcdG94sdnkN3rjNdrp+DAWkBgZ8nF+YEaWpbSvbDPuPJwtE8XCMU7BYVIPZzgT9deqxpdNphTPkM1cDgItbIdHB/lhwF86PDdUg+EMm+l9tbhq7vu9RZs7/ulhEKurt2os= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de; spf=pass smtp.mailfrom=simonwunderlich.de; arc=none smtp.client-ip=23.88.38.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=simonwunderlich.de Received: from sven-desktop.home.narfation.org (p200300C597021AE00000000000000c00.dip0.t-ipconnect.de [IPv6:2003:c5:9702:1ae0::c00]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (prime256v1) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.simonwunderlich.de (Postfix) with ESMTPSA id 55A69FA182; Tue, 7 Oct 2025 10:11:34 +0200 (CEST) From: "Sven Eckelmann (Plasma Cloud)" Date: Tue, 07 Oct 2025 10:11:15 +0200 Subject: [PATCH mt76 v3 2/3] dt-bindings: net: wireless: mt76: introduce backoff limit properties Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251007-backoff-table-support-v3-2-fd6e2684988f@simonwunderlich.de> References: <20251007-backoff-table-support-v3-0-fd6e2684988f@simonwunderlich.de> In-Reply-To: <20251007-backoff-table-support-v3-0-fd6e2684988f@simonwunderlich.de> To: Felix Fietkau , Lorenzo Bianconi , Ryder Lee , Shayne Chen , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Maxime Coquelin , Alexandre Torgue , Johannes Berg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, devicetree@vger.kernel.org, "Sven Eckelmann (Plasma Cloud)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=3956; i=se@simonwunderlich.de; h=from:subject:message-id; bh=JmHhqGG89jO2WbYbTgMaIlIgIBZxFYzyAwDnCRUHBlo=; b=owGbwMvMwCXmy1+ufVnk62nG02pJDBlPTuu+idRU67z180mKioCT4VH/1EdOHvJrlC3SPqpIN XzS2b6po5SFQYyLQVZMkWXPlfzzm9nfyn+e9vEozBxWJpAhDFycAjCRS1GMDK9S9V2ePS4wvPVt 8T6/3YUptzZe7FbYvejzJNYuh36VTHaGf/aP7cVCDredkss+HSu91kPrUJ9c5ev92zb+7l9z58y ZFzwA X-Developer-Key: i=se@simonwunderlich.de; a=openpgp; fpr=522D7163831C73A635D12FE5EC371482956781AF Introduce path backoff limit properties in mt76 binding in order to specify beamforming and non-beamforming backoff limits for 802.11n/ac/ax. Reviewed-by: Rob Herring (Arm) Signed-off-by: Sven Eckelmann (Plasma Cloud) --- .../bindings/net/wireless/mediatek,mt76.yaml | 60 ++++++++++++++++++= ++++ 1 file changed, 60 insertions(+) diff --git a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.y= aml b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml index 82b224c2f6f7..ae6b97cdc44b 100644 --- a/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml +++ b/Documentation/devicetree/bindings/net/wireless/mediatek,mt76.yaml @@ -216,6 +216,66 @@ properties: minItems: 13 maxItems: 13 =20 + paths-cck: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 4 + maxItems: 4 + description: + 4 half-dBm backoff values (1 - 4 antennas, single sp= acial + stream) + + paths-ofdm: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 4 + maxItems: 4 + description: + 4 half-dBm backoff values (1 - 4 antennas, single sp= acial + stream) + + paths-ofdm-bf: + $ref: /schemas/types.yaml#/definitions/uint8-array + minItems: 4 + maxItems: 4 + description: + 4 half-dBm backoff values for beamforming + (1 - 4 antennas, single spacial stream) + + paths-ru: + $ref: /schemas/types.yaml#/definitions/uint8-matrix + description: + Sets of half-dBm backoff values for 802.11ax rates f= or + 1T1ss (aka 1 transmitting antenna with 1 spacial str= eam), + 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3T3ss, 4T3= ss + and 4T4ss. + Each set starts with the number of channel bandwidth= or + resource unit settings for which the rate set applie= s, + followed by 10 power limit values. The order of the + channel resource unit settings is RU26, RU52, RU106, + RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160. + minItems: 1 + maxItems: 7 + items: + minItems: 11 + maxItems: 11 + + paths-ru-bf: + $ref: /schemas/types.yaml#/definitions/uint8-matrix + description: + Sets of half-dBm backoff (beamforming) values for 80= 2.11ax + rates for 1T1ss (aka 1 transmitting antenna with 1 s= pacial + stream), 2T1ss, 3T1ss, 4T1ss, 2T2ss, 3T2ss, 4T2ss, 3= T3ss, + 4T3ss and 4T4ss. + Each set starts with the number of channel bandwidth= or + resource unit settings for which the rate set applie= s, + followed by 10 power limit values. The order of the + channel resource unit settings is RU26, RU52, RU106, + RU242/SU20, RU484/SU40, RU996/SU80 and RU2x996/SU160. + minItems: 1 + maxItems: 7 + items: + minItems: 11 + maxItems: 11 + txs-delta: $ref: /schemas/types.yaml#/definitions/uint32-array description: --=20 2.47.3 From nobody Wed Dec 17 08:52:28 2025 Received: from mail.simonwunderlich.de (mail.simonwunderlich.de [23.88.38.48]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA8ED261B70; Tue, 7 Oct 2025 08:11:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=23.88.38.48 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759824702; cv=none; b=EktumrqhUSLDkrxOJqU9OnDaAebt273lvPZljDHptT7Nxh64F9nuGARI2MQelH9ccXSQoQZ9VL22XLTc2RGqn+nQdsRD1obK8P9WAtDZTQGT/voU+OBWsskxHpf47YZqdTQYZldGiuZkXiQyXihRH9nh4qzuaOD/A0EZmAWTeAI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1759824702; c=relaxed/simple; bh=uPZ1RFWAyi2zaF95vgdrnPgW5I1R9qdPrmbRHP6UFu0=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=GeMoajvkWF72tbCEkIiokZ7jnM1t+/+TQQhS8wKTw8MVQLqSlxnp/kZhTMvR3ZkRyh/AnyH+YbXO6oKd095/IM42tFW5qbRwt84qQRDpOWCnPkLErp/OwDcGZ+eN0pE/q6WRV41p9cH2fe5tqClSYTUBJvNkygcgkTwiRm8ZTXM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de; spf=pass smtp.mailfrom=simonwunderlich.de; arc=none smtp.client-ip=23.88.38.48 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=simonwunderlich.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=simonwunderlich.de Received: from sven-desktop.home.narfation.org (p200300c597021Ae00000000000000c00.dip0.t-ipconnect.de [IPv6:2003:c5:9702:1ae0::c00]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange ECDHE (prime256v1) server-signature RSA-PSS (4096 bits) server-digest SHA256) (No client certificate requested) by mail.simonwunderlich.de (Postfix) with ESMTPSA id 4CE97FA184; Tue, 7 Oct 2025 10:11:38 +0200 (CEST) From: "Sven Eckelmann (Plasma Cloud)" Date: Tue, 07 Oct 2025 10:11:16 +0200 Subject: [PATCH mt76 v3 3/3] wifi: mt76: mt7915: add bf backoff limit table support Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20251007-backoff-table-support-v3-3-fd6e2684988f@simonwunderlich.de> References: <20251007-backoff-table-support-v3-0-fd6e2684988f@simonwunderlich.de> In-Reply-To: <20251007-backoff-table-support-v3-0-fd6e2684988f@simonwunderlich.de> To: Felix Fietkau , Lorenzo Bianconi , Ryder Lee , Shayne Chen , Sean Wang , Matthias Brugger , AngeloGioacchino Del Regno , Maxime Coquelin , Alexandre Torgue , Johannes Berg , Rob Herring , Krzysztof Kozlowski , Conor Dooley Cc: linux-wireless@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, linux-mediatek@lists.infradead.org, linux-stm32@st-md-mailman.stormreply.com, devicetree@vger.kernel.org, "Sven Eckelmann (Plasma Cloud)" X-Mailer: b4 0.14.3 X-Developer-Signature: v=1; a=openpgp-sha256; l=21466; i=se@simonwunderlich.de; h=from:subject:message-id; bh=AZfICyDNGqNlPS0p7hnQCldD1Ap4MuqI8Wn8Wcr2Tlc=; b=owGbwMvMwCXmy1+ufVnk62nG02pJDBlPTuvO5U6PCJmt7vA7zeDFf/m5v+97tLzNXSQd/7295 Pb0V+q3OkpZGMS4GGTFFFn2XMk/v5n9rfznaR+PwsxhZQIZwsDFKQATyfnKyHD1+3a+lY4zXdjj mDoWMkmuW7nl4cfuw0uNguy3Tdy0ZsJNhv8xAc/uzNi0ylzBX739x39ZwUpFbdZ61YropOOT7r1 4d4MJAA== X-Developer-Key: i=se@simonwunderlich.de; a=openpgp; fpr=522D7163831C73A635D12FE5EC371482956781AF From: Shayne Chen The commit 22b980badc0f ("mt76: add functions for parsing rate power limits from DT") introduced generic support for rates limits in the devicetree. But the mt7915 supports beamforming and has another table for configuring the backoff limits. These can be configured in the DT with the paths-* properties. The path-*-bf are the ones relevant for beamforming and the ones without -bf suffix for "traditional" path backoff. Signed-off-by: Shayne Chen Signed-off-by: Sven Eckelmann (Plasma Cloud) --- drivers/net/wireless/mediatek/mt76/debugfs.c | 4 +- drivers/net/wireless/mediatek/mt76/eeprom.c | 38 ++++- drivers/net/wireless/mediatek/mt76/mt76.h | 8 + .../net/wireless/mediatek/mt76/mt7915/debugfs.c | 74 ++++++++- drivers/net/wireless/mediatek/mt76/mt7915/init.c | 7 + drivers/net/wireless/mediatek/mt76/mt7915/main.c | 2 +- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 182 ++++++++++++++++-= ---- drivers/net/wireless/mediatek/mt76/mt7915/mcu.h | 6 + drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h | 9 +- .../net/wireless/mediatek/mt76/mt7915/testmode.c | 2 +- 10 files changed, 277 insertions(+), 55 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/debugfs.c b/drivers/net/wir= eless/mediatek/mt76/debugfs.c index b6a2746c187d..bee1177594d3 100644 --- a/drivers/net/wireless/mediatek/mt76/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/debugfs.c @@ -93,9 +93,9 @@ void mt76_seq_puts_array(struct seq_file *file, const cha= r *str, { int i; =20 - seq_printf(file, "%10s:", str); + seq_printf(file, "%16s:", str); for (i =3D 0; i < len; i++) - seq_printf(file, " %2d", val[i]); + seq_printf(file, " %4d", val[i]); seq_puts(file, "\n"); } EXPORT_SYMBOL_GPL(mt76_seq_puts_array); diff --git a/drivers/net/wireless/mediatek/mt76/eeprom.c b/drivers/net/wire= less/mediatek/mt76/eeprom.c index 6ce8e4af18fe..cbda19a86882 100644 --- a/drivers/net/wireless/mediatek/mt76/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/eeprom.c @@ -324,9 +324,10 @@ mt76_apply_array_limit(s8 *pwr, size_t pwr_len, const = s8 *data, static void mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s8 pwr_num, const s8 *data, size_t len, s8 target_power, - s8 nss_delta, s8 *max_power) + s8 nss_delta) { int i, cur; + s8 max_power =3D -128; =20 if (!data) return; @@ -337,7 +338,7 @@ mt76_apply_multi_array_limit(s8 *pwr, size_t pwr_len, s= 8 pwr_num, break; =20 mt76_apply_array_limit(pwr + pwr_len * i, pwr_len, data + 1, - target_power, nss_delta, max_power); + target_power, nss_delta, &max_power); if (--cur > 0) continue; =20 @@ -364,12 +365,16 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, char band; size_t len; s8 max_power =3D 0; + s8 max_power_backoff =3D -127; s8 txs_delta; + int n_chains =3D hweight16(phy->chainmask); + s8 target_power_combine =3D target_power + mt76_tx_power_path_delta(n_cha= ins); =20 if (!mcs_rates) mcs_rates =3D 10; =20 - memset(dest, target_power, sizeof(*dest)); + memset(dest, target_power, sizeof(*dest) - sizeof(dest->path)); + memset(&dest->path, 0, sizeof(dest->path)); =20 if (!IS_ENABLED(CONFIG_OF)) return target_power; @@ -415,12 +420,35 @@ s8 mt76_get_rate_power_limits(struct mt76_phy *phy, val =3D mt76_get_of_array_s8(np, "rates-mcs", &len, mcs_rates + 1); 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); + target_power, txs_delta); =20 val =3D mt76_get_of_array_s8(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); + target_power, txs_delta); + + max_power_backoff =3D max_power; + val =3D mt76_get_of_array_s8(np, "paths-cck", &len, ARRAY_SIZE(dest->path= .cck)); + mt76_apply_array_limit(dest->path.cck, ARRAY_SIZE(dest->path.cck), val, + target_power_combine, txs_delta, &max_power_backoff); + + val =3D mt76_get_of_array_s8(np, "paths-ofdm", &len, ARRAY_SIZE(dest->pat= h.ofdm)); + mt76_apply_array_limit(dest->path.ofdm, ARRAY_SIZE(dest->path.ofdm), val, + target_power_combine, txs_delta, &max_power_backoff); + + val =3D mt76_get_of_array_s8(np, "paths-ofdm-bf", &len, ARRAY_SIZE(dest->= path.ofdm_bf)); + mt76_apply_array_limit(dest->path.ofdm_bf, ARRAY_SIZE(dest->path.ofdm_bf)= , val, + target_power_combine, txs_delta, &max_power_backoff); + + val =3D mt76_get_of_array_s8(np, "paths-ru", &len, ARRAY_SIZE(dest->path.= ru[0]) + 1); + mt76_apply_multi_array_limit(dest->path.ru[0], ARRAY_SIZE(dest->path.ru[0= ]), + ARRAY_SIZE(dest->path.ru), val, len, + target_power_combine, txs_delta); + + val =3D mt76_get_of_array_s8(np, "paths-ru-bf", &len, ARRAY_SIZE(dest->pa= th.ru_bf[0]) + 1); + mt76_apply_multi_array_limit(dest->path.ru_bf[0], ARRAY_SIZE(dest->path.r= u_bf[0]), + ARRAY_SIZE(dest->path.ru_bf), val, len, + target_power_combine, txs_delta); =20 return max_power; } diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wirele= ss/mediatek/mt76/mt76.h index e0d50b58cd01..86b812f68c97 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -1113,6 +1113,14 @@ struct mt76_power_limits { s8 mcs[4][10]; s8 ru[7][12]; s8 eht[16][16]; + + struct { + s8 cck[4]; + s8 ofdm[4]; + s8 ofdm_bf[4]; + s8 ru[7][10]; + s8 ru_bf[7][10]; + } path; }; =20 struct mt76_ethtool_worker_info { diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c b/drivers/= net/wireless/mediatek/mt76/mt7915/debugfs.c index b287b7d9394e..6ff0d262c28a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/debugfs.c @@ -1008,7 +1008,7 @@ mt7915_rate_txpower_get(struct file *file, char __use= r *user_buf, if (!buf) return -ENOMEM; =20 - ret =3D mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr)); + ret =3D mt7915_mcu_get_txpower_sku(phy, txpwr, sizeof(txpwr), TX_POWER_IN= FO_RATE); if (ret) goto out; =20 @@ -1118,7 +1118,7 @@ mt7915_rate_txpower_set(struct file *file, const char= __user *user_buf, =20 mutex_lock(&dev->mt76.mutex); ret =3D mt7915_mcu_get_txpower_sku(phy, req.txpower_sku, - sizeof(req.txpower_sku)); + sizeof(req.txpower_sku), TX_POWER_INFO_RATE); if (ret) goto out; =20 @@ -1160,7 +1160,7 @@ mt7915_rate_txpower_set(struct file *file, const char= __user *user_buf, return ret ? ret : count; } =20 -static const struct file_operations mt7915_rate_txpower_fops =3D { +static const struct file_operations mt7915_txpower_fops =3D { .write =3D mt7915_rate_txpower_set, .read =3D mt7915_rate_txpower_get, .open =3D simple_open, @@ -1168,6 +1168,70 @@ static const struct file_operations mt7915_rate_txpo= wer_fops =3D { .llseek =3D default_llseek, }; =20 +static int +mt7915_path_txpower_show(struct seq_file *file) +{ + struct mt7915_phy *phy =3D file->private; + s8 txpower[MT7915_SKU_PATH_NUM], *buf =3D txpower; + int ret; + +#define PATH_POWER_SHOW(_name, _len, _skip) do { \ + size_t __len =3D (_len); \ + if (_skip) { \ + buf -=3D 1; \ + *buf =3D 0; \ + } \ + mt76_seq_puts_array(file, _name, buf, __len); \ + buf +=3D __len; \ + } while (0) + + seq_printf(file, "\n%*c", 18, ' '); + seq_puts(file, "1T1S/2T1S/3T1S/4T1S/2T2S/3T2S/4T2S/3T3S/4T3S/4T4S\n"); + ret =3D mt7915_mcu_get_txpower_sku(phy, txpower, sizeof(txpower), + TX_POWER_INFO_PATH); + if (ret) + return ret; + + PATH_POWER_SHOW("CCK", 4, 0); + PATH_POWER_SHOW("OFDM", 4, 0); + PATH_POWER_SHOW("BF-OFDM", 4, 1); + + PATH_POWER_SHOW("HT/VHT20", 10, 0); + PATH_POWER_SHOW("BF-HT/VHT20", 10, 1); + PATH_POWER_SHOW("HT/VHT40", 10, 0); + PATH_POWER_SHOW("BF-HT/VHT40", 10, 1); + + PATH_POWER_SHOW("BW20/RU242", 10, 0); + PATH_POWER_SHOW("BF-BW20/RU242", 10, 1); + PATH_POWER_SHOW("BW40/RU484", 10, 0); + PATH_POWER_SHOW("BF-BW40/RU484", 10, 1); + PATH_POWER_SHOW("BW80/RU996", 10, 0); + PATH_POWER_SHOW("BF-BW80/RU996", 10, 1); + PATH_POWER_SHOW("BW160/RU2x996", 10, 0); + PATH_POWER_SHOW("BF-BW160/RU2x996", 10, 1); + PATH_POWER_SHOW("RU26", 10, 0); + PATH_POWER_SHOW("BF-RU26", 10, 0); + PATH_POWER_SHOW("RU52", 10, 0); + PATH_POWER_SHOW("BF-RU52", 10, 0); + PATH_POWER_SHOW("RU106", 10, 0); + PATH_POWER_SHOW("BF-RU106", 10, 0); +#undef PATH_POWER_SHOW + + return 0; +} + +static int +mt7915_txpower_path_show(struct seq_file *file, void *data) +{ + struct mt7915_phy *phy =3D file->private; + + seq_printf(file, "\nBand %d\n", phy !=3D &phy->dev->phy); + + return mt7915_path_txpower_show(file); +} + +DEFINE_SHOW_ATTRIBUTE(mt7915_txpower_path); + static int mt7915_twt_stats(struct seq_file *s, void *data) { @@ -1254,7 +1318,9 @@ int mt7915_init_debugfs(struct mt7915_phy *phy) debugfs_create_file("implicit_txbf", 0600, dir, dev, &fops_implicit_txbf); debugfs_create_file("txpower_sku", 0400, dir, phy, - &mt7915_rate_txpower_fops); + &mt7915_txpower_fops); + debugfs_create_file("txpower_path", 0400, dir, phy, + &mt7915_txpower_path_fops); debugfs_create_devm_seqfile(dev->mt76.dev, "twt_stats", dir, mt7915_twt_stats); debugfs_create_file("rf_regval", 0600, dir, dev, &fops_rf_regval); diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net= /wireless/mediatek/mt76/mt7915/init.c index 5ea8b46e092e..1ac7ee2922b0 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c @@ -289,6 +289,8 @@ static void __mt7915_init_txpower(struct mt7915_phy *ph= y, int pwr_delta =3D mt7915_eeprom_get_power_delta(dev, sband->band); struct mt76_power_limits limits; =20 + phy->sku_limit_en =3D true; + phy->sku_path_en =3D true; for (i =3D 0; i < sband->n_channels; i++) { struct ieee80211_channel *chan =3D &sband->channels[i]; u32 target_power =3D 0; @@ -305,6 +307,11 @@ static void __mt7915_init_txpower(struct mt7915_phy *p= hy, target_power =3D mt76_get_rate_power_limits(phy->mt76, chan, &limits, target_power); + + /* MT7915N can not enable Backoff table without setting value in dts */ + if (!limits.path.ofdm[0]) + phy->sku_path_en =3D false; + target_power +=3D path_delta; target_power =3D DIV_ROUND_UP(target_power, 2); chan->max_power =3D min_t(int, chan->max_reg_power, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net= /wireless/mediatek/mt76/mt7915/main.c index fe0639c14bf9..fa135447a263 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -73,7 +73,7 @@ int mt7915_run(struct ieee80211_hw *hw) if (ret) goto out; =20 - ret =3D mt7915_mcu_set_sku_en(phy, true); + ret =3D mt7915_mcu_set_sku_en(phy); if (ret) goto out; =20 diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/= wireless/mediatek/mt76/mt7915/mcu.c index c1fdd3c4f1ba..673338d508a8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -3336,7 +3336,8 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy *p= hy, int ret; s8 txpower_sku[MT7915_SKU_RATE_NUM]; =20 - ret =3D mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku)); + ret =3D mt7915_mcu_get_txpower_sku(phy, txpower_sku, sizeof(txpower_sku), + TX_POWER_INFO_RATE); if (ret) return ret; =20 @@ -3376,51 +3377,136 @@ int mt7915_mcu_set_txpower_frame(struct mt7915_phy= *phy, sizeof(req), true); } =20 +static void +mt7915_update_txpower(struct mt7915_phy *phy, int tx_power) +{ + struct mt76_phy *mphy =3D phy->mt76; + struct ieee80211_channel *chan =3D mphy->main_chandef.chan; + int chain_idx, val, e2p_power_limit =3D 0; + + if (!chan) { + mphy->txpower_cur =3D tx_power; + return; + } + + for (chain_idx =3D 0; chain_idx < hweight16(mphy->chainmask); chain_idx++= ) { + val =3D mt7915_eeprom_get_target_power(phy->dev, chan, chain_idx); + val +=3D mt7915_eeprom_get_power_delta(phy->dev, chan->band); + + e2p_power_limit =3D max_t(int, e2p_power_limit, val); + } + + if (phy->sku_limit_en) + mphy->txpower_cur =3D min_t(int, e2p_power_limit, tx_power); + else + mphy->txpower_cur =3D e2p_power_limit; +} + int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy) { +#define TX_POWER_LIMIT_TABLE_RATE 0 +#define TX_POWER_LIMIT_TABLE_PATH 1 struct mt7915_dev *dev =3D phy->dev; struct mt76_phy *mphy =3D phy->mt76; struct ieee80211_hw *hw =3D mphy->hw; - struct mt7915_mcu_txpower_sku req =3D { + struct mt7915_sku_val { + u8 format_id; + u8 limit_type; + u8 band_idx; + } __packed hdr =3D { .format_id =3D TX_POWER_LIMIT_TABLE, + .limit_type =3D TX_POWER_LIMIT_TABLE_RATE, .band_idx =3D phy->mt76->band_idx, }; - struct mt76_power_limits limits_array; - s8 *la =3D (s8 *)&limits_array; - int i, idx; - int tx_power; + int i, ret, tx_power; + const u8 *len =3D mt7915_sku_group_len; + struct mt76_power_limits la =3D {}; + struct sk_buff *skb; =20 tx_power =3D mt76_get_power_bound(mphy, hw->conf.power_level); - tx_power =3D mt76_get_rate_power_limits(mphy, mphy->chandef.chan, - &limits_array, tx_power); - mphy->txpower_cur =3D tx_power; - - for (i =3D 0, idx =3D 0; i < ARRAY_SIZE(mt7915_sku_group_len); i++) { - u8 mcs_num, len =3D mt7915_sku_group_len[i]; - int j; - - if (i >=3D SKU_HT_BW20 && i <=3D SKU_VHT_BW160) { - mcs_num =3D 10; - - if (i =3D=3D SKU_HT_BW20 || i =3D=3D SKU_VHT_BW20) - la =3D (s8 *)&limits_array + 12; - } else { - mcs_num =3D len; - } - - for (j =3D 0; j < min_t(u8, mcs_num, len); j++) - req.txpower_sku[idx + j] =3D la[j]; - - la +=3D mcs_num; - idx +=3D len; + if (phy->sku_limit_en) { + tx_power =3D mt76_get_rate_power_limits(mphy, mphy->chandef.chan, + &la, tx_power); + mt7915_update_txpower(phy, tx_power); + } else { + mt7915_update_txpower(phy, tx_power); + return 0; } =20 - return mt76_mcu_send_msg(&dev->mt76, - MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, - sizeof(req), true); + skb =3D mt76_mcu_msg_alloc(&dev->mt76, NULL, + sizeof(hdr) + MT7915_SKU_RATE_NUM); + if (!skb) + return -ENOMEM; + + skb_put_data(skb, &hdr, sizeof(hdr)); + skb_put_data(skb, &la.cck, len[SKU_CCK] + len[SKU_OFDM]); + skb_put_data(skb, &la.mcs[0], len[SKU_HT_BW20]); + skb_put_data(skb, &la.mcs[1], len[SKU_HT_BW40]); + + /* vht */ + for (i =3D 0; i < 4; i++) { + skb_put_data(skb, &la.mcs[i], sizeof(la.mcs[i])); + skb_put_zero(skb, 2); /* padding */ + } + + /* he */ + skb_put_data(skb, &la.ru[0], sizeof(la.ru)); + ret =3D mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), true); + if (ret) + return ret; + + /* only set per-path power table when it's configured */ + if (!phy->sku_path_en) + return 0; + + skb =3D mt76_mcu_msg_alloc(&dev->mt76, NULL, + sizeof(hdr) + MT7915_SKU_PATH_NUM); + if (!skb) + return -ENOMEM; + + hdr.limit_type =3D TX_POWER_LIMIT_TABLE_PATH; + skb_put_data(skb, &hdr, sizeof(hdr)); + skb_put_data(skb, &la.path.cck, sizeof(la.path.cck)); + skb_put_data(skb, &la.path.ofdm, sizeof(la.path.ofdm)); + skb_put_data(skb, &la.path.ofdm_bf[1], sizeof(la.path.ofdm_bf) - 1); + + /* HT20 and HT40 */ + skb_put_data(skb, &la.path.ru[3], sizeof(la.path.ru[3])); + skb_put_data(skb, &la.path.ru_bf[3][1], sizeof(la.path.ru_bf[3]) - 1); + skb_put_data(skb, &la.path.ru[4], sizeof(la.path.ru[4])); + skb_put_data(skb, &la.path.ru_bf[4][1], sizeof(la.path.ru_bf[4]) - 1); + + /* start from non-bf and bf fields of + * BW20/RU242, BW40/RU484, BW80/RU996, BW160/RU2x996, + * RU26, RU52, and RU106 + */ + + for (i =3D 0; i < 8; i++) { + bool bf =3D i % 2; + u8 idx =3D (i + 6) / 2; + s8 *buf =3D bf ? la.path.ru_bf[idx] : la.path.ru[idx]; + /* The non-bf fields of RU26 to RU106 are special cases */ + if (bf) + skb_put_data(skb, buf + 1, 9); + else + skb_put_data(skb, buf, 10); + } + + for (i =3D 0; i < 6; i++) { + bool bf =3D i % 2; + u8 idx =3D i / 2; + s8 *buf =3D bf ? la.path.ru_bf[idx] : la.path.ru[idx]; + + skb_put_data(skb, buf, 10); + } + + return mt76_mcu_skb_send_msg(&dev->mt76, skb, + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), true); } =20 -int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int le= n) +int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int le= n, + u8 category) { #define RATE_POWER_INFO 2 struct mt7915_dev *dev =3D phy->dev; @@ -3431,10 +3517,9 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *ph= y, s8 *txpower, int len) u8 _rsv; } __packed req =3D { .format_id =3D TX_POWER_LIMIT_INFO, - .category =3D RATE_POWER_INFO, + .category =3D category, .band_idx =3D phy->mt76->band_idx, }; - s8 txpower_sku[MT7915_SKU_RATE_NUM][2]; struct sk_buff *skb; int ret, i; =20 @@ -3444,9 +3529,15 @@ int mt7915_mcu_get_txpower_sku(struct mt7915_phy *ph= y, s8 *txpower, int len) if (ret) return ret; =20 - memcpy(txpower_sku, skb->data + 4, sizeof(txpower_sku)); - for (i =3D 0; i < len; i++) - txpower[i] =3D txpower_sku[i][req.band_idx]; + if (category =3D=3D TX_POWER_INFO_RATE) { + s8 res[MT7915_SKU_RATE_NUM][2]; + + memcpy(res, skb->data + 4, sizeof(res)); + for (i =3D 0; i < len; i++) + txpower[i] =3D res[i][req.band_idx]; + } else if (category =3D=3D TX_POWER_INFO_PATH) { + memcpy(txpower, skb->data + 4, len); + } =20 dev_kfree_skb(skb); =20 @@ -3475,7 +3566,7 @@ int mt7915_mcu_set_test_param(struct mt7915_dev *dev,= u8 param, bool test_mode, sizeof(req), false); } =20 -int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable) +int mt7915_mcu_set_sku_en(struct mt7915_phy *phy) { struct mt7915_dev *dev =3D phy->dev; struct mt7915_sku { @@ -3484,10 +3575,21 @@ int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, b= ool enable) u8 band_idx; u8 rsv; } __packed req =3D { - .format_id =3D TX_POWER_LIMIT_ENABLE, .band_idx =3D phy->mt76->band_idx, - .sku_enable =3D enable, }; + int ret; + + req.sku_enable =3D phy->sku_limit_en; + req.format_id =3D TX_POWER_LIMIT_ENABLE; + + ret =3D mt76_mcu_send_msg(&dev->mt76, + MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, + sizeof(req), true); + if (ret) + return ret; + + req.sku_enable =3D phy->sku_path_en; + req.format_id =3D TX_POWER_LIMIT_PATH_ENABLE; =20 return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD(TX_POWER_FEATURE_CTRL), &req, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/= wireless/mediatek/mt76/mt7915/mcu.h index 086ad89ecd91..b72535efc6d7 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -429,12 +429,18 @@ enum { =20 enum { TX_POWER_LIMIT_ENABLE, + TX_POWER_LIMIT_PATH_ENABLE =3D 0x3, TX_POWER_LIMIT_TABLE =3D 0x4, TX_POWER_LIMIT_INFO =3D 0x7, TX_POWER_LIMIT_FRAME =3D 0x11, TX_POWER_LIMIT_FRAME_MIN =3D 0x12, }; =20 +enum { + TX_POWER_INFO_PATH =3D 1, + TX_POWER_INFO_RATE, +}; + enum { SPR_ENABLE =3D 0x1, SPR_ENABLE_SD =3D 0x3, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/n= et/wireless/mediatek/mt76/mt7915/mt7915.h index 2e94347c46d6..b15d31d36a87 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h @@ -70,6 +70,7 @@ #define MT7915_CDEV_THROTTLE_MAX 99 =20 #define MT7915_SKU_RATE_NUM 161 +#define MT7915_SKU_PATH_NUM 185 =20 #define MT7915_MAX_TWT_AGRT 16 #define MT7915_MAX_STA_TWT_AGRT 8 @@ -223,6 +224,9 @@ struct mt7915_phy { struct mt76_mib_stats mib; struct mt76_channel_state state_ts; =20 + bool sku_limit_en:1; + bool sku_path_en:1; + #ifdef CONFIG_NL80211_TESTMODE struct { u32 *reg_backup; @@ -491,9 +495,10 @@ int mt7915_mcu_set_mac(struct mt7915_dev *dev, int ban= d, bool enable, int mt7915_mcu_set_test_param(struct mt7915_dev *dev, u8 param, bool test_= mode, u8 en); int mt7915_mcu_set_ser(struct mt7915_dev *dev, u8 action, u8 set, u8 band); -int mt7915_mcu_set_sku_en(struct mt7915_phy *phy, bool enable); +int mt7915_mcu_set_sku_en(struct mt7915_phy *phy); int mt7915_mcu_set_txpower_sku(struct mt7915_phy *phy); -int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int le= n); +int mt7915_mcu_get_txpower_sku(struct mt7915_phy *phy, s8 *txpower, int le= n, + u8 category); int mt7915_mcu_set_txpower_frame_min(struct mt7915_phy *phy, s8 txpower); int mt7915_mcu_set_txpower_frame(struct mt7915_phy *phy, struct ieee80211_vif *vif, diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c b/drivers= /net/wireless/mediatek/mt76/mt7915/testmode.c index d534fff5c952..5836b9733f27 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/testmode.c @@ -409,7 +409,7 @@ mt7915_tm_init(struct mt7915_phy *phy, bool en) if (!test_bit(MT76_STATE_RUNNING, &phy->mt76->state)) return; =20 - mt7915_mcu_set_sku_en(phy, !en); + mt7915_mcu_set_sku_en(phy); =20 mt7915_tm_mode_ctrl(dev, en); mt7915_tm_reg_backup_restore(phy); --=20 2.47.3