119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345
  1. From 20f2c5fa3af060401c72e444999470a4cab641cf Mon Sep 17 00:00:00 2001
  2. From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <[email protected]>
  3. Date: Thu, 26 Dec 2019 14:30:50 +0100
  4. Subject: [PATCH] brcmfmac: add initial support for monitor mode
  5. MIME-Version: 1.0
  6. Content-Type: text/plain; charset=UTF-8
  7. Content-Transfer-Encoding: 8bit
  8. Report monitor interface availability using cfg80211 and support it in
  9. the add_virtual_intf() and del_virtual_intf() callbacks. This new
  10. feature is conditional and depends on firmware flagging monitor packets.
  11. Receiving monitor frames is already handled by the brcmf_netif_mon_rx().
  12. Signed-off-by: Rafał Miłecki <[email protected]>
  13. Signed-off-by: Kalle Valo <[email protected]>
  14. ---
  15. .../broadcom/brcm80211/brcmfmac/cfg80211.c | 112 ++++++++++++++++--
  16. .../broadcom/brcm80211/brcmfmac/core.c | 68 ++++++++++-
  17. .../broadcom/brcm80211/brcmfmac/core.h | 2 +
  18. .../broadcom/brcm80211/brcmfmac/feature.c | 1 +
  19. .../broadcom/brcm80211/brcmfmac/feature.h | 2 +
  20. .../broadcom/brcm80211/brcmfmac/fwil.h | 2 +
  21. 6 files changed, 174 insertions(+), 13 deletions(-)
  22. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
  23. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
  24. @@ -11,6 +11,7 @@
  25. #include <linux/vmalloc.h>
  26. #include <net/cfg80211.h>
  27. #include <net/netlink.h>
  28. +#include <uapi/linux/if_arp.h>
  29. #include <brcmu_utils.h>
  30. #include <defs.h>
  31. @@ -619,6 +620,82 @@ static bool brcmf_is_ibssmode(struct brc
  32. return vif->wdev.iftype == NL80211_IFTYPE_ADHOC;
  33. }
  34. +/**
  35. + * brcmf_mon_add_vif() - create monitor mode virtual interface
  36. + *
  37. + * @wiphy: wiphy device of new interface.
  38. + * @name: name of the new interface.
  39. + */
  40. +static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy,
  41. + const char *name)
  42. +{
  43. + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
  44. + struct brcmf_cfg80211_vif *vif;
  45. + struct net_device *ndev;
  46. + struct brcmf_if *ifp;
  47. + int err;
  48. +
  49. + if (cfg->pub->mon_if) {
  50. + err = -EEXIST;
  51. + goto err_out;
  52. + }
  53. +
  54. + vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_MONITOR);
  55. + if (IS_ERR(vif)) {
  56. + err = PTR_ERR(vif);
  57. + goto err_out;
  58. + }
  59. +
  60. + ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, ether_setup);
  61. + if (!ndev) {
  62. + err = -ENOMEM;
  63. + goto err_free_vif;
  64. + }
  65. + ndev->type = ARPHRD_IEEE80211_RADIOTAP;
  66. + ndev->ieee80211_ptr = &vif->wdev;
  67. + ndev->needs_free_netdev = true;
  68. + ndev->priv_destructor = brcmf_cfg80211_free_netdev;
  69. + SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy));
  70. +
  71. + ifp = netdev_priv(ndev);
  72. + ifp->vif = vif;
  73. + ifp->ndev = ndev;
  74. + ifp->drvr = cfg->pub;
  75. +
  76. + vif->ifp = ifp;
  77. + vif->wdev.netdev = ndev;
  78. +
  79. + err = brcmf_net_mon_attach(ifp);
  80. + if (err) {
  81. + brcmf_err("Failed to attach %s device\n", ndev->name);
  82. + free_netdev(ndev);
  83. + goto err_free_vif;
  84. + }
  85. +
  86. + cfg->pub->mon_if = ifp;
  87. +
  88. + return &vif->wdev;
  89. +
  90. +err_free_vif:
  91. + brcmf_free_vif(vif);
  92. +err_out:
  93. + return ERR_PTR(err);
  94. +}
  95. +
  96. +static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
  97. +{
  98. + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy);
  99. + struct net_device *ndev = wdev->netdev;
  100. +
  101. + ndev->netdev_ops->ndo_stop(ndev);
  102. +
  103. + brcmf_net_detach(ndev, true);
  104. +
  105. + cfg->pub->mon_if = NULL;
  106. +
  107. + return 0;
  108. +}
  109. +
  110. static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy,
  111. const char *name,
  112. unsigned char name_assign_type,
  113. @@ -641,9 +718,10 @@ static struct wireless_dev *brcmf_cfg802
  114. case NL80211_IFTYPE_STATION:
  115. case NL80211_IFTYPE_AP_VLAN:
  116. case NL80211_IFTYPE_WDS:
  117. - case NL80211_IFTYPE_MONITOR:
  118. case NL80211_IFTYPE_MESH_POINT:
  119. return ERR_PTR(-EOPNOTSUPP);
  120. + case NL80211_IFTYPE_MONITOR:
  121. + return brcmf_mon_add_vif(wiphy, name);
  122. case NL80211_IFTYPE_AP:
  123. wdev = brcmf_ap_add_vif(wiphy, name, params);
  124. break;
  125. @@ -826,9 +904,10 @@ int brcmf_cfg80211_del_iface(struct wiph
  126. case NL80211_IFTYPE_STATION:
  127. case NL80211_IFTYPE_AP_VLAN:
  128. case NL80211_IFTYPE_WDS:
  129. - case NL80211_IFTYPE_MONITOR:
  130. case NL80211_IFTYPE_MESH_POINT:
  131. return -EOPNOTSUPP;
  132. + case NL80211_IFTYPE_MONITOR:
  133. + return brcmf_mon_del_vif(wiphy, wdev);
  134. case NL80211_IFTYPE_AP:
  135. return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
  136. case NL80211_IFTYPE_P2P_CLIENT:
  137. @@ -6479,9 +6558,10 @@ static int brcmf_setup_ifmodes(struct wi
  138. struct ieee80211_iface_limit *c0_limits = NULL;
  139. struct ieee80211_iface_limit *p2p_limits = NULL;
  140. struct ieee80211_iface_limit *mbss_limits = NULL;
  141. - bool mbss, p2p, rsdb, mchan;
  142. - int i, c, n_combos;
  143. + bool mon_flag, mbss, p2p, rsdb, mchan;
  144. + int i, c, n_combos, n_limits;
  145. + mon_flag = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FLAG);
  146. mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS);
  147. p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P);
  148. rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB);
  149. @@ -6495,6 +6575,8 @@ static int brcmf_setup_ifmodes(struct wi
  150. wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) |
  151. BIT(NL80211_IFTYPE_ADHOC) |
  152. BIT(NL80211_IFTYPE_AP);
  153. + if (mon_flag)
  154. + wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
  155. if (p2p)
  156. wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) |
  157. BIT(NL80211_IFTYPE_P2P_GO) |
  158. @@ -6502,18 +6584,18 @@ static int brcmf_setup_ifmodes(struct wi
  159. c = 0;
  160. i = 0;
  161. - if (p2p && rsdb)
  162. - c0_limits = kcalloc(4, sizeof(*c0_limits), GFP_KERNEL);
  163. - else if (p2p)
  164. - c0_limits = kcalloc(3, sizeof(*c0_limits), GFP_KERNEL);
  165. - else
  166. - c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL);
  167. + n_limits = 1 + mon_flag + (p2p ? 2 : 0) + (rsdb || !p2p);
  168. + c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL);
  169. if (!c0_limits)
  170. goto err;
  171. combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan));
  172. c0_limits[i].max = 1 + rsdb;
  173. c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION);
  174. + if (mon_flag) {
  175. + c0_limits[i].max = 1;
  176. + c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR);
  177. + }
  178. if (p2p) {
  179. c0_limits[i].max = 1;
  180. c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE);
  181. @@ -6562,14 +6644,20 @@ static int brcmf_setup_ifmodes(struct wi
  182. if (mbss) {
  183. c++;
  184. i = 0;
  185. - mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL);
  186. + n_limits = 1 + mon_flag;
  187. + mbss_limits = kcalloc(n_limits, sizeof(*mbss_limits),
  188. + GFP_KERNEL);
  189. if (!mbss_limits)
  190. goto err;
  191. mbss_limits[i].max = 4;
  192. mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP);
  193. + if (mon_flag) {
  194. + mbss_limits[i].max = 1;
  195. + mbss_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR);
  196. + }
  197. combo[c].beacon_int_infra_match = true;
  198. combo[c].num_different_channels = 1;
  199. - combo[c].max_interfaces = 4;
  200. + combo[c].max_interfaces = 4 + mon_flag;
  201. combo[c].n_limits = i;
  202. combo[c].limits = mbss_limits;
  203. }
  204. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
  205. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c
  206. @@ -690,7 +690,7 @@ fail:
  207. return -EBADE;
  208. }
  209. -static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
  210. +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked)
  211. {
  212. if (ndev->reg_state == NETREG_REGISTERED) {
  213. if (rtnl_locked)
  214. @@ -703,6 +703,72 @@ static void brcmf_net_detach(struct net_
  215. }
  216. }
  217. +static int brcmf_net_mon_open(struct net_device *ndev)
  218. +{
  219. + struct brcmf_if *ifp = netdev_priv(ndev);
  220. + struct brcmf_pub *drvr = ifp->drvr;
  221. + u32 monitor;
  222. + int err;
  223. +
  224. + brcmf_dbg(TRACE, "Enter\n");
  225. +
  226. + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_MONITOR, &monitor);
  227. + if (err) {
  228. + bphy_err(drvr, "BRCMF_C_GET_MONITOR error (%d)\n", err);
  229. + return err;
  230. + } else if (monitor) {
  231. + bphy_err(drvr, "Monitor mode is already enabled\n");
  232. + return -EEXIST;
  233. + }
  234. +
  235. + monitor = 3;
  236. + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor);
  237. + if (err)
  238. + bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err);
  239. +
  240. + return err;
  241. +}
  242. +
  243. +static int brcmf_net_mon_stop(struct net_device *ndev)
  244. +{
  245. + struct brcmf_if *ifp = netdev_priv(ndev);
  246. + struct brcmf_pub *drvr = ifp->drvr;
  247. + u32 monitor;
  248. + int err;
  249. +
  250. + brcmf_dbg(TRACE, "Enter\n");
  251. +
  252. + monitor = 0;
  253. + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor);
  254. + if (err)
  255. + bphy_err(drvr, "BRCMF_C_SET_MONITOR error (%d)\n", err);
  256. +
  257. + return err;
  258. +}
  259. +
  260. +static const struct net_device_ops brcmf_netdev_ops_mon = {
  261. + .ndo_open = brcmf_net_mon_open,
  262. + .ndo_stop = brcmf_net_mon_stop,
  263. +};
  264. +
  265. +int brcmf_net_mon_attach(struct brcmf_if *ifp)
  266. +{
  267. + struct brcmf_pub *drvr = ifp->drvr;
  268. + struct net_device *ndev;
  269. + int err;
  270. +
  271. + brcmf_dbg(TRACE, "Enter\n");
  272. +
  273. + ndev = ifp->ndev;
  274. + ndev->netdev_ops = &brcmf_netdev_ops_mon;
  275. +
  276. + err = register_netdevice(ndev);
  277. + if (err)
  278. + bphy_err(drvr, "Failed to register %s device\n", ndev->name);
  279. +
  280. + return err;
  281. +}
  282. +
  283. void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on)
  284. {
  285. struct net_device *ndev;
  286. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
  287. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h
  288. @@ -210,6 +210,8 @@ void brcmf_txflowblock_if(struct brcmf_i
  289. void brcmf_txfinalize(struct brcmf_if *ifp, struct sk_buff *txp, bool success);
  290. void brcmf_netif_rx(struct brcmf_if *ifp, struct sk_buff *skb);
  291. void brcmf_netif_mon_rx(struct brcmf_if *ifp, struct sk_buff *skb);
  292. +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked);
  293. +int brcmf_net_mon_attach(struct brcmf_if *ifp);
  294. void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on);
  295. int __init brcmf_core_init(void);
  296. void __exit brcmf_core_exit(void);
  297. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
  298. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c
  299. @@ -38,6 +38,7 @@ static const struct brcmf_feat_fwcap brc
  300. { BRCMF_FEAT_MCHAN, "mchan" },
  301. { BRCMF_FEAT_P2P, "p2p" },
  302. { BRCMF_FEAT_MONITOR, "monitor" },
  303. + { BRCMF_FEAT_MONITOR_FLAG, "rtap" },
  304. { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" },
  305. { BRCMF_FEAT_DOT11H, "802.11h" }
  306. };
  307. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
  308. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h
  309. @@ -23,6 +23,7 @@
  310. * GSCAN: enhanced scan offload feature.
  311. * FWSUP: Firmware supplicant.
  312. * MONITOR: firmware can pass monitor packets to host.
  313. + * MONITOR_FLAG: firmware flags monitor packets.
  314. * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header
  315. * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header
  316. * DOT11H: firmware supports 802.11h
  317. @@ -43,6 +44,7 @@
  318. BRCMF_FEAT_DEF(GSCAN) \
  319. BRCMF_FEAT_DEF(FWSUP) \
  320. BRCMF_FEAT_DEF(MONITOR) \
  321. + BRCMF_FEAT_DEF(MONITOR_FLAG) \
  322. BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \
  323. BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \
  324. BRCMF_FEAT_DEF(DOT11H)
  325. --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
  326. +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h
  327. @@ -49,6 +49,8 @@
  328. #define BRCMF_C_GET_PM 85
  329. #define BRCMF_C_SET_PM 86
  330. #define BRCMF_C_GET_REVINFO 98
  331. +#define BRCMF_C_GET_MONITOR 107
  332. +#define BRCMF_C_SET_MONITOR 108
  333. #define BRCMF_C_GET_CURR_RATESET 114
  334. #define BRCMF_C_GET_AP 117
  335. #define BRCMF_C_SET_AP 118