forked from openwrt/mt76
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
wifi: mt76: connac: add connac3 mac library
Introduce connac3_mac in mt76_connac library to reuse mac code shared between WiFi7 chipsets. So far connac3 library contains just radiotap parsing code. Signed-off-by: Lorenzo Bianconi <[email protected]> Signed-off-by: Felix Fietkau <[email protected]>
- Loading branch information
1 parent
0dc4326
commit 29cfabb
Showing
4 changed files
with
187 additions
and
180 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
// 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) | ||
|
||
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_OFFSET); | ||
} | ||
|
||
#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_SIZE); | ||
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); |
Oops, something went wrong.