diff options
Diffstat (limited to 'drivers/net/wireless/mediatek/mt76/mt7915/mcu.c')
-rw-r--r-- | drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 94 |
1 files changed, 94 insertions, 0 deletions
diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index a87b10e8fda7..dde053a76261 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -3404,3 +3404,97 @@ int mt7915_mcu_add_obss_spr(struct mt7915_dev *dev, struct ieee80211_vif *vif, return mt76_mcu_send_msg(&dev->mt76, MCU_EXT_CMD_SET_SPR, &req, sizeof(req), true); } + +int mt7915_mcu_get_rx_rate(struct mt7915_phy *phy, struct ieee80211_vif *vif, + struct ieee80211_sta *sta, struct rate_info *rate) +{ + struct mt7915_vif *mvif = (struct mt7915_vif *)vif->drv_priv; + struct mt7915_sta *msta = (struct mt7915_sta *)sta->drv_priv; + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = phy->mt76; + struct { + u8 category; + u8 band; + __le16 wcid; + } __packed req = { + .category = MCU_PHY_STATE_CONTENTION_RX_RATE, + .band = mvif->band_idx, + .wcid = cpu_to_le16(msta->wcid.idx), + }; + struct ieee80211_supported_band *sband; + struct mt7915_mcu_phy_rx_info *res; + struct sk_buff *skb; + u16 flags = 0; + int ret; + int i; + + ret = mt76_mcu_send_and_get_msg(&dev->mt76, MCU_EXT_CMD_PHY_STAT_INFO, + &req, sizeof(req), true, &skb); + if (ret) + return ret; + + res = (struct mt7915_mcu_phy_rx_info *)skb->data; + + rate->mcs = res->rate; + rate->nss = res->nsts + 1; + + switch (res->mode) { + case MT_PHY_TYPE_CCK: + case MT_PHY_TYPE_OFDM: + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) + sband = &mphy->sband_5g.sband; + else + sband = &mphy->sband_2g.sband; + + for (i = 0; i < sband->n_bitrates; i++) { + if (rate->mcs != (sband->bitrates[i].hw_value & 0xf)) + continue; + + rate->legacy = sband->bitrates[i].bitrate; + break; + } + break; + case MT_PHY_TYPE_HT: + case MT_PHY_TYPE_HT_GF: + rate->mcs += (rate->nss - 1) * 8; + flags |= RATE_INFO_FLAGS_MCS; + + if (res->gi) + flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_VHT: + flags |= RATE_INFO_FLAGS_VHT_MCS; + + if (res->gi) + flags |= RATE_INFO_FLAGS_SHORT_GI; + break; + case MT_PHY_TYPE_HE_SU: + case MT_PHY_TYPE_HE_EXT_SU: + case MT_PHY_TYPE_HE_TB: + case MT_PHY_TYPE_HE_MU: + rate->he_gi = res->gi; + + flags |= RATE_INFO_FLAGS_HE_MCS; + break; + default: + break; + } + rate->flags = flags; + + switch (res->bw) { + case IEEE80211_STA_RX_BW_160: + rate->bw = RATE_INFO_BW_160; + break; + case IEEE80211_STA_RX_BW_80: + rate->bw = RATE_INFO_BW_80; + break; + case IEEE80211_STA_RX_BW_40: + rate->bw = RATE_INFO_BW_40; + break; + default: + rate->bw = RATE_INFO_BW_20; + break; + } + + return 0; +} |