From: Rafał Miłecki Date: Thu, 6 Feb 2020 10:36:15 +0000 (+0100) Subject: mac80211: brcm: backport remaining 5.6 kernel patches X-Git-Url: http://git.cdn.openwrt.org/?a=commitdiff_plain;h=aca274091ad3b50b770c0dd44f3ceefe8095d528;p=openwrt%2Fstaging%2Fthess.git mac80211: brcm: backport remaining 5.6 kernel patches Signed-off-by: Rafał Miłecki --- diff --git a/package/kernel/mac80211/patches/brcm/115-v5.6-brcmfmac-Fix-memory-leak-in-brcmf_usbdev_qinit.patch b/package/kernel/mac80211/patches/brcm/115-v5.6-brcmfmac-Fix-memory-leak-in-brcmf_usbdev_qinit.patch new file mode 100644 index 0000000000..a55d286e57 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/115-v5.6-brcmfmac-Fix-memory-leak-in-brcmf_usbdev_qinit.patch @@ -0,0 +1,26 @@ +From 4282dc057d750c6a7dd92953564b15c26b54c22c Mon Sep 17 00:00:00 2001 +From: Navid Emamdoost +Date: Sat, 14 Dec 2019 19:51:14 -0600 +Subject: [PATCH] brcmfmac: Fix memory leak in brcmf_usbdev_qinit + +In the implementation of brcmf_usbdev_qinit() the allocated memory for +reqs is leaking if usb_alloc_urb() fails. Release reqs in the error +handling path. + +Fixes: 71bb244ba2fd ("brcm80211: fmac: add USB support for bcm43235/6/8 chipsets") +Signed-off-by: Navid Emamdoost +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c | 1 + + 1 file changed, 1 insertion(+) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/usb.c +@@ -430,6 +430,7 @@ fail: + usb_free_urb(req->urb); + list_del(q->next); + } ++ kfree(reqs); + return NULL; + + } diff --git a/package/kernel/mac80211/patches/brcm/116-v5.6-brcmfmac-Keep-OOB-wake-interrupt-disabled-when-it-sh.patch b/package/kernel/mac80211/patches/brcm/116-v5.6-brcmfmac-Keep-OOB-wake-interrupt-disabled-when-it-sh.patch new file mode 100644 index 0000000000..f579e16a7f --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/116-v5.6-brcmfmac-Keep-OOB-wake-interrupt-disabled-when-it-sh.patch @@ -0,0 +1,66 @@ +From a32de68edab7b73ded850bcf76cdf6858e92a7e5 Mon Sep 17 00:00:00 2001 +From: Dmitry Osipenko +Date: Sun, 15 Dec 2019 21:42:24 +0300 +Subject: [PATCH] brcmfmac: Keep OOB wake-interrupt disabled when it shouldn't + be enabled + +NVIDIA Tegra SoCs do not like when OOB wake is enabled and WiFi interface +is in DOWN state during suspend. This results in a CPU hang on programming +OOB wake-up state of the GPIO controller during of system's suspend. + +The solution is trivial: don't enable wake for the OOB interrupt when it +should be disabled. + +This fixes hang on Tegra20 (Acer A500) and Tegra30 (Nexus 7) devices which +are using BCM4329 and BCM4330 WiFi chips respectively. + +Signed-off-by: Dmitry Osipenko +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c | 10 +++++----- + .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.h | 1 - + 2 files changed, 5 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/bcmsdh.c +@@ -120,7 +120,7 @@ int brcmf_sdiod_intr_register(struct brc + brcmf_err("enable_irq_wake failed %d\n", ret); + return ret; + } +- sdiodev->irq_wake = true; ++ disable_irq_wake(pdata->oob_irq_nr); + + sdio_claim_host(sdiodev->func1); + +@@ -179,10 +179,6 @@ void brcmf_sdiod_intr_unregister(struct + sdio_release_host(sdiodev->func1); + + sdiodev->oob_irq_requested = false; +- if (sdiodev->irq_wake) { +- disable_irq_wake(pdata->oob_irq_nr); +- sdiodev->irq_wake = false; +- } + free_irq(pdata->oob_irq_nr, &sdiodev->func1->dev); + sdiodev->irq_en = false; + sdiodev->oob_irq_requested = false; +@@ -1173,6 +1169,10 @@ static int brcmf_ops_sdio_resume(struct + if (ret) + brcmf_err("Failed to probe device on resume\n"); + } else { ++ if (sdiodev->wowl_enabled && ++ sdiodev->settings->bus.sdio.oob_irq_supported) ++ disable_irq_wake(sdiodev->settings->bus.sdio.oob_irq_nr); ++ + brcmf_sdiod_freezer_off(sdiodev); + } + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.h +@@ -178,7 +178,6 @@ struct brcmf_sdio_dev { + bool sd_irq_requested; + bool irq_en; /* irq enable flags */ + spinlock_t irq_en_lock; +- bool irq_wake; /* irq wake enable flags */ + bool sg_support; + uint max_request_size; + ushort max_segment_count; diff --git a/package/kernel/mac80211/patches/brcm/117-v5.6-brcmfmac-use-true-false-for-bool-variable.patch b/package/kernel/mac80211/patches/brcm/117-v5.6-brcmfmac-use-true-false-for-bool-variable.patch new file mode 100644 index 0000000000..0eb169c2d3 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/117-v5.6-brcmfmac-use-true-false-for-bool-variable.patch @@ -0,0 +1,27 @@ +From b92c017deda819e45a0f054f6df6b53e645d7fe4 Mon Sep 17 00:00:00 2001 +From: zhengbin +Date: Tue, 24 Dec 2019 22:16:06 +0800 +Subject: [PATCH] brcmfmac: use true,false for bool variable + +Fixes coccicheck warning: + +drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c:911:2-24: WARNING: Assignment of 0/1 to bool variable + +Reported-by: Hulk Robot +Signed-off-by: zhengbin +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwsignal.c +@@ -908,7 +908,7 @@ static u8 brcmf_fws_hdrpush(struct brcmf + wlh += wlh[1] + 2; + + if (entry->send_tim_signal) { +- entry->send_tim_signal = 0; ++ entry->send_tim_signal = false; + wlh[0] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP; + wlh[1] = BRCMF_FWS_TYPE_PENDING_TRAFFIC_BMP_LEN; + wlh[2] = entry->mac_handle; diff --git a/package/kernel/mac80211/patches/brcm/118-v5.6-brcmfmac-sdio-Fix-OOB-interrupt-initialization-on-br.patch b/package/kernel/mac80211/patches/brcm/118-v5.6-brcmfmac-sdio-Fix-OOB-interrupt-initialization-on-br.patch new file mode 100644 index 0000000000..5ec2e9b131 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/118-v5.6-brcmfmac-sdio-Fix-OOB-interrupt-initialization-on-br.patch @@ -0,0 +1,57 @@ +From 8c8e60fb86a90a30721bbd797f58f96b3980dcc1 Mon Sep 17 00:00:00 2001 +From: Jean-Philippe Brucker +Date: Thu, 26 Dec 2019 10:20:33 +0100 +Subject: [PATCH] brcmfmac: sdio: Fix OOB interrupt initialization on brcm43362 + +Commit 262f2b53f679 ("brcmfmac: call brcmf_attach() just before calling +brcmf_bus_started()") changed the initialization order of the brcmfmac +SDIO driver. Unfortunately since brcmf_sdiod_intr_register() is now +called before the sdiodev->bus_if initialization, it reads the wrong +chip ID and fails to initialize the GPIO on brcm43362. Thus the chip +cannot send interrupts and fails to probe: + +[ 12.517023] brcmfmac: brcmf_sdio_bus_rxctl: resumed on timeout +[ 12.531214] ieee80211 phy0: brcmf_bus_started: failed: -110 +[ 12.536976] ieee80211 phy0: brcmf_attach: dongle is not responding: err=-110 +[ 12.566467] brcmfmac: brcmf_sdio_firmware_callback: brcmf_attach failed + +Initialize the bus interface earlier to ensure that +brcmf_sdiod_intr_register() properly sets up the OOB interrupt. + +BugLink: https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=908438 +Fixes: 262f2b53f679 ("brcmfmac: call brcmf_attach() just before calling brcmf_bus_started()") +Signed-off-by: Jean-Philippe Brucker +Reviewed-by: Arend van Spriel +Signed-off-by: Kalle Valo +--- + .../net/wireless/broadcom/brcm80211/brcmfmac/sdio.c | 12 ++++++------ + 1 file changed, 6 insertions(+), 6 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/sdio.c +@@ -4243,6 +4243,12 @@ static void brcmf_sdio_firmware_callback + } + + if (err == 0) { ++ /* Assign bus interface call back */ ++ sdiod->bus_if->dev = sdiod->dev; ++ sdiod->bus_if->ops = &brcmf_sdio_bus_ops; ++ sdiod->bus_if->chip = bus->ci->chip; ++ sdiod->bus_if->chiprev = bus->ci->chiprev; ++ + /* Allow full data communication using DPC from now on. */ + brcmf_sdiod_change_state(bus->sdiodev, BRCMF_SDIOD_DATA); + +@@ -4259,12 +4265,6 @@ static void brcmf_sdio_firmware_callback + + sdio_release_host(sdiod->func1); + +- /* Assign bus interface call back */ +- sdiod->bus_if->dev = sdiod->dev; +- sdiod->bus_if->ops = &brcmf_sdio_bus_ops; +- sdiod->bus_if->chip = bus->ci->chip; +- sdiod->bus_if->chiprev = bus->ci->chiprev; +- + err = brcmf_alloc(sdiod->dev, sdiod->settings); + if (err) { + brcmf_err("brcmf_alloc failed\n"); diff --git a/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch b/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch new file mode 100644 index 0000000000..d52a7a1cc0 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/119-v5.6-0001-brcmfmac-simplify-building-interface-combinations.patch @@ -0,0 +1,103 @@ +From 24332f8068ff6df7f16aefee45d514de1de4de80 Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 26 Dec 2019 14:30:49 +0100 +Subject: [PATCH] brcmfmac: simplify building interface combinations +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Move similar/duplicated code out of combination specific code blocks. +This simplifies code a bit and allows adding more combinations later. +A list of combinations remains unchanged. + +Signed-off-by: Rafał Miłecki +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 43 ++++++------------- + 1 file changed, 14 insertions(+), 29 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -6479,12 +6479,13 @@ static int brcmf_setup_ifmodes(struct wi + struct ieee80211_iface_limit *c0_limits = NULL; + struct ieee80211_iface_limit *p2p_limits = NULL; + struct ieee80211_iface_limit *mbss_limits = NULL; +- bool mbss, p2p, rsdb; ++ bool mbss, p2p, rsdb, mchan; + int i, c, n_combos; + + mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); + p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); + rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); ++ mchan = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN); + + n_combos = 1 + !!(p2p && !rsdb) + !!mbss; + combo = kcalloc(n_combos, sizeof(*combo), GFP_KERNEL); +@@ -6494,6 +6495,10 @@ static int brcmf_setup_ifmodes(struct wi + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); ++ if (p2p) ++ wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | ++ BIT(NL80211_IFTYPE_P2P_GO) | ++ BIT(NL80211_IFTYPE_P2P_DEVICE); + + c = 0; + i = 0; +@@ -6505,48 +6510,28 @@ static int brcmf_setup_ifmodes(struct wi + c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); + if (!c0_limits) + goto err; +- if (p2p && rsdb) { +- combo[c].num_different_channels = 2; +- wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | +- BIT(NL80211_IFTYPE_P2P_GO) | +- BIT(NL80211_IFTYPE_P2P_DEVICE); +- c0_limits[i].max = 2; +- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); ++ ++ combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan)); ++ c0_limits[i].max = 1 + rsdb; ++ c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); ++ if (p2p) { + c0_limits[i].max = 1; + c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +- c0_limits[i].max = 2; ++ c0_limits[i].max = 1 + rsdb; + c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO); ++ } ++ if (p2p && rsdb) { + c0_limits[i].max = 2; + c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); + combo[c].max_interfaces = 5; + } else if (p2p) { +- if (brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MCHAN)) +- combo[c].num_different_channels = 2; +- else +- combo[c].num_different_channels = 1; +- c0_limits[i].max = 1; +- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); +- wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | +- BIT(NL80211_IFTYPE_P2P_GO) | +- BIT(NL80211_IFTYPE_P2P_DEVICE); +- c0_limits[i].max = 1; +- c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +- c0_limits[i].max = 1; +- c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_CLIENT) | +- BIT(NL80211_IFTYPE_P2P_GO); + combo[c].max_interfaces = i; + } else if (rsdb) { +- combo[c].num_different_channels = 2; +- c0_limits[i].max = 2; +- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); + c0_limits[i].max = 2; + c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); + combo[c].max_interfaces = 3; + } else { +- combo[c].num_different_channels = 1; +- c0_limits[i].max = 1; +- c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); + c0_limits[i].max = 1; + c0_limits[i++].types = BIT(NL80211_IFTYPE_AP); + combo[c].max_interfaces = i; diff --git a/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch b/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch new file mode 100644 index 0000000000..08fa1544ec --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/119-v5.6-0002-brcmfmac-add-initial-support-for-monitor-mode.patch @@ -0,0 +1,345 @@ +From 20f2c5fa3af060401c72e444999470a4cab641cf Mon Sep 17 00:00:00 2001 +From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= +Date: Thu, 26 Dec 2019 14:30:50 +0100 +Subject: [PATCH] brcmfmac: add initial support for monitor mode +MIME-Version: 1.0 +Content-Type: text/plain; charset=UTF-8 +Content-Transfer-Encoding: 8bit + +Report monitor interface availability using cfg80211 and support it in +the add_virtual_intf() and del_virtual_intf() callbacks. This new +feature is conditional and depends on firmware flagging monitor packets. +Receiving monitor frames is already handled by the brcmf_netif_mon_rx(). + +Signed-off-by: Rafał Miłecki +Signed-off-by: Kalle Valo +--- + .../broadcom/brcm80211/brcmfmac/cfg80211.c | 112 ++++++++++++++++-- + .../broadcom/brcm80211/brcmfmac/core.c | 68 ++++++++++- + .../broadcom/brcm80211/brcmfmac/core.h | 2 + + .../broadcom/brcm80211/brcmfmac/feature.c | 1 + + .../broadcom/brcm80211/brcmfmac/feature.h | 2 + + .../broadcom/brcm80211/brcmfmac/fwil.h | 2 + + 6 files changed, 174 insertions(+), 13 deletions(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +@@ -11,6 +11,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -619,6 +620,82 @@ static bool brcmf_is_ibssmode(struct brc + 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, +@@ -641,9 +718,10 @@ static struct wireless_dev *brcmf_cfg802 + 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; +@@ -826,9 +904,10 @@ int brcmf_cfg80211_del_iface(struct wiph + 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: +@@ -6479,9 +6558,10 @@ static int brcmf_setup_ifmodes(struct wi + struct ieee80211_iface_limit *c0_limits = NULL; + struct ieee80211_iface_limit *p2p_limits = NULL; + struct ieee80211_iface_limit *mbss_limits = NULL; +- bool mbss, p2p, rsdb, mchan; +- int i, c, n_combos; ++ bool mon_flag, mbss, p2p, rsdb, mchan; ++ int i, c, n_combos, n_limits; + ++ mon_flag = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MONITOR_FLAG); + mbss = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_MBSS); + p2p = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_P2P); + rsdb = brcmf_feat_is_enabled(ifp, BRCMF_FEAT_RSDB); +@@ -6495,6 +6575,8 @@ static int brcmf_setup_ifmodes(struct wi + wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) | + BIT(NL80211_IFTYPE_ADHOC) | + BIT(NL80211_IFTYPE_AP); ++ if (mon_flag) ++ wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR); + if (p2p) + wiphy->interface_modes |= BIT(NL80211_IFTYPE_P2P_CLIENT) | + BIT(NL80211_IFTYPE_P2P_GO) | +@@ -6502,18 +6584,18 @@ static int brcmf_setup_ifmodes(struct wi + + c = 0; + i = 0; +- if (p2p && rsdb) +- c0_limits = kcalloc(4, sizeof(*c0_limits), GFP_KERNEL); +- else if (p2p) +- c0_limits = kcalloc(3, sizeof(*c0_limits), GFP_KERNEL); +- else +- c0_limits = kcalloc(2, sizeof(*c0_limits), GFP_KERNEL); ++ n_limits = 1 + mon_flag + (p2p ? 2 : 0) + (rsdb || !p2p); ++ c0_limits = kcalloc(n_limits, sizeof(*c0_limits), GFP_KERNEL); + if (!c0_limits) + goto err; + + combo[c].num_different_channels = 1 + (rsdb || (p2p && mchan)); + c0_limits[i].max = 1 + rsdb; + c0_limits[i++].types = BIT(NL80211_IFTYPE_STATION); ++ if (mon_flag) { ++ c0_limits[i].max = 1; ++ c0_limits[i++].types = BIT(NL80211_IFTYPE_MONITOR); ++ } + if (p2p) { + c0_limits[i].max = 1; + c0_limits[i++].types = BIT(NL80211_IFTYPE_P2P_DEVICE); +@@ -6562,14 +6644,20 @@ static int brcmf_setup_ifmodes(struct wi + if (mbss) { + c++; + i = 0; +- mbss_limits = kcalloc(1, sizeof(*mbss_limits), GFP_KERNEL); ++ n_limits = 1 + mon_flag; ++ 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_flag) { ++ 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_flag; + combo[c].n_limits = i; + combo[c].limits = mbss_limits; + } +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +@@ -690,7 +690,7 @@ fail: + 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) +@@ -703,6 +703,72 @@ static void brcmf_net_detach(struct net_ + } + } + ++static int brcmf_net_mon_open(struct net_device *ndev) ++{ ++ struct brcmf_if *ifp = netdev_priv(ndev); ++ struct brcmf_pub *drvr = ifp->drvr; ++ u32 monitor; ++ int err; ++ ++ brcmf_dbg(TRACE, "Enter\n"); ++ ++ err = brcmf_fil_cmd_int_get(ifp, BRCMF_C_GET_MONITOR, &monitor); ++ if (err) { ++ bphy_err(drvr, "BRCMF_C_GET_MONITOR error (%d)\n", err); ++ return err; ++ } else if (monitor) { ++ bphy_err(drvr, "Monitor mode is already enabled\n"); ++ return -EEXIST; ++ } ++ ++ monitor = 3; ++ err = brcmf_fil_cmd_int_set(ifp, BRCMF_C_SET_MONITOR, monitor); ++ if (err) ++ bphy_err(drvr, "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); ++ struct brcmf_pub *drvr = ifp->drvr; ++ 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) ++ bphy_err(drvr, "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 brcmf_pub *drvr = ifp->drvr; ++ 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) ++ bphy_err(drvr, "Failed to register %s device\n", ndev->name); ++ ++ return err; ++} ++ + void brcmf_net_setcarrier(struct brcmf_if *ifp, bool on) + { + struct net_device *ndev; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.h +@@ -210,6 +210,8 @@ void brcmf_txflowblock_if(struct brcmf_i + 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); +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.c +@@ -38,6 +38,7 @@ static const struct brcmf_feat_fwcap brc + { BRCMF_FEAT_MCHAN, "mchan" }, + { BRCMF_FEAT_P2P, "p2p" }, + { BRCMF_FEAT_MONITOR, "monitor" }, ++ { BRCMF_FEAT_MONITOR_FLAG, "rtap" }, + { BRCMF_FEAT_MONITOR_FMT_RADIOTAP, "rtap" }, + { BRCMF_FEAT_DOT11H, "802.11h" } + }; +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/feature.h +@@ -23,6 +23,7 @@ + * GSCAN: enhanced scan offload feature. + * FWSUP: Firmware supplicant. + * MONITOR: firmware can pass monitor packets to host. ++ * MONITOR_FLAG: firmware flags monitor packets. + * MONITOR_FMT_RADIOTAP: firmware provides monitor packets with radiotap header + * MONITOR_FMT_HW_RX_HDR: firmware provides monitor packets with hw/ucode header + * DOT11H: firmware supports 802.11h +@@ -43,6 +44,7 @@ + BRCMF_FEAT_DEF(GSCAN) \ + BRCMF_FEAT_DEF(FWSUP) \ + BRCMF_FEAT_DEF(MONITOR) \ ++ BRCMF_FEAT_DEF(MONITOR_FLAG) \ + BRCMF_FEAT_DEF(MONITOR_FMT_RADIOTAP) \ + BRCMF_FEAT_DEF(MONITOR_FMT_HW_RX_HDR) \ + BRCMF_FEAT_DEF(DOT11H) +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/fwil.h +@@ -49,6 +49,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 diff --git a/package/kernel/mac80211/patches/brcm/120-v5.6-brcmfmac-Remove-always-false-idx-0-statement.patch b/package/kernel/mac80211/patches/brcm/120-v5.6-brcmfmac-Remove-always-false-idx-0-statement.patch new file mode 100644 index 0000000000..9efa762830 --- /dev/null +++ b/package/kernel/mac80211/patches/brcm/120-v5.6-brcmfmac-Remove-always-false-idx-0-statement.patch @@ -0,0 +1,24 @@ +From 627b0d094240c38393b2f2d40626c33a8fff6103 Mon Sep 17 00:00:00 2001 +From: yuehaibing +Date: Wed, 8 Jan 2020 21:57:48 +0800 +Subject: [PATCH] brcmfmac: Remove always false 'idx < 0' statement + +idx is declared as u32, it will never less than 0. + +Signed-off-by: yuehaibing +Signed-off-by: Kalle Valo +--- + drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c | 2 +- + 1 file changed, 1 insertion(+), 1 deletion(-) + +--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c ++++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/msgbuf.c +@@ -365,7 +365,7 @@ brcmf_msgbuf_get_pktid(struct device *de + struct brcmf_msgbuf_pktid *pktid; + struct sk_buff *skb; + +- if (idx < 0 || idx >= pktids->array_size) { ++ if (idx >= pktids->array_size) { + brcmf_err("Invalid packet id %d (max %d)\n", idx, + pktids->array_size); + return NULL; diff --git a/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch index f64167b1c3..a1bcbfaec8 100644 --- a/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch +++ b/package/kernel/mac80211/patches/brcm/860-brcmfmac-register-wiphy-s-during-module_init.patch @@ -13,7 +13,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/core.c -@@ -1479,6 +1479,7 @@ int __init brcmf_core_init(void) +@@ -1545,6 +1545,7 @@ int __init brcmf_core_init(void) { if (!schedule_work(&brcmf_driver_work)) return -EBUSY; diff --git a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch index 5f0fa7faab..37ebb5190b 100644 --- a/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch +++ b/package/kernel/mac80211/patches/brcm/861-brcmfmac-workaround-bug-with-some-inconsistent-BSSes.patch @@ -10,7 +10,7 @@ Signed-off-by: Rafał Miłecki --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -628,8 +628,36 @@ static struct wireless_dev *brcmf_cfg802 +@@ -705,8 +705,36 @@ static struct wireless_dev *brcmf_cfg802 struct brcmf_cfg80211_info *cfg = wiphy_to_cfg(wiphy); struct brcmf_pub *drvr = cfg->pub; struct wireless_dev *wdev; diff --git a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch index 6412653a3a..988ece1f5f 100644 --- a/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch +++ b/package/kernel/mac80211/patches/brcm/862-brcmfmac-Disable-power-management.patch @@ -14,7 +14,7 @@ Signed-off-by: Phil Elwell --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c -@@ -2795,6 +2795,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip +@@ -2874,6 +2874,10 @@ brcmf_cfg80211_set_power_mgmt(struct wip * preference in cfg struct to apply this to * FW later while initializing the dongle */