mac80211: brcmfmac: fix interfaces management
[openwrt/svn-archive/archive.git] / package / kernel / mac80211 / patches / 351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch
diff --git a/package/kernel/mac80211/patches/351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch b/package/kernel/mac80211/patches/351-0025-brcmfmac-support-removing-AP-interfaces-with-interfa.patch
new file mode 100644 (file)
index 0000000..4545207
--- /dev/null
@@ -0,0 +1,84 @@
+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
+@@ -750,12 +750,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;
+@@ -772,12 +808,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: