Commit c336318f authored by Ryder Lee's avatar Ryder Lee Committed by Felix Fietkau

mt76: mt7915: add HE capabilities support for peers

Set peer's bsic HE capabilities through starec.
Signed-off-by: default avatarRyder Lee <ryder.lee@mediatek.com>
Suggested-by: default avatarShihwei Lin <shihwei.lin@mediatek.com>
Tested-by: default avatarShayne Chen <shayne.chen@mediatek.com>
Tested-by: default avatarChih-Min Chen <chih-min.chen@mediatek.com>
Tested-by: default avatarEvelyn Tsai <evelyn.tsai@mediatek.com>
Acked-by: default avatarYiwei Chung <yiwei.chung@mediatek.com>
Acked-by: default avatarYF Luo <yf.luo@mediatek.com>
Signed-off-by: default avatarFelix Fietkau <nbd@nbd.name>
parent 6094f86f
......@@ -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)
{
......@@ -1234,6 +1237,187 @@ mt7915_mcu_sta_basic_tlv(struct sk_buff *skb, struct ieee80211_vif *vif,
basic->qos = sta->wme;
}
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)) {
......
......@@ -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
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment