c729fe0269
To work correctly hostapd requires wireless driver to allow interfaces removal. It was working with brcmfmac only partially. Firmware for BCM43602 got some special hack (feature?) that allowed removing all interfaces by disabling mbss mode. It wasn't working with BCM4366 firmware and remaining interfaces were preventing hostapd from starting again. Those patches add support for "interface_remove" firmware method which works with BCM4366 firmware and they make it finally possible to use BCM4366 & brcmfmac & multiple interfaces. Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
84 lines
2.5 KiB
Diff
84 lines
2.5 KiB
Diff
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <zajec5@gmail.com>
|
|
Date: Wed, 29 Jun 2016 21:54:27 +0200
|
|
Subject: [PATCH] brcmfmac: support removing AP interfaces with
|
|
"interface_remove"
|
|
MIME-Version: 1.0
|
|
Content-Type: text/plain; charset=UTF-8
|
|
Content-Transfer-Encoding: 8bit
|
|
|
|
New firmwares (e.g. 10.10.69.36 for BCM4366) support "interface_remove"
|
|
for removing interfaces. Try to use this method on cfg80211 request. In
|
|
case of older firmwares (e.g. 7.35.177.56 for BCM43602 as I tested) this
|
|
will just result in firmware rejecting command and this won't change any
|
|
behavior.
|
|
|
|
Signed-off-by: Rafał Miłecki <zajec5@gmail.com>
|
|
Signed-off-by: Kalle Valo <kvalo@codeaurora.org>
|
|
---
|
|
|
|
--- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
+++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c
|
|
@@ -785,12 +785,48 @@ s32 brcmf_notify_escan_complete(struct b
|
|
return err;
|
|
}
|
|
|
|
+static int brcmf_cfg80211_del_ap_iface(struct wiphy *wiphy,
|
|
+ struct wireless_dev *wdev)
|
|
+{
|
|
+ struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
|
|
+ struct net_device *ndev = wdev->netdev;
|
|
+ struct brcmf_if *ifp = netdev_priv(ndev);
|
|
+ int ret;
|
|
+ int err;
|
|
+
|
|
+ brcmf_cfg80211_arm_vif_event(cfg, ifp->vif);
|
|
+
|
|
+ err = brcmf_fil_bsscfg_data_set(ifp, "interface_remove", NULL, 0);
|
|
+ if (err) {
|
|
+ brcmf_err("interface_remove failed %d\n", err);
|
|
+ goto err_unarm;
|
|
+ }
|
|
+
|
|
+ /* wait for firmware event */
|
|
+ ret = brcmf_cfg80211_wait_vif_event(cfg, BRCMF_E_IF_DEL,
|
|
+ BRCMF_VIF_EVENT_TIMEOUT);
|
|
+ if (!ret) {
|
|
+ brcmf_err("timeout occurred\n");
|
|
+ err = -EIO;
|
|
+ goto err_unarm;
|
|
+ }
|
|
+
|
|
+ brcmf_remove_interface(ifp, true);
|
|
+
|
|
+err_unarm:
|
|
+ brcmf_cfg80211_arm_vif_event(cfg, NULL);
|
|
+ return err;
|
|
+}
|
|
+
|
|
static
|
|
int brcmf_cfg80211_del_iface(struct wiphy *wiphy, struct wireless_dev *wdev)
|
|
{
|
|
struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
|
|
struct net_device *ndev = wdev->netdev;
|
|
|
|
+ if (ndev && ndev == cfg_to_ndev(cfg))
|
|
+ return -ENOTSUPP;
|
|
+
|
|
/* vif event pending in firmware */
|
|
if (brcmf_cfg80211_vif_event_armed(cfg))
|
|
return -EBUSY;
|
|
@@ -807,12 +843,13 @@ int brcmf_cfg80211_del_iface(struct wiph
|
|
switch (wdev->iftype) {
|
|
case NL80211_IFTYPE_ADHOC:
|
|
case NL80211_IFTYPE_STATION:
|
|
- case NL80211_IFTYPE_AP:
|
|
case NL80211_IFTYPE_AP_VLAN:
|
|
case NL80211_IFTYPE_WDS:
|
|
case NL80211_IFTYPE_MONITOR:
|
|
case NL80211_IFTYPE_MESH_POINT:
|
|
return -EOPNOTSUPP;
|
|
+ case NL80211_IFTYPE_AP:
|
|
+ return brcmf_cfg80211_del_ap_iface(wiphy, wdev);
|
|
case NL80211_IFTYPE_P2P_CLIENT:
|
|
case NL80211_IFTYPE_P2P_GO:
|
|
case NL80211_IFTYPE_P2P_DEVICE:
|