public inbox for linux-wireless@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH wireless] wifi: mt76: mt7915: expose all physical chains via available_antennas
@ 2026-04-07  1:43 Joshua Klinesmith
  0 siblings, 0 replies; only message in thread
From: Joshua Klinesmith @ 2026-04-07  1:43 UTC (permalink / raw)
  To: linux-wireless
  Cc: nbd, lorenzo, ryder.lee, shayne.chen, sean.wang,
	Joshua Klinesmith

On MT7916/MT7981 3T3R variants with 2 spatial streams on the 5 GHz
band, wiphy->available_antennas_{tx,rx} is set from antenna_mask which
is derived from NSS, reporting only 2 available antennas. This
contradicts get_antenna() which already returns the full 3-chain
chainmask, causing a mismatch visible in "iw list":

  Available Antennas: TX 0x3 RX 0x3
  Configured Antennas: TX 0x1c RX 0x1c

Station signal reporting also only includes 2 per-chain RSSI values
instead of all 3.

Set available_antennas from chainmask instead of antenna_mask, matching
the approach used by the mt7996 driver. Save the original antenna_mask
at EEPROM parse time so set_antenna can cap it to preserve correct
HT/VHT/HE stream capability announcements. The existing 3T3R special
case in set_antenna becomes unnecessary with all chains exposed.

Update RX status chain reporting and ACK signal aggregation to use
the physical chain count so all receive chains contribute. Vendor
driver analysis confirms the hardware populates all RCPI fields in
the P-RXV unconditionally.

Fixes: a7ec8bcf0003 ("wifi: mt76: mt7915: rework eeprom tx paths and streams init")
Link: https://github.com/openwrt/openwrt/issues/19323
Signed-off-by: Joshua Klinesmith <joshuaklinesmith@gmail.com>
---
 .../net/wireless/mediatek/mt76/mt7915/eeprom.c    |  1 +
 drivers/net/wireless/mediatek/mt76/mt7915/init.c  |  4 ++--
 drivers/net/wireless/mediatek/mt76/mt7915/mac.c   |  5 +++--
 drivers/net/wireless/mediatek/mt76/mt7915/main.c  | 15 ++++-----------
 .../net/wireless/mediatek/mt76/mt7915/mt7915.h    |  2 ++
 5 files changed, 12 insertions(+), 15 deletions(-)

diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
index eb92cbf1a284..db6788a7ebc3 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/eeprom.c
@@ -260,6 +260,7 @@ void mt7915_eeprom_parse_hw_cap(struct mt7915_dev *dev,
 	if (band)
 		mphy->chainmask <<= dev->chainshift;
 	mphy->antenna_mask = BIT(nss) - 1;
+	phy->orig_antenna_mask = mphy->antenna_mask;
 	dev->chainmask |= mphy->chainmask;
 	dev->chainshift = hweight8(dev->mphy.chainmask);
 }
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/init.c b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
index 22443cbc74ad..ffcd3871e289 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/init.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/init.c
@@ -470,8 +470,8 @@ mt7915_init_wiphy(struct mt7915_phy *phy)
 	mt7915_set_stream_he_caps(phy);
 	mt7915_init_txpower(phy);
 
-	wiphy->available_antennas_rx = phy->mt76->antenna_mask;
-	wiphy->available_antennas_tx = phy->mt76->antenna_mask;
+	wiphy->available_antennas_rx = phy->mt76->chainmask;
+	wiphy->available_antennas_tx = phy->mt76->chainmask;
 
 	/* init led callbacks */
 	if (IS_ENABLED(CONFIG_MT76_LEDS)) {
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
index cefe56c05731..34a0690c5864 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mac.c
@@ -224,7 +224,8 @@ static void mt7915_mac_sta_poll(struct mt7915_dev *dev)
 		rssi[3] = to_rssi(GENMASK(31, 14), val);
 
 		msta->ack_signal =
-			mt76_rx_signal(msta->vif->phy->mt76->antenna_mask, rssi);
+			mt76_rx_signal(BIT(hweight16(msta->vif->phy->mt76->chainmask)) - 1,
+				       rssi);
 
 		ewma_avg_signal_add(&msta->avg_ack_signal, -msta->ack_signal);
 	}
@@ -450,7 +451,7 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
 		if (v0 & MT_PRXV_HT_AD_CODE)
 			status->enc_flags |= RX_ENC_FLAG_LDPC;
 
-		status->chains = mphy->antenna_mask;
+		status->chains = BIT(hweight16(mphy->chainmask)) - 1;
 		status->chain_signal[0] = to_rssi(MT_PRXV_RCPI0, v1);
 		status->chain_signal[1] = to_rssi(MT_PRXV_RCPI1, v1);
 		status->chain_signal[2] = to_rssi(MT_PRXV_RCPI2, v1);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
index 90d5e79fbf74..a47b9cca3b46 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c
@@ -1121,23 +1121,16 @@ mt7915_set_antenna(struct ieee80211_hw *hw, int radio_idx, u32 tx_ant, u32 rx_an
 {
 	struct mt7915_dev *dev = mt7915_hw_dev(hw);
 	struct mt7915_phy *phy = mt7915_hw_phy(hw);
-	int max_nss = hweight8(hw->wiphy->available_antennas_tx);
-	u8 chainshift = dev->chainshift;
 	u8 band = phy->mt76->band_idx;
+	u8 shift = dev->chainshift * band;
 
-	if (!tx_ant || tx_ant != rx_ant || ffs(tx_ant) > max_nss)
+	if (!tx_ant || tx_ant != rx_ant)
 		return -EINVAL;
 
 	mutex_lock(&dev->mt76.mutex);
 
-	phy->mt76->antenna_mask = tx_ant;
-
-	/* handle a variant of mt7916/mt7981 which has 3T3R but nss2 on 5 GHz band */
-	if ((is_mt7916(&dev->mt76) || is_mt7981(&dev->mt76)) &&
-	    band && hweight8(tx_ant) == max_nss)
-		phy->mt76->chainmask = (dev->chainmask >> chainshift) << chainshift;
-	else
-		phy->mt76->chainmask = tx_ant << (chainshift * band);
+	phy->mt76->chainmask = tx_ant;
+	phy->mt76->antenna_mask = (tx_ant >> shift) & phy->orig_antenna_mask;
 
 	mt76_set_stream_caps(phy->mt76, true);
 	mt7915_set_stream_vht_txbf_caps(phy);
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
index b5c06201b707..69fdedaa61fb 100644
--- a/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
+++ b/drivers/net/wireless/mediatek/mt76/mt7915/mt7915.h
@@ -208,6 +208,8 @@ struct mt7915_phy {
 	u8 throttle_state;
 	u32 throttle_temp[2]; /* 0: critical high, 1: maximum */
 
+	u8 orig_antenna_mask;
+
 	u32 rxfilter;
 	u64 omac_mask;
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] only message in thread

only message in thread, other threads:[~2026-04-07  1:44 UTC | newest]

Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-04-07  1:43 [PATCH wireless] wifi: mt76: mt7915: expose all physical chains via available_antennas Joshua Klinesmith

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox