From patchwork Tue May 22 13:18:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Patchwork-Submitter: =?utf-8?b?UmFmYcWCIE1pxYJlY2tp?= X-Patchwork-Id: 10418649 X-Patchwork-Delegate: kvalo@adurom.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 707316032A for ; Tue, 22 May 2018 13:20:34 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 5751C28CCE for ; Tue, 22 May 2018 13:20:34 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 28A0B28CEF; Tue, 22 May 2018 13:20:34 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, FREEMAIL_FROM, MAILING_LIST_MULTI, RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 2C63028CD6 for ; Tue, 22 May 2018 13:20:21 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751343AbeEVNUP (ORCPT ); Tue, 22 May 2018 09:20:15 -0400 Received: from mail-wm0-f67.google.com ([74.125.82.67]:52124 "EHLO mail-wm0-f67.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751329AbeEVNUN (ORCPT ); Tue, 22 May 2018 09:20:13 -0400 Received: by mail-wm0-f67.google.com with SMTP id j4-v6so31926925wme.1 for ; Tue, 22 May 2018 06:20:12 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=ubT+idGnc/8akYJRWLSjCIoHooAXbQ9P+Oj87+SpBkg=; b=IPoMmGnPkBEqNeH9Vlm/BOg6R0NpBnuHnmGe4AvBL6/FmbhQ0tDrtdq/i82yHGEeyq TN6CFXHajtWPnQ/fxUsreHfKBYtFbL2xL90oAEKoMsH+16oFz0GI2weLtBntM3g7/EqZ rHh5JMKdV/yZWFgonVlOOCtf7KW2YVV0Jp6dIan+tkXhW11RBXCmbfBxxXIPZXQqxwC3 Ici0t9J/AyMdYuXvepDHK6QIboOgHUgYNbFyAb5V3bpYHMzlk28RQGJ44CZ2EZRAlj+6 ZiHhPmz2weaudRJ53cAIoBwB8jd77FcZl35sHsI3KVqSFQbBUWjY1z5LbBCrXQDYeOnX Sedw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=ubT+idGnc/8akYJRWLSjCIoHooAXbQ9P+Oj87+SpBkg=; b=LxYi5IkVmTFoJH4Q7BIAzh06j8s3N6L9eMizQrZLRKazW8NDUUB26AAYUBlhV15c/A c3D8Zsnz+p9SIsBAMYJzbmTe1YK7EbaGqRpzVTRuN4T7xX+zjb537c9CzeMJj81qGS8f JEcxjIRdlJRvXWn2qwZUjvdWuwQ17qgF9Y+DqIiqLnswP6j/VNda0az7w0+7Spbsbh7X LhlxgAP1JhMrmmbfqmY3L32aMGVxv+hm9ba+WWF3gWl9GR7NRoAfdd5JKvXxaAxp9seg dEJT8/OwFGVggMZdqzcIKM+pgVbQc00w1nc/34F9a+bo5zmltuDg3mDnd0zOH7fvcrpO FBVg== X-Gm-Message-State: ALKqPwdHtM1pCt+Xwa2BiSSoR+/xhcP0Z7yAwwkrDkkaY1uCcHsjo/ks /F/9G48xQH+fE0usQq+xSXaw4g== X-Google-Smtp-Source: AB8JxZprF1Y4fKQAfuXl/OttqiLEr9f3DK0KiFs/UVdYudd5QxqtrVoHQlwYJf+TAFqgNqkpzH/+pw== X-Received: by 2002:a2e:5855:: with SMTP id x21-v6mr9542578ljd.84.1526995211904; Tue, 22 May 2018 06:20:11 -0700 (PDT) Received: from linux-veee.lan (ip-194-187-74-233.konfederacka.maverick.com.pl. [194.187.74.233]) by smtp.gmail.com with ESMTPSA id t4-v6sm3977752lff.48.2018.05.22.06.20.10 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Tue, 22 May 2018 06:20:11 -0700 (PDT) From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= To: Kalle Valo Cc: Arend van Spriel , Franky Lin , Hante Meuleman , Chi-Hsien Lin , Wright Feng , Pieter-Paul Giesberts , Chung-Hsien Hsu , linux-wireless@vger.kernel.org, brcm80211-dev-list.pdl@broadcom.com, brcm80211-dev-list@cypress.com, =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Subject: [PATCH 3/3] brcmfmac: add initial support for monitor mode interface Date: Tue, 22 May 2018 15:18:36 +0200 Message-Id: <20180522131836.26858-3-zajec5@gmail.com> X-Mailer: git-send-email 2.13.6 In-Reply-To: <20180522131836.26858-1-zajec5@gmail.com> References: <20180522131836.26858-1-zajec5@gmail.com> MIME-Version: 1.0 Sender: linux-wireless-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-wireless@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP From: Rafał Miłecki Right now it's limited to firmwares that mark monitor interface packets with a special flag. It's required to distinguish them from other interface packets as firmware doesn't use any unique ifidx for monitor interface. In the future one may also add support for older firmwares without support for proper packet flags. That will require limiting interface combos to allow monitor mode *only* and adjusting condition in the brcmf_msgbuf_process_rx_complete(). Signed-off-by: Rafał Miłecki --- .../broadcom/brcm80211/brcmfmac/cfg80211.c | 107 +++++++++++++++++++-- .../wireless/broadcom/brcm80211/brcmfmac/core.c | 65 ++++++++++++- .../wireless/broadcom/brcm80211/brcmfmac/core.h | 2 + .../wireless/broadcom/brcm80211/brcmfmac/fwil.h | 2 + 4 files changed, 168 insertions(+), 8 deletions(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c index f5b405c98047..bbb4f913eece 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -608,6 +609,82 @@ static bool brcmf_is_ibssmode(struct brcmf_cfg80211_vif *vif) return vif->wdev.iftype == NL80211_IFTYPE_ADHOC; } +/** + * brcmf_mon_add_vif() - create monitor mode virtual interface + * + * @wiphy: wiphy device of new interface. + * @name: name of the new interface. + */ +static struct wireless_dev *brcmf_mon_add_vif(struct wiphy *wiphy, + const char *name) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct brcmf_cfg80211_vif *vif; + struct net_device *ndev; + struct brcmf_if *ifp; + int err; + + if (cfg->pub->mon_if) { + err = -EEXIST; + goto err_out; + } + + vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_MONITOR); + if (IS_ERR(vif)) { + err = PTR_ERR(vif); + goto err_out; + } + + ndev = alloc_netdev(sizeof(*ifp), name, NET_NAME_UNKNOWN, ether_setup); + if (!ndev) { + err = -ENOMEM; + goto err_free_vif; + } + ndev->type = ARPHRD_IEEE80211_RADIOTAP; + ndev->ieee80211_ptr = &vif->wdev; + ndev->needs_free_netdev = true; + ndev->priv_destructor = brcmf_cfg80211_free_netdev; + SET_NETDEV_DEV(ndev, wiphy_dev(cfg->wiphy)); + + ifp = netdev_priv(ndev); + ifp->vif = vif; + ifp->ndev = ndev; + ifp->drvr = cfg->pub; + + vif->ifp = ifp; + vif->wdev.netdev = ndev; + + err = brcmf_net_mon_attach(ifp); + if (err) { + brcmf_err("Failed to attach %s device\n", ndev->name); + free_netdev(ndev); + goto err_free_vif; + } + + cfg->pub->mon_if = ifp; + + return &vif->wdev; + +err_free_vif: + brcmf_free_vif(vif); +err_out: + return ERR_PTR(err); +} + +static int brcmf_mon_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev) +{ + struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); + struct net_device *ndev = wdev->netdev; + + ndev->netdev_ops->ndo_stop(ndev); + + brcmf_net_detach(ndev, true); + + cfg->pub->mon_if = NULL; + + return 0; +} + static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, const char *name, unsigned char name_assign_type, @@ -628,9 +705,10 @@ static struct wireless_dev *brcmf_cfg80211_add_iface(struct wiphy *wiphy, case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: return ERR_PTR(-EOPNOTSUPP); + case NL80211_IFTYPE_MONITOR: + return brcmf_mon_add_vif(wiphy, name); case NL80211_IFTYPE_AP: wdev = brcmf_ap_add_vif(wiphy, name, params); break; @@ -810,9 +888,10 @@ int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev) case NL80211_IFTYPE_STATION: case NL80211_IFTYPE_AP_VLAN: case NL80211_IFTYPE_WDS: - case NL80211_IFTYPE_MONITOR: case NL80211_IFTYPE_MESH_POINT: return -EOPNOTSUPP; + case NL80211_IFTYPE_MONITOR: + return brcmf_mon_del_vif(wiphy, wdev); case NL80211_IFTYPE_AP: return brcmf_cfg80211_del_ap_iface(wiphy, wdev); case NL80211_IFTYPE_P2P_CLIENT: @@ -6339,9 +6418,10 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) struct ieee80211_iface_limit *c0_limits = NULL; struct ieee80211_iface_limit *p2p_limits = NULL; struct ieee80211_iface_limit *mbss_limits = NULL; - bool mbss, p2p; - int i, c, n_combos; + bool mon, mbss, p2p; + int i, c, n_combos, n_limits; + mon = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MON_802_11_FLAG); mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); @@ -6353,14 +6433,21 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP); + if (mon) + wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); c = 0; i = 0; - c0_limits = kcalloc(p2p ? 3 : 2, sizeof(*c0_limits), GFP_KERNEL); + n_limits = 1 + mon + p2p ? 2 : 1; + c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL); if (!c0_limits) goto err; c0_limits[i].max = 1; c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); + if (mon) { + c0_limits[i].max = 1; + c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); + } if (p2p) { if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) combo[c].num_different_channels = 2; @@ -6406,14 +6493,20 @@ static int brcmf_setup_ifmodes(struct wiphy *wiphy, struct brcmf_if *ifp) if (mbss) { c++; i = 0; - mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL); + n_limits = 1 + mon; + mbss_limits = kcalloc(n_limits, sizeof(*mbss_limits), + GFP_KERNEL); if (!mbss_limits) goto err; mbss_limits[i].max = 4; mbss_limits[i++].types = BIT(NL80211_IFTYPE_AP); + if (mon) { + mbss_limits[i].max = 1; + mbss_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); + } combo[c].beacon_int_infra_match = true; combo[c].num_different_channels = 1; - combo[c].max_interfaces = 4; + combo[c].max_interfaces = 4 + mon; combo[c].n_limits = i; combo[c].limits = mbss_limits; } diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c index f58d7f7f1359..3f62e75dfa44 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c @@ -623,7 +623,7 @@ int brcmf_net_attach(struct brcmf_if *ifp, bool rtnl_locked) return -EBADE; } -static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) +void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) { if (ndev->reg_state == NETREG_REGISTERED) { if (rtnl_locked) @@ -636,6 +636,69 @@ static void brcmf_net_detach(struct net_device *ndev, bool rtnl_locked) } } +static int brcmf_net_mon_open(struct net_device *ndev) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + u32 monitor; + int err; + + brcmf_dbg(TRACE, "Enter\n"); + + err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_MONITOR, &monitor); + if (err) { + brcmf_err("BRCMF_C_GET_MONITOR error (%d)\n", err); + return err; + } else if (monitor) { + brcmf_err("Monitor mode is already enabled\n"); + return -EEXIST; + } + + monitor = 3; + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); + if (err) + brcmf_err("BRCMF_C_SET_MONITOR error (%d)\n", err); + + return err; +} + +static int brcmf_net_mon_stop(struct net_device *ndev) +{ + struct brcmf_if *ifp = netdev_priv(ndev); + u32 monitor; + int err; + + brcmf_dbg(TRACE, "Enter\n"); + + monitor = 0; + err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); + if (err) + brcmf_err("BRCMF_C_SET_MONITOR error (%d)\n", err); + + return err; +} + +static const struct net_device_ops brcmf_netdev_ops_mon = { + .ndo_open = brcmf_net_mon_open, + .ndo_stop = brcmf_net_mon_stop, +}; + +int brcmf_net_mon_attach(struct brcmf_if *ifp) +{ + struct net_device *ndev; + int err; + + brcmf_dbg(TRACE, "Enter\n"); + + ndev = ifp->ndev; + ndev->netdev_ops = &brcmf_netdev_ops_mon; + + err = register_netdevice(ndev); + if (err) + brcmf_err("Failed to register %s device\n", ndev->name); + + return err; +} + void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) { struct net_device *ndev; diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h index dcf6e27cc16f..2d37a2fc6a6f 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h @@ -218,6 +218,8 @@ void brcmf_txflowblock_if(struct brcmf_if *ifp, 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_detach(struct net_device *ndev, bool rtnl_locked); +int brcmf_net_mon_attach(struct brcmf_if *ifp); void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on); int __init brcmf_core_init(void); void __exit brcmf_core_exit(void); diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h index 63b1287e2e6d..0d9492fd758d 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h @@ -60,6 +60,8 @@ #define BRCMF_C_GET_PM 85 #define BRCMF_C_SET_PM 86 #define BRCMF_C_GET_REVINFO 98 +#define BRCMF_C_GET_MONITOR 107 +#define BRCMF_C_SET_MONITOR 108 #define BRCMF_C_GET_CURR_RATESET 114 #define BRCMF_C_GET_AP 117 #define BRCMF_C_SET_AP 118