339-v5.1-0004-brcmfmac-support-monitor-frames-with-the-hardware-uc.patch 4.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  1. From e665988be29ccea3584528967b432a5cfd801ca4 Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
  3. Date: Fri, 8 Feb 2019 07:42:30 +0100
  4. Subject: [PATCH] brcmfmac: support monitor frames with the hardware/ucode
  5. header
  6. MIME-Version: 1.0
  7. Content-Type: text/plain; charset=UTF-8
  8. Content-Transfer-Encoding: 8bit
  9. So far there were two monitor frame formats:
  10. 1) 802.11 frames (with frame (sub)type & all addresses)
  11. 2) 802.11 frames with the radiotap header
  12. Testing the latest FullMAC firmwares for 4366b1/4366c0 resulted in
  13. discovering a new format being used. It seems (almost?) identical to the
  14. one known from ucode used in SoftMAC devices which is most likely the
  15. same codebase anyway.
  16. While new firmwares will /announce/ radiotap header support using the
  17. "rtap" fw capability string it seems no string was added for the new
  18. ucode header format.
  19. All above means that:
  20. 1) We need new format support when dealing with a received frame
  21. 2) A new feature bit & mapping quirks have to be added manually
  22. As for now only an empty radiotap is being created. Adding support for
  23. extracting some info (band, channel, signal, etc.) is planned for the
  24. future.
  25. Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
  26. Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
  27. Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
  28. ---
  29. .../broadcom/brcm80211/brcmfmac/core.c | 55 +++++++++++++++++++
  30. .../broadcom/brcm80211/brcmfmac/feature.c | 4 ++
  31. .../broadcom/brcm80211/brcmfmac/feature.h | 4 +-
  32. 3 files changed, 62 insertions(+), 1 deletion(-)
  33. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
  34. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
  35. @@ -42,6 +42,36 @@
  36. #define BRCMF_BSSIDX_INVALID -1
  37. +#define RXS_PBPRES BIT(2)
  38. +
  39. +#define D11_PHY_HDR_LEN 6
  40. +
  41. +struct d11rxhdr_le {
  42. + __le16 RxFrameSize;
  43. + u16 PAD;
  44. + __le16 PhyRxStatus_0;
  45. + __le16 PhyRxStatus_1;
  46. + __le16 PhyRxStatus_2;
  47. + __le16 PhyRxStatus_3;
  48. + __le16 PhyRxStatus_4;
  49. + __le16 PhyRxStatus_5;
  50. + __le16 RxStatus1;
  51. + __le16 RxStatus2;
  52. + __le16 RxTSFTime;
  53. + __le16 RxChan;
  54. + u8 unknown[12];
  55. +} __packed;
  56. +
  57. +struct wlc_d11rxhdr {
  58. + struct d11rxhdr_le rxhdr;
  59. + __le32 tsf_l;
  60. + s8 rssi;
  61. + s8 rxpwr0;
  62. + s8 rxpwr1;
  63. + s8 do_rssi_ma;
  64. + s8 rxpwr[4];
  65. +} __packed;
  66. +
  67. char *brcmf_ifname(struct brcmf_if *ifp)
  68. {
  69. if (!ifp)
  70. @@ -361,6 +391,35 @@ void brcmf_netif_mon_rx(struct brcmf_if
  71. {
  72. if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
  73. /* Do nothing */
  74. + } else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR)) {
  75. + struct wlc_d11rxhdr *wlc_rxhdr = (struct wlc_d11rxhdr *)skb->data;
  76. + struct ieee80211_radiotap_header *radiotap;
  77. + unsigned int offset;
  78. + u16 RxStatus1;
  79. +
  80. + RxStatus1 = le16_to_cpu(wlc_rxhdr->rxhdr.RxStatus1);
  81. +
  82. + offset = sizeof(struct wlc_d11rxhdr);
  83. + /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU
  84. + * subframes
  85. + */
  86. + if (RxStatus1 & RXS_PBPRES)
  87. + offset += 2;
  88. + offset += D11_PHY_HDR_LEN;
  89. +
  90. + skb_pull(skb, offset);
  91. +
  92. + /* TODO: use RX header to fill some radiotap data */
  93. +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
  94. + radiotap = skb_push(skb, sizeof(*radiotap));
  95. +#else
  96. + radiotap = (struct ieee80211_radiotap_header *)skb_push(skb, sizeof(*radiotap));
  97. +#endif
  98. + memset(radiotap, 0, sizeof(*radiotap));
  99. + radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
  100. +
  101. + /* TODO: 4 bytes with receive status? */
  102. + skb->len -= 4;
  103. } else {
  104. struct ieee80211_radiotap_header *radiotap;
  105. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
  106. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
  107. @@ -102,6 +102,10 @@ static const struct brcmf_feat_fwfeat br
  108. { "01-6cb8e269", BIT(BRCMF_FEAT_MONITOR) },
  109. /* brcmfmac4366b-pcie.bin from linux-firmware.git commit 52442afee990 */
  110. { "01-c47a91a4", BIT(BRCMF_FEAT_MONITOR) },
  111. + /* brcmfmac4366b-pcie.bin from linux-firmware.git commit 211de1679a68 */
  112. + { "01-801fb449", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) },
  113. + /* brcmfmac4366c-pcie.bin from linux-firmware.git commit 211de1679a68 */
  114. + { "01-d2cbb8fd", BIT(BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR) },
  115. };
  116. static void brcmf_feat_firmware_overrides(struct brcmf_pub *drv)
  117. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
  118. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
  119. @@ -33,6 +33,7 @@
  120. * MFP: 802.11w Management Frame Protection.
  121. * MONITOR: firmware can pass monitor packets to host.
  122. * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
  123. + * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
  124. */
  125. #define BRCMF_FEAT_LIST \
  126. BRCMF_FEAT_DEF(MBSS) \
  127. @@ -48,7 +49,8 @@
  128. BRCMF_FEAT_DEF(WOWL_ARP_ND) \
  129. BRCMF_FEAT_DEF(MFP) \
  130. BRCMF_FEAT_DEF(MONITOR) \
  131. - BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
  132. + BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
  133. + BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR)
  134. /*
  135. * Quirks: