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 --- .../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