mt76_connac3_mac.c 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  1. // SPDX-License-Identifier: BSD-3-Clause-Clear
  2. /* Copyright (C) 2023 MediaTek Inc. */
  3. #include "mt76_connac.h"
  4. #include "mt76_connac3_mac.h"
  5. #include "dma.h"
  6. #define HE_BITS(f) cpu_to_le16(IEEE80211_RADIOTAP_HE_##f)
  7. #define EHT_BITS(f) cpu_to_le32(IEEE80211_RADIOTAP_EHT_##f)
  8. #define HE_PREP(f, m, v) le16_encode_bits(le32_get_bits(v, MT_CRXV_HE_##m),\
  9. IEEE80211_RADIOTAP_HE_##f)
  10. #define EHT_PREP(f, m, v) le32_encode_bits(le32_get_bits(v, MT_CRXV_EHT_##m),\
  11. IEEE80211_RADIOTAP_EHT_##f)
  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. status->bw = RATE_INFO_BW_HE_RU;
  19. switch (ru) {
  20. case 0 ... 36:
  21. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_26;
  22. offs = ru;
  23. break;
  24. case 37 ... 52:
  25. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_52;
  26. offs = ru - 37;
  27. break;
  28. case 53 ... 60:
  29. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_106;
  30. offs = ru - 53;
  31. break;
  32. case 61 ... 64:
  33. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_242;
  34. offs = ru - 61;
  35. break;
  36. case 65 ... 66:
  37. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_484;
  38. offs = ru - 65;
  39. break;
  40. case 67:
  41. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_996;
  42. break;
  43. case 68:
  44. status->he_ru = NL80211_RATE_INFO_HE_RU_ALLOC_2x996;
  45. break;
  46. }
  47. he->data1 |= HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
  48. he->data2 |= HE_BITS(DATA2_RU_OFFSET_KNOWN) |
  49. le16_encode_bits(offs,
  50. IEEE80211_RADIOTAP_HE_DATA2_RU_OFFSET);
  51. }
  52. #define MU_PREP(f, v) le16_encode_bits(v, IEEE80211_RADIOTAP_HE_MU_##f)
  53. static void
  54. mt76_connac3_mac_decode_he_mu_radiotap(struct sk_buff *skb, __le32 *rxv)
  55. {
  56. struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
  57. static const struct ieee80211_radiotap_he_mu mu_known = {
  58. .flags1 = HE_BITS(MU_FLAGS1_SIG_B_MCS_KNOWN) |
  59. HE_BITS(MU_FLAGS1_SIG_B_DCM_KNOWN) |
  60. HE_BITS(MU_FLAGS1_CH1_RU_KNOWN) |
  61. HE_BITS(MU_FLAGS1_SIG_B_SYMS_USERS_KNOWN),
  62. .flags2 = HE_BITS(MU_FLAGS2_BW_FROM_SIG_A_BW_KNOWN),
  63. };
  64. struct ieee80211_radiotap_he_mu *he_mu;
  65. status->flag |= RX_FLAG_RADIOTAP_HE_MU;
  66. he_mu = skb_push(skb, sizeof(mu_known));
  67. memcpy(he_mu, &mu_known, sizeof(mu_known));
  68. he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_MCS, status->rate_idx);
  69. if (status->he_dcm)
  70. he_mu->flags1 |= MU_PREP(FLAGS1_SIG_B_DCM, status->he_dcm);
  71. he_mu->flags2 |= MU_PREP(FLAGS2_BW_FROM_SIG_A_BW, status->bw) |
  72. MU_PREP(FLAGS2_SIG_B_SYMS_USERS,
  73. le32_get_bits(rxv[4], MT_CRXV_HE_NUM_USER));
  74. he_mu->ru_ch1[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU0) & 0xff;
  75. if (status->bw >= RATE_INFO_BW_40) {
  76. he_mu->flags1 |= HE_BITS(MU_FLAGS1_CH2_RU_KNOWN);
  77. he_mu->ru_ch2[0] = le32_get_bits(rxv[16], MT_CRXV_HE_RU1) & 0xff;
  78. }
  79. if (status->bw >= RATE_INFO_BW_80) {
  80. u32 ru_h, ru_l;
  81. he_mu->ru_ch1[1] = le32_get_bits(rxv[16], MT_CRXV_HE_RU2) & 0xff;
  82. ru_l = le32_get_bits(rxv[16], MT_CRXV_HE_RU3_L);
  83. ru_h = le32_get_bits(rxv[17], MT_CRXV_HE_RU3_H) & 0x7;
  84. he_mu->ru_ch2[1] = (u8)(ru_l | ru_h << 4);
  85. }
  86. }
  87. void mt76_connac3_mac_decode_he_radiotap(struct sk_buff *skb, __le32 *rxv,
  88. u8 mode)
  89. {
  90. struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
  91. static const struct ieee80211_radiotap_he known = {
  92. .data1 = HE_BITS(DATA1_DATA_MCS_KNOWN) |
  93. HE_BITS(DATA1_DATA_DCM_KNOWN) |
  94. HE_BITS(DATA1_STBC_KNOWN) |
  95. HE_BITS(DATA1_CODING_KNOWN) |
  96. HE_BITS(DATA1_LDPC_XSYMSEG_KNOWN) |
  97. HE_BITS(DATA1_DOPPLER_KNOWN) |
  98. HE_BITS(DATA1_SPTL_REUSE_KNOWN) |
  99. HE_BITS(DATA1_BSS_COLOR_KNOWN),
  100. .data2 = HE_BITS(DATA2_GI_KNOWN) |
  101. HE_BITS(DATA2_TXBF_KNOWN) |
  102. HE_BITS(DATA2_PE_DISAMBIG_KNOWN) |
  103. HE_BITS(DATA2_TXOP_KNOWN),
  104. };
  105. u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
  106. struct ieee80211_radiotap_he *he;
  107. status->flag |= RX_FLAG_RADIOTAP_HE;
  108. he = skb_push(skb, sizeof(known));
  109. memcpy(he, &known, sizeof(known));
  110. he->data3 = HE_PREP(DATA3_BSS_COLOR, BSS_COLOR, rxv[9]) |
  111. HE_PREP(DATA3_LDPC_XSYMSEG, LDPC_EXT_SYM, rxv[4]);
  112. he->data4 = HE_PREP(DATA4_SU_MU_SPTL_REUSE, SR_MASK, rxv[13]);
  113. he->data5 = HE_PREP(DATA5_PE_DISAMBIG, PE_DISAMBIG, rxv[5]) |
  114. le16_encode_bits(ltf_size,
  115. IEEE80211_RADIOTAP_HE_DATA5_LTF_SIZE);
  116. if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
  117. he->data5 |= HE_BITS(DATA5_TXBF);
  118. he->data6 = HE_PREP(DATA6_TXOP, TXOP_DUR, rxv[9]) |
  119. HE_PREP(DATA6_DOPPLER, DOPPLER, rxv[9]);
  120. switch (mode) {
  121. case MT_PHY_TYPE_HE_SU:
  122. he->data1 |= HE_BITS(DATA1_FORMAT_SU) |
  123. HE_BITS(DATA1_UL_DL_KNOWN) |
  124. HE_BITS(DATA1_BEAM_CHANGE_KNOWN) |
  125. HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
  126. he->data3 |= HE_PREP(DATA3_BEAM_CHANGE, BEAM_CHNG, rxv[8]) |
  127. HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
  128. break;
  129. case MT_PHY_TYPE_HE_EXT_SU:
  130. he->data1 |= HE_BITS(DATA1_FORMAT_EXT_SU) |
  131. HE_BITS(DATA1_UL_DL_KNOWN) |
  132. HE_BITS(DATA1_BW_RU_ALLOC_KNOWN);
  133. he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
  134. break;
  135. case MT_PHY_TYPE_HE_MU:
  136. he->data1 |= HE_BITS(DATA1_FORMAT_MU) |
  137. HE_BITS(DATA1_UL_DL_KNOWN);
  138. he->data3 |= HE_PREP(DATA3_UL_DL, UPLINK, rxv[5]);
  139. he->data4 |= HE_PREP(DATA4_MU_STA_ID, MU_AID, rxv[8]);
  140. mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv);
  141. mt76_connac3_mac_decode_he_mu_radiotap(skb, rxv);
  142. break;
  143. case MT_PHY_TYPE_HE_TB:
  144. he->data1 |= HE_BITS(DATA1_FORMAT_TRIG) |
  145. HE_BITS(DATA1_SPTL_REUSE2_KNOWN) |
  146. HE_BITS(DATA1_SPTL_REUSE3_KNOWN) |
  147. HE_BITS(DATA1_SPTL_REUSE4_KNOWN);
  148. he->data4 |= HE_PREP(DATA4_TB_SPTL_REUSE1, SR_MASK, rxv[13]) |
  149. HE_PREP(DATA4_TB_SPTL_REUSE2, SR1_MASK, rxv[13]) |
  150. HE_PREP(DATA4_TB_SPTL_REUSE3, SR2_MASK, rxv[13]) |
  151. HE_PREP(DATA4_TB_SPTL_REUSE4, SR3_MASK, rxv[13]);
  152. mt76_connac3_mac_decode_he_radiotap_ru(status, he, rxv);
  153. break;
  154. default:
  155. break;
  156. }
  157. }
  158. EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_he_radiotap);
  159. static void *
  160. mt76_connac3_mac_radiotap_push_tlv(struct sk_buff *skb, u16 type, u16 len)
  161. {
  162. struct ieee80211_radiotap_tlv *tlv;
  163. tlv = skb_push(skb, sizeof(*tlv) + len);
  164. tlv->type = cpu_to_le16(type);
  165. tlv->len = cpu_to_le16(len);
  166. memset(tlv->data, 0, len);
  167. return tlv->data;
  168. }
  169. void mt76_connac3_mac_decode_eht_radiotap(struct sk_buff *skb, __le32 *rxv,
  170. u8 mode)
  171. {
  172. struct mt76_rx_status *status = (struct mt76_rx_status *)skb->cb;
  173. struct ieee80211_radiotap_eht_usig *usig;
  174. struct ieee80211_radiotap_eht *eht;
  175. u32 ltf_size = le32_get_bits(rxv[4], MT_CRXV_HE_LTF_SIZE) + 1;
  176. u8 bw = FIELD_GET(MT_PRXV_FRAME_MODE, le32_to_cpu(rxv[2]));
  177. if (WARN_ONCE(skb_mac_header(skb) != skb->data,
  178. "Should push tlv at the top of mac hdr"))
  179. return;
  180. eht = mt76_connac3_mac_radiotap_push_tlv(skb, IEEE80211_RADIOTAP_EHT,
  181. sizeof(*eht) + sizeof(u32));
  182. usig = mt76_connac3_mac_radiotap_push_tlv(skb, IEEE80211_RADIOTAP_EHT_USIG,
  183. sizeof(*usig));
  184. status->flag |= RX_FLAG_RADIOTAP_TLV_AT_END;
  185. eht->known |= EHT_BITS(KNOWN_SPATIAL_REUSE) |
  186. EHT_BITS(KNOWN_GI) |
  187. EHT_BITS(KNOWN_EHT_LTF) |
  188. EHT_BITS(KNOWN_LDPC_EXTRA_SYM_OM) |
  189. EHT_BITS(KNOWN_PE_DISAMBIGUITY_OM) |
  190. EHT_BITS(KNOWN_NSS_S);
  191. eht->data[0] |=
  192. EHT_PREP(DATA0_SPATIAL_REUSE, SR_MASK, rxv[13]) |
  193. cpu_to_le32(FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_GI, status->eht.gi) |
  194. FIELD_PREP(IEEE80211_RADIOTAP_EHT_DATA0_LTF, ltf_size)) |
  195. EHT_PREP(DATA0_PE_DISAMBIGUITY_OM, PE_DISAMBIG, rxv[5]) |
  196. EHT_PREP(DATA0_LDPC_EXTRA_SYM_OM, LDPC_EXT_SYM, rxv[4]);
  197. /* iwlwifi and wireshark expect radiotap to report zero-based NSS, so subtract 1. */
  198. eht->data[7] |= le32_encode_bits(status->nss - 1, IEEE80211_RADIOTAP_EHT_DATA7_NSS_S);
  199. eht->user_info[0] |=
  200. EHT_BITS(USER_INFO_MCS_KNOWN) |
  201. EHT_BITS(USER_INFO_CODING_KNOWN) |
  202. EHT_BITS(USER_INFO_NSS_KNOWN_O) |
  203. EHT_BITS(USER_INFO_BEAMFORMING_KNOWN_O) |
  204. EHT_BITS(USER_INFO_DATA_FOR_USER) |
  205. le32_encode_bits(status->rate_idx, IEEE80211_RADIOTAP_EHT_USER_INFO_MCS) |
  206. le32_encode_bits(status->nss - 1, IEEE80211_RADIOTAP_EHT_USER_INFO_NSS_O);
  207. if (le32_to_cpu(rxv[0]) & MT_PRXV_TXBF)
  208. eht->user_info[0] |= EHT_BITS(USER_INFO_BEAMFORMING_O);
  209. if (le32_to_cpu(rxv[0]) & MT_PRXV_HT_AD_CODE)
  210. eht->user_info[0] |= EHT_BITS(USER_INFO_CODING);
  211. if (mode == MT_PHY_TYPE_EHT_MU)
  212. eht->user_info[0] |= EHT_BITS(USER_INFO_STA_ID_KNOWN) |
  213. EHT_PREP(USER_INFO_STA_ID, MU_AID, rxv[8]);
  214. usig->common |=
  215. EHT_BITS(USIG_COMMON_PHY_VER_KNOWN) |
  216. EHT_BITS(USIG_COMMON_BW_KNOWN) |
  217. EHT_BITS(USIG_COMMON_UL_DL_KNOWN) |
  218. EHT_BITS(USIG_COMMON_BSS_COLOR_KNOWN) |
  219. EHT_BITS(USIG_COMMON_TXOP_KNOWN) |
  220. le32_encode_bits(0, IEEE80211_RADIOTAP_EHT_USIG_COMMON_PHY_VER) |
  221. le32_encode_bits(bw, IEEE80211_RADIOTAP_EHT_USIG_COMMON_BW) |
  222. EHT_PREP(USIG_COMMON_UL_DL, UPLINK, rxv[5]) |
  223. EHT_PREP(USIG_COMMON_BSS_COLOR, BSS_COLOR, rxv[9]) |
  224. EHT_PREP(USIG_COMMON_TXOP, TXOP_DUR, rxv[9]);
  225. }
  226. EXPORT_SYMBOL_GPL(mt76_connac3_mac_decode_eht_radiotap);