1 From 20f2c5fa3af060401c72e444999470a4cab641cf Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Thu, 26 Dec 2019 14:30:50 +0100
4 Subject: [PATCH] brcmfmac: add initial support for monitor mode
6 Content-Type: text/plain; charset=UTF-8
7 Content-Transfer-Encoding: 8bit
9 Report monitor interface availability using cfg80211 and support it in
10 the add_virtual_intf() and del_virtual_intf() callbacks. This new
11 feature is conditional and depends on firmware flagging monitor packets.
12 Receiving monitor frames is already handled by the brcmf_netif_mon_rx().
14 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
15 Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
17 .../broadcom/brcm80211/brcmfmac/cfg80211.c | 112 ++++++++++++++++--
18 .../broadcom/brcm80211/brcmfmac/core.c | 68 ++++++++++-
19 .../broadcom/brcm80211/brcmfmac/core.h | 2 +
20 .../broadcom/brcm80211/brcmfmac/feature.c | 1 +
21 .../broadcom/brcm80211/brcmfmac/feature.h | 2 +
22 .../broadcom/brcm80211/brcmfmac/fwil.h | 2 +
23 6 files changed, 174 insertions(+), 13 deletions(-)
25 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
26 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
28 #include <linux/vmalloc.h>
29 #include <net/cfg80211.h>
30 #include <net/netlink.h>
31 +#include <uapi/linux/if_arp.h>
33 #include <brcmu_utils.h>
35 @@ -619,6 +620,82 @@ static bool brcmf_is_ibssmode(struct brc
36 return vif->wdev.iftype == NL80211_IFTYPE_ADHOC;
40 + * brcmf_mon_add_vif() - create monitor mode virtual interface
42 + * @wiphy: wiphy device of new interface.
43 + * @name: name of the new interface.
45 +static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy,
48 + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
49 + struct brcmf_cfg80211_vif *vif;
50 + struct net_device *ndev;
51 + struct brcmf_if *ifp;
54 + if (cfg->pub->mon_if) {
59 + vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_MONITOR);
65 + ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, ether_setup);
70 + ndev->type = ARPHRD_IEEE80211_RADIOTAP;
71 + ndev->ieee80211_ptr = &vif->wdev;
72 + ndev->needs_free_netdev = true;
73 + ndev->priv_destructor = brcmf_cfg80211_free_netdev;
74 + SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
76 + ifp = netdev_priv(ndev);
79 + ifp->drvr = cfg->pub;
82 + vif->wdev.netdev = ndev;
84 + err = brcmf_net_mon_attach(ifp);
86 + brcmf_err("Failed to attach %s device\n", ndev->name);
91 + cfg->pub->mon_if = ifp;
96 + brcmf_free_vif(vif);
98 + return ERR_PTR(err);
101 +static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
103 + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
104 + struct net_device *ndev = wdev->netdev;
106 + ndev->netdev_ops->ndo_stop(ndev);
108 + brcmf_net_detach(ndev, true);
110 + cfg->pub->mon_if = NULL;
115 static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
117 unsigned char name_assign_type,
118 @@ -641,9 +718,10 @@ static struct wireless_dev *brcmf_cfg802
119 case NL80211_IFTYPE_STATION:
120 case NL80211_IFTYPE_AP_VLAN:
121 case NL80211_IFTYPE_WDS:
122 - case NL80211_IFTYPE_MONITOR:
123 case NL80211_IFTYPE_MESH_POINT:
124 return ERR_PTR(-EOPNOTSUPP);
125 + case NL80211_IFTYPE_MONITOR:
126 + return brcmf_mon_add_vif(wiphy, name);
127 case NL80211_IFTYPE_AP:
128 wdev = brcmf_ap_add_vif(wiphy, name, params);
130 @@ -826,9 +904,10 @@ int brcmf_cfg80211_del_iface(struct wiph
131 case NL80211_IFTYPE_STATION:
132 case NL80211_IFTYPE_AP_VLAN:
133 case NL80211_IFTYPE_WDS:
134 - case NL80211_IFTYPE_MONITOR:
135 case NL80211_IFTYPE_MESH_POINT:
137 + case NL80211_IFTYPE_MONITOR:
138 + return brcmf_mon_del_vif(wiphy, wdev);
139 case NL80211_IFTYPE_AP:
140 return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
141 case NL80211_IFTYPE_P2P_CLIENT:
142 @@ -6479,9 +6558,10 @@ static int brcmf_setup_ifmodes(struct wi
143 struct ieee80211_iface_limit *c0_limits = NULL;
144 struct ieee80211_iface_limit *p2p_limits = NULL;
145 struct ieee80211_iface_limit *mbss_limits = NULL;
146 - bool mbss, p2p, rsdb, mchan;
147 - int i, c, n_combos;
148 + bool mon_flag, mbss, p2p, rsdb, mchan;
149 + int i, c, n_combos, n_limits;
151 + mon_flag = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FLAG);
152 mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
153 p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
154 rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB);
155 @@ -6495,6 +6575,8 @@ static int brcmf_setup_ifmodes(struct wi
156 wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
157 BIT(NL80211_IFTYPE_ADHOC) |
158 BIT(NL80211_IFTYPE_AP);
160 + wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
162 wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
163 BIT(NL80211_IFTYPE_P2P_GO) |
164 @@ -6502,18 +6584,18 @@ static int brcmf_setup_ifmodes(struct wi
169 - c0_limits = kcalloc(4, sizeof(*c0_limits), GFP_KERNEL);
171 - c0_limits = kcalloc(3, sizeof(*c0_limits), GFP_KERNEL);
173 - c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL);
174 + n_limits = 1 + mon_flag + (p2p ? 2 : 0) + (rsdb || !p2p);
175 + c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL);
179 combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan));
180 c0_limits[i].max = 1 + rsdb;
181 c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
183 + c0_limits[i].max = 1;
184 + c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR);
187 c0_limits[i].max = 1;
188 c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
189 @@ -6562,14 +6644,20 @@ static int brcmf_setup_ifmodes(struct wi
193 - mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
194 + n_limits = 1 + mon_flag;
195 + mbss_limits = kcalloc(n_limits, sizeof(*mbss_limits),
199 mbss_limits[i].max = 4;
200 mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP);
202 + mbss_limits[i].max = 1;
203 + mbss_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR);
205 combo[c].beacon_int_infra_match = true;
206 combo[c].num_different_channels = 1;
207 - combo[c].max_interfaces = 4;
208 + combo[c].max_interfaces = 4 + mon_flag;
209 combo[c].n_limits = i;
210 combo[c].limits = mbss_limits;
212 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
213 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
214 @@ -690,7 +690,7 @@ fail:
218 -static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
219 +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
221 if (ndev->reg_state == NETREG_REGISTERED) {
223 @@ -703,6 +703,72 @@ static void brcmf_net_detach(struct net_
227 +static int brcmf_net_mon_open(struct net_device *ndev)
229 + struct brcmf_if *ifp = netdev_priv(ndev);
230 + struct brcmf_pub *drvr = ifp->drvr;
234 + brcmf_dbg(TRACE, "Enter\n");
236 + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_MONITOR, &monitor);
238 + bphy_err(drvr, "BRCMF_C_GET_MONITOR error (%d)\n", err);
240 + } else if (monitor) {
241 + bphy_err(drvr, "Monitor mode is already enabled\n");
246 + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor);
248 + bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err);
253 +static int brcmf_net_mon_stop(struct net_device *ndev)
255 + struct brcmf_if *ifp = netdev_priv(ndev);
256 + struct brcmf_pub *drvr = ifp->drvr;
260 + brcmf_dbg(TRACE, "Enter\n");
263 + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor);
265 + bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err);
270 +static const struct net_device_ops brcmf_netdev_ops_mon = {
271 + .ndo_open = brcmf_net_mon_open,
272 + .ndo_stop = brcmf_net_mon_stop,
275 +int brcmf_net_mon_attach(struct brcmf_if *ifp)
277 + struct brcmf_pub *drvr = ifp->drvr;
278 + struct net_device *ndev;
281 + brcmf_dbg(TRACE, "Enter\n");
284 + ndev->netdev_ops = &brcmf_netdev_ops_mon;
286 + err = register_netdevice(ndev);
288 + bphy_err(drvr, "Failed to register %s device\n", ndev->name);
293 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
295 struct net_device *ndev;
296 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
297 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
298 @@ -210,6 +210,8 @@ void brcmf_txflowblock_if(struct brcmf_i
299 void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
300 void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
301 void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
302 +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked);
303 +int brcmf_net_mon_attach(struct brcmf_if *ifp);
304 void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
305 int __init brcmf_core_init(void);
306 void __exit brcmf_core_exit(void);
307 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
308 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
309 @@ -38,6 +38,7 @@ static const struct brcmf_feat_fwcap brc
310 { BRCMF_FEAT_MCHAN, "mchan" },
311 { BRCMF_FEAT_P2P, "p2p" },
312 { BRCMF_FEAT_MONITOR, "monitor" },
313 + { BRCMF_FEAT_MONITOR_FLAG, "rtap" },
314 { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
315 { BRCMF_FEAT_DOT11H, "802.11h" }
317 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
318 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
320 * GSCAN: enhanced scan offload feature.
321 * FWSUP: Firmware supplicant.
322 * MONITOR: firmware can pass monitor packets to host.
323 + * MONITOR_FLAG: firmware flags monitor packets.
324 * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
325 * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
326 * DOT11H: firmware supports 802.11h
328 BRCMF_FEAT_DEF(GSCAN) \
329 BRCMF_FEAT_DEF(FWSUP) \
330 BRCMF_FEAT_DEF(MONITOR) \
331 + BRCMF_FEAT_DEF(MONITOR_FLAG) \
332 BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
333 BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
334 BRCMF_FEAT_DEF(DOT11H)
335 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
336 +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
338 #define BRCMF_C_GET_PM 85
339 #define BRCMF_C_SET_PM 86
340 #define BRCMF_C_GET_REVINFO 98
341 +#define BRCMF_C_GET_MONITOR 107
342 +#define BRCMF_C_SET_MONITOR 108
343 #define BRCMF_C_GET_CURR_RATESET 114
344 #define BRCMF_C_GET_AP 117
345 #define BRCMF_C_SET_AP 118