return err;
 }
 
+static int brcmf_p2p_disable_p2p_if(struct brcmf_cfg80211_vif *vif)
+{
+       struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
+       struct net_device *pri_ndev = cfg_to_ndev(cfg);
+       struct brcmf_if *ifp = netdev_priv(pri_ndev);
+       u8 *addr = vif->wdev.netdev->dev_addr;
+
+       return brcmf_fil_iovar_data_set(ifp, "p2p_ifdis", addr, ETH_ALEN);
+}
+
+static int brcmf_p2p_release_p2p_if(struct brcmf_cfg80211_vif *vif)
+{
+       struct brcmf_cfg80211_info *cfg = wdev_to_cfg(&vif->wdev);
+       struct net_device *pri_ndev = cfg_to_ndev(cfg);
+       struct brcmf_if *ifp = netdev_priv(pri_ndev);
+       u8 *addr = vif->wdev.netdev->dev_addr;
+
+       return brcmf_fil_iovar_data_set(ifp, "p2p_ifdel", addr, ETH_ALEN);
+}
+
 /**
  * brcmf_p2p_add_vif() - create a new P2P virtual interface.
  *
 {
        struct brcmf_cfg80211_info *cfg = wiphy_priv(wiphy);
        struct brcmf_cfg80211_vif *vif;
+       unsigned long jiffie_timeout = msecs_to_jiffies(1500);
+       bool wait_for_disable = false;
        int err;
 
+       brcmf_dbg(TRACE, "delete P2P vif\n");
        vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev);
 
-       if (brcmf_cfg80211_vif_event_armed(cfg))
-               return -EBUSY;
+       switch (vif->wdev.iftype) {
+       case NL80211_IFTYPE_P2P_CLIENT:
+               if (test_bit(BRCMF_VIF_STATUS_DISCONNECTING, &vif->sme_state))
+                       wait_for_disable = true;
+               break;
+
+       case NL80211_IFTYPE_P2P_GO:
+               if (!brcmf_p2p_disable_p2p_if(vif))
+                       wait_for_disable = true;
+               break;
+
+       case NL80211_IFTYPE_P2P_DEVICE:
+       default:
+               return -ENOTSUPP;
+               break;
+       }
+
+       if (wait_for_disable)
+               wait_for_completion_timeout(&cfg->vif_disabled, 500);
+
+       brcmf_vif_clear_mgmt_ies(vif);
 
        brcmf_cfg80211_arm_vif_event(cfg, vif);
-       /* wait for firmware event */
-       err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
-                                                   msecs_to_jiffies(1500));
+       err = brcmf_p2p_release_p2p_if(vif);
+       if (!err)
+               /* wait for firmware event */
+               err = brcmf_cfg80211_wait_vif_event_timeout(cfg, BRCMF_E_IF_DEL,
+                                                           jiffie_timeout);
        brcmf_cfg80211_arm_vif_event(cfg, NULL);
-       if (wdev->netdev)
-               brcmf_dbg(INFO, "deleting vif \"%s\"\n", wdev->netdev->name);
-       else
-               brcmf_dbg(INFO, "deleting vif \"wdev-%u\"\n",
-                         wdev->identifier);
-       brcmf_err("enter - not supported yet\n");
-       return -EOPNOTSUPP;
+       brcmf_free_vif(vif);
+
+       return err;
 }
 
        }
 }
 
+static void brcmf_set_mpc(struct net_device *ndev, int mpc)
+{
+       struct brcmf_if *ifp = netdev_priv(ndev);
+       s32 err = 0;
+
+       if (check_vif_up(ifp->vif)) {
+               err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
+               if (err) {
+                       brcmf_err("fail to set mpc\n");
+                       return;
+               }
+               brcmf_dbg(INFO, "MPC : %d\n", mpc);
+       }
+}
+
+static s32
+brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
+                           struct net_device *ndev,
+                           bool aborted, bool fw_abort)
+{
+       struct brcmf_scan_params_le params_le;
+       struct cfg80211_scan_request *scan_request;
+       s32 err = 0;
+
+       brcmf_dbg(SCAN, "Enter\n");
+
+       /* clear scan request, because the FW abort can cause a second call */
+       /* to this functon and might cause a double cfg80211_scan_done      */
+       scan_request = cfg->scan_request;
+       cfg->scan_request = NULL;
+
+       if (timer_pending(&cfg->escan_timeout))
+               del_timer_sync(&cfg->escan_timeout);
+
+       if (fw_abort) {
+               /* Do a scan abort to stop the driver's scan engine */
+               brcmf_dbg(SCAN, "ABORT scan in firmware\n");
+               memset(¶ms_le, 0, sizeof(params_le));
+               memset(params_le.bssid, 0xFF, ETH_ALEN);
+               params_le.bss_type = DOT11_BSSTYPE_ANY;
+               params_le.scan_type = 0;
+               params_le.channel_num = cpu_to_le32(1);
+               params_le.nprobes = cpu_to_le32(1);
+               params_le.active_time = cpu_to_le32(-1);
+               params_le.passive_time = cpu_to_le32(-1);
+               params_le.home_time = cpu_to_le32(-1);
+               /* Scan is aborted by setting channel_list[0] to -1 */
+               params_le.channel_list[0] = cpu_to_le16(-1);
+               /* E-Scan (or anyother type) can be aborted by SCAN */
+               err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
+                                            ¶ms_le, sizeof(params_le));
+               if (err)
+                       brcmf_err("Scan abort  failed\n");
+       }
+       /*
+        * e-scan can be initiated by scheduled scan
+        * which takes precedence.
+        */
+       if (cfg->sched_escan) {
+               brcmf_dbg(SCAN, "scheduled scan completed\n");
+               cfg->sched_escan = false;
+               if (!aborted)
+                       cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
+               brcmf_set_mpc(ndev, 1);
+       } else if (scan_request) {
+               brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
+                         aborted ? "Aborted" : "Done");
+               cfg80211_scan_done(scan_request, aborted);
+               brcmf_set_mpc(ndev, 1);
+       }
+       if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
+               brcmf_err("Scan complete while device not scanning\n");
+               return -EPERM;
+       }
+
+       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;
+
+       /* vif event pending in firmware */
+       if (brcmf_cfg80211_vif_event_armed(cfg))
+               return -EBUSY;
+
+       if (ndev) {
+               if (test_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status) &&
+                   cfg->escan_info.ndev == ndev)
+                       brcmf_notify_escan_complete(cfg, ndev, true,
+                                                   true);
+
+               brcmf_fil_iovar_int_set(netdev_priv(ndev), "mpc", 1);
+       }
+
        switch (wdev->iftype) {
        case NL80211_IFTYPE_ADHOC:
        case NL80211_IFTYPE_STATION:
        return err;
 }
 
-static void brcmf_set_mpc(struct net_device *ndev, int mpc)
-{
-       struct brcmf_if *ifp = netdev_priv(ndev);
-       s32 err = 0;
-
-       if (check_vif_up(ifp->vif)) {
-               err = brcmf_fil_iovar_int_set(ifp, "mpc", mpc);
-               if (err) {
-                       brcmf_err("fail to set mpc\n");
-                       return;
-               }
-               brcmf_dbg(INFO, "MPC : %d\n", mpc);
-       }
-}
-
 static void brcmf_escan_prep(struct brcmf_scan_params_le *params_le,
                             struct cfg80211_scan_request *request)
 {
                        (n_channels & BRCMF_SCAN_PARAMS_COUNT_MASK));
 }
 
-static s32
-brcmf_notify_escan_complete(struct brcmf_cfg80211_info *cfg,
-                           struct net_device *ndev,
-                           bool aborted, bool fw_abort)
-{
-       struct brcmf_scan_params_le params_le;
-       struct cfg80211_scan_request *scan_request;
-       s32 err = 0;
-
-       brcmf_dbg(SCAN, "Enter\n");
-
-       /* clear scan request, because the FW abort can cause a second call */
-       /* to this functon and might cause a double cfg80211_scan_done      */
-       scan_request = cfg->scan_request;
-       cfg->scan_request = NULL;
-
-       if (timer_pending(&cfg->escan_timeout))
-               del_timer_sync(&cfg->escan_timeout);
-
-       if (fw_abort) {
-               /* Do a scan abort to stop the driver's scan engine */
-               brcmf_dbg(SCAN, "ABORT scan in firmware\n");
-               memset(¶ms_le, 0, sizeof(params_le));
-               memset(params_le.bssid, 0xFF, ETH_ALEN);
-               params_le.bss_type = DOT11_BSSTYPE_ANY;
-               params_le.scan_type = 0;
-               params_le.channel_num = cpu_to_le32(1);
-               params_le.nprobes = cpu_to_le32(1);
-               params_le.active_time = cpu_to_le32(-1);
-               params_le.passive_time = cpu_to_le32(-1);
-               params_le.home_time = cpu_to_le32(-1);
-               /* Scan is aborted by setting channel_list[0] to -1 */
-               params_le.channel_list[0] = cpu_to_le16(-1);
-               /* E-Scan (or anyother type) can be aborted by SCAN */
-               err = brcmf_fil_cmd_data_set(netdev_priv(ndev), BRCMF_C_SCAN,
-                                            ¶ms_le, sizeof(params_le));
-               if (err)
-                       brcmf_err("Scan abort  failed\n");
-       }
-       /*
-        * e-scan can be initiated by scheduled scan
-        * which takes precedence.
-        */
-       if (cfg->sched_escan) {
-               brcmf_dbg(SCAN, "scheduled scan completed\n");
-               cfg->sched_escan = false;
-               if (!aborted)
-                       cfg80211_sched_scan_results(cfg_to_wiphy(cfg));
-               brcmf_set_mpc(ndev, 1);
-       } else if (scan_request) {
-               brcmf_dbg(SCAN, "ESCAN Completed scan: %s\n",
-                         aborted ? "Aborted" : "Done");
-               cfg80211_scan_done(scan_request, aborted);
-               brcmf_set_mpc(ndev, 1);
-       }
-       if (!test_and_clear_bit(BRCMF_SCAN_STATUS_BUSY, &cfg->scan_status)) {
-               brcmf_err("Scan complete while device not scanning\n");
-               return -EPERM;
-       }
-
-       return err;
-}
-
 static s32
 brcmf_run_escan(struct brcmf_cfg80211_info *cfg, struct net_device *ndev,
                struct cfg80211_scan_request *request, u16 action)
        return err;
 }
 
+s32 brcmf_vif_clear_mgmt_ies(struct brcmf_cfg80211_vif *vif)
+{
+       s32 pktflags[] = {
+               BRCMF_VNDR_IE_PRBREQ_FLAG,
+               BRCMF_VNDR_IE_PRBRSP_FLAG,
+               BRCMF_VNDR_IE_BEACON_FLAG
+       };
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(pktflags); i++)
+               brcmf_vif_set_mgmt_ie(vif, pktflags[i], NULL, 0);
+
+       memset(&vif->saved_ie, 0, sizeof(vif->saved_ie));
+       return 0;
+}
+
 static s32
 brcmf_cfg80211_start_ap(struct wiphy *wiphy, struct net_device *ndev,
                        struct cfg80211_ap_settings *settings)
        struct station_info sinfo;
 
        brcmf_dbg(CONN, "event %d, reason %d\n", event, reason);
+       if (event == BRCMF_E_LINK && reason == BRCMF_E_REASON_LINK_BSSCFG_DIS &&
+           ndev != cfg_to_ndev(cfg)) {
+               brcmf_dbg(CONN, "AP mode link down\n");
+               complete(&cfg->vif_disabled);
+               return 0;
+       }
 
        if (((event == BRCMF_E_ASSOC_IND) || (event == BRCMF_E_REASSOC_IND)) &&
            (reason == BRCMF_E_STATUS_SUCCESS)) {
                }
                brcmf_link_down(ifp->vif);
                brcmf_init_prof(ndev_to_prof(ndev));
+               if (ndev != cfg_to_ndev(cfg))
+                       complete(&cfg->vif_disabled);
        } else if (brcmf_is_nonetwork(cfg, e)) {
                if (brcmf_is_ibssmode(ifp->vif))
                        clear_bit(BRCMF_VIF_STATUS_CONNECTING,
 
        case BRCMF_E_IF_DEL:
                ifp->vif = NULL;
-               brcmf_free_vif(vif);
                mutex_unlock(&event->vif_event_lock);
                /* event may not be upon user request */
                if (brcmf_cfg80211_vif_event_armed(cfg))
        mutex_init(&cfg->usr_sync);
        brcmf_init_escan(cfg);
        brcmf_init_conf(cfg->conf);
-
+       init_completion(&cfg->vif_disabled);
        return err;
 }