From d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d Mon Sep 17 00:00:00 2001
From: hc <hc@nodka.com>
Date: Mon, 11 Dec 2023 02:45:28 +0000
Subject: [PATCH] add boot partition  size

---
 kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c |  891 +++++++++++++++++++++++++++++++++++++----------------------
 1 files changed, 555 insertions(+), 336 deletions(-)

diff --git a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
index b5aac14..7b5c8b8 100644
--- a/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
+++ b/kernel/drivers/net/wireless/rockchip_wlan/cywdhd/bcmdhd/wl_cfgp2p.c
@@ -1,15 +1,16 @@
-/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Linux cfgp2p driver
  *
- * Copyright (C) 1999-2019, Broadcom Corporation
- * 
+ * Portions of this code are copyright (c) 2022 Cypress Semiconductor Corporation
+ *
+ * Copyright (C) 1999-2017, Broadcom Corporation
+ *
  *      Unless you and Broadcom execute a separate written software license
  * agreement governing use of this software, this software is licensed to you
  * under the terms of the GNU General Public License version 2 (the "GPL"),
  * available at http://www.broadcom.com/licenses/GPLv2.php, with the
  * following added to such license:
- * 
+ *
  *      As a special exception, the copyright holders of this software give you
  * permission to link this software with independent modules, and to copy and
  * distribute the resulting executable under terms of your choice, provided that
@@ -17,7 +18,7 @@
  * the license of that module.  An independent module is a module which is not
  * derived from this software.  The special exception does not apply to any
  * modifications of the software.
- * 
+ *
  *      Notwithstanding the above, under no circumstances may you combine this
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
@@ -25,7 +26,7 @@
  *
  * <<Broadcom-WL-IPTag/Open:>>
  *
- * $Id: wl_cfgp2p.c 709309 2019-01-17 09:04:00Z $
+ * $Id: wl_cfgp2p.c 815562 2019-04-18 02:33:27Z $
  *
  */
 #include <typedefs.h>
@@ -39,28 +40,33 @@
 #include <linux/string.h>
 #include <linux/timer.h>
 #include <linux/if_arp.h>
-#include <linux/uaccess.h>
+#include <asm/uaccess.h>
 
 #include <bcmutils.h>
+#include <bcmstdlib_s.h>
 #include <bcmendian.h>
-#include <proto/ethernet.h>
-#include <proto/802.11.h>
+#include <ethernet.h>
+#include <802.11.h>
 #include <net/rtnetlink.h>
 
 #include <wl_cfg80211.h>
 #include <wl_cfgp2p.h>
+#include <wl_cfgscan.h>
 #include <wldev_common.h>
+#ifdef OEM_ANDROID
 #include <wl_android.h>
+#endif // endif
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhd_linux.h>
 #include <dhdioctl.h>
 #include <wlioctl.h>
 #include <dhd_cfg80211.h>
+#include <dhd_bus.h>
 
 static s8 scanparambuf[WLC_IOCTL_SMLEN];
-static bool
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
+static bool wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
+                             const u8 *oui, u32 oui_len, u8 type);
 
 static s32 wl_cfgp2p_cancel_listen(struct bcm_cfg80211 *cfg, struct net_device *ndev,
 	struct wireless_dev *wdev, bool notify);
@@ -79,6 +85,22 @@
 };
 #endif /* WL_ENABLE_P2P_IF */
 
+#if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
+static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+static int wl_cfgp2p_do_ioctl(struct net_device *net, struct ifreq *ifr, int cmd);
+
+static int wl_cfgp2p_if_dummy(struct net_device *net)
+{
+	return 0;
+}
+
+static const struct net_device_ops wl_cfgp2p_if_ops = {
+	.ndo_open       = wl_cfgp2p_if_dummy,
+	.ndo_stop       = wl_cfgp2p_if_dummy,
+	.ndo_do_ioctl   = wl_cfgp2p_do_ioctl,
+	.ndo_start_xmit = wl_cfgp2p_start_xmit,
+};
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 
 bool wl_cfgp2p_is_pub_action(void *frame, u32 frame_len)
 {
@@ -126,17 +148,17 @@
 
 bool wl_cfgp2p_find_gas_subtype(u8 subtype, u8* data, u32 len)
 {
-	bcm_tlv_t *ie = (bcm_tlv_t *)data;
-	u8 *frame = NULL;
+	const bcm_tlv_t *ie = (bcm_tlv_t *)data;
+	const u8 *frame = NULL;
 	u16 id, flen;
 
 	/* Skipped first ANQP Element, if frame has anqp elemnt */
-	ie = bcm_parse_tlvs(ie, (int)len, DOT11_MNG_ADVERTISEMENT_ID);
+	ie = bcm_parse_tlvs(ie, len, DOT11_MNG_ADVERTISEMENT_ID);
 
 	if (ie == NULL)
 		return false;
 
-	frame = (uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
+	frame = (const uint8 *)ie + ie->len + TLV_HDR_LEN + GAS_RESP_LEN;
 	id = ((u16) (((frame)[1] << 8) | (frame)[0]));
 	flen = ((u16) (((frame)[3] << 8) | (frame)[2]));
 
@@ -314,7 +336,6 @@
 					" channel=%d\n", (tx)? "TX" : "RX", channel));
 		}
 
-
 	}
 }
 
@@ -325,7 +346,8 @@
 s32
 wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
 {
-	if (!(cfg->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
+	cfg->p2p = MALLOCZ(cfg->osh, sizeof(struct p2p_info));
+	if (cfg->p2p == NULL) {
 		CFGP2P_ERR(("struct p2p_info allocation failed\n"));
 		return -ENOMEM;
 	}
@@ -338,9 +360,6 @@
 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION1) = -1;
 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_CONNECTION2) = NULL;
 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_CONNECTION2) = -1;
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
-	cfg->p2p->cfg = cfg;
-#endif
 	return BCME_OK;
 
 }
@@ -351,9 +370,9 @@
 void
 wl_cfgp2p_deinit_priv(struct bcm_cfg80211 *cfg)
 {
-	CFGP2P_ERR(("In\n"));
+	CFGP2P_INFO(("In\n"));
 	if (cfg->p2p) {
-		kfree(cfg->p2p);
+		MFREE(cfg->osh, cfg->p2p, sizeof(struct p2p_info));
 		cfg->p2p = NULL;
 	}
 	cfg->p2p_supported = 0;
@@ -376,7 +395,7 @@
 	}
 	if (val == 0) {
 		val = 1;
-		ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true);
+		ret = wldev_ioctl_set(ndev, WLC_DOWN, &val, sizeof(s32));
 		if (ret < 0) {
 			CFGP2P_ERR(("WLC_DOWN error %d\n", ret));
 			return ret;
@@ -389,7 +408,7 @@
 			return ret;
 		}
 
-		ret = wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), true);
+		ret = wldev_ioctl_set(ndev, WLC_UP, &val, sizeof(s32));
 		if (ret < 0) {
 			CFGP2P_ERR(("WLC_UP error %d\n", ret));
 			return ret;
@@ -435,27 +454,22 @@
 {
 	wl_p2p_if_t ifreq;
 	s32 err;
-	u32 scb_timeout = WL_SCB_TIMEOUT;
 	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
 
 	ifreq.type = if_type;
 	ifreq.chspec = chspec;
 	memcpy(ifreq.addr.octet, mac->octet, sizeof(ifreq.addr.octet));
 
-	CFGP2P_DBG(("---cfg p2p_ifadd "MACDBG" %s %u\n",
+	CFGP2P_ERR(("---cfg p2p_ifadd "MACDBG" %s %u\n",
 		MAC2STRDBG(ifreq.addr.octet),
 		(if_type == WL_P2P_IF_GO) ? "go" : "client",
 	        (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
 
 	err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
-	if (unlikely(err < 0))
+	if (unlikely(err < 0)) {
 		printk("'cfg p2p_ifadd' error %d\n", err);
-	else if (if_type == WL_P2P_IF_GO) {
-		err = wldev_ioctl(ndev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
-		if (unlikely(err < 0))
-			printk("'cfg scb_timeout' error %d\n", err);
+		return err;
 	}
 
 	return err;
@@ -472,8 +486,8 @@
 	s32 ret;
 	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
 
-	CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdis "MACDBG"\n",
-		netdev->ifindex, MAC2STRDBG(mac->octet)));
+	CFGP2P_INFO(("------ cfg p2p_ifdis "MACDBG" dev->ifindex:%d \n",
+		MAC2STRDBG(mac->octet), netdev->ifindex));
 	ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
 	if (unlikely(ret < 0)) {
@@ -491,15 +505,31 @@
 wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
 {
 	s32 ret;
+#ifdef WL_DISABLE_HE_P2P
+	s32 bssidx = 0;
+#endif /* WL_DISABLE_HE_P2P */
 	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
 
-	CFGP2P_INFO(("------primary idx %d : cfg p2p_ifdel "MACDBG"\n",
-	    netdev->ifindex, MAC2STRDBG(mac->octet)));
+	CFGP2P_ERR(("------ cfg p2p_ifdel "MACDBG" dev->ifindex:%d\n",
+	    MAC2STRDBG(mac->octet), netdev->ifindex));
 	ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
 	if (unlikely(ret < 0)) {
 		printk("'cfg p2p_ifdel' error %d\n", ret);
 	}
+#ifdef WL_DISABLE_HE_P2P
+	if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) {
+		WL_ERR(("Find index failed\n"));
+		ret = BCME_ERROR;
+		return ret;
+	}
+	WL_DBG(("Enabling back HE for P2P\n"));
+	wl_cfg80211_set_he_mode(netdev, cfg, bssidx, WL_IF_TYPE_P2P_DISC, TRUE);
+	if (ret < 0) {
+		WL_ERR(("failed to set he features, error=%d\n", ret));
+	}
+#endif /* WL_DISABLE_HE_P2P */
+
 	return ret;
 }
 
@@ -514,7 +544,6 @@
 {
 	wl_p2p_if_t ifreq;
 	s32 err;
-	u32 scb_timeout = WL_SCB_TIMEOUT;
 
 	struct net_device *netdev =  wl_to_p2p_bss_ndev(cfg, conn_idx);
 
@@ -530,18 +559,13 @@
 
 	err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
 	if (unlikely(err < 0)) {
 		printk("'cfg p2p_ifupd' error %d\n", err);
 	} else if (if_type == WL_P2P_IF_GO) {
 		cfg->p2p->p2p_go_count++;
-		err = wldev_ioctl(netdev, WLC_SET_SCB_TIMEOUT, &scb_timeout, sizeof(u32), true);
-		if (unlikely(err < 0))
-			printk("'cfg scb_timeout' error %d\n", err);
 	}
 	return err;
 }
-
 
 /* Get the index of a created P2P BSS.
  * Parameters:
@@ -563,7 +587,7 @@
 
 	if (ret == 0) {
 		memcpy(index, getbuf, sizeof(s32));
-		CFGP2P_INFO(("---cfg p2p_if   ==> %d\n", *index));
+		CFGP2P_DBG(("---cfg p2p_if   ==> %d\n", *index));
 	}
 
 	return ret;
@@ -635,7 +659,7 @@
 
 	/* Put the WL driver into P2P Listen Mode to respond to P2P probe reqs */
 	discovery_mode.state = mode;
-	discovery_mode.chspec = wl_ch_host_to_driver(bssidx, channel);
+	discovery_mode.chspec = wl_ch_host_to_driver(channel);
 	discovery_mode.dwell = listen_ms;
 	ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
 		sizeof(discovery_mode), cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
@@ -675,7 +699,7 @@
 					CFGP2P_ERR(("Multi p2p not supported"));
 					return BCME_ERROR;
 				}
-				if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 1) {
+				if ((connected_cnt = wl_get_drv_status_all(cfg, CONNECTED)) > 2) {
 					CFGP2P_ERR(("Failed to create second p2p interface"
 						"Already one connection exists"));
 					return BCME_ERROR;
@@ -693,33 +717,42 @@
 
 	s32 bssidx = 0;
 	s32 ret = BCME_OK;
+	struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
 
+	BCM_REFERENCE(ndev);
 	CFGP2P_DBG(("enter\n"));
 
 	if (wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) > 0) {
 		CFGP2P_ERR(("do nothing, already initialized\n"));
-		return ret;
+		goto exit;
 	}
 
 	ret = wl_cfgp2p_set_discovery(cfg, 1);
 	if (ret < 0) {
 		CFGP2P_ERR(("set discover error\n"));
-		return ret;
+		goto exit;
 	}
 	/* Enable P2P Discovery in the WL Driver */
 	ret = wl_cfgp2p_get_disc_idx(cfg, &bssidx);
-
 	if (ret < 0) {
-		return ret;
+		goto exit;
 	}
+
 	/* In case of CFG80211 case, check if p2p_discovery interface has allocated p2p_wdev */
 	if (!cfg->p2p_wdev) {
 		CFGP2P_ERR(("p2p_wdev is NULL.\n"));
-		return BCME_NODEVICE;
+		ret = -ENODEV;
+		goto exit;
 	}
-	/* Make an entry in the netinfo */
-	wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_MODE_BSS, 0, bssidx);
 
+	/* Once p2p also starts using interface_create iovar, the ifidx may change.
+	 * so that time, the ifidx returned in WLC_E_IF should be used for populating
+	 * the netinfo
+	 */
+	ret = wl_alloc_netinfo(cfg, NULL, cfg->p2p_wdev, WL_IF_TYPE_STA, 0, bssidx, 0);
+	if (unlikely(ret)) {
+		goto exit;
+	}
 	wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) =
 	    wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
 	wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = bssidx;
@@ -733,7 +766,15 @@
 		wl_cfgp2p_set_discovery(cfg, 0);
 		wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE) = 0;
 		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
-		return 0;
+		ret = 0;
+		goto exit;
+	}
+
+	/* Clear our saved WPS and P2P IEs for the discovery BSS */
+	wl_cfg80211_clear_p2p_disc_ies(cfg);
+exit:
+	if (ret) {
+		wl_flush_fw_log_buffer(ndev, FW_LOGSET_MASK_ALL);
 	}
 	return ret;
 }
@@ -757,7 +798,7 @@
 	}
 
 	/* Clear our saved WPS and P2P IEs for the discovery BSS */
-	wl_cfg80211_clear_per_bss_ies(cfg, bssidx);
+	wl_cfg80211_clear_p2p_disc_ies(cfg);
 
 	/* Set the discovery state to SCAN */
 	wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
@@ -787,10 +828,19 @@
 {
 	s32 ret = BCME_OK;
 	s32 bssidx;
+	bcm_struct_cfgdev *cfgdev;
 
 	CFGP2P_DBG(("enter\n"));
+	mutex_lock(&cfg->if_sync);
+#ifdef WL_IFACE_MGMT
+	if ((ret = wl_cfg80211_handle_if_role_conflict(cfg, WL_IF_TYPE_P2P_DISC)) != BCME_OK) {
+		WL_ERR(("secondary iface is active, p2p enable discovery is not supported\n"));
+		goto exit;
+	}
+#endif /* WL_IFACE_MGMT */
+
 	if (wl_get_p2p_status(cfg, DISCOVERY_ON)) {
-		CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n"));
+		CFGP2P_DBG((" DISCOVERY is already initialized, we have nothing to do\n"));
 		goto set_ie;
 	}
 
@@ -817,19 +867,29 @@
 			bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
 		} else if ((bssidx = wl_get_bssidx_by_wdev(cfg, cfg->p2p_wdev)) < 0) {
 			WL_ERR(("Find p2p index from wdev(%p) failed\n", cfg->p2p_wdev));
-			return BCME_ERROR;
+			ret = BCME_ERROR;
+			goto exit;
 		}
 
-		ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, ndev_to_cfgdev(dev),
-			bssidx,
-			VNDR_IE_PRBREQ_FLAG, ie, ie_len);
-
+#if defined(WL_CFG80211_P2P_DEV_IF)
+		/* For 3.8+ kernels, pass p2p discovery wdev */
+		cfgdev = cfg->p2p_wdev;
+#else
+		/* Prior to 3.8 kernel, there is no netless p2p, so pass p2p0 ndev */
+		cfgdev = ndev_to_cfgdev(dev);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+		ret = wl_cfg80211_set_mgmt_vndr_ies(cfg, cfgdev,
+				bssidx, VNDR_IE_PRBREQ_FLAG, ie, ie_len);
 		if (unlikely(ret < 0)) {
 			CFGP2P_ERR(("set probreq ie occurs error %d\n", ret));
 			goto exit;
 		}
 	}
 exit:
+	if (ret) {
+		wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
+	}
+	mutex_unlock(&cfg->if_sync);
 	return ret;
 }
 
@@ -843,24 +903,21 @@
 {
 	s32 ret = BCME_OK;
 	s32 bssidx;
+
 	CFGP2P_DBG((" enter\n"));
 	wl_clr_p2p_status(cfg, DISCOVERY_ON);
-
 #ifdef DHD_IFDEBUG
-	WL_ERR(("%s: (cfg)->p2p->bss[type].bssidx: %d\n",
+	WL_ERR(("%s: bssidx: %d\n",
 		__FUNCTION__, (cfg)->p2p->bss[P2PAPI_BSSCFG_DEVICE].bssidx));
-#endif
+#endif // endif
 	bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
 	if (bssidx <= 0) {
 		CFGP2P_ERR((" do nothing, not initialized\n"));
 		return 0;
 	}
 
-	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0,
-	            bssidx);
-
+	ret = wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
 	if (unlikely(ret < 0)) {
-
 		CFGP2P_ERR(("unable to set WL_P2P_DISC_ST_SCAN\n"));
 	}
 	/* Do a scan abort to stop the driver's scan engine in case it is still
@@ -871,8 +928,15 @@
 	return ret;
 }
 
+/* Scan parameters */
+#define P2PAPI_SCAN_NPROBES 1
+#define P2PAPI_SCAN_DWELL_TIME_MS 80
+#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
+#define P2PAPI_SCAN_HOME_TIME_MS 60
+#define P2PAPI_SCAN_NPROBS_TIME_MS 30
+#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
 s32
-wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active,
+wl_cfgp2p_escan(struct bcm_cfg80211 *cfg, struct net_device *dev, u16 active_scan,
 	u32 num_chans, u16 *channels,
 	s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr,
 	p2p_scan_purpose_t p2p_scan_purpose)
@@ -884,20 +948,26 @@
 	s8 *memblk;
 	wl_p2p_scan_t *p2p_params;
 	wl_escan_params_t *eparams;
+	wl_escan_params_v2_t *eparams_v2;
 	wlc_ssid_t ssid;
-	/* Scan parameters */
-#define P2PAPI_SCAN_NPROBES 1
-#define P2PAPI_SCAN_DWELL_TIME_MS 80
-#define P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS 40
-#define P2PAPI_SCAN_HOME_TIME_MS 60
-#define P2PAPI_SCAN_NPROBS_TIME_MS 30
-#define P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS 100
+	u32 sync_id = 0;
+	s32 nprobes = 0;
+	s32 active_time = 0;
+	const struct ether_addr *mac_addr = NULL;
+	u32 scan_type = 0;
+	struct net_device *pri_dev = NULL;
 
-	struct net_device *pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
+	pri_dev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY);
 	/* Allocate scan params which need space for 3 channels and 0 ssids */
-	eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
-	    OFFSETOF(wl_escan_params_t, params)) +
-		num_chans * sizeof(eparams->params.channel_list[0]);
+	if (cfg->scan_params_v2) {
+		eparams_size = (WL_SCAN_PARAMS_V2_FIXED_SIZE +
+			OFFSETOF(wl_escan_params_v2_t, params)) +
+			num_chans * sizeof(eparams->params.channel_list[0]);
+	} else {
+		eparams_size = (WL_SCAN_PARAMS_FIXED_SIZE +
+			OFFSETOF(wl_escan_params_t, params)) +
+			num_chans * sizeof(eparams->params.channel_list[0]);
+	}
 
 	memsize = sizeof(wl_p2p_scan_t) + eparams_size;
 	memblk = scanparambuf;
@@ -906,8 +976,8 @@
 		    memsize, sizeof(scanparambuf)));
 		return -1;
 	}
-	memset(memblk, 0, memsize);
-	memset(cfg->ioctl_buf, 0, WLC_IOCTL_MAXLEN);
+	bzero(memblk, memsize);
+	bzero(cfg->ioctl_buf, WLC_IOCTL_MAXLEN);
 	if (search_state == WL_P2P_DISC_ST_SEARCH) {
 		/*
 		 * If we in SEARCH STATE, we don't need to set SSID explictly
@@ -916,7 +986,7 @@
 		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx);
 		/* use null ssid */
 		ssid.SSID_len = 0;
-		memset(&ssid.SSID, 0, sizeof(ssid.SSID));
+		bzero(&ssid.SSID, sizeof(ssid.SSID));
 	} else if (search_state == WL_P2P_DISC_ST_SCAN) {
 		/* SCAN STATE 802.11 SCAN
 		 * WFD Supplicant has p2p_find command with (type=progressive, type= full)
@@ -927,91 +997,122 @@
 		wl_cfgp2p_set_p2p_mode(cfg, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx);
 		/* use wild card ssid */
 		ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN;
-		memset(&ssid.SSID, 0, sizeof(ssid.SSID));
+		bzero(&ssid.SSID, sizeof(ssid.SSID));
 		memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN);
 	} else {
 		CFGP2P_ERR((" invalid search state %d\n", search_state));
 		return -1;
 	}
 
-
 	/* Fill in the P2P scan structure at the start of the iovar param block */
 	p2p_params = (wl_p2p_scan_t*) memblk;
 	p2p_params->type = 'E';
-	/* Fill in the Scan structure that follows the P2P scan structure */
-	eparams = (wl_escan_params_t*) (p2p_params + 1);
-	eparams->params.bss_type = DOT11_BSSTYPE_ANY;
-	if (active)
-		eparams->params.scan_type = DOT11_SCANTYPE_ACTIVE;
-	else
-		eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE;
 
-	if (tx_dst_addr == NULL)
-		memcpy(&eparams->params.bssid, &ether_bcast, ETHER_ADDR_LEN);
-	else
-		memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN);
+	if (!active_scan) {
+		scan_type = WL_SCANFLAGS_PASSIVE;
+	}
 
-	if (ssid.SSID_len)
-		memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t));
-
-	eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+	if (tx_dst_addr == NULL) {
+		mac_addr = &ether_bcast;
+	} else {
+		mac_addr = tx_dst_addr;
+	}
 
 	switch (p2p_scan_purpose) {
 		case P2P_SCAN_SOCIAL_CHANNEL:
-		eparams->params.active_time = htod32(P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS);
+			active_time = P2PAPI_SCAN_SOCIAL_DWELL_TIME_MS;
 			break;
 		case P2P_SCAN_AFX_PEER_NORMAL:
 		case P2P_SCAN_AFX_PEER_REDUCED:
-		eparams->params.active_time = htod32(P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS);
+			active_time = P2PAPI_SCAN_AF_SEARCH_DWELL_TIME_MS;
 			break;
 		case P2P_SCAN_CONNECT_TRY:
-			eparams->params.active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS);
+			active_time = WL_SCAN_CONNECT_DWELL_TIME_MS;
 			break;
-		default :
-			if (wl_get_drv_status_all(cfg, CONNECTED))
-		eparams->params.active_time = -1;
-	else
-		eparams->params.active_time = htod32(P2PAPI_SCAN_DWELL_TIME_MS);
+		default:
+			active_time = wl_get_drv_status_all(cfg, CONNECTED) ?
+				-1 : P2PAPI_SCAN_DWELL_TIME_MS;
 			break;
 	}
 
-	if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY)
-		eparams->params.nprobes = htod32(eparams->params.active_time /
-			WL_SCAN_JOIN_PROBE_INTERVAL_MS);
-	else
-	eparams->params.nprobes = htod32((eparams->params.active_time /
-		P2PAPI_SCAN_NPROBS_TIME_MS));
-
-
-	if (eparams->params.nprobes <= 0)
-		eparams->params.nprobes = 1;
-	CFGP2P_DBG(("nprobes # %d, active_time %d\n",
-		eparams->params.nprobes, eparams->params.active_time));
-	eparams->params.passive_time = htod32(-1);
-	eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
-	    (num_chans & WL_SCAN_PARAMS_COUNT_MASK));
-
-	for (i = 0; i < num_chans; i++) {
-		eparams->params.channel_list[i] = wl_ch_host_to_driver(bssidx, channels[i]);
+	if (p2p_scan_purpose == P2P_SCAN_CONNECT_TRY) {
+		nprobes = active_time /
+			WL_SCAN_JOIN_PROBE_INTERVAL_MS;
+	} else {
+		nprobes = active_time /
+			P2PAPI_SCAN_NPROBS_TIME_MS;
 	}
-	eparams->version = htod32(ESCAN_REQ_VERSION);
-	eparams->action =  htod16(action);
-	wl_escan_set_sync_id(eparams->sync_id, cfg);
+
+	if (nprobes <= 0) {
+		nprobes = 1;
+	}
+
+	wl_escan_set_sync_id(sync_id, cfg);
+	/* Fill in the Scan structure that follows the P2P scan structure */
+	if (cfg->scan_params_v2) {
+		eparams_v2 = (wl_escan_params_v2_t*) (p2p_params + 1);
+		eparams_v2->version = htod16(ESCAN_REQ_VERSION_V2);
+		eparams_v2->action =  htod16(action);
+		eparams_v2->params.version = htod16(WL_SCAN_PARAMS_VERSION_V2);
+		eparams_v2->params.length = htod16(sizeof(wl_scan_params_v2_t));
+		eparams_v2->params.bss_type = DOT11_BSSTYPE_ANY;
+		eparams_v2->params.scan_type = htod32(scan_type);
+		(void)memcpy_s(&eparams_v2->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
+		eparams_v2->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+		eparams_v2->params.active_time = htod32(active_time);
+		eparams_v2->params.nprobes = htod32(nprobes);
+		eparams_v2->params.passive_time = htod32(-1);
+		eparams_v2->sync_id = sync_id;
+		for (i = 0; i < num_chans; i++) {
+			eparams_v2->params.channel_list[i] =
+				wl_ch_host_to_driver(channels[i]);
+		}
+		eparams_v2->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
+			(num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+		if (ssid.SSID_len)
+			(void)memcpy_s(&eparams_v2->params.ssid,
+					sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
+		sync_id = eparams_v2->sync_id;
+	} else {
+		eparams = (wl_escan_params_t*) (p2p_params + 1);
+		eparams->version = htod32(ESCAN_REQ_VERSION);
+		eparams->action =  htod16(action);
+		eparams->params.bss_type = DOT11_BSSTYPE_ANY;
+		eparams->params.scan_type = htod32(scan_type);
+		(void)memcpy_s(&eparams->params.bssid, ETHER_ADDR_LEN, mac_addr, ETHER_ADDR_LEN);
+		eparams->params.home_time = htod32(P2PAPI_SCAN_HOME_TIME_MS);
+		eparams->params.active_time = htod32(active_time);
+		eparams->params.nprobes = htod32(nprobes);
+		eparams->params.passive_time = htod32(-1);
+		eparams->sync_id = sync_id;
+		for (i = 0; i < num_chans; i++) {
+			eparams->params.channel_list[i] =
+				wl_ch_host_to_driver(channels[i]);
+		}
+		eparams->params.channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
+			(num_chans & WL_SCAN_PARAMS_COUNT_MASK));
+		if (ssid.SSID_len)
+			(void)memcpy_s(&eparams->params.ssid,
+					sizeof(wlc_ssid_t), &ssid, sizeof(wlc_ssid_t));
+		sync_id = eparams->sync_id;
+	}
+
 	wl_escan_set_type(cfg, WL_SCANTYPE_P2P);
-	CFGP2P_INFO(("SCAN CHANNELS : "));
 
-	for (i = 0; i < num_chans; i++) {
-		if (i == 0) CFGP2P_INFO(("%d", channels[i]));
-		else CFGP2P_INFO((",%d", channels[i]));
+	CFGP2P_DBG(("nprobes:%d active_time:%d\n", nprobes, active_time));
+	CFGP2P_DBG(("SCAN CHANNELS : "));
+	CFGP2P_DBG(("%d", channels[0]));
+	for (i = 1; i < num_chans; i++) {
+		CFGP2P_DBG((",%d", channels[i]));
 	}
-
-	CFGP2P_INFO(("\n"));
+	CFGP2P_DBG(("\n"));
 
 	ret = wldev_iovar_setbuf_bsscfg(pri_dev, "p2p_scan",
 		memblk, memsize, cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
-	WL_ERR(("P2P_SEARCH sync ID: %d, bssidx: %d\n", eparams->sync_id, bssidx));
-	if (ret == BCME_OK)
+	WL_INFORM(("P2P_SEARCH sync ID: %d, bssidx: %d\n", sync_id, bssidx));
+	if (ret == BCME_OK) {
 		wl_set_p2p_status(cfg, SCANNING);
+	}
 	return ret;
 }
 
@@ -1039,7 +1140,17 @@
 		chan_cnt = AF_PEER_SEARCH_CNT;
 	else
 		chan_cnt = SOCIAL_CHAN_CNT;
-	default_chan_list = kzalloc(chan_cnt * sizeof(*default_chan_list), GFP_KERNEL);
+
+	if (cfg->afx_hdl->pending_tx_act_frm && cfg->afx_hdl->is_active) {
+		wl_action_frame_t *action_frame;
+		action_frame = &(cfg->afx_hdl->pending_tx_act_frm->action_frame);
+		if (wl_cfgp2p_is_p2p_gas_action(action_frame->data, action_frame->len))	{
+			chan_cnt = 1;
+			p2p_scan_purpose = P2P_SCAN_AFX_PEER_REDUCED;
+		}
+	}
+
+	default_chan_list = (u16 *)MALLOCZ(cfg->osh, chan_cnt * sizeof(*default_chan_list));
 	if (default_chan_list == NULL) {
 		CFGP2P_ERR(("channel list allocation failed \n"));
 		ret = -ENOMEM;
@@ -1059,7 +1170,7 @@
 	ret = wl_cfgp2p_escan(cfg, ndev, true, chan_cnt,
 		default_chan_list, WL_P2P_DISC_ST_SEARCH,
 		WL_SCAN_ACTION_START, bssidx, NULL, p2p_scan_purpose);
-	kfree(default_chan_list);
+	MFREE(cfg->osh, default_chan_list, chan_cnt * sizeof(*default_chan_list));
 exit:
 	return ret;
 }
@@ -1076,90 +1187,87 @@
 /* Check whether the given IE looks like WFA WFDisplay IE. */
 #ifndef WFA_OUI_TYPE_WFD
 #define WFA_OUI_TYPE_WFD	0x0a			/* WiFi Display OUI TYPE */
-#endif
+#endif // endif
 #define wl_cfgp2p_is_wfd_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
 		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD)
-
 
 /* Is any of the tlvs the expected entry? If
  * not update the tlvs buffer pointer/length.
  */
 static bool
-wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type)
+wl_cfgp2p_has_ie(const bcm_tlv_t *ie, const u8 **tlvs, u32 *tlvs_len,
+                 const u8 *oui, u32 oui_len, u8 type)
 {
 	/* If the contents match the OUI and the type */
-	if (ie[TLV_LEN_OFF] >= oui_len + 1 &&
-		!bcmp(&ie[TLV_BODY_OFF], oui, oui_len) &&
-		type == ie[TLV_BODY_OFF + oui_len]) {
+	if (ie->len >= oui_len + 1 &&
+	    !bcmp(ie->data, oui, oui_len) &&
+	    type == ie->data[oui_len]) {
 		return TRUE;
 	}
 
-	if (tlvs == NULL)
-		return FALSE;
 	/* point to the next ie */
-	ie += ie[TLV_LEN_OFF] + TLV_HDR_LEN;
-	/* calculate the length of the rest of the buffer */
-	*tlvs_len -= (int)(ie - *tlvs);
-	/* update the pointer to the start of the buffer */
-	*tlvs = ie;
+	if (tlvs != NULL) {
+		bcm_tlv_buffer_advance_past(ie, tlvs, tlvs_len);
+	}
 
 	return FALSE;
 }
 
-wpa_ie_fixed_t *
-wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
+const wpa_ie_fixed_t *
+wl_cfgp2p_find_wpaie(const u8 *parse, u32 len)
 {
-	bcm_tlv_t *ie;
+	const bcm_tlv_t *ie;
 
-	while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_wpa_ie((u8*)ie, &parse, &len)) {
-			return (wpa_ie_fixed_t *)ie;
+	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+		if (wl_cfgp2p_is_wpa_ie(ie, &parse, &len)) {
+			return (const wpa_ie_fixed_t *)ie;
 		}
 	}
 	return NULL;
 }
 
-wpa_ie_fixed_t *
-wl_cfgp2p_find_wpsie(u8 *parse, u32 len)
+const wpa_ie_fixed_t *
+wl_cfgp2p_find_wpsie(const u8 *parse, u32 len)
 {
-	bcm_tlv_t *ie;
+	const bcm_tlv_t *ie;
 
-	while ((ie = bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_wps_ie((u8*)ie, &parse, &len)) {
-			return (wpa_ie_fixed_t *)ie;
+	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+		if (wl_cfgp2p_is_wps_ie(ie, &parse, &len)) {
+			return (const wpa_ie_fixed_t *)ie;
 		}
 	}
 	return NULL;
 }
 
 wifi_p2p_ie_t *
-wl_cfgp2p_find_p2pie(u8 *parse, u32 len)
+wl_cfgp2p_find_p2pie(const u8 *parse, u32 len)
 {
 	bcm_tlv_t *ie;
 
-	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len)) {
+	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+		if (wl_cfgp2p_is_p2p_ie(ie, &parse, &len)) {
 			return (wifi_p2p_ie_t *)ie;
 		}
 	}
 	return NULL;
 }
 
-wifi_wfd_ie_t *
-wl_cfgp2p_find_wfdie(u8 *parse, u32 len)
+const wifi_wfd_ie_t *
+wl_cfgp2p_find_wfdie(const u8 *parse, u32 len)
 {
-	bcm_tlv_t *ie;
+	const bcm_tlv_t *ie;
 
-	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_wfd_ie((uint8*)ie, &parse, &len)) {
-			return (wifi_wfd_ie_t *)ie;
+	while ((ie = bcm_parse_tlvs(parse, len, DOT11_MNG_VS_ID))) {
+		if (wl_cfgp2p_is_wfd_ie(ie, &parse, &len)) {
+			return (const wifi_wfd_ie_t *)ie;
 		}
 	}
 	return NULL;
 }
+
 u32
 wl_cfgp2p_vndr_ie(struct bcm_cfg80211 *cfg, u8 *iebuf, s32 pktflag,
-            s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd)
+            s8 *oui, s32 ie_id, const s8 *data, s32 datalen, const s8* add_del_cmd)
 {
 	vndr_ie_setbuf_t hdr;	/* aligned temporary vndr_ie buffer header */
 	s32 iecount;
@@ -1168,18 +1276,23 @@
 	/* Validate the pktflag parameter */
 	if ((pktflag & ~(VNDR_IE_BEACON_FLAG | VNDR_IE_PRBRSP_FLAG |
 	            VNDR_IE_ASSOCRSP_FLAG | VNDR_IE_AUTHRSP_FLAG |
-	            VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG))) {
+	            VNDR_IE_PRBREQ_FLAG | VNDR_IE_ASSOCREQ_FLAG |
+	            VNDR_IE_DISASSOC_FLAG))) {
 		CFGP2P_ERR(("p2pwl_vndr_ie: Invalid packet flag 0x%x\n", pktflag));
 		return -1;
 	}
 
 	/* Copy the vndr_ie SET command ("add"/"del") to the buffer */
-	strncpy(hdr.cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
-	hdr.cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+	strlcpy(hdr.cmd, add_del_cmd, sizeof(hdr.cmd));
 
 	/* Set the IE count - the buffer contains only 1 IE */
 	iecount = htod32(1);
 	memcpy((void *)&hdr.vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+	/* For vendor ID DOT11_MNG_ID_EXT_ID, need to set pkt flag to VNDR_IE_CUSTOM_FLAG */
+	if (ie_id == DOT11_MNG_ID_EXT_ID) {
+		pktflag = pktflag | VNDR_IE_CUSTOM_FLAG;
+	}
 
 	/* Copy packet flags that indicate which packets will contain this IE */
 	pktflag = htod32(pktflag);
@@ -1249,7 +1362,10 @@
 		CFGP2P_ERR((" argument is invalid\n"));
 		goto exit;
 	}
-
+	if (!cfg->p2p) {
+		CFGP2P_ERR(("p2p if does not exist\n"));
+		goto exit;
+	}
 	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
 		if (bssidx == wl_to_p2p_bss_bssidx(cfg, i)) {
 			*type = i;
@@ -1276,10 +1392,31 @@
 
 	CFGP2P_DBG((" Enter\n"));
 #ifdef DHD_IFDEBUG
-	WL_ERR(("%s: cfg: %p, cfgdev: %p, cfg->wdev: %p, cfg->p2p_wdev: %p\n",
-		__FUNCTION__, cfg, cfgdev, cfg->wdev, cfg->p2p_wdev));
-#endif
+	PRINT_WDEV_INFO(cfgdev);
+#endif /* DHD_IFDEBUG */
+
 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+
+#ifdef P2P_LISTEN_OFFLOADING
+	if (wl_get_p2p_status(cfg, DISC_IN_PROGRESS)) {
+		wl_clr_p2p_status(cfg, DISC_IN_PROGRESS);
+		CFGP2P_ERR(("DISC_IN_PROGRESS cleared\n"));
+		if (ndev && (ndev->ieee80211_ptr != NULL)) {
+#if defined(WL_CFG80211_P2P_DEV_IF)
+			if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
+				cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
+						&cfg->remain_on_chan, GFP_KERNEL);
+			} else {
+				CFGP2P_ERR(("Invalid cfgdev. Dropping the"
+						"remain_on_channel_expired event.\n"));
+			}
+#else
+			cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
+					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
+#endif /* WL_CFG80211_P2P_DEV_IF */
+		}
+	}
+#endif /* P2P_LISTEN_OFFLOADING */
 
 	if (wl_get_p2p_status(cfg, LISTEN_EXPIRED) == 0) {
 		wl_set_p2p_status(cfg, LISTEN_EXPIRED);
@@ -1318,20 +1455,36 @@
 #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
 			if (ndev && (ndev->ieee80211_ptr != NULL)) {
 #if defined(WL_CFG80211_P2P_DEV_IF)
-				if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy) {
+				if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy &&
+				    bcmcfg_to_p2p_wdev(cfg)) {
 					/*
 					 * To prevent kernel panic,
 					 * if cfgdev->wiphy may be invalid, adding explicit check
 					 */
-					cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
-						&cfg->remain_on_chan, GFP_KERNEL);
-				} else {
+					struct wireless_dev *wdev_dpp_listen = NULL;
+					wdev_dpp_listen = wl_get_wdev_by_dpp_listen(cfg);
+					/*
+					 * check if dpp listen was trigerred
+					 * if so, clear dpp disten flag and route the event for listen
+					 * complete on the interface on which listen was reqeusted.
+					 */
+					if (wdev_dpp_listen) {
+						wl_set_dpp_listen_by_netdev(cfg, wdev_dpp_listen->netdev, 0);
+						cfg80211_remain_on_channel_expired(wdev_dpp_listen,
+							cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
+					} else {
+						cfg80211_remain_on_channel_expired(bcmcfg_to_p2p_wdev(cfg),
+						cfg->last_roc_id, &cfg->remain_on_chan, GFP_KERNEL);
+					}
+
+				} else
 					CFGP2P_ERR(("Invalid cfgdev. Dropping the"
 						"remain_on_channel_expired event.\n"));
-				}
 #else
-				cfg80211_remain_on_channel_expired(cfgdev, cfg->last_roc_id,
-					&cfg->remain_on_chan, cfg->remain_on_chan_type, GFP_KERNEL);
+				if (cfgdev && ((struct wireless_dev *)cfgdev)->wiphy)
+					cfg80211_remain_on_channel_expired(cfgdev,
+						cfg->last_roc_id, &cfg->remain_on_chan,
+						cfg->remain_on_chan_type, GFP_KERNEL);
 #endif /* WL_CFG80211_P2P_DEV_IF */
 			}
 		}
@@ -1351,30 +1504,32 @@
  *  We can't report cfg80211_remain_on_channel_expired from Timer ISR context,
  *  so lets do it from thread context.
  */
-
 void
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0))
-wl_cfgp2p_listen_expired(struct timer_list *t)
-{
-	struct p2p_info *p2p = from_timer(p2p, t, listen_timer);
-	struct bcm_cfg80211 *cfg = p2p->cfg;
-#else
 wl_cfgp2p_listen_expired(unsigned long data)
 {
-	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
-#endif
 	wl_event_msg_t msg;
+	struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
+	struct net_device *ndev;
 	CFGP2P_DBG((" Enter\n"));
+
+	if (!cfg) {
+		CFGP2P_ERR((" No cfg\n"));
+		return;
+	}
 	bzero(&msg, sizeof(wl_event_msg_t));
 	msg.event_type =  hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
 	msg.bsscfgidx  =  wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
 #if defined(WL_ENABLE_P2P_IF)
-	wl_cfg80211_event(cfg->p2p_net ? cfg->p2p_net :
-		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg, NULL);
+	ndev = cfg->p2p_net ? cfg->p2p_net :
+		wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
 #else
-	wl_cfg80211_event(wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE), &msg,
-		NULL);
+	ndev = wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE);
 #endif /* WL_ENABLE_P2P_IF */
+	if (!ndev) {
+		CFGP2P_ERR((" No ndev\n"));
+		return;
+	}
+	wl_cfg80211_event(ndev, &msg, NULL);
 }
 /*
  *  Routine for cancelling the P2P LISTEN
@@ -1391,7 +1546,7 @@
 		del_timer_sync(&cfg->p2p->listen_timer);
 		if (notify) {
 #if defined(WL_CFG80211_P2P_DEV_IF)
-			if (wdev)
+			if (bcmcfg_to_p2p_wdev(cfg))
 				cfg80211_remain_on_channel_expired(wdev, cfg->last_roc_id,
 					&cfg->remain_on_chan, GFP_KERNEL);
 #else
@@ -1419,7 +1574,7 @@
 {
 #define EXTRA_DELAY_TIME	100
 	s32 ret = BCME_OK;
-	struct timer_list *_timer;
+	timer_list_compat_t *_timer;
 	s32 extra_delay;
 	struct net_device *netdev = bcmcfg_to_prmry_ndev(cfg);
 
@@ -1469,7 +1624,6 @@
 	return ret;
 }
 
-
 s32
 wl_cfgp2p_discover_enable_search(struct bcm_cfg80211 *cfg, u8 enable)
 {
@@ -1509,6 +1663,8 @@
 	u32 event_type = ntoh32(e->event_type);
 	u32 status = ntoh32(e->status);
 	struct net_device *ndev = NULL;
+	u8 bsscfgidx = e->bsscfgidx;
+
 	CFGP2P_DBG((" Enter\n"));
 
 	ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
@@ -1516,22 +1672,26 @@
 	if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM)) {
 		if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
 
-			CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
+			CFGP2P_DBG((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
 			if (status == WLC_E_STATUS_SUCCESS) {
 				wl_set_p2p_status(cfg, ACTION_TX_COMPLETED);
-				CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n"));
+				CFGP2P_ACTION(("TX actfrm : ACK\n"));
 				if (!cfg->need_wait_afrx && cfg->af_sent_channel) {
 					CFGP2P_DBG(("no need to wait next AF.\n"));
-					wl_stop_wait_next_action_frame(cfg, ndev);
+					wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
 				}
 			}
 			else if (!wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
 				wl_set_p2p_status(cfg, ACTION_TX_NOACK);
-				CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
-				wl_stop_wait_next_action_frame(cfg, ndev);
+				if (status == WLC_E_STATUS_SUPPRESS) {
+					CFGP2P_ACTION(("TX actfrm : SUPPRES\n"));
+				} else {
+					CFGP2P_ACTION(("TX actfrm : NO ACK\n"));
+				}
+				wl_stop_wait_next_action_frame(cfg, ndev, bsscfgidx);
 			}
 		} else {
-			CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
+			CFGP2P_DBG((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
 						"status : %d\n", status));
 
 			if (wl_get_drv_status_all(cfg, SENDING_ACT_FRM))
@@ -1557,9 +1717,8 @@
 	s32 timeout = 0;
 	wl_eventmsg_buf_t buf;
 
-
-	CFGP2P_INFO(("\n"));
-	CFGP2P_INFO(("channel : %u , dwell time : %u\n",
+	CFGP2P_DBG(("\n"));
+	CFGP2P_DBG(("channel : %u , dwell time : %u\n",
 	    af_params->channel, af_params->dwell_time));
 
 	wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
@@ -1580,7 +1739,7 @@
 		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
 
 	if (ret < 0) {
-		CFGP2P_ERR((" sending action frame is failed\n"));
+		CFGP2P_ACTION(("TX actfrm : ERROR\n"));
 		goto exit;
 	}
 
@@ -1588,21 +1747,21 @@
 		msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX));
 
 	if (timeout >= 0 && wl_get_p2p_status(cfg, ACTION_TX_COMPLETED)) {
-		CFGP2P_INFO(("tx action frame operation is completed\n"));
+		CFGP2P_DBG(("tx action frame operation is completed\n"));
 		ret = BCME_OK;
 	} else if (ETHER_ISBCAST(&cfg->afx_hdl->tx_dst_addr)) {
-		CFGP2P_INFO(("bcast tx action frame operation is completed\n"));
+		CFGP2P_DBG(("bcast tx action frame operation is completed\n"));
 		ret = BCME_OK;
 	} else {
 		ret = BCME_ERROR;
-		CFGP2P_INFO(("tx action frame operation is failed\n"));
+		CFGP2P_DBG(("tx action frame operation is failed\n"));
 	}
 	/* clear status bit for action tx */
 	wl_clr_p2p_status(cfg, ACTION_TX_COMPLETED);
 	wl_clr_p2p_status(cfg, ACTION_TX_NOACK);
 
 exit:
-	CFGP2P_INFO((" via act frame iovar : status = %d\n", ret));
+	CFGP2P_DBG((" via act frame iovar : status = %d\n", ret));
 
 	bzero(&buf, sizeof(wl_eventmsg_buf_t));
 	wl_cfg80211_add_to_eventbuffer(&buf, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE, false);
@@ -1688,64 +1847,7 @@
 		subel += subelt_len;
 	}
 }
-/*
- * Check if a BSS is up.
- * This is a common implementation called by most OSL implementations of
- * p2posl_bss_isup().  DO NOT call this function directly from the
- * common code -- call p2posl_bss_isup() instead to allow the OSL to
- * override the common implementation if necessary.
- */
-bool
-wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
-{
-	s32 result, val;
-	bool isup = false;
-	s8 getbuf[64];
 
-	/* Check if the BSS is up */
-	*(int*)getbuf = -1;
-	result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
-		sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0, NULL);
-	if (result != 0) {
-		CFGP2P_ERR(("'cfg bss -C %d' failed: %d\n", bsscfg_idx, result));
-		CFGP2P_ERR(("NOTE: this ioctl error is normal "
-					"when the BSS has not been created yet.\n"));
-	} else {
-		val = *(int*)getbuf;
-		val = dtoh32(val);
-		CFGP2P_INFO(("---cfg bss -C %d   ==> %d\n", bsscfg_idx, val));
-		isup = (val ? TRUE : FALSE);
-	}
-	return isup;
-}
-
-
-/* Bring up or down a BSS */
-s32
-wl_cfgp2p_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev, s32 bsscfg_idx, s32 is_up)
-{
-	s32 ret = BCME_OK;
-	s32 val = is_up ? 1 : 0;
-
-	struct {
-		s32 cfg;
-		s32 val;
-	} bss_setbuf;
-
-	bss_setbuf.cfg = htod32(bsscfg_idx);
-	bss_setbuf.val = htod32(val);
-	CFGP2P_INFO(("---cfg bss -C %d %s\n", bsscfg_idx, is_up ? "up" : "down"));
-	ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
-		cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
-
-	if (ret != 0) {
-		CFGP2P_ERR(("'bss %d' failed with %d\n", is_up, ret));
-	}
-
-	return ret;
-}
-
-/* Check if 'p2p' is supported in the driver */
 s32
 wl_cfgp2p_supported(struct bcm_cfg80211 *cfg, struct net_device *ndev)
 {
@@ -1776,7 +1878,6 @@
 {
 	struct net_device *ndev = NULL;
 	struct wireless_dev *wdev = NULL;
-	s32 i = 0, index = -1;
 
 #if defined(WL_CFG80211_P2P_DEV_IF)
 	ndev = bcmcfg_to_prmry_ndev(cfg);
@@ -1788,18 +1889,21 @@
 
 	wl_cfgp2p_cancel_listen(cfg, ndev, wdev, TRUE);
 	wl_cfgp2p_disable_discovery(cfg);
-#if defined(WL_CFG80211_P2P_DEV_IF)
+
+#if defined(WL_CFG80211_P2P_DEV_IF) && !defined(KEEP_WIFION_OPTION)
+/*
+ * In CUSTOMER_HW4 implementation "ifconfig wlan0 down" can get
+ * called during phone suspend and customer requires the p2p
+ * discovery interface to be left untouched so that the user
+ * space can resume without any problem.
+ */
 	if (cfg->p2p_wdev) {
 		/* If p2p wdev is left out, clean it up */
 		WL_ERR(("Clean up the p2p discovery IF\n"));
 		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
 	}
-#endif /* WL_CFG80211_P2P_DEV_IF */
-	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
-			index = wl_to_p2p_bss_bssidx(cfg, i);
-			if (index != WL_INVALID)
-				wl_cfg80211_clear_per_bss_ies(cfg, index);
-	}
+#endif /* WL_CFG80211_P2P_DEV_IF !defined(KEEP_WIFION_OPTION) */
+
 	wl_cfgp2p_deinit_priv(cfg);
 	return 0;
 }
@@ -1821,9 +1925,10 @@
 	int count, start, duration;
 	wl_p2p_sched_t dongle_noa;
 	s32 bssidx, type;
+	int iovar_len = sizeof(dongle_noa);
 	CFGP2P_DBG((" Enter\n"));
 
-	memset(&dongle_noa, 0, sizeof(dongle_noa));
+	bzero(&dongle_noa, sizeof(dongle_noa));
 
 	if (wl_cfgp2p_vif_created(cfg)) {
 		cfg->p2p->noa.desc[0].start = 0;
@@ -1882,8 +1987,12 @@
 		if (wl_cfgp2p_find_type(cfg, bssidx, &type) != BCME_OK)
 			return BCME_ERROR;
 
+		if (dongle_noa.action == WL_P2P_SCHED_ACTION_RESET) {
+			iovar_len -= sizeof(wl_p2p_sched_desc_t);
+		}
+
 		ret = wldev_iovar_setbuf(wl_to_p2p_bss_ndev(cfg, type),
-			"p2p_noa", &dongle_noa, sizeof(dongle_noa), cfg->ioctl_buf,
+			"p2p_noa", &dongle_noa, iovar_len, cfg->ioctl_buf,
 			WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
 
 		if (ret < 0) {
@@ -1972,8 +2081,8 @@
 		}
 
 		if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) {
-			ret = wldev_ioctl(dev,
-				WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true);
+			ret = wldev_ioctl_set(dev,
+				WLC_SET_PM, &legacy_ps, sizeof(legacy_ps));
 			if (unlikely(ret))
 				CFGP2P_ERR(("error (%d)\n", ret));
 			wl_cfg80211_update_power_mode(dev);
@@ -2015,11 +2124,12 @@
 			return BCME_ERROR;
 		}
 
+		memset_s(&csa_arg, sizeof(csa_arg), 0, sizeof(csa_arg));
 		csa_arg.mode = DOT11_CSA_MODE_ADVISORY;
 		csa_arg.count = P2P_ECSA_CNT;
 		csa_arg.reg = 0;
 
-		sprintf(buf, "%d/%d", ch, bw);
+		snprintf(buf, len, "%d/%d", ch, bw);
 		chnsp = wf_chspec_aton(buf);
 		if (chnsp == 0) {
 			CFGP2P_ERR(("%s:chsp is not correct\n", __FUNCTION__));
@@ -2041,12 +2151,46 @@
 	return BCME_OK;
 }
 
-u8 *
-wl_cfgp2p_retreive_p2pattrib(void *buf, u8 element_id)
+s32
+wl_cfgp2p_increase_p2p_bw(struct bcm_cfg80211 *cfg, struct net_device *ndev, char* buf, int len)
 {
-	wifi_p2p_ie_t *ie = NULL;
+	int algo;
+	int bw;
+	int ret = BCME_OK;
+
+	sscanf(buf, "%3d", &bw);
+	if (bw == 0) {
+		algo = 0;
+		ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
+				WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+		if (ret < 0) {
+			CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
+			return BCME_ERROR;
+		}
+	} else {
+		algo = 1;
+		ret = wldev_iovar_setbuf(ndev, "mchan_algo", &algo, sizeof(algo), cfg->ioctl_buf,
+				WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+		if (ret < 0) {
+			CFGP2P_ERR(("fw set mchan_algo failed %d\n", ret));
+			return BCME_ERROR;
+		}
+		ret = wldev_iovar_setbuf(ndev, "mchan_bw", &bw, sizeof(algo), cfg->ioctl_buf,
+				WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
+		if (ret < 0) {
+			CFGP2P_ERR(("fw set mchan_bw failed %d\n", ret));
+			return BCME_ERROR;
+		}
+	}
+	return BCME_OK;
+}
+
+const u8 *
+wl_cfgp2p_retreive_p2pattrib(const void *buf, u8 element_id)
+{
+	const wifi_p2p_ie_t *ie = NULL;
 	u16 len = 0;
-	u8 *subel;
+	const u8 *subel;
 	u8 subelt_id;
 	u16 subelt_len;
 
@@ -2055,7 +2199,7 @@
 		return 0;
 	}
 
-	ie = (wifi_p2p_ie_t*) buf;
+	ie = (const wifi_p2p_ie_t*) buf;
 	len = ie->len;
 
 	/* Point subel to the P2P IE's subelt field.
@@ -2094,43 +2238,50 @@
 
 #define P2P_GROUP_CAPAB_GO_BIT	0x01
 
-u8*
-wl_cfgp2p_find_attrib_in_all_p2p_Ies(u8 *parse, u32 len, u32 attrib)
+const u8*
+wl_cfgp2p_find_attrib_in_all_p2p_Ies(const u8 *parse, u32 len, u32 attrib)
 {
 	bcm_tlv_t *ie;
-	u8* pAttrib;
+	const u8* pAttrib;
+	uint ie_len;
 
-	CFGP2P_INFO(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
-	while ((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID))) {
-		if (wl_cfgp2p_is_p2p_ie((uint8*)ie, &parse, &len) == TRUE) {
+	CFGP2P_DBG(("Starting parsing parse %p attrib %d remaining len %d ", parse, attrib, len));
+	ie_len = len;
+	while ((ie = bcm_parse_tlvs(parse, ie_len, DOT11_MNG_VS_ID))) {
+		if (wl_cfgp2p_is_p2p_ie(ie, &parse, &ie_len) == TRUE) {
 			/* Have the P2p ie. Now check for attribute */
-			if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(parse, attrib)) != NULL) {
-				CFGP2P_INFO(("P2P attribute %d was found at parse %p",
+			if ((pAttrib = wl_cfgp2p_retreive_p2pattrib(ie, attrib)) != NULL) {
+				CFGP2P_DBG(("P2P attribute %d was found at parse %p",
 					attrib, parse));
 				return pAttrib;
 			}
 			else {
-				parse += (ie->len + TLV_HDR_LEN);
-				len -= (ie->len + TLV_HDR_LEN);
+				/* move to next IE */
+				bcm_tlv_buffer_advance_past(ie, &parse, &ie_len);
+
 				CFGP2P_INFO(("P2P Attribute %d not found Moving parse"
-					" to %p len to %d", attrib, parse, len));
+					" to %p len to %d", attrib, parse, ie_len));
 			}
 		}
 		else {
 			/* It was not p2p IE. parse will get updated automatically to next TLV */
-			CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, len));
+			CFGP2P_INFO(("IT was NOT P2P IE parse %p len %d", parse, ie_len));
 		}
 	}
 	CFGP2P_ERR(("P2P attribute %d was NOT found", attrib));
 	return NULL;
 }
 
-u8 *
+const u8 *
 wl_cfgp2p_retreive_p2p_dev_addr(wl_bss_info_t *bi, u32 bi_length)
 {
-	u8 *capability = NULL;
+	const u8 *capability = NULL;
 	bool p2p_go	= 0;
-	u8 *ptr = NULL;
+	const u8 *ptr = NULL;
+
+	if (bi->length != bi->ie_offset + bi->ie_length) {
+		return NULL;
+	}
 
 	if ((capability = wl_cfgp2p_find_attrib_in_all_p2p_Ies(((u8 *) bi) + bi->ie_offset,
 	bi->ie_length, P2P_SEID_P2P_INFO)) == NULL) {
@@ -2173,13 +2324,15 @@
 };
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
 
-#if defined(WL_ENABLE_P2P_IF)
+#if defined(WL_ENABLE_P2P_IF) || defined(WL_NEWCFG_PRIVCMD_SUPPORT)
 s32
 wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
 {
 	int ret = 0;
 	struct net_device* net = NULL;
+#ifndef	WL_NEWCFG_PRIVCMD_SUPPORT
 	struct wireless_dev *wdev = NULL;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 	uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 };
 
 	if (cfg->p2p_net) {
@@ -2193,15 +2346,16 @@
 		return -ENODEV;
 	}
 
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+#ifndef	WL_NEWCFG_PRIVCMD_SUPPORT
+	wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
 	if (unlikely(!wdev)) {
 		WL_ERR(("Could not allocate wireless device\n"));
 		free_netdev(net);
 		return -ENOMEM;
 	}
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 
-	strncpy(net->name, "p2p%d", sizeof(net->name) - 1);
-	net->name[IFNAMSIZ - 1] = '\0';
+	strlcpy(net->name, "p2p%d", sizeof(net->name));
 
 	/* Copy the reference to bcm_cfg80211 */
 	memcpy((void *)netdev_priv(net), &cfg, sizeof(struct bcm_cfg80211 *));
@@ -2215,38 +2369,50 @@
 #else
 	ASSERT(!net->netdev_ops);
 	net->netdev_ops = &wl_cfgp2p_if_ops;
-#endif
+#endif // endif
 
 	/* Register with a dummy MAC addr */
 	memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN);
 
+#ifndef	WL_NEWCFG_PRIVCMD_SUPPORT
 	wdev->wiphy = cfg->wdev->wiphy;
 
 	wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
 
 	net->ieee80211_ptr = wdev;
+#else
+	net->ieee80211_ptr = NULL;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 	net->ethtool_ops = &cfgp2p_ethtool_ops;
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24) */
 
+#ifndef	WL_NEWCFG_PRIVCMD_SUPPORT
 	SET_NETDEV_DEV(net, wiphy_dev(wdev->wiphy));
 
 	/* Associate p2p0 network interface with new wdev */
 	wdev->netdev = net;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 
 	ret = register_netdev(net);
 	if (ret) {
 		CFGP2P_ERR((" register_netdevice failed (%d)\n", ret));
 		free_netdev(net);
-		kfree(wdev);
+#ifndef	WL_NEWCFG_PRIVCMD_SUPPORT
+		MFREE(cfg->osh, wdev, sizeof(*wdev));
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 		return -ENODEV;
 	}
 
 	/* store p2p net ptr for further reference. Note that iflist won't have this
 	 * entry as there corresponding firmware interface is a "Hidden" interface.
 	 */
+#ifndef	WL_NEWCFG_PRIVCMD_SUPPORT
 	cfg->p2p_wdev = wdev;
+#else
+	cfg->p2p_wdev = NULL;
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 	cfg->p2p_net = net;
 
 	printk("%s: P2P Interface Registered\n", net->name);
@@ -2292,7 +2458,11 @@
 	 * For Android PRIV CMD handling map it to primary I/F
 	 */
 	if (cmd == SIOCDEVPRIVATE+1) {
-		ret = wl_android_priv_cmd(ndev, ifr, cmd);
+#if defined(OEM_ANDROID)
+		ret = wl_android_priv_cmd(ndev, ifr);
+#else
+	(void)ndev;
+#endif // endif
 
 	} else {
 		CFGP2P_ERR(("%s: IOCTL req 0x%x on p2p0 I/F. Ignoring. \n",
@@ -2302,14 +2472,14 @@
 
 	return ret;
 }
-#endif 
+#endif /* WL_ENABLE_P2P_IF || WL_NEWCFG_PRIVCMD_SUPPORT  */
 
 #if defined(WL_ENABLE_P2P_IF)
 static int wl_cfgp2p_if_open(struct net_device *net)
 {
 	struct wireless_dev *wdev = net->ieee80211_ptr;
 
-	if (!wdev || !wl_cfg80211_is_p2p_active())
+	if (!wdev || !wl_cfg80211_is_p2p_active(net))
 		return -EINVAL;
 	WL_TRACE(("Enter\n"));
 #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
@@ -2330,11 +2500,12 @@
 static int wl_cfgp2p_if_stop(struct net_device *net)
 {
 	struct wireless_dev *wdev = net->ieee80211_ptr;
+	struct bcm_cfg80211 *cfg = wl_get_cfg(net);
 
 	if (!wdev)
 		return -EINVAL;
 
-	wl_cfg80211_scan_stop(net);
+	wl_cfg80211_scan_stop(cfg, net);
 
 #if !defined(WL_IFACE_COMB_NUM_CHANNELS)
 	wdev->wiphy->interface_modes = (wdev->wiphy->interface_modes)
@@ -2363,27 +2534,54 @@
 	WL_TRACE(("Enter\n"));
 
 	if (cfg->p2p_wdev) {
-		 /*
-		* This is not expected. This can happen due to
-		* supplicant crash/unclean de-initialization which
-		* didn't free the p2p discovery interface. Indicate
-		* driver hang to user space so that the framework
-		* can rei-init the Wi-Fi.
-		*/
+#ifndef EXPLICIT_DISCIF_CLEANUP
+		dhd_pub_t *dhd = (dhd_pub_t *)(cfg->pub);
+#endif /* EXPLICIT_DISCIF_CLEANUP */
+		/*
+		 * This is not expected. This can happen due to
+		 * supplicant crash/unclean de-initialization which
+		 * didn't free the p2p discovery interface. Indicate
+		 * driver hang to user space so that the framework
+		 * can rei-init the Wi-Fi.
+		 */
 		CFGP2P_ERR(("p2p_wdev defined already.\n"));
 		wl_probe_wdev_all(cfg);
-
+#ifdef EXPLICIT_DISCIF_CLEANUP
+		/*
+		 * CUSTOMER_HW4 design doesn't delete the p2p discovery
+		 * interface on ifconfig wlan0 down context which comes
+		 * without a preceeding NL80211_CMD_DEL_INTERFACE for p2p
+		 * discovery. But during supplicant crash the DEL_IFACE
+		 * command will not happen and will cause a left over iface
+		 * even after ifconfig wlan0 down. So delete the iface
+		 * first and then indicate the HANG event
+		 */
+		wl_cfgp2p_del_p2p_disc_if(cfg->p2p_wdev, cfg);
+#else
+		dhd->hang_reason = HANG_REASON_IFACE_DEL_FAILURE;
+#ifdef OEM_ANDROID
+#if defined(BCMPCIE) && defined(DHD_FW_COREDUMP)
+		if (dhd->memdump_enabled) {
+			/* Load the dongle side dump to host
+			 * memory and then BUG_ON()
+			 */
+			dhd->memdump_type = DUMP_TYPE_IFACE_OP_FAILURE;
+			dhd_bus_mem_dump(dhd);
+		}
+#endif /* BCMPCIE && DHD_FW_COREDUMP */
 		net_os_send_hang_message(bcmcfg_to_prmry_ndev(cfg));
+#endif /* OEM_ANDROID */
 		return ERR_PTR(-ENODEV);
+#endif /* EXPLICIT_DISCIF_CLEANUP */
 	}
 
-	wdev = kzalloc(sizeof(*wdev), GFP_KERNEL);
+	wdev = (struct wireless_dev *)MALLOCZ(cfg->osh, sizeof(*wdev));
 	if (unlikely(!wdev)) {
 		WL_ERR(("Could not allocate wireless device\n"));
 		return ERR_PTR(-ENOMEM);
 	}
 
-	memset(&primary_mac, 0, sizeof(primary_mac));
+	bzero(&primary_mac, sizeof(primary_mac));
 	get_primary_mac(cfg, &primary_mac);
 	wl_cfgp2p_generate_bss_mac(cfg, &primary_mac);
 
@@ -2391,12 +2589,16 @@
 	wdev->iftype = NL80211_IFTYPE_P2P_DEVICE;
 	memcpy(wdev->address, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE), ETHER_ADDR_LEN);
 
+#if defined(WL_NEWCFG_PRIVCMD_SUPPORT)
+	if (cfg->p2p_net)
+		memcpy(cfg->p2p_net->dev_addr, wl_to_p2p_bss_macaddr(cfg, P2PAPI_BSSCFG_DEVICE),
+			ETHER_ADDR_LEN);
+#endif /* WL_NEWCFG_PRIVCMD_SUPPORT */
 
 	/* store p2p wdev ptr for further reference. */
 	cfg->p2p_wdev = wdev;
 
 	CFGP2P_ERR(("P2P interface registered\n"));
-
 	return wdev;
 }
 
@@ -2426,7 +2628,7 @@
 	p2p_on(cfg) = true;
 #if defined(P2P_IE_MISSING_FIX)
 	cfg->p2p_prb_noti = false;
-#endif
+#endif // endif
 
 	CFGP2P_DBG(("P2P interface started\n"));
 
@@ -2438,6 +2640,7 @@
 wl_cfgp2p_stop_p2p_device(struct wiphy *wiphy, struct wireless_dev *wdev)
 {
 	int ret = 0;
+	struct net_device *ndev = NULL;
 	struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
 
 	if (!cfg)
@@ -2445,13 +2648,28 @@
 
 	CFGP2P_DBG(("Enter\n"));
 
-	ret = wl_cfg80211_scan_stop(wdev);
+	/* Check if cfg80211 interface is already down */
+	ndev = bcmcfg_to_prmry_ndev(cfg);
+	if (!wl_get_drv_status(cfg, READY, ndev)) {
+		WL_DBG(("cfg80211 interface is already down\n"));
+		return;	/* it is even not ready */
+	}
+
+	ret = wl_cfg80211_scan_stop(cfg, wdev);
 	if (unlikely(ret < 0)) {
 		CFGP2P_ERR(("P2P scan stop failed, ret=%d\n", ret));
 	}
 
-	if (!cfg->p2p)
+	if (!p2p_is_on(cfg)) {
 		return;
+	}
+
+#ifdef P2P_LISTEN_OFFLOADING
+	wl_cfg80211_p2plo_deinit(cfg);
+#endif /* P2P_LISTEN_OFFLOADING */
+
+	/* Cancel any on-going listen */
+	wl_cfgp2p_cancel_listen(cfg, bcmcfg_to_prmry_ndev(cfg), wdev, TRUE);
 
 	ret = wl_cfgp2p_disable_discovery(cfg);
 	if (unlikely(ret < 0)) {
@@ -2470,10 +2688,12 @@
 {
 	bool rollback_lock = false;
 
-	if (!wdev)
+	if (!wdev || !cfg) {
+		WL_ERR(("null ptr. wdev:%p cfg:%p\n", wdev, cfg));
 		return -EINVAL;
+	}
 
-	WL_TRACE(("Enter\n"));
+	WL_INFORM(("Enter\n"));
 
 	if (!rtnl_is_locked()) {
 		rtnl_lock();
@@ -2487,10 +2707,9 @@
 
 	synchronize_rcu();
 
-	kfree(wdev);
+	MFREE(cfg->osh, wdev, sizeof(*wdev));
 
-	if (cfg)
-		cfg->p2p_wdev = NULL;
+	cfg->p2p_wdev = NULL;
 
 	CFGP2P_ERR(("P2P interface unregistered\n"));
 

--
Gitblit v1.6.2