mt76: mt7915: add HE capabilities support for peers
authorRyder Lee <ryder.lee@mediatek.com>
Fri, 24 Apr 2020 19:32:32 +0000 (03:32 +0800)
committerFelix Fietkau <nbd@nbd.name>
Tue, 12 May 2020 17:52:36 +0000 (19:52 +0200)
Set peer's bsic HE capabilities through starec.

Signed-off-by: Ryder Lee <ryder.lee@mediatek.com>
Suggested-by: Shihwei Lin <shihwei.lin@mediatek.com>
Tested-by: Shayne Chen <shayne.chen@mediatek.com>
Tested-by: Chih-Min Chen <chih-min.chen@mediatek.com>
Tested-by: Evelyn Tsai <evelyn.tsai@mediatek.com>
Acked-by: Yiwei Chung <yiwei.chung@mediatek.com>
Acked-by: YF Luo <yf.luo@mediatek.com>
Signed-off-by: Felix Fietkau <nbd@nbd.name>
drivers/net/wireless/mediatek/mt76/mt7915/mcu.c
drivers/net/wireless/mediatek/mt76/mt7915/mcu.h

index 61bab6b..aa24f13 100644 (file)
@@ -85,6 +85,9 @@ struct mt7915_fw_region {
 #define to_wcid_lo(id)                 FIELD_GET(GENMASK(7, 0), (u16)id)
 #define to_wcid_hi(id)                 FIELD_GET(GENMASK(9, 8), (u16)id)
 
+#define HE_PHY(p, c)                   u8_get_bits(c, IEEE80211_HE_PHY_##p)
+#define HE_MAC(m, c)                   u8_get_bits(c, IEEE80211_HE_MAC_##m)
+
 static enum mt7915_cipher_type
 mt7915_mcu_get_cipher(int cipher)
 {
@@ -1235,6 +1238,187 @@ mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
 }
 
 static void
+mt7915_mcu_sta_he_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+{
+       struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
+       struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
+       struct sta_rec_he *he;
+       struct tlv *tlv;
+       u32 cap = 0;
+
+       tlv = mt7915_mcu_add_tlv(skb, STA_REC_HE, sizeof(*he));
+
+       he = (struct sta_rec_he *)tlv;
+
+       if (elem->mac_cap_info[0] & IEEE80211_HE_MAC_CAP0_HTC_HE)
+               cap |= STA_REC_HE_CAP_HTC;
+
+       if (elem->mac_cap_info[2] & IEEE80211_HE_MAC_CAP2_BSR)
+               cap |= STA_REC_HE_CAP_BSR;
+
+       if (elem->mac_cap_info[3] & IEEE80211_HE_MAC_CAP3_OMI_CONTROL)
+               cap |= STA_REC_HE_CAP_OM;
+
+       if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_AMDSU_IN_AMPDU)
+               cap |= STA_REC_HE_CAP_AMSDU_IN_AMPDU;
+
+       if (elem->mac_cap_info[4] & IEEE80211_HE_MAC_CAP4_BQR)
+               cap |= STA_REC_HE_CAP_BQR;
+
+       if (elem->phy_cap_info[0] &
+           (IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_2G |
+            IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_RU_MAPPING_IN_5G))
+               cap |= STA_REC_HE_CAP_BW20_RU242_SUPPORT;
+
+       if (elem->phy_cap_info[1] &
+           IEEE80211_HE_PHY_CAP1_LDPC_CODING_IN_PAYLOAD)
+               cap |= STA_REC_HE_CAP_LDPC;
+
+       if (elem->phy_cap_info[1] &
+           IEEE80211_HE_PHY_CAP1_HE_LTF_AND_GI_FOR_HE_PPDUS_0_8US)
+               cap |= STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI;
+
+       if (elem->phy_cap_info[2] &
+           IEEE80211_HE_PHY_CAP2_NDP_4x_LTF_AND_3_2US)
+               cap |= STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI;
+
+       if (elem->phy_cap_info[2] &
+           IEEE80211_HE_PHY_CAP2_STBC_TX_UNDER_80MHZ)
+               cap |= STA_REC_HE_CAP_LE_EQ_80M_TX_STBC;
+
+       if (elem->phy_cap_info[2] &
+           IEEE80211_HE_PHY_CAP2_STBC_RX_UNDER_80MHZ)
+               cap |= STA_REC_HE_CAP_LE_EQ_80M_RX_STBC;
+
+       if (elem->phy_cap_info[6] &
+           IEEE80211_HE_PHY_CAP6_PARTIAL_BW_EXT_RANGE)
+               cap |= STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE;
+
+       if (elem->phy_cap_info[7] &
+           IEEE80211_HE_PHY_CAP7_HE_SU_MU_PPDU_4XLTF_AND_08_US_GI)
+               cap |= STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI;
+
+       if (elem->phy_cap_info[7] &
+           IEEE80211_HE_PHY_CAP7_STBC_TX_ABOVE_80MHZ)
+               cap |= STA_REC_HE_CAP_GT_80M_TX_STBC;
+
+       if (elem->phy_cap_info[7] &
+           IEEE80211_HE_PHY_CAP7_STBC_RX_ABOVE_80MHZ)
+               cap |= STA_REC_HE_CAP_GT_80M_RX_STBC;
+
+       if (elem->phy_cap_info[8] &
+           IEEE80211_HE_PHY_CAP8_HE_ER_SU_PPDU_4XLTF_AND_08_US_GI)
+               cap |= STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI;
+
+       if (elem->phy_cap_info[8] &
+           IEEE80211_HE_PHY_CAP8_HE_ER_SU_1XLTF_AND_08_US_GI)
+               cap |= STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI;
+
+       if (elem->phy_cap_info[9] &
+           IEEE80211_HE_PHY_CAP9_NON_TRIGGERED_CQI_FEEDBACK)
+               cap |= STA_REC_HE_CAP_TRIG_CQI_FK;
+
+       if (elem->phy_cap_info[9] &
+           IEEE80211_HE_PHY_CAP9_TX_1024_QAM_LESS_THAN_242_TONE_RU)
+               cap |= STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242;
+
+       if (elem->phy_cap_info[9] &
+           IEEE80211_HE_PHY_CAP9_RX_1024_QAM_LESS_THAN_242_TONE_RU)
+               cap |= STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242;
+
+       he->he_cap = cpu_to_le32(cap);
+
+       switch (sta->bandwidth) {
+       case IEEE80211_STA_RX_BW_160:
+               if (elem->phy_cap_info[0] &
+                   IEEE80211_HE_PHY_CAP0_CHANNEL_WIDTH_SET_80PLUS80_MHZ_IN_5G)
+                       he->max_nss_mcs[CMD_HE_MCS_BW8080] =
+                               he_cap->he_mcs_nss_supp.rx_mcs_80p80;
+
+               he->max_nss_mcs[CMD_HE_MCS_BW160] =
+                               he_cap->he_mcs_nss_supp.rx_mcs_160;
+               /* fall through */
+       default:
+               he->max_nss_mcs[CMD_HE_MCS_BW80] =
+                               he_cap->he_mcs_nss_supp.rx_mcs_80;
+               break;
+       }
+
+       he->t_frame_dur =
+               HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);
+       he->max_ampdu_exp =
+               HE_MAC(CAP3_MAX_AMPDU_LEN_EXP_MASK, elem->mac_cap_info[3]);
+
+       he->bw_set =
+               HE_PHY(CAP0_CHANNEL_WIDTH_SET_MASK, elem->phy_cap_info[0]);
+       he->device_class =
+               HE_PHY(CAP1_DEVICE_CLASS_A, elem->phy_cap_info[1]);
+       he->punc_pream_rx =
+               HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
+
+       he->dcm_tx_mode =
+               HE_PHY(CAP3_DCM_MAX_CONST_TX_MASK, elem->phy_cap_info[3]);
+       he->dcm_tx_max_nss =
+               HE_PHY(CAP3_DCM_MAX_TX_NSS_2, elem->phy_cap_info[3]);
+       he->dcm_rx_mode =
+               HE_PHY(CAP3_DCM_MAX_CONST_RX_MASK, elem->phy_cap_info[3]);
+       he->dcm_rx_max_nss =
+               HE_PHY(CAP3_DCM_MAX_RX_NSS_2, elem->phy_cap_info[3]);
+       he->dcm_rx_max_nss =
+               HE_PHY(CAP8_DCM_MAX_RU_MASK, elem->phy_cap_info[8]);
+
+       he->pkt_ext = 2;
+}
+
+static void
+mt7915_mcu_sta_muru_tlv(struct sk_buff *skb, struct ieee80211_sta *sta)
+{
+       struct ieee80211_sta_he_cap *he_cap = &sta->he_cap;
+       struct ieee80211_he_cap_elem *elem = &he_cap->he_cap_elem;
+       struct sta_rec_muru *muru;
+       struct tlv *tlv;
+
+       tlv = mt7915_mcu_add_tlv(skb, STA_REC_MURU, sizeof(*muru));
+
+       muru = (struct sta_rec_muru *)tlv;
+       muru->cfg.ofdma_dl_en = true;
+       muru->cfg.ofdma_ul_en = true;
+       muru->cfg.mimo_dl_en = true;
+       muru->cfg.mimo_ul_en = true;
+
+       muru->ofdma_dl.punc_pream_rx =
+               HE_PHY(CAP1_PREAMBLE_PUNC_RX_MASK, elem->phy_cap_info[1]);
+       muru->ofdma_dl.he_20m_in_40m_2g =
+               HE_PHY(CAP8_20MHZ_IN_40MHZ_HE_PPDU_IN_2G, elem->phy_cap_info[8]);
+       muru->ofdma_dl.he_20m_in_160m =
+               HE_PHY(CAP8_20MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
+       muru->ofdma_dl.he_80m_in_160m =
+               HE_PHY(CAP8_80MHZ_IN_160MHZ_HE_PPDU, elem->phy_cap_info[8]);
+       muru->ofdma_dl.lt16_sigb = 0;
+       muru->ofdma_dl.rx_su_comp_sigb = 0;
+       muru->ofdma_dl.rx_su_non_comp_sigb = 0;
+
+       muru->ofdma_ul.t_frame_dur =
+               HE_MAC(CAP1_TF_MAC_PAD_DUR_MASK, elem->mac_cap_info[1]);
+       muru->ofdma_ul.mu_cascading =
+               HE_MAC(CAP2_MU_CASCADING, elem->mac_cap_info[2]);
+       muru->ofdma_ul.uo_ra =
+               HE_MAC(CAP3_OFDMA_RA, elem->mac_cap_info[3]);
+       muru->ofdma_ul.he_2x996_tone = 0;
+       muru->ofdma_ul.rx_t_frame_11ac = 0;
+
+       muru->mimo_dl.vht_mu_bfee =
+               !!(sta->vht_cap.cap & IEEE80211_VHT_CAP_MU_BEAMFORMEE_CAPABLE);
+       muru->mimo_dl.partial_bw_dl_mimo =
+               HE_PHY(CAP6_PARTIAL_BANDWIDTH_DL_MUMIMO, elem->phy_cap_info[6]);
+
+       muru->mimo_ul.full_ul_mimo =
+               HE_PHY(CAP2_UL_MU_FULL_MU_MIMO, elem->phy_cap_info[2]);
+       muru->mimo_ul.partial_ul_mimo =
+               HE_PHY(CAP2_UL_MU_PARTIAL_MU_MIMO, elem->phy_cap_info[2]);
+}
+
+static void
 mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
                   struct ieee80211_sta *sta)
 {
@@ -1259,6 +1443,14 @@ mt7915_mcu_sta_tlv(struct mt7915_dev *dev, struct sk_buff *skb,
                vht->vht_rx_mcs_map = sta->vht_cap.vht_mcs.rx_mcs_map;
                vht->vht_tx_mcs_map = sta->vht_cap.vht_mcs.tx_mcs_map;
        }
+
+       /* starec he */
+       if (sta->he_cap.has_he)
+               mt7915_mcu_sta_he_tlv(skb, sta);
+
+       /* starec muru */
+       if (sta->he_cap.has_he || sta->vht_cap.vht_supported)
+               mt7915_mcu_sta_muru_tlv(skb, sta);
 }
 
 static void
@@ -1454,6 +1646,11 @@ mt7915_mcu_sta_rate_ctrl_tlv(struct sk_buff *skb, struct mt7915_dev *dev,
                }
        }
 
+       if (sta->he_cap.has_he) {
+               ra->supp_mode |= MODE_HE;
+               cap |= STA_CAP_HE;
+       }
+
        ra->sta_status = cpu_to_le32(cap);
 
        switch (BIT(fls(ra->supp_mode) - 1)) {
index 85ef1b3..cc0e277 100644 (file)
@@ -658,6 +658,75 @@ struct sta_rec_vht {
        u8 rsv[3];
 } __packed;
 
+struct sta_rec_muru {
+       __le16 tag;
+       __le16 len;
+
+       struct {
+               bool ofdma_dl_en;
+               bool ofdma_ul_en;
+               bool mimo_dl_en;
+               bool mimo_ul_en;
+               bool rsv[4];
+       } cfg;
+
+       struct {
+               u8 punc_pream_rx;
+               bool he_20m_in_40m_2g;
+               bool he_20m_in_160m;
+               bool he_80m_in_160m;
+               bool lt16_sigb;
+               bool rx_su_comp_sigb;
+               bool rx_su_non_comp_sigb;
+               bool rsv;
+       } ofdma_dl;
+
+       struct {
+               u8 t_frame_dur;
+               u8 mu_cascading;
+               u8 uo_ra;
+               u8 he_2x996_tone;
+               u8 rx_t_frame_11ac;
+               u8 rsv[3];
+       } ofdma_ul;
+
+       struct {
+               bool vht_mu_bfee;
+               bool partial_bw_dl_mimo;
+               u8 rsv[2];
+       } mimo_dl;
+
+       struct {
+               bool full_ul_mimo;
+               bool partial_ul_mimo;
+               u8 rsv[2];
+       } mimo_ul;
+} __packed;
+
+struct sta_rec_he {
+       __le16 tag;
+       __le16 len;
+
+       __le32 he_cap;
+
+       u8 t_frame_dur;
+       u8 max_ampdu_exp;
+       u8 bw_set;
+       u8 device_class;
+       u8 dcm_tx_mode;
+       u8 dcm_tx_max_nss;
+       u8 dcm_rx_mode;
+       u8 dcm_rx_max_nss;
+       u8 dcm_max_ru;
+       u8 punc_pream_rx;
+       u8 pkt_ext;
+       u8 rsv1;
+
+       __le16 max_nss_mcs[CMD_HE_MCS_BW_NUM];
+
+       u8 rsv2[2];
+} __packed;
+
 struct sta_rec_ba {
        __le16 tag;
        __le16 len;
@@ -803,9 +872,11 @@ enum {
 #define MT7915_STA_UPDATE_MAX_SIZE     (sizeof(struct sta_req_hdr) +   \
                                         sizeof(struct sta_rec_basic) + \
                                         sizeof(struct sta_rec_ht) +    \
+                                        sizeof(struct sta_rec_he) +    \
                                         sizeof(struct sta_rec_ba) +    \
                                         sizeof(struct sta_rec_vht) +   \
                                         sizeof(struct tlv) +           \
+                                        sizeof(struct sta_rec_muru) +  \
                                         sizeof(struct sta_rec_sec) +   \
                                         sizeof(struct sta_rec_ra) +    \
                                         MT7915_WTBL_UPDATE_MAX_SIZE)
@@ -833,6 +904,7 @@ enum {
 #define MODE_OFDM                      BIT(1)
 #define MODE_HT                                BIT(2)
 #define MODE_VHT                       BIT(3)
+#define MODE_HE                                BIT(4)
 
 #define STA_CAP_WMM                    BIT(0)
 #define STA_CAP_SGI_20                 BIT(4)
@@ -847,5 +919,33 @@ enum {
 #define STA_CAP_LDPC                   BIT(24)
 #define STA_CAP_HT                     BIT(26)
 #define STA_CAP_VHT                    BIT(27)
+#define STA_CAP_HE                     BIT(28)
+
+/* HE MAC */
+#define STA_REC_HE_CAP_HTC                     BIT(0)
+#define STA_REC_HE_CAP_BQR                     BIT(1)
+#define STA_REC_HE_CAP_BSR                     BIT(2)
+#define STA_REC_HE_CAP_OM                      BIT(3)
+#define STA_REC_HE_CAP_AMSDU_IN_AMPDU          BIT(4)
+/* HE PHY */
+#define STA_REC_HE_CAP_DUAL_BAND               BIT(5)
+#define STA_REC_HE_CAP_LDPC                    BIT(6)
+#define STA_REC_HE_CAP_TRIG_CQI_FK             BIT(7)
+#define STA_REC_HE_CAP_PARTIAL_BW_EXT_RANGE    BIT(8)
+/* STBC */
+#define STA_REC_HE_CAP_LE_EQ_80M_TX_STBC       BIT(9)
+#define STA_REC_HE_CAP_LE_EQ_80M_RX_STBC       BIT(10)
+#define STA_REC_HE_CAP_GT_80M_TX_STBC          BIT(11)
+#define STA_REC_HE_CAP_GT_80M_RX_STBC          BIT(12)
+/* GI */
+#define STA_REC_HE_CAP_SU_PPDU_1LTF_8US_GI     BIT(13)
+#define STA_REC_HE_CAP_SU_MU_PPDU_4LTF_8US_GI  BIT(14)
+#define STA_REC_HE_CAP_ER_SU_PPDU_1LTF_8US_GI  BIT(15)
+#define STA_REC_HE_CAP_ER_SU_PPDU_4LTF_8US_GI  BIT(16)
+#define STA_REC_HE_CAP_NDP_4LTF_3DOT2MS_GI     BIT(17)
+/* 242 TONE */
+#define STA_REC_HE_CAP_BW20_RU242_SUPPORT      BIT(18)
+#define STA_REC_HE_CAP_TX_1024QAM_UNDER_RU242  BIT(19)
+#define STA_REC_HE_CAP_RX_1024QAM_UNDER_RU242  BIT(20)
 
 #endif