1 // SPDX-License-Identifier: ISC 2 /* Copyright (C) 2023 MediaTek Inc. */ 3 4 #include "mt76_connac.h" 5 #include "mt76_connac3_mac.h" 6 #include "dma.h" 7 8 #define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f) 9 #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\ 10 IEEE80211_RADIOTAP_HE_##f) 11 12 static void 13 mt76_connac3_mac_decode_he_radiotap_ru(struct mt76_rx_status *status, 14 struct ieee80211_radiotap_he *he, 15 __le32 *rxv) 16 { 17 u32 ru = le32_get_bits(rxv[0], MT_PRXV_HE_RU_ALLOC), offs = 0; 18 19 status->bw = RATE_INFO_BW_HE_RU; 20 21 switch (ru) { 22 case 0 ... 36: 23 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26; 24 offs = ru; 25 break; 26 case 37 ... 52: 27 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52; 28 offs = ru - 37; 29 break; 30 case 53 ... 60: 31 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106; 32 offs = ru - 53; 33 break; 34 case 61 ... 64: 35 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242; 36 offs = ru - 61; 37 break; 38 case 65 ... 66: 39 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484; 40 offs = ru - 65; 41 break; 42 case 67: 43 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996; 44 break; 45 case 68: 46 status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996; 47 break; 48 } 49 50 he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 51 he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) | 52 le16_encode_bits(offs, 53 IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET); 54 } 55 56 #define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f) 57 static void 58 mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv) 59 { 60 struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 61 static const struct ieee80211_radiotap_he_mu mu_known = { 62 .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) | 63 HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) | 64 HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) | 65 HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN), 66 .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN), 67 }; 68 struct ieee80211_radiotap_he_mu *he_mu; 69 70 status->flag |= RX_FLAG_RADIOTAP_HE_MU; 71 72 he_mu = skb_push(skb, sizeof(mu_known)); 73 memcpy(he_mu, &mu_known, sizeof(mu_known)); 74 75 he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx); 76 if (status->he_dcm) 77 he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm); 78 79 he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) | 80 MU_PREP(FLAGS2_SIG_B_SYMS_USERS, 81 le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER)); 82 83 he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff; 84 85 if (status->bw >= RATE_INFO_BW_40) { 86 he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN); 87 he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff; 88 } 89 90 if (status->bw >= RATE_INFO_BW_80) { 91 u32 ru_h, ru_l; 92 93 he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff; 94 95 ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L); 96 ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7; 97 he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4); 98 } 99 } 100 101 void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv, 102 u8 mode) 103 { 104 struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb; 105 static const struct ieee80211_radiotap_he known = { 106 .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) | 107 HE_BITS(DATA1_DATA_DCM_KNOWN) | 108 HE_BITS(DATA1_STBC_KNOWN) | 109 HE_BITS(DATA1_CODING_KNOWN) | 110 HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) | 111 HE_BITS(DATA1_DOPPLER_KNOWN) | 112 HE_BITS(DATA1_SPTL_REUSE_KNOWN) | 113 HE_BITS(DATA1_BSS_COLOR_KNOWN), 114 .data2 = HE_BITS(DATA2_GI_KNOWN) | 115 HE_BITS(DATA2_TXBF_KNOWN) | 116 HE_BITS(DATA2_PE_DISAMBIG_KNOWN) | 117 HE_BITS(DATA2_TXOP_KNOWN), 118 }; 119 u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1; 120 struct ieee80211_radiotap_he *he; 121 122 status->flag |= RX_FLAG_RADIOTAP_HE; 123 124 he = skb_push(skb, sizeof(known)); 125 memcpy(he, &known, sizeof(known)); 126 127 he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) | 128 HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]); 129 he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]); 130 he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) | 131 le16_encode_bits(ltf_size, 132 IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE); 133 if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF) 134 he->data5 |= HE_BITS(DATA5_TXBF); 135 he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) | 136 HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]); 137 138 switch (mode) { 139 case MT_PHY_TYPE_HE_SU: 140 he->data1 |= HE_BITS(DATA1_FORMAT_SU) | 141 HE_BITS(DATA1_UL_DL_KNOWN) | 142 HE_BITS(DATA1_BEAM_CHANGE_KNOWN) | 143 HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 144 145 he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) | 146 HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 147 break; 148 case MT_PHY_TYPE_HE_EXT_SU: 149 he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) | 150 HE_BITS(DATA1_UL_DL_KNOWN) | 151 HE_BITS(DATA1_BW_RU_ALLOC_KNOWN); 152 153 he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 154 break; 155 case MT_PHY_TYPE_HE_MU: 156 he->data1 |= HE_BITS(DATA1_FORMAT_MU) | 157 HE_BITS(DATA1_UL_DL_KNOWN); 158 159 he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]); 160 he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]); 161 162 mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv); 163 mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv); 164 break; 165 case MT_PHY_TYPE_HE_TB: 166 he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) | 167 HE_BITS(DATA1_SPTL_REUSE2_KNOWN) | 168 HE_BITS(DATA1_SPTL_REUSE3_KNOWN) | 169 HE_BITS(DATA1_SPTL_REUSE4_KNOWN); 170 171 he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) | 172 HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) | 173 HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) | 174 HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]); 175 176 mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv); 177 break; 178 default: 179 break; 180 } 181 } 182 EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap); 183