Merge ath-next from ath.git
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / brcm80211 / brcmfmac / p2p.c
index 710fbe570eb24da1d316c94679b0ed390bc1a29c..2e1598f76d4b7821c129b9cd904c43f74012cb3f 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/slab.h>
 #include <linux/netdevice.h>
 #include <linux/etherdevice.h>
+#include <linux/rtnetlink.h>
 #include <net/cfg80211.h>
 
 #include <brcmu_wifi.h>
@@ -1907,105 +1908,6 @@ s32 brcmf_p2p_notify_rx_mgmt_p2p_probereq(struct brcmf_if *ifp,
 }
 
 
-/**
- * brcmf_p2p_attach() - attach for P2P.
- *
- * @cfg: driver private data for cfg80211 interface.
- */
-s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
-{
-       struct brcmf_if *pri_ifp;
-       struct brcmf_if *p2p_ifp;
-       struct brcmf_cfg80211_vif *p2p_vif;
-       struct brcmf_p2p_info *p2p;
-       struct brcmf_pub *drvr;
-       s32 bssidx;
-       s32 err = 0;
-
-       p2p = &cfg->p2p;
-       p2p->cfg = cfg;
-
-       drvr = cfg->pub;
-
-       pri_ifp = drvr->iflist[0];
-       p2p_ifp = drvr->iflist[1];
-
-       p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
-
-       if (p2p_ifp) {
-               p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
-                                         false);
-               if (IS_ERR(p2p_vif)) {
-                       brcmf_err("could not create discovery vif\n");
-                       err = -ENOMEM;
-                       goto exit;
-               }
-
-               p2p_vif->ifp = p2p_ifp;
-               p2p_ifp->vif = p2p_vif;
-               p2p_vif->wdev.netdev = p2p_ifp->ndev;
-               p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
-               SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
-
-               p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
-
-               brcmf_p2p_generate_bss_mac(p2p, NULL);
-               memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
-               brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
-
-               /* Initialize P2P Discovery in the firmware */
-               err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
-               if (err < 0) {
-                       brcmf_err("set p2p_disc error\n");
-                       brcmf_free_vif(p2p_vif);
-                       goto exit;
-               }
-               /* obtain bsscfg index for P2P discovery */
-               err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
-               if (err < 0) {
-                       brcmf_err("retrieving discover bsscfg index failed\n");
-                       brcmf_free_vif(p2p_vif);
-                       goto exit;
-               }
-               /* Verify that firmware uses same bssidx as driver !! */
-               if (p2p_ifp->bssidx != bssidx) {
-                       brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
-                                 bssidx, p2p_ifp->bssidx);
-                       brcmf_free_vif(p2p_vif);
-                       goto exit;
-               }
-
-               init_completion(&p2p->send_af_done);
-               INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
-               init_completion(&p2p->afx_hdl.act_frm_scan);
-               init_completion(&p2p->wait_next_af);
-       }
-exit:
-       return err;
-}
-
-
-/**
- * brcmf_p2p_detach() - detach P2P.
- *
- * @p2p: P2P specific data.
- */
-void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
-{
-       struct brcmf_cfg80211_vif *vif;
-
-       vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
-       if (vif != NULL) {
-               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
-               brcmf_p2p_deinit_discovery(p2p);
-               /* remove discovery interface */
-               brcmf_free_vif(vif);
-               p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
-       }
-       /* just set it all to zero */
-       memset(p2p, 0, sizeof(*p2p));
-}
-
 /**
  * brcmf_p2p_get_current_chanspec() - Get current operation channel.
  *
@@ -2238,6 +2140,7 @@ static void brcmf_p2p_delete_p2pdev(struct brcmf_p2p_info *p2p,
 {
        cfg80211_unregister_wdev(&vif->wdev);
        p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL;
+       kfree(vif->ifp);
        brcmf_free_vif(vif);
 }
 
@@ -2364,6 +2267,8 @@ int brcmf_p2p_del_vif(struct wiphy *wiphy, struct wireless_dev *wdev)
                break;
 
        case NL80211_IFTYPE_P2P_DEVICE:
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
                brcmf_p2p_delete_p2pdev(p2p, vif);
                return 0;
        default:
@@ -2425,3 +2330,103 @@ void brcmf_p2p_stop_device(struct wiphy *wiphy, struct wireless_dev *wdev)
        clear_bit(BRCMF_VIF_STATUS_READY, &vif->sme_state);
        mutex_unlock(&cfg->usr_sync);
 }
+
+/**
+ * brcmf_p2p_attach() - attach for P2P.
+ *
+ * @cfg: driver private data for cfg80211 interface.
+ */
+s32 brcmf_p2p_attach(struct brcmf_cfg80211_info *cfg)
+{
+       struct brcmf_if *pri_ifp;
+       struct brcmf_if *p2p_ifp;
+       struct brcmf_cfg80211_vif *p2p_vif;
+       struct brcmf_p2p_info *p2p;
+       struct brcmf_pub *drvr;
+       s32 bssidx;
+       s32 err = 0;
+
+       p2p = &cfg->p2p;
+       p2p->cfg = cfg;
+
+       drvr = cfg->pub;
+
+       pri_ifp = drvr->iflist[0];
+       p2p_ifp = drvr->iflist[1];
+
+       p2p->bss_idx[P2PAPI_BSSCFG_PRIMARY].vif = pri_ifp->vif;
+
+       if (p2p_ifp) {
+               p2p_vif = brcmf_alloc_vif(cfg, NL80211_IFTYPE_P2P_DEVICE,
+                                         false);
+               if (IS_ERR(p2p_vif)) {
+                       brcmf_err("could not create discovery vif\n");
+                       err = -ENOMEM;
+                       goto exit;
+               }
+
+               p2p_vif->ifp = p2p_ifp;
+               p2p_ifp->vif = p2p_vif;
+               p2p_vif->wdev.netdev = p2p_ifp->ndev;
+               p2p_ifp->ndev->ieee80211_ptr = &p2p_vif->wdev;
+               SET_NETDEV_DEV(p2p_ifp->ndev, wiphy_dev(cfg->wiphy));
+
+               p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif = p2p_vif;
+
+               brcmf_p2p_generate_bss_mac(p2p, NULL);
+               memcpy(p2p_ifp->mac_addr, p2p->dev_addr, ETH_ALEN);
+               brcmf_p2p_set_firmware(pri_ifp, p2p->dev_addr);
+
+               /* Initialize P2P Discovery in the firmware */
+               err = brcmf_fil_iovar_int_set(pri_ifp, "p2p_disc", 1);
+               if (err < 0) {
+                       brcmf_err("set p2p_disc error\n");
+                       brcmf_free_vif(p2p_vif);
+                       goto exit;
+               }
+               /* obtain bsscfg index for P2P discovery */
+               err = brcmf_fil_iovar_int_get(pri_ifp, "p2p_dev", &bssidx);
+               if (err < 0) {
+                       brcmf_err("retrieving discover bsscfg index failed\n");
+                       brcmf_free_vif(p2p_vif);
+                       goto exit;
+               }
+               /* Verify that firmware uses same bssidx as driver !! */
+               if (p2p_ifp->bssidx != bssidx) {
+                       brcmf_err("Incorrect bssidx=%d, compared to p2p_ifp->bssidx=%d\n",
+                                 bssidx, p2p_ifp->bssidx);
+                       brcmf_free_vif(p2p_vif);
+                       goto exit;
+               }
+
+               init_completion(&p2p->send_af_done);
+               INIT_WORK(&p2p->afx_hdl.afx_work, brcmf_p2p_afx_handler);
+               init_completion(&p2p->afx_hdl.act_frm_scan);
+               init_completion(&p2p->wait_next_af);
+       }
+exit:
+       return err;
+}
+
+/**
+ * brcmf_p2p_detach() - detach P2P.
+ *
+ * @p2p: P2P specific data.
+ */
+void brcmf_p2p_detach(struct brcmf_p2p_info *p2p)
+{
+       struct brcmf_cfg80211_vif *vif;
+
+       vif = p2p->bss_idx[P2PAPI_BSSCFG_DEVICE].vif;
+       if (vif != NULL) {
+               brcmf_p2p_cancel_remain_on_channel(vif->ifp);
+               brcmf_p2p_deinit_discovery(p2p);
+               /* remove discovery interface */
+               rtnl_lock();
+               brcmf_p2p_delete_p2pdev(p2p, vif);
+               rtnl_unlock();
+       }
+       /* just set it all to zero */
+       memset(p2p, 0, sizeof(*p2p));
+}
+