On Jun 09, Ryder Lee wrote: > On Fri, 2023-06-09 at 10:15 +0200, Lorenzo Bianconi wrote: > > > > External email : Please do not click links or open attachments until > > you have verified the sender or the content. > > Introduce connac3_mac in mt76_connac library to reuse mac code > > shared > > between WiFi7 chipsets. > > > > Signed-off-by: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> > > --- > > drivers/net/wireless/mediatek/mt76/Makefile | 2 +- > > .../net/wireless/mediatek/mt76/mt76_connac.h | 19 + > > .../wireless/mediatek/mt76/mt76_connac3_mac.c | 742 > > +++++++++++++++++ > > .../wireless/mediatek/mt76/mt76_connac3_mac.h | 18 + > > .../net/wireless/mediatek/mt76/mt7996/init.c | 4 +- > > .../net/wireless/mediatek/mt76/mt7996/mac.c | 761 +--------------- > > -- > > .../net/wireless/mediatek/mt76/mt7996/main.c | 8 +- > > .../net/wireless/mediatek/mt76/mt7996/mcu.c | 9 +- > > .../wireless/mediatek/mt76/mt7996/mt7996.h | 28 +- > > 9 files changed, 807 insertions(+), 784 deletions(-) > > create mode 100644 > > drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c > > > > diff --git a/drivers/net/wireless/mediatek/mt76/Makefile > > b/drivers/net/wireless/mediatek/mt76/Makefile > > index 84c99b7e57f9..d8e8079c8b54 100644 > > --- a/drivers/net/wireless/mediatek/mt76/Makefile > > +++ b/drivers/net/wireless/mediatek/mt76/Makefile > > @@ -27,7 +27,7 @@ mt76x02-lib-y := mt76x02_util.o mt76x02_mac.o > > mt76x02_mcu.o \ > > > > mt76x02-usb-y := mt76x02_usb_mcu.o mt76x02_usb_core.o > > > > -mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o > > +mt76-connac-lib-y := mt76_connac_mcu.o mt76_connac_mac.o > > mt76_connac3_mac.o > > > > obj-$(CONFIG_MT76x0_COMMON) += mt76x0/ > > obj-$(CONFIG_MT76x2_COMMON) += mt76x2/ > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac.h > > b/drivers/net/wireless/mediatek/mt76/mt76_connac.h > > index 68bdeada1421..20111678537b 100644 > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac.h > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac.h > > @@ -415,4 +415,23 @@ void mt76_connac2_txwi_free(struct mt76_dev > > *dev, struct mt76_txwi_cache *t, > > struct list_head *free_list); > > void mt76_connac2_tx_token_put(struct mt76_dev *dev); > > > > +/* connac3 */ > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32 > > *txwi); > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 > > *rxv, > > + u8 mode); > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev, > > + struct mt76_rx_status *status, > > + struct ieee80211_supported_band > > *sband, > > + __le32 *rxv, u8 *mode); > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, > > + struct sk_buff *skb, struct mt76_wcid > > *wcid, > > + struct ieee80211_key_conf *key, int > > pid, > > + enum mt76_txq_id qid, u32 changed); > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct > > mt76_txwi_cache *t, > > + struct ieee80211_sta *sta, > > + struct list_head *free_list); > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data, > > + u32 max_wtbl_size); > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev); > > + > > #endif /* __MT76_CONNAC_H */ > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c > > new file mode 100644 > > index 000000000000..4b745bb74ca0 > > --- /dev/null > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.c > > @@ -0,0 +1,742 @@ > > +// SPDX-License-Identifier: ISC > > +/* Copyright (C) 2023 MediaTek Inc. */ > > + > > +#include "mt76_connac.h" > > +#include "mt76_connac3_mac.h" > > +#include "dma.h" > > + > > +#define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) > > +#define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, > > MT_CRXV_HE_##m),\ > > + IEEE80211_RADIOTAP_HE_ > > ##f) > > + > > +void mt76_connac3_tx_check_aggr(struct ieee80211_sta *sta, __le32 > > *txwi) > > +{ > > + struct mt76_wcid *wcid; > > + u16 fc, tid; > > + u32 val; > > + > > + if (!sta || > > + !(sta->deflink.ht_cap.ht_supported || sta- > > >deflink.he_cap.has_he)) > > + return; > > + > > + tid = le32_get_bits(txwi[1], MT_TXD1_TID); > > + if (tid >= 6) /* skip VO queue */ > > + return; > > + > > + val = le32_to_cpu(txwi[2]); > > + fc = FIELD_GET(MT_TXD2_FRAME_TYPE, val) << 2 | > > + FIELD_GET(MT_TXD2_SUB_TYPE, val) << 4; > > + if (unlikely(fc != (IEEE80211_FTYPE_DATA | > > IEEE80211_STYPE_QOS_DATA))) > > + return; > > + > > + wcid = (struct mt76_wcid *)sta->drv_priv; > > + if (!test_and_set_bit(tid, &wcid->ampdu_state)) > > + ieee80211_start_tx_ba_session(sta, tid, 0); > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_check_aggr); > > + > > +static void > > +mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status > > *status, > > + struct ieee80211_radiotap_he > > *he, > > + __le32 *rxv) > > +{ > > + u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0; > > + > > + status->bw = RATE_INFO_BW_HE_RU; > > + > > + switch (ru) { > > + case 0 ... 36: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; > > + offs = ru; > > + break; > > + case 37 ... 52: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; > > + offs = ru - 37; > > + break; > > + case 53 ... 60: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; > > + offs = ru - 53; > > + break; > > + case 61 ... 64: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; > > + offs = ru - 61; > > + break; > > + case 65 ... 66: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; > > + offs = ru - 65; > > + break; > > + case 67: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; > > + break; > > + case 68: > > + status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; > > + break; > > + } > > + > > + he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); > > + he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | > > + le16_encode_bits(offs, > > + IEEE80211_RADIOTAP_HE_DATA2_RU_OF > > FSET); > > +} > > + > > +#define MU_PREP(f, v) le16_encode_bits(v, > > IEEE80211_RADIOTAP_HE_MU_##f) > > +static void > > +mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 > > *rxv) > > +{ > > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb- > > >cb; > > + static const struct ieee80211_radiotap_he_mu mu_known = { > > + .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | > > + HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | > > + HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | > > + HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), > > + .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), > > + }; > > + struct ieee80211_radiotap_he_mu *he_mu; > > + > > + status->flag |= RX_FLAG_RADIOTAP_HE_MU; > > + > > + he_mu = skb_push(skb, sizeof(mu_known)); > > + memcpy(he_mu, &mu_known, sizeof(mu_known)); > > + > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); > > + if (status->he_dcm) > > + he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status- > > >he_dcm); > > + > > + he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | > > + MU_PREP(FLAGS2_SIG_B_SYMS_USERS, > > + le32_get_bits(rxv[4], > > MT_CRXV_HE_NUM_USER)); > > + > > + he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & > > 0xff; > > + > > + if (status->bw >= RATE_INFO_BW_40) { > > + he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); > > + he_mu->ru_ch2[0] = le32_get_bits(rxv[16], > > MT_CRXV_HE_RU1) & 0xff; > > + } > > + > > + if (status->bw >= RATE_INFO_BW_80) { > > + u32 ru_h, ru_l; > > + > > + he_mu->ru_ch1[1] = le32_get_bits(rxv[16], > > MT_CRXV_HE_RU2) & 0xff; > > + > > + ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); > > + ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; > > + he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); > > + } > > +} > > + > > +void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 > > *rxv, > > + u8 mode) > > +{ > > + struct mt76_rx_status *status = (struct mt76_rx_status *)skb- > > >cb; > > + static const struct ieee80211_radiotap_he known = { > > + .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | > > + HE_BITS(DATA1_DATA_DCM_KNOWN) | > > + HE_BITS(DATA1_STBC_KNOWN) | > > + HE_BITS(DATA1_CODING_KNOWN) | > > + HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | > > + HE_BITS(DATA1_DOPPLER_KNOWN) | > > + HE_BITS(DATA1_SPTL_REUSE_KNOWN) | > > + HE_BITS(DATA1_BSS_COLOR_KNOWN), > > + .data2 = HE_BITS(DATA2_GI_KNOWN) | > > + HE_BITS(DATA2_TXBF_KNOWN) | > > + HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | > > + HE_BITS(DATA2_TXOP_KNOWN), > > + }; > > + u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; > > + struct ieee80211_radiotap_he *he; > > + > > + status->flag |= RX_FLAG_RADIOTAP_HE; > > + > > + he = skb_push(skb, sizeof(known)); > > + memcpy(he, &known, sizeof(known)); > > + > > + he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | > > + HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); > > + he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); > > + he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | > > + le16_encode_bits(ltf_size, > > + IEEE80211_RADIOTAP_HE_DATA5_LTF_SI > > ZE); > > + if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) > > + he->data5 |= HE_BITS(DATA5_TXBF); > > + he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | > > + HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); > > + > > + switch (mode) { > > + case MT_PHY_TYPE_HE_SU: > > + he->data1 |= HE_BITS(DATA1_FORMAT_SU) | > > + HE_BITS(DATA1_UL_DL_KNOWN) | > > + HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); > > + > > + he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, > > rxv[8]) | > > + HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); > > + break; > > + case MT_PHY_TYPE_HE_EXT_SU: > > + he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | > > + HE_BITS(DATA1_UL_DL_KNOWN) | > > + HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); > > + > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); > > + break; > > + case MT_PHY_TYPE_HE_MU: > > + he->data1 |= HE_BITS(DATA1_FORMAT_MU) | > > + HE_BITS(DATA1_UL_DL_KNOWN); > > + > > + he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); > > + he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); > > + > > + mt76_connac3_mac_decode_he_radiotap_ru(status, he, > > rxv); > > + mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv); > > + break; > > + case MT_PHY_TYPE_HE_TB: > > + he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | > > + HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | > > + HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | > > + HE_BITS(DATA1_SPTL_REUSE4_KNOWN); > > + > > + he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, > > rxv[13]) | > > + HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, > > rxv[13]) | > > + HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, > > rxv[13]) | > > + HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, > > rxv[13]); > > + > > + mt76_connac3_mac_decode_he_radiotap_ru(status, he, > > rxv); > > + break; > > + default: > > + break; > > + } > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap); > > + > > +int mt76_connac3_mac_fill_rx_rate(struct mt76_dev *dev, > > + struct mt76_rx_status *status, > > + struct ieee80211_supported_band > > *sband, > > + __le32 *rxv, u8 *mode) > > +{ > > + u8 stbc, gi, bw, dcm, nss; > > + bool cck = false; > > + u32 v0, v2; > > + int i, idx; > > + > > + v0 = le32_to_cpu(rxv[0]); > > + v2 = le32_to_cpu(rxv[2]); > > + > > + idx = FIELD_GET(MT_PRXV_TX_RATE, v0); > > + i = idx; > > + nss = FIELD_GET(MT_PRXV_NSTS, v0) + 1; > > + > > + stbc = FIELD_GET(MT_PRXV_HT_STBC, v2); > > + gi = FIELD_GET(MT_PRXV_HT_SHORT_GI, v2); > > + *mode = FIELD_GET(MT_PRXV_TX_MODE, v2); > > + dcm = FIELD_GET(MT_PRXV_DCM, v2); > > + bw = FIELD_GET(MT_PRXV_FRAME_MODE, v2); > > + > > + switch (*mode) { > > + case MT_PHY_TYPE_CCK: > > + cck = true; > > + fallthrough; > > + case MT_PHY_TYPE_OFDM: > > + i = mt76_get_rate(dev, sband, i, cck); > > + break; > > + case MT_PHY_TYPE_HT_GF: > > + case MT_PHY_TYPE_HT: > > + status->encoding = RX_ENC_HT; > > + if (gi) > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; > > + if (i > 31) > > + return -EINVAL; > > + break; > > + case MT_PHY_TYPE_VHT: > > + status->nss = nss; > > + status->encoding = RX_ENC_VHT; > > + if (gi) > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; > > + if (i > 11) > > + return -EINVAL; > > + break; > > + case MT_PHY_TYPE_HE_MU: > > + case MT_PHY_TYPE_HE_SU: > > + case MT_PHY_TYPE_HE_EXT_SU: > > + case MT_PHY_TYPE_HE_TB: > > + status->nss = nss; > > + status->encoding = RX_ENC_HE; > > + i &= GENMASK(3, 0); > > + > > + if (gi <= NL80211_RATE_INFO_HE_GI_3_2) > > + status->he_gi = gi; > > + > > + status->he_dcm = dcm; > > + break; > > + case MT_PHY_TYPE_EHT_SU: > > + case MT_PHY_TYPE_EHT_TRIG: > > + case MT_PHY_TYPE_EHT_MU: > > + status->nss = nss; > > + status->encoding = RX_ENC_EHT; > > + i &= GENMASK(3, 0); > > + > > + if (gi <= NL80211_RATE_INFO_EHT_GI_3_2) > > + status->eht.gi = gi; > > + break; > > + default: > > + return -EINVAL; > > + } > > + status->rate_idx = i; > > + > > + switch (bw) { > > + case IEEE80211_STA_RX_BW_20: > > + break; > > + case IEEE80211_STA_RX_BW_40: > > + if (*mode & MT_PHY_TYPE_HE_EXT_SU && > > + (idx & MT_PRXV_TX_ER_SU_106T)) { > > + status->bw = RATE_INFO_BW_HE_RU; > > + status->he_ru = > > + NL80211_RATE_INFO_HE_RU_ALLOC_106; > > + } else { > > + status->bw = RATE_INFO_BW_40; > > + } > > + break; > > + case IEEE80211_STA_RX_BW_80: > > + status->bw = RATE_INFO_BW_80; > > + break; > > + case IEEE80211_STA_RX_BW_160: > > + status->bw = RATE_INFO_BW_160; > > + break; > > + case IEEE80211_STA_RX_BW_320: > > + status->bw = RATE_INFO_BW_320; > > + break; > > + default: > > + return -EINVAL; > > + } > > + > > + status->enc_flags |= RX_ENC_FLAG_STBC_MASK * stbc; > > + if (*mode < MT_PHY_TYPE_HE_SU && gi) > > + status->enc_flags |= RX_ENC_FLAG_SHORT_GI; > > + > > + return 0; > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_fill_rx_rate); > > + > > +static void > > +mt76_connac3_mac_write_txwi_8023(__le32 *txwi, struct sk_buff *skb, > > + struct mt76_wcid *wcid) > > +{ > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; > > + u8 fc_type, fc_stype; > > + u16 ethertype; > > + bool wmm = false; > > + u32 val; > > + > > + if (wcid->sta) { > > + struct ieee80211_sta *sta; > > + > > + sta = container_of((void *)wcid, struct ieee80211_sta, > > drv_priv); > > + wmm = sta->wme; > > + } > > + > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_3) | > > + FIELD_PREP(MT_TXD1_TID, tid); > > + > > + ethertype = get_unaligned_be16(&skb->data[12]); > > + if (ethertype >= ETH_P_802_3_MIN) > > + val |= MT_TXD1_ETH_802_3; > > + > > + txwi[1] |= cpu_to_le32(val); > > + > > + fc_type = IEEE80211_FTYPE_DATA >> 2; > > + fc_stype = wmm ? IEEE80211_STYPE_QOS_DATA >> 4 : 0; > > + > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); > > + > > + txwi[2] |= cpu_to_le32(val); > > +} > > + > > +static void > > +mt76_connac3_mac_write_txwi_80211(struct mt76_dev *dev, __le32 > > *txwi, > > + struct sk_buff *skb, > > + struct ieee80211_key_conf *key) > > +{ > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)skb->data; > > + struct ieee80211_mgmt *mgmt = (struct ieee80211_mgmt *)skb- > > >data; > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); > > + bool multicast = is_multicast_ether_addr(hdr->addr1); > > + u8 tid = skb->priority & IEEE80211_QOS_CTL_TID_MASK; > > + __le16 fc = hdr->frame_control; > > + u8 fc_type, fc_stype; > > + u32 val; > > + > > + if (ieee80211_is_action(fc) && > > + mgmt->u.action.category == WLAN_CATEGORY_BACK && > > + mgmt->u.action.u.addba_req.action_code == > > WLAN_ACTION_ADDBA_REQ) > > + tid = MT_TX_ADDBA; > > + else if (ieee80211_is_mgmt(hdr->frame_control)) > > + tid = MT_TX_NORMAL; > > + > > + val = FIELD_PREP(MT_TXD1_HDR_FORMAT, MT_HDR_FORMAT_802_11) | > > + FIELD_PREP(MT_TXD1_HDR_INFO, > > + ieee80211_get_hdrlen_from_skb(skb) / 2) | > > + FIELD_PREP(MT_TXD1_TID, tid); > > + > > + if (!ieee80211_is_data(fc) || multicast || > > + info->flags & IEEE80211_TX_CTL_USE_MINRATE) > > + val |= MT_TXD1_FIXED_RATE; > > + > > + if (key && multicast && ieee80211_is_robust_mgmt_frame(skb) && > > + key->cipher == WLAN_CIPHER_SUITE_AES_CMAC) { > > + val |= MT_TXD1_BIP; > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_PROTECT_FRAME); > > + } > > + > > + txwi[1] |= cpu_to_le32(val); > > + > > + fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; > > + fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; > > + > > + val = FIELD_PREP(MT_TXD2_FRAME_TYPE, fc_type) | > > + FIELD_PREP(MT_TXD2_SUB_TYPE, fc_stype); > > + > > + txwi[2] |= cpu_to_le32(val); > > + > > + txwi[3] |= cpu_to_le32(FIELD_PREP(MT_TXD3_BCM, multicast)); > > + if (ieee80211_is_beacon(fc)) { > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_SW_POWER_MGMT); > > + txwi[3] |= cpu_to_le32(MT_TXD3_REM_TX_COUNT); > > + } > > + > > + if (info->flags & IEEE80211_TX_CTL_INJECTED) { > > + u16 seqno = le16_to_cpu(hdr->seq_ctrl); > > + > > + if (ieee80211_is_back_req(hdr->frame_control)) { > > + struct ieee80211_bar *bar; > > + > > + bar = (struct ieee80211_bar *)skb->data; > > + seqno = le16_to_cpu(bar->start_seq_num); > > + } > > + > > + val = MT_TXD3_SN_VALID | > > + FIELD_PREP(MT_TXD3_SEQ, > > IEEE80211_SEQ_TO_SN(seqno)); > > + txwi[3] |= cpu_to_le32(val); > > + txwi[3] &= ~cpu_to_le32(MT_TXD3_HW_AMSDU); > > + } > > +} > > + > > +void mt76_connac3_mac_write_txwi(struct mt76_dev *dev, __le32 *txwi, > > + struct sk_buff *skb, struct mt76_wcid > > *wcid, > > + struct ieee80211_key_conf *key, int > > pid, > > + enum mt76_txq_id qid, u32 changed) > > +{ > > + u32 val, sz_txd = mt76_is_mmio(dev) ? MT_TXD_SIZE : > > MT_SDIO_TXD_SIZE; > > + struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); > > + struct ieee80211_vif *vif = info->control.vif; > > + u8 band_idx = (info->hw_queue & MT_TX_HW_QUEUE_PHY) >> 2; > > + u8 p_fmt, q_idx, omac_idx = 0, wmm_idx = 0; > > + bool is_8023 = info->flags & IEEE80211_TX_CTL_HW_80211_ENCAP; > > + struct mt76_vif *mvif; > > + u16 tx_count = 15; > > + bool beacon = !!(changed & (BSS_CHANGED_BEACON | > > + BSS_CHANGED_BEACON_ENABLED)); > > + bool inband_disc = !!(changed & > > (BSS_CHANGED_UNSOL_BCAST_PROBE_RESP | > > + BSS_CHANGED_FILS_DISCOVERY)); > > + > > + mvif = vif ? (struct mt76_vif *)vif->drv_priv : NULL; > > + if (mvif) { > > + omac_idx = mvif->omac_idx; > > + wmm_idx = mvif->wmm_idx; > > + band_idx = mvif->band_idx; > > + } > > + > > + if (inband_disc) { > > + p_fmt = MT_TX_TYPE_FW; > > + q_idx = MT_LMAC_ALTX0; > > + } else if (beacon) { > > + p_fmt = MT_TX_TYPE_FW; > > + q_idx = MT_LMAC_BCN0; > > + } else if (qid >= MT_TXQ_PSD) { > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : > > MT_TX_TYPE_SF; > > + q_idx = MT_LMAC_ALTX0; > > + } else { > > + p_fmt = mt76_is_mmio(dev) ? MT_TX_TYPE_CT : > > MT_TX_TYPE_SF; > > + q_idx = wmm_idx * MT76_CONNAC_MAX_WMM_SETS + > > + mt76_connac_lmac_mapping(skb_get_queue_mapping( > > skb)); > > + } > > + > > + val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | > > + FIELD_PREP(MT_TXD0_PKT_FMT, p_fmt) | > > + FIELD_PREP(MT_TXD0_Q_IDX, q_idx); > > + txwi[0] = cpu_to_le32(val); > > + > > + val = FIELD_PREP(MT_TXD1_WLAN_IDX, wcid->idx) | > > + FIELD_PREP(MT_TXD1_OWN_MAC, omac_idx); > > + > > + if (band_idx) > > + val |= FIELD_PREP(MT_TXD1_TGID, band_idx); > > + > > + txwi[1] = cpu_to_le32(val); > > + txwi[2] = 0; > > + > > + val = MT_TXD3_SW_POWER_MGMT | > > + FIELD_PREP(MT_TXD3_REM_TX_COUNT, tx_count); > > + if (key) > > + val |= MT_TXD3_PROTECT_FRAME; > > + if (info->flags & IEEE80211_TX_CTL_NO_ACK) > > + val |= MT_TXD3_NO_ACK; > > + if (wcid->amsdu) > > + val |= MT_TXD3_HW_AMSDU; > > + > > + txwi[3] = cpu_to_le32(val); > > + txwi[4] = 0; > > + > > + val = FIELD_PREP(MT_TXD5_PID, pid); > > + if (pid >= MT_PACKET_ID_FIRST) > > + val |= MT_TXD5_TX_STATUS_HOST; > > + txwi[5] = cpu_to_le32(val); > > + > > + val = MT_TXD6_DIS_MAT | MT_TXD6_DAS | > > + FIELD_PREP(MT_TXD6_MSDU_CNT, 1); > > + txwi[6] = cpu_to_le32(val); > > + txwi[7] = 0; > > + > > + if (is_8023) > > + mt76_connac3_mac_write_txwi_8023(txwi, skb, wcid); > > + else > > + mt76_connac3_mac_write_txwi_80211(dev, txwi, skb, key); > > + > > + if (txwi[1] & cpu_to_le32(MT_TXD1_FIXED_RATE)) { > > + struct ieee80211_hdr *hdr = (struct ieee80211_hdr > > *)skb->data; > > + bool mcast = ieee80211_is_data(hdr->frame_control) && > > + is_multicast_ether_addr(hdr->addr1); > > + u8 idx = MT76_CONNAC3_BASIC_RATES_TBL; > > + > > + if (mvif) { > > + if (mcast && mvif->mcast_rates_idx) > > + idx = mvif->mcast_rates_idx; > > + else if (beacon && mvif->beacon_rates_idx) > > + idx = mvif->beacon_rates_idx; > > + else > > + idx = mvif->basic_rates_idx; > > + } > > + > > + txwi[6] |= cpu_to_le32(FIELD_PREP(MT_TXD6_TX_RATE, > > idx)); > > + txwi[3] |= cpu_to_le32(MT_TXD3_BA_DISABLE); > > + } > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_write_txwi); > > + > > +void mt76_connac3_txwi_free(struct mt76_dev *dev, struct > > mt76_txwi_cache *t, > > + struct ieee80211_sta *sta, > > + struct list_head *free_list) > > +{ > > + __le32 *txwi; > > + u16 wcid_idx; > > + > > + mt76_connac_txp_skb_unmap(dev, t); > > + if (!t->skb) > > + goto out; > > + > > + txwi = (__le32 *)mt76_get_txwi_ptr(dev, t); > > + if (sta) { > > + struct mt76_wcid *wcid = (struct mt76_wcid *)sta- > > >drv_priv; > > + > > + wcid_idx = wcid->idx; > > + if (likely(t->skb->protocol != cpu_to_be16(ETH_P_PAE))) > > + mt76_connac3_tx_check_aggr(sta, txwi); > > + } else { > > + wcid_idx = le32_get_bits(txwi[1], MT_TXD1_WLAN_IDX); > > + } > > + > > + __mt76_tx_complete_skb(dev, wcid_idx, t->skb, free_list); > > +out: > > + t->skb = NULL; > > + mt76_put_txwi(dev, t); > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_txwi_free); > > + > > +static bool > > +mt76_connac3_mac_add_txs_skb(struct mt76_dev *dev, struct mt76_wcid > > *wcid, > > + int pid, __le32 *txs_data) > > +{ > > + struct mt76_sta_stats *stats = &wcid->stats; > > + struct ieee80211_supported_band *sband; > > + struct ieee80211_tx_info *info; > > + u32 txrate, txs, mode, stbc; > > + struct rate_info rate = {}; > > + struct sk_buff_head list; > > + struct mt76_phy *mphy; > > + struct sk_buff *skb; > > + bool cck = false; > > + > > + mt76_tx_status_lock(dev, &list); > > + skb = mt76_tx_status_skb_get(dev, wcid, pid, &list); > > + if (!skb) > > + goto out_no_skb; > > + > > + txs = le32_to_cpu(txs_data[0]); > > + > > + info = IEEE80211_SKB_CB(skb); > > + if (!(txs & MT_TXS0_ACK_ERROR_MASK)) > > + info->flags |= IEEE80211_TX_STAT_ACK; > > + > > + info->status.ampdu_len = 1; > > + info->status.ampdu_ack_len = !!(info->flags & > > + IEEE80211_TX_STAT_ACK); > > + info->status.rates[0].idx = -1; > > + > > + txrate = FIELD_GET(MT_TXS0_TX_RATE, txs); > > + > > + rate.mcs = FIELD_GET(MT_TX_RATE_IDX, txrate); > > + rate.nss = FIELD_GET(MT_TX_RATE_NSS, txrate) + 1; > > + stbc = le32_get_bits(txs_data[3], MT_TXS3_RATE_STBC); > > + > > + if (stbc && rate.nss > 1) > > + rate.nss >>= 1; > > + > > + if (rate.nss - 1 < ARRAY_SIZE(stats->tx_nss)) > > + stats->tx_nss[rate.nss - 1]++; > > + if (rate.mcs < ARRAY_SIZE(stats->tx_mcs)) > > + stats->tx_mcs[rate.mcs]++; > > + > > + mode = FIELD_GET(MT_TX_RATE_MODE, txrate); > > + switch (mode) { > > + case MT_PHY_TYPE_CCK: > > + cck = true; > > + fallthrough; > > + case MT_PHY_TYPE_OFDM: > > + mphy = mt76_dev_phy(dev, wcid->phy_idx); > > + > > + if (mphy->chandef.chan->band == NL80211_BAND_5GHZ) > > + sband = &mphy->sband_5g.sband; > > + else if (mphy->chandef.chan->band == NL80211_BAND_6GHZ) > > + sband = &mphy->sband_6g.sband; > > + else > > + sband = &mphy->sband_2g.sband; > > + > > + rate.mcs = mt76_get_rate(mphy->dev, sband, rate.mcs, > > cck); > > + rate.legacy = sband->bitrates[rate.mcs].bitrate; > > + break; > > + case MT_PHY_TYPE_HT: > > + case MT_PHY_TYPE_HT_GF: > > + if (rate.mcs > 31) > > + goto out; > > + > > + rate.flags = RATE_INFO_FLAGS_MCS; > > + if (wcid->rate.flags & RATE_INFO_FLAGS_SHORT_GI) > > + rate.flags |= RATE_INFO_FLAGS_SHORT_GI; > > + break; > > + case MT_PHY_TYPE_VHT: > > + if (rate.mcs > 9) > > + goto out; > > + > > + rate.flags = RATE_INFO_FLAGS_VHT_MCS; > > + 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: > > + if (rate.mcs > 11) > > + goto out; > > + > > + rate.he_gi = wcid->rate.he_gi; > > + rate.he_dcm = FIELD_GET(MT_TX_RATE_DCM, txrate); > > + rate.flags = RATE_INFO_FLAGS_HE_MCS; > > + break; > > + case MT_PHY_TYPE_EHT_SU: > > + case MT_PHY_TYPE_EHT_TRIG: > > + case MT_PHY_TYPE_EHT_MU: > > + if (rate.mcs > 13) > > + goto out; > > + > > + rate.eht_gi = wcid->rate.eht_gi; > > + rate.flags = RATE_INFO_FLAGS_EHT_MCS; > > + break; > > + default: > > + goto out; > > + } > > + > > + stats->tx_mode[mode]++; > > + > > + switch (FIELD_GET(MT_TXS0_BW, txs)) { > > + case IEEE80211_STA_RX_BW_320: > > + rate.bw = RATE_INFO_BW_320; > > + stats->tx_bw[4]++; > > + break; > > + case IEEE80211_STA_RX_BW_160: > > + rate.bw = RATE_INFO_BW_160; > > + stats->tx_bw[3]++; > > + break; > > + case IEEE80211_STA_RX_BW_80: > > + rate.bw = RATE_INFO_BW_80; > > + stats->tx_bw[2]++; > > + break; > > + case IEEE80211_STA_RX_BW_40: > > + rate.bw = RATE_INFO_BW_40; > > + stats->tx_bw[1]++; > > + break; > > + default: > > + rate.bw = RATE_INFO_BW_20; > > + stats->tx_bw[0]++; > > + break; > > + } > > + wcid->rate = rate; > > + > > +out: > > + mt76_tx_status_skb_done(dev, skb, &list); > > + > > +out_no_skb: > > + mt76_tx_status_unlock(dev, &list); > > + > > + return !!skb; > > +} > > + > > +void mt76_connac3_mac_add_txs(struct mt76_dev *dev, void *data, > > + u32 max_wtbl_size) > > +{ > > + struct mt76_wcid *wcid; > > + __le32 *txs_data = data; > > + u16 wcidx; > > + u8 pid; > > + > > + if (le32_get_bits(txs_data[0], MT_TXS0_TXS_FORMAT) > 1) > > + return; > > + > > + wcidx = le32_get_bits(txs_data[2], MT_TXS2_WCID); > > + pid = le32_get_bits(txs_data[3], MT_TXS3_PID); > > + > > + if (pid < MT_PACKET_ID_FIRST) > > + return; > > + > > + if (wcidx >= max_wtbl_size) > > + return; > > + > > + rcu_read_lock(); > > + > > + wcid = rcu_dereference(dev->wcid[wcidx]); > > + if (!wcid) > > + goto out; > > + > > + mt76_connac3_mac_add_txs_skb(dev, wcid, pid, txs_data); > > + if (!wcid->sta) > > + goto out; > > + > > + spin_lock_bh(&dev->sta_poll_lock); > > + if (list_empty(&wcid->poll_list)) > > + list_add_tail(&wcid->poll_list, &dev->sta_poll_list); > > + spin_unlock_bh(&dev->sta_poll_lock); > > + > > +out: > > + rcu_read_unlock(); > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_mac_add_txs); > > + > > +void mt76_connac3_tx_token_put(struct mt76_dev *dev) > > +{ > > + struct mt76_txwi_cache *txwi; > > + int id; > > + > > + spin_lock_bh(&dev->token_lock); > > + idr_for_each_entry(&dev->token, txwi, id) { > > + mt76_connac3_txwi_free(dev, txwi, NULL, NULL); > > + dev->token_count--; > > + } > > + spin_unlock_bh(&dev->token_lock); > > + idr_destroy(&dev->token); > > +} > > +EXPORT_SYMBOL_GPL(mt76_connac3_tx_token_put); > > diff --git a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h > > b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h > > index 6663a0b46541..bcc1d976b2b0 100644 > > --- a/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h > > +++ b/drivers/net/wireless/mediatek/mt76/mt76_connac3_mac.h > > @@ -4,6 +4,24 @@ > > #ifndef __MT76_CONNAC3_MAC_H > > #define __MT76_CONNAC3_MAC_H > > > > +/* NOTE: used to map mt76_rates. idx may change if firmware expands > > table */ > > +#define MT76_CONNAC3_BASIC_RATES_TBL 11 > > +#define MT76_CONNAC3_BEACON_RATES_TBL 25 > > > > Different devices may have different defined value. The other WiFi7 device I am working on relies on the values I moved in mt76_connac3_mac.h (in common with mt7996). Moreover you can still have per-device values in mt7996/mac.h (I have not removed it). > > I'm thinking if it's too early to create this patch for just moving > mt7996 to connac3_lib? The code I moved is used by the other device as well. This series is a preliminary series to support it. Regards, Lorenzo > > Ryder >
Attachment:
signature.asc
Description: PGP signature