Search Linux Wireless

Re: [PATCH v2 15/15] wifi: mt76: connac: add connac3 mac library

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



> 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,

> > 
> > 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

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
> > > > > > 

Attachment: signature.asc
Description: PGP signature


[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux