On Sat, 2023-06-10 at 12:06 +0200, lorenzo@xxxxxxxxxx wrote: > > On Sat, 2023-06-10 at 02:47 +0800, Shayne Chen wrote: > > > > > On Fri, 2023-06-09 at 18:34 +0200, > > > > > lorenzo.bianconi@xxxxxxxxxx > > > > > > > > wrote: > > > > > > 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> > > > > > > Hi Lorenzo, > > Hi Shayne, > Hi Lorenzo, > > > > > > I don't think it's a good idea to start sharing mac or mcu > > > functions > > > for all WiFi7 chipsets at such early stage. > > > > > > The driver is still under many processes of bug fixing, > > > performance > > > tuning, and new features development. > > > Chipsets that mainly used for AP or STA segment have different > > > designs > > > and should face different problems. > > > > > > Start sharing the code at early stage will break the > > > independence, > > > make > > > it more hard to develop and do verifications, since many changes > > > will > > > affect chipsets of both segments. > > my goal is to share the code that hardly will be changed (or that > will have > very few changes in the future, i.e. I have not changed mcu > codebase). > If you consider for example the routines below: > > - mt76_connac*_mac_write_txwi_8023() > - mt76_connac*_mac_write_txwi_80211() > - mt76_connac*_mac_add_txs_skb() > - mt76_connac*_txwi_free() > - ... > > they are the same for mt7615/mt7663, mt7921/mt7915, mt7996/.. , what > is > changing is just register map between versions (e.g. mt7615/mt7663 > and > mt7915/mt7921). I think it is not a good idea to copy-paste the code > because it will just make the code much harder to maintain, and this > will be > more difficult to address in the future. > If you consider the commit below: > > commit ead449023d3acb1424886d7b8cc672ed69bdd27e > Author: Lorenzo Bianconi <lorenzo@xxxxxxxxxx> > Date: Sun May 28 12:28:49 2023 +0200 > > wifi: mt76: mt7996: fix possible NULL pointer dereference in > mt7996_mac_write_txwi() > > Fix possible NULL pointer dereference on mvif pointer in > mt7996_mac_write_txwi routine. > > Deren will needs to monitor the ML and apply the same fix for the > other WiFi7 > chipset too. > > Moreover I kept mt7996/mac.{c,h} to put the per-chipset codebase. > If you think MT76_CONNAC3_BASIC_RATES_TBL11 and > MT76_CONNAC3_BEACON_RATES_TBL25 > are sensible, we can put them in mt7996/mac.h I understand your concern, but if the code starts to be shared at early stage, we may need to add several is_mt7996() to split different parts temporarily or permanently, since we have different development procedure and focusing, on devices of different segements. Below are some examples I concern: - We're doing some tests about switching all TXS to PPDU TXS, and the code in mac_add_txs_skb() needs to be changed. If devices of STA segement don't want to change or won't switch in short time, we may need to add is_mt7996() to split. - When adding MLO support, there will be many changes in mac_write_txwi() and txwi_free(), compared to previous chipsets. To prevent from adding side effects to other devices, we may also need to add is_mt7996() to split code at least for temporary. I would like to know is it fine with you to add some is_mt7996() to the shared code for the above examples? I think this could help to balance the trade off between sharing code and assuring the driver stability on different segements. Thanks, Shayne > > Regards, > Lorenzo > > > > > > > Thanks, > > > Shayne > > > > > > > (Resend for missing CC) > > > > > > > > > > --- > > > > > > > > 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_TBL11 > > > > > > > > +#define MT76_CONNAC3_BEACON_RATES_TBL25 > > > > > > > > > > > > > > > > > > > > > > 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). > > > > > > > > > > > > > > > > Please double check with the mtk folk you work with. The 11 > > > > > and > > > > > 25 > > > > > > > > is > > > > > the value I discussed with firmware folks to avoid > > > > > overlapping > > > > > the > > > > > > > > tbl > > > > > mt7996 use (MU/other algo in fw), or it causes something > > > > > hardly > > > > > > > > solving > > > > > issue > > > > > > > > sure, thx for pointing this out. > > > > @Deren: can you please double check? > > > > > > > > Regards, > > > > Lorenzo > > > > > > > > > > > > > > > > > > > > > > > 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 > > > > > > >