57946dabed1aa46f682e7a5e447b84e605e11804
[oweals/openwrt.git] /
1 From a4176ec356c73a46c07c181c6d04039fafa34a9f Mon Sep 17 00:00:00 2001
2 From: Arend van Spriel <arend.vanspriel@broadcom.com>
3 Date: Thu, 14 Feb 2019 13:43:48 +0100
4 Subject: [PATCH] brcmfmac: add subtype check for event handling in data path
5
6 For USB there is no separate channel being used to pass events
7 from firmware to the host driver and as such are passed over the
8 data path. In order to detect mock event messages an additional
9 check is needed on event subtype. This check is added conditionally
10 using unlikely() keyword.
11
12 Reviewed-by: Hante Meuleman <hante.meuleman@broadcom.com>
13 Reviewed-by: Pieter-Paul Giesberts <pieter-paul.giesberts@broadcom.com>
14 Reviewed-by: Franky Lin <franky.lin@broadcom.com>
15 Signed-off-by: Arend van Spriel <arend.vanspriel@broadcom.com>
16 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
17 ---
18  .../wireless/broadcom/brcm80211/brcmfmac/core.c  |  5 +++--
19  .../wireless/broadcom/brcm80211/brcmfmac/fweh.h  | 16 ++++++++++++----
20  .../broadcom/brcm80211/brcmfmac/msgbuf.c         |  2 +-
21  3 files changed, 16 insertions(+), 7 deletions(-)
22
23 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
24 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
25 @@ -519,7 +519,8 @@ void brcmf_rx_frame(struct device *dev,
26         } else {
27                 /* Process special event packets */
28                 if (handle_event)
29 -                       brcmf_fweh_process_skb(ifp->drvr, skb);
30 +                       brcmf_fweh_process_skb(ifp->drvr, skb,
31 +                                              BCMILCP_SUBTYPE_VENDOR_LONG);
32  
33                 brcmf_netif_rx(ifp, skb);
34         }
35 @@ -536,7 +537,7 @@ void brcmf_rx_event(struct device *dev,
36         if (brcmf_rx_hdrpull(drvr, skb, &ifp))
37                 return;
38  
39 -       brcmf_fweh_process_skb(ifp->drvr, skb);
40 +       brcmf_fweh_process_skb(ifp->drvr, skb, 0);
41         brcmu_pkt_buf_free_skb(skb);
42  }
43  
44 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
45 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fweh.h
46 @@ -211,7 +211,7 @@ enum brcmf_fweh_event_code {
47   */
48  #define BRCM_OUI                               "\x00\x10\x18"
49  #define BCMILCP_BCM_SUBTYPE_EVENT              1
50 -
51 +#define BCMILCP_SUBTYPE_VENDOR_LONG            32769
52  
53  /**
54   * struct brcm_ethhdr - broadcom specific ether header.
55 @@ -334,10 +334,10 @@ void brcmf_fweh_process_event(struct brc
56  void brcmf_fweh_p2pdev_setup(struct brcmf_if *ifp, bool ongoing);
57  
58  static inline void brcmf_fweh_process_skb(struct brcmf_pub *drvr,
59 -                                         struct sk_buff *skb)
60 +                                         struct sk_buff *skb, u16 stype)
61  {
62         struct brcmf_event *event_packet;
63 -       u16 usr_stype;
64 +       u16 subtype, usr_stype;
65  
66         /* only process events when protocol matches */
67         if (skb->protocol != cpu_to_be16(ETH_P_LINK_CTL))
68 @@ -346,8 +346,16 @@ static inline void brcmf_fweh_process_sk
69         if ((skb->len + ETH_HLEN) < sizeof(*event_packet))
70                 return;
71  
72 -       /* check for BRCM oui match */
73         event_packet = (struct brcmf_event *)skb_mac_header(skb);
74 +
75 +       /* check subtype if needed */
76 +       if (unlikely(stype)) {
77 +               subtype = get_unaligned_be16(&event_packet->hdr.subtype);
78 +               if (subtype != stype)
79 +                       return;
80 +       }
81 +
82 +       /* check for BRCM oui match */
83         if (memcmp(BRCM_OUI, &event_packet->hdr.oui[0],
84                    sizeof(event_packet->hdr.oui)))
85                 return;
86 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
87 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c
88 @@ -1116,7 +1116,7 @@ static void brcmf_msgbuf_process_event(s
89  
90         skb->protocol = eth_type_trans(skb, ifp->ndev);
91  
92 -       brcmf_fweh_process_skb(ifp->drvr, skb);
93 +       brcmf_fweh_process_skb(ifp->drvr, skb, 0);
94  
95  exit:
96         brcmu_pkt_buf_free_skb(skb);