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




[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