[PATCH v3 3/8] wifi: brcmfmac: core: populate radiotap header with RSSI
From: Shivesh
Date: Fri Jul 31 2026 - 11:56:33 EST
From: Shivesh <chanelshivesh@xxxxxxxxx>
Populates the radiotap header with dbm_antsignal using the rssi
value extracted from the firmware's hardware RX header, fixing
missing signal data in monitor mode captures.
Signed-off-by: Shivesh <chanelshivesh@xxxxxxxxx>
---
.../broadcom/brcm80211/brcmfmac/core.c | 44 ++++++++++++-------
1 file changed, 29 insertions(+), 15 deletions(-)
diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
index ec170647800d..eefc437dd055 100644
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
@@ -431,45 +431,55 @@ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb)
netif_rx(skb);
}
+struct brcmf_radiotap_info {
+ struct ieee80211_radiotap_header hdr;
+ s8 dbm_antsignal;
+} __packed;
+
void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
{
if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_RADIOTAP)) {
- /* Do nothing */
+ /* Firmware already provided a full radiotap header; do nothing */
} else if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FMT_HW_RX_HDR)) {
struct wlc_d11rxhdr *wlc_rxhdr = (struct wlc_d11rxhdr *)skb->data;
- struct ieee80211_radiotap_header *radiotap;
+ struct brcmf_radiotap_info *rtap;
unsigned int offset;
u16 RxStatus1;
+ s8 rssi;
RxStatus1 = le16_to_cpu(wlc_rxhdr->rxhdr.RxStatus1);
+ rssi = wlc_rxhdr->rssi;
offset = sizeof(struct wlc_d11rxhdr);
- /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU
- * subframes
- */
+ /* MAC inserts 2 pad bytes for a4 headers or QoS or A-MSDU subframes */
if (RxStatus1 & RXS_PBPRES)
offset += 2;
offset += D11_PHY_HDR_LEN;
skb_pull(skb, offset);
- /* TODO: use RX header to fill some radiotap data */
- radiotap = skb_push(skb, sizeof(*radiotap));
- memset(radiotap, 0, sizeof(*radiotap));
- radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
-
- /* TODO: 4 bytes with receive status? */
- skb->len -= 4;
+ /* Insert our radiotap header with RSSI data */
+ if (skb_cow_head(skb, sizeof(*rtap)))
+ goto drop;
+ rtap = skb_push(skb, sizeof(*rtap));
+ memset(rtap, 0, sizeof(*rtap));
+ rtap->hdr.it_len = cpu_to_le16(sizeof(*rtap));
+ rtap->hdr.it_present = cpu_to_le32(1 << IEEE80211_RADIOTAP_DBM_ANTSIGNAL);
+ rtap->dbm_antsignal = rssi;
+
+ /* Strip the 4-byte receive status / FCS tail */
+ skb_trim(skb, skb->len - 4);
} else {
struct ieee80211_radiotap_header *radiotap;
- /* TODO: use RX status to fill some radiotap data */
+ if (skb_cow_head(skb, sizeof(*radiotap)))
+ goto drop;
radiotap = skb_push(skb, sizeof(*radiotap));
memset(radiotap, 0, sizeof(*radiotap));
radiotap->it_len = cpu_to_le16(sizeof(*radiotap));
- /* TODO: 4 bytes with receive status? */
- skb->len -= 4;
+ /* Strip the 4-byte receive status / FCS tail */
+ skb_trim(skb, skb->len - 4);
}
skb->dev = ifp->ndev;
@@ -478,6 +488,10 @@ void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb)
skb->protocol = htons(ETH_P_802_2);
brcmf_netif_rx(ifp, skb);
+ return;
+
+drop:
+ brcmu_pkt_buf_free_skb(skb);
}
static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
--
2.53.0