diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c index dcca8b9312378..e4569d0322214 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mcu.c @@ -1460,17 +1460,21 @@ mt7996_is_ebf_supported(struct mt7996_phy *phy, struct ieee80211_vif *vif, } static void -mt7996_mcu_sta_sounding_rate(struct sta_rec_bf *bf) +mt7996_mcu_sta_sounding_rate(struct sta_rec_bf *bf, struct mt7996_phy *phy) { bf->sounding_phy = MT_PHY_TYPE_OFDM; bf->ndp_rate = 0; /* mcs0 */ - bf->ndpa_rate = MT7996_CFEND_RATE_DEFAULT; /* ofdm 24m */ + if (is_mt7996(phy->mt76->dev)) + bf->ndpa_rate = MT7996_CFEND_RATE_DEFAULT; /* ofdm 24m */ + else + bf->ndpa_rate = MT7992_CFEND_RATE_DEFAULT; /* ofdm 6m */ + bf->rept_poll_rate = MT7996_CFEND_RATE_DEFAULT; /* ofdm 24m */ } static void mt7996_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7996_phy *phy, - struct sta_rec_bf *bf) + struct sta_rec_bf *bf, bool explicit) { struct ieee80211_mcs_info *mcs = &sta->deflink.ht_cap.mcs; u8 n = 0; @@ -1490,7 +1494,8 @@ mt7996_mcu_sta_bfer_ht(struct ieee80211_sta *sta, struct mt7996_phy *phy, bf->nrow = hweight8(phy->mt76->antenna_mask) - 1; bf->ncol = min_t(u8, bf->nrow, n); - bf->ibf_ncol = n; + bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) : + min_t(u8, MT7996_IBF_MAX_NC, n); } static void @@ -1508,7 +1513,7 @@ mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy, if (explicit) { u8 sts, snd_dim; - mt7996_mcu_sta_sounding_rate(bf); + mt7996_mcu_sta_sounding_rate(bf, phy); sts = FIELD_GET(IEEE80211_VHT_CAP_BEAMFORMEE_STS_MASK, pc->cap); @@ -1516,14 +1521,14 @@ mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy, vc->cap); bf->nrow = min_t(u8, min_t(u8, snd_dim, sts), tx_ant); bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = bf->ncol; + bf->ibf_ncol = min_t(u8, MT7996_IBF_MAX_NC, bf->ncol); if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) bf->nrow = 1; } else { bf->nrow = tx_ant; bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = nss_mcs; + bf->ibf_ncol = min_t(u8, MT7996_IBF_MAX_NC, nss_mcs); if (sta->deflink.bandwidth == IEEE80211_STA_RX_BW_160) bf->ibf_nrow = 1; @@ -1532,7 +1537,8 @@ mt7996_mcu_sta_bfer_vht(struct ieee80211_sta *sta, struct mt7996_phy *phy, static void mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, - struct mt7996_phy *phy, struct sta_rec_bf *bf) + struct mt7996_phy *phy, struct sta_rec_bf *bf, + bool explicit) { struct ieee80211_sta_he_cap *pc = &sta->deflink.he_cap; struct ieee80211_he_cap_elem *pe = &pc->he_cap_elem; @@ -1548,7 +1554,7 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, bf->tx_mode = MT_PHY_TYPE_HE_SU; - mt7996_mcu_sta_sounding_rate(bf); + mt7996_mcu_sta_sounding_rate(bf, phy); bf->trigger_su = HE_PHY(CAP6_TRIG_SU_BEAMFORMING_FB, pe->phy_cap_info[6]); @@ -1560,7 +1566,8 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, pe->phy_cap_info[4]); bf->nrow = min_t(u8, snd_dim, sts); bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = bf->ncol; + bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) : + min_t(u8, MT7996_IBF_MAX_NC, nss_mcs); if (sta->deflink.bandwidth != IEEE80211_STA_RX_BW_160) return; @@ -1595,7 +1602,8 @@ mt7996_mcu_sta_bfer_he(struct ieee80211_sta *sta, struct ieee80211_vif *vif, static void mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, - struct mt7996_phy *phy, struct sta_rec_bf *bf) + struct mt7996_phy *phy, struct sta_rec_bf *bf, + bool explicit) { struct ieee80211_sta_eht_cap *pc = &sta->deflink.eht_cap; struct ieee80211_eht_cap_elem_fixed *pe = &pc->eht_cap_elem; @@ -1609,7 +1617,7 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, bf->tx_mode = MT_PHY_TYPE_EHT_MU; - mt7996_mcu_sta_sounding_rate(bf); + mt7996_mcu_sta_sounding_rate(bf, phy); bf->trigger_su = EHT_PHY(CAP3_TRIG_SU_BF_FDBK, pe->phy_cap_info[3]); bf->trigger_mu = EHT_PHY(CAP3_TRIG_MU_BF_PART_BW_FDBK, pe->phy_cap_info[3]); @@ -1618,7 +1626,8 @@ mt7996_mcu_sta_bfer_eht(struct ieee80211_sta *sta, struct ieee80211_vif *vif, (EHT_PHY(CAP1_BEAMFORMEE_SS_80MHZ_MASK, pe->phy_cap_info[1]) << 1); bf->nrow = min_t(u8, snd_dim, sts); bf->ncol = min_t(u8, nss_mcs, bf->nrow); - bf->ibf_ncol = bf->ncol; + bf->ibf_ncol = explicit ? min_t(u8, MT7996_IBF_MAX_NC, bf->ncol) : + min_t(u8, MT7996_IBF_MAX_NC, nss_mcs); if (sta->deflink.bandwidth < IEEE80211_STA_RX_BW_160) return; @@ -1653,12 +1662,15 @@ static void mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, struct ieee80211_vif *vif, struct ieee80211_sta *sta) { +#define EBF_MODE BIT(0) +#define IBF_MODE BIT(1) +#define BF_MAT_ORDER 4 struct mt7996_vif *mvif = (struct mt7996_vif *)vif->drv_priv; struct mt7996_phy *phy = mvif->deflink.phy; int tx_ant = hweight16(phy->mt76->chainmask) - 1; struct sta_rec_bf *bf; struct tlv *tlv; - static const u8 matrix[4][4] = { + static const u8 matrix[BF_MAT_ORDER][BF_MAT_ORDER] = { {0, 0, 0, 0}, {1, 1, 0, 0}, /* 2x1, 2x2, 2x3, 2x4 */ {2, 4, 4, 0}, /* 3x1, 3x2, 3x3, 3x4 */ @@ -1676,35 +1688,44 @@ mt7996_mcu_sta_bfer_tlv(struct mt7996_dev *dev, struct sk_buff *skb, tlv = mt76_connac_mcu_add_tlv(skb, STA_REC_BF, sizeof(*bf)); bf = (struct sta_rec_bf *)tlv; - /* he/eht: eBF only, in accordance with spec + /* he/eht: eBF only, except mt7992 that has 5T on 5GHz also supports iBF * vht: support eBF and iBF * ht: iBF only, since mac80211 lacks of eBF support */ - if (sta->deflink.eht_cap.has_eht && ebf) - mt7996_mcu_sta_bfer_eht(sta, vif, phy, bf); - else if (sta->deflink.he_cap.has_he && ebf) - mt7996_mcu_sta_bfer_he(sta, vif, phy, bf); + if (sta->deflink.eht_cap.has_eht) + mt7996_mcu_sta_bfer_eht(sta, vif, phy, bf, ebf); + else if (sta->deflink.he_cap.has_he) + mt7996_mcu_sta_bfer_he(sta, vif, phy, bf, ebf); else if (sta->deflink.vht_cap.vht_supported) mt7996_mcu_sta_bfer_vht(sta, phy, bf, ebf); else if (sta->deflink.ht_cap.ht_supported) - mt7996_mcu_sta_bfer_ht(sta, phy, bf); + mt7996_mcu_sta_bfer_ht(sta, phy, bf, ebf); else return; - bf->bf_cap = ebf ? ebf : dev->ibf << 1; + bf->bf_cap = ebf ? EBF_MODE : (dev->ibf ? IBF_MODE : 0); + if (is_mt7992(&dev->mt76) && tx_ant == 4) + bf->bf_cap |= IBF_MODE; bf->bw = sta->deflink.bandwidth; bf->ibf_dbw = sta->deflink.bandwidth; bf->ibf_nrow = tx_ant; - if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) - bf->ibf_timeout = 0x48; + if (sta->deflink.eht_cap.has_eht || sta->deflink.he_cap.has_he) + bf->ibf_timeout = is_mt7996(&dev->mt76) ? MT7996_IBF_TIMEOUT : + MT7992_IBF_TIMEOUT; + else if (!ebf && sta->deflink.bandwidth <= IEEE80211_STA_RX_BW_40 && !bf->ncol) + bf->ibf_timeout = MT7996_IBF_TIMEOUT_LEGACY; else - bf->ibf_timeout = 0x18; + bf->ibf_timeout = MT7996_IBF_TIMEOUT; - if (ebf && bf->nrow != tx_ant) - bf->mem_20m = matrix[tx_ant][bf->ncol]; - else - bf->mem_20m = matrix[bf->nrow][bf->ncol]; + if (bf->ncol < BF_MAT_ORDER) { + if (ebf) + bf->mem_20m = tx_ant < BF_MAT_ORDER ? + matrix[tx_ant][bf->ncol] : 0; + else + bf->mem_20m = bf->nrow < BF_MAT_ORDER ? + matrix[bf->nrow][bf->ncol] : 0; + } switch (sta->deflink.bandwidth) { case IEEE80211_STA_RX_BW_160: diff --git a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h index 1cfcac51a3381..29fabb9b04ae3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h +++ b/drivers/net/wireless/mediatek/mt76/mt7996/mt7996.h @@ -68,6 +68,12 @@ #define MT7996_CFEND_RATE_DEFAULT 0x49 /* OFDM 24M */ #define MT7996_CFEND_RATE_11B 0x03 /* 11B LP, 11M */ +#define MT7996_IBF_MAX_NC 2 +#define MT7996_IBF_TIMEOUT 0x18 +#define MT7996_IBF_TIMEOUT_LEGACY 0x48 + +#define MT7992_CFEND_RATE_DEFAULT 0x4b /* OFDM 6M */ +#define MT7992_IBF_TIMEOUT 0xff #define MT7996_SKU_RATE_NUM 417 #define MT7996_SKU_PATH_NUM 494