@@ -424,7 +424,7 @@ int mt76_connac2_reverse_frag0_hdr_trans(struct ieee80211_vif *vif,
int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
- __le32 *rxv, u8 *mode);
+ __le32 *rxv, u8 *mode, u8 *nss);
void mt76_connac2_tx_check_aggr(struct ieee80211_sta *sta, __le32 *txwi);
void mt76_connac2_txwi_free(struct mt76_dev *dev, struct mt76_txwi_cache *t,
struct ieee80211_sta *sta,
@@ -1014,10 +1014,10 @@ EXPORT_SYMBOL_GPL(mt76_connac2_reverse_frag0_hdr_trans);
int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
struct mt76_rx_status *status,
struct ieee80211_supported_band *sband,
- __le32 *rxv, u8 *mode)
+ __le32 *rxv, u8 *mode, u8 *nss)
{
u32 v0, v2;
- u8 stbc, gi, bw, dcm, nss;
+ u8 stbc, gi, bw, dcm;
int i, idx;
bool cck = false;
@@ -1025,7 +1025,7 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
v2 = le32_to_cpu(rxv[2]);
idx = i = FIELD_GET(MT_PRXV_TX_RATE, v0);
- nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
+ *nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1;
if (!is_mt7915(dev)) {
stbc = FIELD_GET(MT_PRXV_HT_STBC, v0);
@@ -1050,17 +1050,21 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
fallthrough;
case MT_PHY_TYPE_OFDM:
i = mt76_get_rate(dev, sband, i, cck);
+ if (stbc)
+ *nss = 2;
+ else
+ *nss = 1;
break;
case MT_PHY_TYPE_HT_GF:
case MT_PHY_TYPE_HT:
status->encoding = RX_ENC_HT;
+ *nss = i / 8 + 1;
if (gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
if (i > 31)
return -EINVAL;
break;
case MT_PHY_TYPE_VHT:
- status->nss = nss;
status->encoding = RX_ENC_VHT;
if (gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
@@ -1071,7 +1075,6 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
case MT_PHY_TYPE_HE_SU:
case MT_PHY_TYPE_HE_EXT_SU:
case MT_PHY_TYPE_HE_TB:
- status->nss = nss;
status->encoding = RX_ENC_HE;
i &= GENMASK(3, 0);
@@ -1112,6 +1115,17 @@ int mt76_connac2_mac_fill_rx_rate(struct mt76_dev *dev,
if (*mode < MT_PHY_TYPE_HE_SU && gi)
status->enc_flags |= RX_ENC_FLAG_SHORT_GI;
+ /* in case stbc is set, the nss value returned by hardware is already
+ * correct (ie, 2 instead of 1 for 1 spatial stream). But, at least in cases
+ * where we are configured for a single antenna, then the second chain RSSI is '17',
+ * which I take to mean 'not set'. To keep from adding this to the average rssi up in
+ * mac80211 rx logic, decrease nss here.
+ */
+ if (stbc)
+ *nss >>= 1;
+
+ status->nss = *nss;
+
return 0;
}
EXPORT_SYMBOL_GPL(mt76_connac2_mac_fill_rx_rate);
@@ -451,6 +451,8 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
u32 v0, v1;
int ret;
+ int i;
+ u8 nss;
rxv = rxd;
rxd += 2;
@@ -463,11 +465,14 @@ 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;
+ /* TODO: When group-5 is enabled, use nss (and stbc) to
+ * calculate chains properly for this particular skb.
+ */
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);
status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1);
+ nss = hweight8(mphy->antenna_mask);
/* RXD Group 5 - C-RXV */
if (rxd1 & MT_RXD1_NORMAL_GROUP_5) {
@@ -478,10 +483,16 @@ mt7915_mac_fill_rx(struct mt7915_dev *dev, struct sk_buff *skb,
if (!is_mt7915(&dev->mt76) || (rxd1 & MT_RXD1_NORMAL_GROUP_5)) {
ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status,
- sband, rxv, &mode);
+ sband, rxv, &mode,
+ &nss);
if (ret < 0)
return ret;
+ } else {
+ status->nss = nss;
}
+
+ for (i = 0; i < nss; i++)
+ status->chains |= BIT(i);
}
amsdu_info = FIELD_GET(MT_RXD4_NORMAL_PAYLOAD_FORMAT, rxd4);
@@ -333,6 +333,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
if (rxd1 & MT_RXD1_NORMAL_GROUP_3) {
u32 v0, v1;
int ret;
+ u8 nss;
rxv = rxd;
rxd += 2;
@@ -346,7 +347,7 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
status->enc_flags |= RX_ENC_FLAG_LDPC;
ret = mt76_connac2_mac_fill_rx_rate(&dev->mt76, status, sband,
- rxv, &mode);
+ rxv, &mode, &nss);
if (ret < 0)
return ret;
@@ -366,12 +367,24 @@ mt7921_mac_fill_rx(struct mt792x_dev *dev, struct sk_buff *skb)
return -EINVAL;
}
- status->chains = mphy->antenna_mask;
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);
status->chain_signal[3] = to_rssi(MT_PRXV_RCPI3, v1);
status->signal = -128;
+
+ if (nss == 1) {
+ if (status->chain_signal[0] >= status->chain_signal[1])
+ status->chains |= BIT(0);
+ else
+ status->chains |= BIT(1);
+ } else if (status->nss == 2) {
+ status->chains = BIT(0) | BIT(1);
+ } else {
+ WARN_ON_ONCE(1); /* this driver is for only 2x2 AFAIK */
+ status->chains = BIT(0);
+ }
+
for (i = 0; i < hweight8(mphy->antenna_mask); i++) {
if (!(status->chains & BIT(i)) ||
status->chain_signal[i] >= 0)