123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141 |
- From a8d7631858aff156b72f807ee7cc062048e63836 Mon Sep 17 00:00:00 2001
- From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
- 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 <rafal@milecki.pl>
- Acked-by: Arend van Spriel <arend.vanspriel@broadcom.com>
- Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
- ---
- .../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>
- @@ -356,6 +357,34 @@ 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 */
- +#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)
- + radiotap = skb_push(skb, sizeof(*radiotap));
- +#else
- + radiotap = (struct ieee80211_radiotap_header *)skb_push(skb, sizeof(*radiotap));
- +#endif
- + 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
- @@ -122,6 +122,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];
- @@ -217,6 +218,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
- @@ -1126,6 +1128,7 @@ brcmf_msgbuf_process_rx_complete(struct
- struct sk_buff *skb;
- u16 data_offset;
- u16 buflen;
- + u16 flags;
- u32 idx;
- struct brcmf_if *ifp;
-
- @@ -1135,6 +1138,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);
- @@ -1148,6 +1152,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",
|