--- /dev/null
+From 01f69dfafdbe7deff58b58053bc3a4a75c6a570c 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:35 +0200
+Subject: [PATCH] brcmfmac: detect firmware support for monitor interface
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Many/most of firmwares support creating monitor interface but only the
+most recent ones explicitly /announce/ it using a "monitor" entry in the
+list of capabilities.
+
+Check for that entry and store internally info about monitor mode
+support using a new feature flag. Once we sort out all details of
+handling monitor interface it will be used when reporting available
+interfaces to the cfg80211.
+
+Later some fallback detecion method may be added for older firmwares.
+For now just stick to the "monitor" capability which should be 100%
+reliable.
+
+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>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 1 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -48,6 +48,7 @@ static const struct brcmf_feat_fwcap brc
+ { BRCMF_FEAT_MBSS, "mbss" },
+ { BRCMF_FEAT_MCHAN, "mchan" },
+ { BRCMF_FEAT_P2P, "p2p" },
++ { BRCMF_FEAT_MONITOR, "monitor" },
+ };
+
+ #ifdef DEBUG
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+@@ -33,6 +33,7 @@
+ * MFP: 802.11w Management Frame Protection.
+ * GSCAN: enhanced scan offload feature.
+ * FWSUP: Firmware supplicant.
++ * MONITOR: firmware can pass monitor packets to host.
+ */
+ #define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MBSS) \
+@@ -48,7 +49,8 @@
+ BRCMF_FEAT_DEF(WOWL_ARP_ND) \
+ BRCMF_FEAT_DEF(MFP) \
+ BRCMF_FEAT_DEF(GSCAN) \
+- BRCMF_FEAT_DEF(FWSUP)
++ BRCMF_FEAT_DEF(FWSUP) \
++ BRCMF_FEAT_DEF(MONITOR)
+
+ /*
+ * Quirks:
--- /dev/null
+From e63410ac65e0ead2040bbd3927c116889edf87e4 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:36 +0200
+Subject: [PATCH] brcmfmac: detect firmware support for radiotap monitor frames
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Depending on used build-time options some firmwares may already include
+radiotap header in passed monitor frames. Add a new feature flag to
+store info about it. It's needed for proper handling of received frames
+before passing them up.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c | 1 +
+ drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h | 4 +++-
+ 2 files changed, 4 insertions(+), 1 deletion(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
+@@ -49,6 +49,7 @@ static const struct brcmf_feat_fwcap brc
+ { BRCMF_FEAT_MCHAN, "mchan" },
+ { BRCMF_FEAT_P2P, "p2p" },
+ { BRCMF_FEAT_MONITOR, "monitor" },
++ { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
+ };
+
+ #ifdef DEBUG
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
+@@ -34,6 +34,7 @@
+ * GSCAN: enhanced scan offload feature.
+ * FWSUP: Firmware supplicant.
+ * MONITOR: firmware can pass monitor packets to host.
++ * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
+ */
+ #define BRCMF_FEAT_LIST \
+ BRCMF_FEAT_DEF(MBSS) \
+@@ -50,7 +51,8 @@
+ BRCMF_FEAT_DEF(MFP) \
+ BRCMF_FEAT_DEF(GSCAN) \
+ BRCMF_FEAT_DEF(FWSUP) \
+- BRCMF_FEAT_DEF(MONITOR)
++ BRCMF_FEAT_DEF(MONITOR) \
++ BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP)
+
+ /*
+ * Quirks:
--- /dev/null
+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>
+@@ -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",
--- /dev/null
+From 4b4a8d808c58fc0defc32a26b2fea35d66692c45 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Thu, 28 Jun 2018 08:16:13 +0200
+Subject: [PATCH] brcmfmac: define more bits for the flags of struct
+ brcmf_sta_info_le
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+That struct is passed by a firmware when querying for STA info. Flags
+are used to indicate what info could be obtained.
+
+These new defines may allow passing more info to the cfg80211 in the
+future. They had been obtained from Broadcom's SDK file wlioctl_defs.h
+used by DD-WRT.
+
+Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
+Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
+---
+ .../broadcom/brcm80211/brcmfmac/fwil_types.h | 29 ++++++++++++++++++----
+ 1 file changed, 24 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -32,11 +32,30 @@
+ #define BRCMF_BSS_INFO_VERSION 109 /* curr ver of brcmf_bss_info_le struct */
+ #define BRCMF_BSS_RSSI_ON_CHANNEL 0x0002
+
+-#define BRCMF_STA_WME 0x00000002 /* WMM association */
+-#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
+-#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
+-#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
+-#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
++#define BRCMF_STA_BRCM 0x00000001 /* Running a Broadcom driver */
++#define BRCMF_STA_WME 0x00000002 /* WMM association */
++#define BRCMF_STA_NONERP 0x00000004 /* No ERP */
++#define BRCMF_STA_AUTHE 0x00000008 /* Authenticated */
++#define BRCMF_STA_ASSOC 0x00000010 /* Associated */
++#define BRCMF_STA_AUTHO 0x00000020 /* Authorized */
++#define BRCMF_STA_WDS 0x00000040 /* Wireless Distribution System */
++#define BRCMF_STA_WDS_LINKUP 0x00000080 /* WDS traffic/probes flowing properly */
++#define BRCMF_STA_PS 0x00000100 /* STA is in power save mode from AP's viewpoint */
++#define BRCMF_STA_APSD_BE 0x00000200 /* APSD delv/trigger for AC_BE is default enabled */
++#define BRCMF_STA_APSD_BK 0x00000400 /* APSD delv/trigger for AC_BK is default enabled */
++#define BRCMF_STA_APSD_VI 0x00000800 /* APSD delv/trigger for AC_VI is default enabled */
++#define BRCMF_STA_APSD_VO 0x00001000 /* APSD delv/trigger for AC_VO is default enabled */
++#define BRCMF_STA_N_CAP 0x00002000 /* STA 802.11n capable */
++#define BRCMF_STA_SCBSTATS 0x00004000 /* Per STA debug stats */
++#define BRCMF_STA_AMPDU_CAP 0x00008000 /* STA AMPDU capable */
++#define BRCMF_STA_AMSDU_CAP 0x00010000 /* STA AMSDU capable */
++#define BRCMF_STA_MIMO_PS 0x00020000 /* mimo ps mode is enabled */
++#define BRCMF_STA_MIMO_RTS 0x00040000 /* send rts in mimo ps mode */
++#define BRCMF_STA_RIFS_CAP 0x00080000 /* rifs enabled */
++#define BRCMF_STA_VHT_CAP 0x00100000 /* STA VHT(11ac) capable */
++#define BRCMF_STA_WPS 0x00200000 /* WPS state */
++#define BRCMF_STA_DWDS_CAP 0x01000000 /* DWDS CAP */
++#define BRCMF_STA_DWDS 0x02000000 /* DWDS active */
+
+ /* size of brcmf_scan_params not including variable length array */
+ #define BRCMF_SCAN_PARAMS_FIXED_SIZE 64
--- /dev/null
+From 07b1ae46874949252625c96f309f96ca0f337020 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
+Date: Thu, 28 Jun 2018 12:36:23 +0200
+Subject: [PATCH] brcmfmac: update STA info struct to the v5
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+That struct is used when querying firmware for the STA. It seem is has
+been changing during the time. Luckily its format seems to be backward
+compatible starting with v2 (the only breakage was v1 -> v2).
+
+The version that was supported by brcmfmac so far was v4. It was what
+43602a1 and 4366b1 firmwares (7.35.177.56 and 10.10.69.3309 accordingly)
+were using. It also seems to be used by early 4366c0 firmwares
+(10.10.69.6908 and 10.10.69.69017).
+
+The problem appears when switching to the 10.10.122.20 firmware. It uses
+v5 and instead of falling back to v4 when submitted buffer isn't big
+enough it fallbacks to the v3.
+
+To receive all v4 specific info with the newest firmware we have to
+submit a struct (buffer) that matches v5.
+
+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>
+---
+ .../net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h | 14 ++++++++++++++
+ 1 file changed, 14 insertions(+)
+
+--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil_types.h
+@@ -174,6 +174,8 @@
+ #define BRCMF_MFP_CAPABLE 1
+ #define BRCMF_MFP_REQUIRED 2
+
++#define BRCMF_VHT_CAP_MCS_MAP_NSS_MAX 8
++
+ /* MAX_CHUNK_LEN is the maximum length for data passing to firmware in each
+ * ioctl. It is relatively small because firmware has small maximum size input
+ * playload restriction for ioctls.
+@@ -550,6 +552,8 @@ struct brcmf_sta_info_le {
+ /* w/hi bit set if basic */
+ __le32 in; /* seconds elapsed since associated */
+ __le32 listen_interval_inms; /* Min Listen interval in ms for STA */
++
++ /* Fields valid for ver >= 3 */
+ __le32 tx_pkts; /* # of packets transmitted */
+ __le32 tx_failures; /* # of packets failed */
+ __le32 rx_ucast_pkts; /* # of unicast packets received */
+@@ -558,6 +562,8 @@ struct brcmf_sta_info_le {
+ __le32 rx_rate; /* Rate of last successful rx frame */
+ __le32 rx_decrypt_succeeds; /* # of packet decrypted successfully */
+ __le32 rx_decrypt_failures; /* # of packet decrypted failed */
++
++ /* Fields valid for ver >= 4 */
+ __le32 tx_tot_pkts; /* # of tx pkts (ucast + mcast) */
+ __le32 rx_tot_pkts; /* # of data packets recvd (uni + mcast) */
+ __le32 tx_mcast_pkts; /* # of mcast pkts txed */
+@@ -594,6 +600,14 @@ struct brcmf_sta_info_le {
+ */
+ __le32 rx_pkts_retried; /* # rx with retry bit set */
+ __le32 tx_rate_fallback; /* lowest fallback TX rate */
++
++ /* Fields valid for ver >= 5 */
++ struct {
++ __le32 count; /* # rates in this set */
++ u8 rates[BRCMF_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */
++ u8 mcs[BRCMF_MCSSET_LEN]; /* supported mcs index bit map */
++ __le16 vht_mcs[BRCMF_VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */
++ } rateset_adv;
+ };
+
+ struct brcmf_chanspec_list {
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
-@@ -1322,6 +1322,7 @@ int __init brcmf_core_init(void)
+@@ -1347,6 +1347,7 @@ int __init brcmf_core_init(void)
{
if (!schedule_work(&brcmf_driver_work))
return -EBUSY;