From 6094f86fb3713e1b7d0c7f264c3a76263745efae Mon Sep 17 00:00:00 2001 From: Ryder Lee Date: Sat, 25 Apr 2020 03:32:31 +0800 Subject: [PATCH] mt76: mt7915: add HE bss_conf support for interfaces Add basic HE BSS's info for interfaces. As for the advanced features will be added gradually in the future patches. (i.e. BSS color, TWT, spatial reuse and OFDMA) Signed-off-by: Ryder Lee Tested-by: Shayne Chen Tested-by: Chih-Min Chen Tested-by: Evelyn Tsai Acked-by: Yiwei Chung Acked-by: YF Luo Signed-off-by: Felix Fietkau --- drivers/net/wireless/mediatek/mt76/mt7915/mcu.c | 95 ++++++++++++++++++++++++- drivers/net/wireless/mediatek/mt76/mt7915/mcu.h | 10 +++ 2 files changed, 104 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c index 47c0ff8..61bab6b 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.c @@ -744,6 +744,47 @@ mt7915_mcu_bss_omac_tlv(struct sk_buff *skb, struct ieee80211_vif *vif) omac->hw_bss_idx = idx; } +struct mt7915_he_obss_narrow_bw_ru_data { + bool tolerated; +}; + +static void mt7915_check_he_obss_narrow_bw_ru_iter(struct wiphy *wiphy, + struct cfg80211_bss *bss, + void *_data) +{ + struct mt7915_he_obss_narrow_bw_ru_data *data = _data; + const struct element *elem; + + elem = cfg80211_find_elem(WLAN_EID_EXT_CAPABILITY, bss->ies->data, + bss->ies->len); + + if (!elem || elem->datalen < 10 || + !(elem->data[10] & + WLAN_EXT_CAPA10_OBSS_NARROW_BW_RU_TOLERANCE_SUPPORT)) + data->tolerated = false; +} + +static bool mt7915_check_he_obss_narrow_bw_ru(struct ieee80211_hw *hw, + struct ieee80211_vif *vif) +{ + struct mt7915_he_obss_narrow_bw_ru_data iter_data = { + .tolerated = true, + }; + + if (!(vif->bss_conf.chandef.chan->flags & IEEE80211_CHAN_RADAR)) + return false; + + cfg80211_bss_iter(hw->wiphy, &vif->bss_conf.chandef, + mt7915_check_he_obss_narrow_bw_ru_iter, + &iter_data); + + /* + * If there is at least one AP on radar channel that cannot + * tolerate 26-tone RU UL OFDMA transmissions using HE TB PPDU. + */ + return !iter_data.tolerated; +} + static void mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, struct mt7915_phy *phy) @@ -766,7 +807,20 @@ mt7915_mcu_bss_rfch_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, ch->center_ch1 = ieee80211_frequency_to_channel(freq2); } - ch->he_all_disable = true; + if (vif->bss_conf.he_support && vif->type == NL80211_IFTYPE_STATION) { + struct mt7915_dev *dev = phy->dev; + struct mt76_phy *mphy = &dev->mt76.phy; + bool ext_phy = phy != &dev->phy; + + if (ext_phy && dev->mt76.phy2) + mphy = dev->mt76.phy2; + + ch->he_ru26_block = + mt7915_check_he_obss_narrow_bw_ru(mphy->hw, vif); + ch->he_all_disable = false; + } else { + ch->he_all_disable = true; + } } static void @@ -796,6 +850,42 @@ mt7915_mcu_bss_ra_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, } static void +mt7915_mcu_bss_he_tlv(struct sk_buff *skb, struct ieee80211_vif *vif, + struct mt7915_phy *phy) +{ +#define DEFAULT_HE_PE_DURATION 4 +#define DEFAULT_HE_DURATION_RTS_THRES 1023 + struct cfg80211_chan_def *chandef = &phy->mt76->chandef; + enum nl80211_band band = chandef->chan->band; + struct ieee80211_supported_band *sband; + const struct ieee80211_sta_he_cap *cap; + struct bss_info_he *he; + struct tlv *tlv; + + if (band == NL80211_BAND_2GHZ) + sband = &phy->mt76->sband_2g.sband; + else + sband = &phy->mt76->sband_5g.sband; + + cap = ieee80211_get_he_iftype_cap(sband, vif->type); + + tlv = mt7915_mcu_add_tlv(skb, BSS_INFO_HE_BASIC, sizeof(*he)); + + he = (struct bss_info_he *)tlv; + he->he_pe_duration = vif->bss_conf.htc_trig_based_pkt_ext * 4; + if (!he->he_pe_duration) + he->he_pe_duration = DEFAULT_HE_PE_DURATION; + + he->he_rts_thres = cpu_to_le16(vif->bss_conf.frame_time_rts_th * 32); + if (!he->he_rts_thres) + he->he_rts_thres = cpu_to_le16(DEFAULT_HE_DURATION_RTS_THRES); + + he->max_nss_mcs[CMD_HE_MCS_BW80] = cap->he_mcs_nss_supp.tx_mcs_80; + he->max_nss_mcs[CMD_HE_MCS_BW160] = cap->he_mcs_nss_supp.tx_mcs_160; + he->max_nss_mcs[CMD_HE_MCS_BW8080] = cap->he_mcs_nss_supp.tx_mcs_80p80; +} + +static void mt7915_mcu_bss_ext_tlv(struct sk_buff *skb, struct mt7915_vif *mvif) { /* SIFS 20us + 512 byte beacon tranmitted by 1Mbps (3906us) */ @@ -870,6 +960,9 @@ int mt7915_mcu_add_bss_info(struct mt7915_phy *phy, mt7915_mcu_bss_bmc_tlv(skb, phy); mt7915_mcu_bss_ra_tlv(skb, vif, phy); + if (vif->bss_conf.he_support) + mt7915_mcu_bss_he_tlv(skb, vif, phy); + if (mvif->omac_idx > HW_BSSID_MAX) mt7915_mcu_bss_ext_tlv(skb, mvif); else diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h index c71161a..85ef1b3 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h +++ b/drivers/net/wireless/mediatek/mt76/mt7915/mcu.h @@ -396,6 +396,16 @@ struct bss_info_ra { __le32 fast_interval; } __packed; +struct bss_info_he { + __le16 tag; + __le16 len; + u8 he_pe_duration; + u8 vht_op_info_present; + __le16 he_rts_thres; + __le16 max_nss_mcs[CMD_HE_MCS_BW_NUM]; + u8 rsv[6]; +} __packed; + struct bss_info_bcn { __le16 tag; __le16 len; -- 2.7.4