|
|
@@ -0,0 +1,137 @@
|
|
|
+From a8d7631858aff156b72f807ee7cc062048e63836 Mon Sep 17 00:00:00 2001
|
|
|
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
|
|
|
+Date: Sun, 24 Jun 2018 21:44:37 +0200
|
|
|
+Subject: [PATCH] brcmfmac: handle msgbuf packets marked with monitor mode flag
|
|
|
+MIME-Version: 1.0
|
|
|
+Content-Type: text/plain; charset=UTF-8
|
|
|
+Content-Transfer-Encoding: 8bit
|
|
|
+
|
|
|
+New Broadcom firmwares mark monitor mode packets using a newly defined
|
|
|
+bit in the flags field. Use it to filter them out and pass to the
|
|
|
+monitor interface. These defines were found in bcmmsgbuf.h from SDK.
|
|
|
+
|
|
|
+As not every firmware generates radiotap header this commit introduces
|
|
|
+BRCMF_FEAT_MONITOR_FMT_RADIOTAP flag. It has to be has based on firmware
|
|
|
+capabilities. If not present brcmf_netif_mon_rx() will assume packet is
|
|
|
+a raw 802.11 frame and will prepend it with an empty radiotap header.
|
|
|
+
|
|
|
+This new code is limited to the msgbuf protocol at this point. Adding
|
|
|
+support for SDIO/USB devices will require some extra work (possibly a
|
|
|
+new firmware release).
|
|
|
+
|
|
|
+Signed-off-by: Rafał Miłecki <[email protected]>
|
|
|
+Acked-by: Arend van Spriel <[email protected]>
|
|
|
+Signed-off-by: Kalle Valo <[email protected]>
|
|
|
+---
|
|
|
+ .../wireless/broadcom/brcm80211/brcmfmac/core.c | 25 ++++++++++++++++++++++
|
|
|
+ .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 ++
|
|
|
+ .../wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 18 ++++++++++++++++
|
|
|
+ 3 files changed, 45 insertions(+)
|
|
|
+
|
|
|
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
|
|
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
|
|
|
+@@ -21,6 +21,7 @@
|
|
|
+ #include <net/cfg80211.h>
|
|
|
+ #include <net/rtnetlink.h>
|
|
|
+ #include <net/addrconf.h>
|
|
|
++#include <net/ieee80211_radiotap.h>
|
|
|
+ #include <net/ipv6.h>
|
|
|
+ #include <brcmu_utils.h>
|
|
|
+ #include <brcmu_wifi.h>
|
|
|
+@@ -404,6 +405,30 @@ void brcmf_netif_rx(struct brcmf_if *ifp
|
|
|
+ netif_rx_ni(skb);
|
|
|
+ }
|
|
|
+
|
|
|
++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 */
|
|
|
++ } else {
|
|
|
++ struct ieee80211_radiotap_header *radiotap;
|
|
|
++
|
|
|
++ /* TODO: use RX status 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;
|
|
|
++ }
|
|
|
++
|
|
|
++ skb->dev = ifp->ndev;
|
|
|
++ skb_reset_mac_header(skb);
|
|
|
++ skb->pkt_type = PACKET_OTHERHOST;
|
|
|
++ skb->protocol = htons(ETH_P_802_2);
|
|
|
++
|
|
|
++ brcmf_netif_rx(ifp, skb);
|
|
|
++}
|
|
|
++
|
|
|
+ static int brcmf_rx_hdrpull(struct brcmf_pub *drvr, struct sk_buff *skb,
|
|
|
+ struct brcmf_if **ifp)
|
|
|
+ {
|
|
|
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
|
|
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
|
|
|
+@@ -121,6 +121,7 @@ struct brcmf_pub {
|
|
|
+
|
|
|
+ struct brcmf_if *iflist[BRCMF_MAX_IFS];
|
|
|
+ s32 if2bss[BRCMF_MAX_IFS];
|
|
|
++ struct brcmf_if *mon_if;
|
|
|
+
|
|
|
+ struct mutex proto_block;
|
|
|
+ unsigned char proto_buf[BRCMF_DCMD_MAXLEN];
|
|
|
+@@ -216,6 +217,7 @@ void brcmf_txflowblock_if(struct brcmf_i
|
|
|
+ enum brcmf_netif_stop_reason reason, bool state);
|
|
|
+ void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
|
|
|
+ void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
|
|
++void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
|
|
|
+ void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
|
|
|
+ int __init brcmf_core_init(void);
|
|
|
+ void __exit brcmf_core_exit(void);
|
|
|
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
|
|
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
|
|
|
+@@ -69,6 +69,8 @@
|
|
|
+ #define BRCMF_MSGBUF_MAX_EVENTBUF_POST 8
|
|
|
+
|
|
|
+ #define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_3 0x01
|
|
|
++#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11 0x02
|
|
|
++#define BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK 0x07
|
|
|
+ #define BRCMF_MSGBUF_PKT_FLAGS_PRIO_SHIFT 5
|
|
|
+
|
|
|
+ #define BRCMF_MSGBUF_TX_FLUSH_CNT1 32
|
|
|
+@@ -1128,6 +1130,7 @@ brcmf_msgbuf_process_rx_complete(struct
|
|
|
+ struct sk_buff *skb;
|
|
|
+ u16 data_offset;
|
|
|
+ u16 buflen;
|
|
|
++ u16 flags;
|
|
|
+ u32 idx;
|
|
|
+ struct brcmf_if *ifp;
|
|
|
+
|
|
|
+@@ -1137,6 +1140,7 @@ brcmf_msgbuf_process_rx_complete(struct
|
|
|
+ data_offset = le16_to_cpu(rx_complete->data_offset);
|
|
|
+ buflen = le16_to_cpu(rx_complete->data_len);
|
|
|
+ idx = le32_to_cpu(rx_complete->msg.request_id);
|
|
|
++ flags = le16_to_cpu(rx_complete->flags);
|
|
|
+
|
|
|
+ skb = brcmf_msgbuf_get_pktid(msgbuf->drvr->bus_if->dev,
|
|
|
+ msgbuf->rx_pktids, idx);
|
|
|
+@@ -1150,6 +1154,20 @@ brcmf_msgbuf_process_rx_complete(struct
|
|
|
+
|
|
|
+ skb_trim(skb, buflen);
|
|
|
+
|
|
|
++ if ((flags & BRCMF_MSGBUF_PKT_FLAGS_FRAME_MASK) ==
|
|
|
++ BRCMF_MSGBUF_PKT_FLAGS_FRAME_802_11) {
|
|
|
++ ifp = msgbuf->drvr->mon_if;
|
|
|
++
|
|
|
++ if (!ifp) {
|
|
|
++ brcmf_err("Received unexpected monitor pkt\n");
|
|
|
++ brcmu_pkt_buf_free_skb(skb);
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
++ brcmf_netif_mon_rx(ifp, skb);
|
|
|
++ return;
|
|
|
++ }
|
|
|
++
|
|
|
+ ifp = brcmf_get_ifp(msgbuf->drvr, rx_complete->msg.ifidx);
|
|
|
+ if (!ifp || !ifp->ndev) {
|
|
|
+ brcmf_err("Received pkt for invalid ifidx %d\n",
|