From cf77d4ca64d7cd0793f967559cbe063a21060a5b Mon Sep 17 00:00:00 2001
From: "Howard M. Harte" <hharte@broadcom.com>
Date: Fri, 27 May 2011 16:07:36 -0700
Subject: [PATCH] Update to 5.90.125.22:

    * Add support for SoftAP, keepalive, ARP offload.
    * Clean up cfg80211 and p2p code.
    * Update Makefile to support new features.
Change-Id: I1e7a16acd400d7baf5625ca8ba6552a6f1c80661
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
---
 drivers/net/wireless/bcmdhd/Makefile          |    5 +-
 drivers/net/wireless/bcmdhd/dhd.h             |   10 +
 drivers/net/wireless/bcmdhd/dhd_cdc.c         |    6 +-
 drivers/net/wireless/bcmdhd/dhd_common.c      |  257 +++-
 drivers/net/wireless/bcmdhd/dhd_custom_gpio.c |   68 +-
 drivers/net/wireless/bcmdhd/dhd_sdio.c        |   36 +-
 drivers/net/wireless/bcmdhd/include/epivers.h |    8 +-
 .../net/wireless/bcmdhd/include/linuxver.h    |    2 +-
 drivers/net/wireless/bcmdhd/include/wlioctl.h |   13 +-
 drivers/net/wireless/bcmdhd/wl_cfg80211.c     | 1108 +++++++++--------
 drivers/net/wireless/bcmdhd/wl_cfg80211.h     |   72 +-
 drivers/net/wireless/bcmdhd/wl_cfgp2p.c       |  495 ++------
 drivers/net/wireless/bcmdhd/wl_cfgp2p.h       |   30 +-
 drivers/net/wireless/bcmdhd/wldev_common.c    |  238 ++++
 drivers/net/wireless/bcmdhd/wldev_common.h    |   91 ++
 15 files changed, 1451 insertions(+), 988 deletions(-)
 create mode 100644 drivers/net/wireless/bcmdhd/wldev_common.c
 create mode 100644 drivers/net/wireless/bcmdhd/wldev_common.h

diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile
index b9aaf79760e3..410f1f053ffb 100644
--- a/drivers/net/wireless/bcmdhd/Makefile
+++ b/drivers/net/wireless/bcmdhd/Makefile
@@ -6,13 +6,14 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Werror -Dlinux -DBCMDRIVER             \
 	-DCUSTOMER_HW3 -DCUSTOM_OOB_GPIO_NUM=135 -DOOB_INTR_ONLY              \
 	-DMMC_SDIO_ABORT -DCONFIG_FIRST_SCAN -DBCMSDIO -DBCMLXSDMMC           \
 	-DBCMPLATFORM_BUS -DHW_OOB -DNEW_COMPAT_WIRELESS -DWL_CFG80211        \
-	-DWLP2P -DWIFI_ACT_FRAME                                              \
+	-DWLP2P -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DKEEP_ALIVE -DCSCAN   \
 	-Idrivers/net/wireless/bcmdhd -Idrivers/net/wireless/bcmdhd/include
 
 DHDOFILES = aiutils.o bcmsdh_sdmmc_linux.o dhd_linux.o siutils.o bcmutils.o   \
 	dhd_linux_sched.o wl_cfg80211.o bcmwifi.o dhd_sdio.o wl_cfgp2p.o      \
 	bcmevent.o dhd_bta.o hndpmu.o bcmsdh.o dhd_cdc.o bcmsdh_linux.o       \
-	dhd_common.o linux_osl.o bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o
+	dhd_common.o linux_osl.o bcmsdh_sdmmc.o dhd_custom_gpio.o sbutils.o   \
+	wldev_common.o
 
 obj-$(CONFIG_BCMDHD) += bcmdhd.o
 bcmdhd-objs += $(DHDOFILES)
diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h
index 961a66d71fa0..bb39913a4ec8 100644
--- a/drivers/net/wireless/bcmdhd/dhd.h
+++ b/drivers/net/wireless/bcmdhd/dhd.h
@@ -484,6 +484,9 @@ extern uint dhd_sdiod_drive_strength;
 
 /* Override to force tx queueing all the time */
 extern uint dhd_force_tx_queueing;
+/* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */
+#define KEEP_ALIVE_PERIOD 55000
+#define NULL_PKT_STR	"null_pkt"
 
 #ifdef SDTEST
 /* Echo packet generator (SDIO), pkts/s */
@@ -641,4 +644,11 @@ int dhd_os_wlfc_unblock(dhd_pub_t *pub);
 extern void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar);
 extern void dhd_wait_event_wakeup(dhd_pub_t*dhd);
 
+#ifdef ARP_OFFLOAD_SUPPORT
+/* dhd_commn arp offload wrapers */
+void dhd_aoe_hostip_clr(dhd_pub_t *dhd);
+void dhd_aoe_arp_clr(dhd_pub_t *dhd);
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen);
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr);
+#endif /* ARP_OFFLOAD_SUPPORT */
 #endif /* _dhd_h_ */
diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c
index b4270e02c840..fb0d5ad7f6b4 100644
--- a/drivers/net/wireless/bcmdhd/dhd_cdc.c
+++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c
@@ -116,7 +116,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
 	return ret;
 }
 
-static int
+int
 dhdcdc_query_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
 {
 	dhd_prot_t *prot = dhd->prot;
@@ -203,7 +203,7 @@ done:
 	return ret;
 }
 
-static int
+int
 dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action)
 {
 	dhd_prot_t *prot = dhd->prot;
@@ -271,6 +271,7 @@ dhd_prot_ioctl(dhd_pub_t *dhd, int ifidx, wl_ioctl_t * ioc, void * buf, int len)
 		goto done;
 	}
 
+
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
 	ASSERT(len <= WLC_IOCTL_MAXLEN);
@@ -2294,6 +2295,7 @@ dhd_prot_init(dhd_pub_t *dhd)
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
 
+
 	/* Get the device rev info */
 	memset(&revinfo, 0, sizeof(revinfo));
 	ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c
index ae92489dcf15..b1d9e7c87601 100644
--- a/drivers/net/wireless/bcmdhd/dhd_common.c
+++ b/drivers/net/wireless/bcmdhd/dhd_common.c
@@ -41,8 +41,15 @@
 #include <dhd_dbg.h>
 #include <msgtrace.h>
 
+#ifdef WL_CFG80211
+#include <wl_cfg80211.h>
+#endif
 #include <proto/bt_amp_hci.h>
 #include <dhd_bta.h>
+#ifdef SET_RANDOM_MAC_SOFTAP
+#include <linux/random.h>
+#include <linux/jiffies.h>
+#endif
 
 #ifdef PROP_TXSTATUS
 #include <wlfc_proto.h>
@@ -80,6 +87,13 @@ extern int dhd_iscan_in_progress(void *h);
 void dhd_iscan_lock(void);
 void dhd_iscan_unlock(void);
 extern int dhd_change_mtu(dhd_pub_t *dhd, int new_mtu, int ifidx);
+#if defined(SOFTAP)
+extern bool ap_fw_loaded;
+#endif 
+
+#if defined(KEEP_ALIVE)
+int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on);
+#endif /* KEEP_ALIVE */
 
 /* Packet alignment for most efficient SDIO (can change based on platform) */
 #ifndef DHD_SDALIGN
@@ -1025,12 +1039,30 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata,
 }
 #endif /* PROP_TXSTATUS */
 
-		if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
+#ifdef WL_CFG80211
+			if (wl_cfg80211_is_progress_ifchange()) {
+				DHD_ERROR(("%s:  ifidx %d for %s action %d\n",
+					__FUNCTION__, ifevent->ifidx,
+					event->ifname, ifevent->action));
 			if (ifevent->action == WLC_E_IF_ADD)
-				dhd_add_if(dhd_pub->info, ifevent->ifidx,
-				           NULL, event->ifname,
-				           event->addr.octet,
-				           ifevent->flags, ifevent->bssidx);
+					wl_cfg80211_notify_ifchange();
+				return (BCME_OK);
+			}
+#endif /* WL_CFG80211 */
+				if (ifevent->ifidx > 0 && ifevent->ifidx < DHD_MAX_IFS) {
+					if (ifevent->action == WLC_E_IF_ADD) {
+						if (dhd_add_if(dhd_pub->info, ifevent->ifidx,
+							NULL, event->ifname,
+							event->addr.octet,
+							ifevent->flags, ifevent->bssidx)) {
+							DHD_ERROR(("%s: dhd_add_if failed!!"
+									" ifidx: %d for %s\n",
+									__FUNCTION__,
+									ifevent->ifidx,
+									event->ifname));
+							return (BCME_ERROR);
+						}
+					}
 			else
 				dhd_del_if(dhd_pub->info, ifevent->ifidx);
 		} else {
@@ -1114,6 +1146,7 @@ wl_event_to_host_order(wl_event_msg_t * evt)
 void
 dhd_print_buf(void *pbuf, int len, int bytes_per_line)
 {
+#ifdef DHD_DEBUG
 	int i, j = 0;
 	unsigned char *buf = pbuf;
 
@@ -1132,6 +1165,7 @@ dhd_print_buf(void *pbuf, int len, int bytes_per_line)
 		}
 	}
 	printf("\n");
+#endif /* DHD_DEBUG */
 }
 
 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
@@ -1366,6 +1400,10 @@ fail:
 		MFREE(dhd->osh, buf, BUF_SIZE);
 }
 
+/* ========================== */
+/* ==== ARP OFFLOAD SUPPORT = */
+/* ========================== */
+#ifdef ARP_OFFLOAD_SUPPORT
 void
 dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode)
 {
@@ -1400,6 +1438,86 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable)
 		__FUNCTION__, arp_enable));
 }
 
+void dhd_aoe_arp_clr(dhd_pub_t *dhd)
+{
+	int ret = 0;
+	int iov_len = 0;
+	char iovbuf[128];
+
+	if (dhd == NULL) return;
+
+	iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf));
+	if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0) < 0))
+		DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+}
+
+void dhd_aoe_hostip_clr(dhd_pub_t *dhd)
+{
+	int ret = 0;
+	int iov_len = 0;
+	char iovbuf[128];
+
+	if (dhd == NULL) return;
+
+	iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf));
+	if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0)) < 0)
+		DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret));
+}
+
+void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr)
+{
+	int iov_len = 0;
+	char iovbuf[32];
+	int retcode;
+
+	iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf));
+	retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0);
+
+	if (retcode)
+		DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n",
+		__FUNCTION__, retcode));
+	else
+		DHD_TRACE(("%s: sARP H ipaddr entry added \n",
+		__FUNCTION__));
+}
+
+
+int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen)
+{
+#define MAX_IPV4_ENTRIES 8
+
+	int retcode, i;
+	int iov_len = 0;
+	uint32 *ptr32 = buf;
+	bool clr_bottom = FALSE;
+
+	if (!buf)
+		return -1;
+
+	iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen);
+	retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, TRUE, 0);
+
+	/* clean up the buf, ascii reminder */
+	for (i = 0; i < MAX_IPV4_ENTRIES; i++) {
+
+		if (!clr_bottom) {
+			if (*ptr32 == 0)
+			clr_bottom = TRUE;
+		} else {
+			*ptr32 = 0;
+		}
+		ptr32++;
+	}
+
+	if (retcode) {
+		DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n",
+		__FUNCTION__, retcode));
+
+		return -1;
+	}
+	return 0;
+}
+#endif /* ARP_OFFLOAD_SUPPORT  */
 int
 dhd_preinit_ioctls(dhd_pub_t *dhd)
 {
@@ -1411,10 +1529,11 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 	uint power_mode = PM_FAST;
 	uint32 dongle_align = DHD_SDALIGN;
 	uint32 glom = 0;
+	uint bcn_timeout = 4;
 	int arpoe = 1;
 	int arp_ol = 0xf;
 	int scan_assoc_time = 40;
-	int scan_unassoc_time = 80;
+	int scan_unassoc_time = 40;
 	const char 				*str;
 	wl_pkt_filter_t		pkt_filter;
 	wl_pkt_filter_t		*pkt_filterp;
@@ -1426,18 +1545,67 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 	char *ptr;
 	uint filter_mode = 1;
 	uint32 listen_interval = LISTEN_INTERVAL; /* Default Listen Interval in Beacons */
+#if defined(SOFTAP)
+	uint dtim = 1;
+#endif
 #ifdef AP
 	uint32 mpc = 0; /* Turn MPC off for AP/APSTA mode */
 	uint32 apsta = 1; /* Enable APSTA mode */
 #endif
+#ifdef GET_CUSTOM_MAC_ENABLE
+	struct ether_addr ea_addr;
+#endif /* GET_CUSTOM_MAC_ENABLE */
 
-	/* Get the device MAC address */
+#ifdef GET_CUSTOM_MAC_ENABLE
+	/*
+	** Read MAC address from external customer place
+	** NOTE that default mac address has to be present in otp or nvram file
+	** to bring up firmware but unique per board mac address maybe provided
+	** by customer code
+	*/
+	ret = dhd_custom_get_mac_address(ea_addr.octet);
+	if (!ret) {
+		bcm_mkiovar("cur_etheraddr", (void *)&ea_addr, ETHER_ADDR_LEN, buf, sizeof(buf));
+		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+		if (ret < 0) {
+			DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+		} else
+			memcpy(dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN);
+	}
+#else
+	/* Get the default device MAC address directly from firmware */
 	strcpy(iovbuf, "cur_etheraddr");
 	if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {
 		DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
 		return BCME_NOTUP;
 	}
 	memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
+#endif /* GET_CUSTOM_MAC_ENABLE */
+
+#ifdef SET_RANDOM_MAC_SOFTAP
+	if (strstr(fw_path, "apsta") != NULL) {
+		uint rand_mac;
+
+		srandom32((uint)jiffies);
+		rand_mac = random32();
+		iovbuf[0] = 0x02;              /* locally administered bit */
+		iovbuf[1] = 0x1A;
+		iovbuf[2] = 0x11;
+		iovbuf[3] = (unsigned char)(rand_mac & 0x0F) | 0xF0;
+		iovbuf[4] = (unsigned char)(rand_mac >> 8);
+		iovbuf[5] = (unsigned char)(rand_mac >> 16);
+
+		printk("Broadcom Dongle Host Driver mac=%02x:%02x:%02x:%02x:%02x:%02x\n",
+			iovbuf[0], iovbuf[1], iovbuf[2], iovbuf[3], iovbuf[4], iovbuf[5]);
+
+		bcm_mkiovar("cur_etheraddr", (void *)iovbuf, ETHER_ADDR_LEN, buf, sizeof(buf));
+		ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0);
+		if (ret < 0) {
+			DHD_ERROR(("%s: can't set MAC address , error=%d\n", __FUNCTION__, ret));
+		} else
+			memcpy(dhd->mac.octet, iovbuf, ETHER_ADDR_LEN);
+	}
+#endif /* SET_RANDOM_MAC_SOFTAP */
 
 	/* Set Country code  */
 	if (dhd->dhd_cspec.ccode[0] != 0) {
@@ -1472,6 +1640,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
 	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
 
+	/* Setup timeout if Beacons are lost and roam is off to report link down */
+	bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf, sizeof(iovbuf));
+	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
 #ifdef AP
 	/* Turn off MPC in AP mode */
 	bcm_mkiovar("mpc", (char *)&mpc, 4, iovbuf, sizeof(iovbuf));
@@ -1481,6 +1652,24 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 	bcm_mkiovar("apsta", (char *)&apsta, 4, iovbuf, sizeof(iovbuf));
 	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
 #endif
+#if defined(SOFTAP)
+	if (ap_fw_loaded == TRUE) {
+		dhd_wl_ioctl_cmd(dhd, WLC_SET_DTIMPRD, (char *)&dtim, sizeof(dtim), TRUE, 0);
+	}
+#endif
+
+#if defined(KEEP_ALIVE)
+	{
+	/* Set Keep Alive : be sure to use FW with -keepalive */
+	int res;
+
+	if (ap_fw_loaded == FALSE) {
+		if ((res = dhd_keep_alive_onoff(dhd, 1)) < 0)
+			DHD_ERROR(("%s set keeplive failed %d\n",
+			__FUNCTION__, res));
+		}
+	}
+#endif
 
 	/* Force STA UP */
 	ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0);
@@ -1518,6 +1707,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #endif
 	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf));
 	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+
 	dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_CHANNEL_TIME, (char *)&scan_assoc_time,
 		sizeof(scan_assoc_time), TRUE, 0);
 	dhd_wl_ioctl_cmd(dhd, WLC_SET_SCAN_UNASSOC_TIME, (char *)&scan_unassoc_time,
@@ -1579,6 +1769,12 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 	/* set mode to allow pattern */
 	bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf, sizeof(iovbuf));
 	dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
+#ifdef ARP_OFFLOAD_SUPPORT
+	/* Set and enable ARP offload feature */
+	if (dhd_arp_enable)
+		dhd_arp_offload_set(dhd, dhd_arp_mode);
+	dhd_arp_offload_enable(dhd, dhd_arp_enable);
+#endif /* ARP_OFFLOAD_SUPPORT */
 
 
 done:
@@ -2030,6 +2226,53 @@ dhd_pno_get_status(dhd_pub_t *dhd)
 
 #endif /* PNO_SUPPORT */
 
+#if defined(KEEP_ALIVE)
+int dhd_keep_alive_onoff(dhd_pub_t *dhd, int ka_on)
+{
+	char buf[256];
+	char *buf_ptr = buf;
+	wl_keep_alive_pkt_t keep_alive_pkt;
+	char * str;
+	int str_len, buf_len;
+	int res = -1;
+	int keep_alive_period = KEEP_ALIVE_PERIOD; /* in ms */
+
+	DHD_TRACE(("%s: param=%d\n", __FUNCTION__, ka_on));
+
+	if (ka_on) { /* on suspend */
+		keep_alive_pkt.period_msec = keep_alive_period;
+
+	} else {
+		/* on resume, turn off keep_alive packets  */
+		keep_alive_pkt.period_msec = 0;
+	}
+
+	/* IOC var name  */
+	str = "keep_alive";
+	str_len = strlen(str);
+	strncpy(buf, str, str_len);
+	buf[str_len] = '\0';
+	buf_len = str_len + 1;
+
+	/* set ptr to IOCTL payload after the var name */
+	buf_ptr += buf_len; /* include term Z */
+
+	/* copy Keep-alive attributes from local var keep_alive_pkt */
+	str = NULL_PKT_STR;
+	keep_alive_pkt.len_bytes = strlen(str);
+
+	memcpy(buf_ptr, &keep_alive_pkt, WL_KEEP_ALIVE_FIXED_LEN);
+	buf_ptr += WL_KEEP_ALIVE_FIXED_LEN;
+
+	/* copy packet data */
+	memcpy(buf_ptr, str, keep_alive_pkt.len_bytes);
+	buf_len += (WL_KEEP_ALIVE_FIXED_LEN + keep_alive_pkt.len_bytes);
+/*
+	res = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, buf_len, TRUE, 0);
+*/
+	return res;
+}
+#endif /* defined(KEEP_ALIVE) */
 /* Android ComboSCAN support */
 
 /*
diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
index b11e4b3b7339..88d0da2e3d22 100644
--- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
@@ -89,12 +89,12 @@ int dhd_customer_oob_irq_map(unsigned long *irq_flags_ptr)
 #ifdef CUSTOMER_HW2
 	host_oob_irq = wifi_get_irq_number(irq_flags_ptr);
 
-#else /* for NOT  CUSTOMER_HW2 */
+#else
 #if defined(CUSTOM_OOB_GPIO_NUM)
 	if (dhd_oob_gpio_num < 0) {
 		dhd_oob_gpio_num = CUSTOM_OOB_GPIO_NUM;
 	}
-#endif
+#endif /* CUSTOMER_HW2 */
 
 	if (dhd_oob_gpio_num < 0) {
 		WL_ERROR(("%s: ERROR customer specific Host GPIO is NOT defined \n",
@@ -199,18 +199,48 @@ dhd_custom_get_mac_address(unsigned char *buf)
 const struct cntry_locales_custom translate_custom_table[] = {
 /* Table should be filled out based on custom platform regulatory requirement */
 #ifdef EXAMPLE_TABLE
+	{"",   "XY", 4},  /* Universal if Country code is unknown or empty */
 	{"US", "US", 69}, /* input ISO "US" to : US regrev 69 */
 	{"CA", "US", 69}, /* input ISO "CA" to : US regrev 69 */
-	{"EU", "EU", 05}, /* input ISO "CA" to : US regrev 69 */
-	{"FR", "EU", 05},
-	{"DE", "EU", 05},
-	{"IE", "EU", 05},
-	{"GB", "EU", 05}, /* input ISO "GB" to : EU regrev 05 */
-	{"KR", "XY", 03},
-	{"AU", "XY", 03},
-	{"CN", "XY", 03}, /* input ISO "CN" to : XY regrev 03 */
-	{"TW", "XY", 03},
-	{"AR", "XY", 03}
+	{"EU", "EU", 5},  /* European union countries to : EU regrev 05 */
+	{"AT", "EU", 5},
+	{"BE", "EU", 5},
+	{"BG", "EU", 5},
+	{"CY", "EU", 5},
+	{"CZ", "EU", 5},
+	{"DK", "EU", 5},
+	{"EE", "EU", 5},
+	{"FI", "EU", 5},
+	{"FR", "EU", 5},
+	{"DE", "EU", 5},
+	{"GR", "EU", 5},
+	{"HU", "EU", 5},
+	{"IE", "EU", 5},
+	{"IT", "EU", 5},
+	{"LV", "EU", 5},
+	{"LI", "EU", 5},
+	{"LT", "EU", 5},
+	{"LU", "EU", 5},
+	{"MT", "EU", 5},
+	{"NL", "EU", 5},
+	{"PL", "EU", 5},
+	{"PT", "EU", 5},
+	{"RO", "EU", 5},
+	{"SK", "EU", 5},
+	{"SI", "EU", 5},
+	{"ES", "EU", 5},
+	{"SE", "EU", 5},
+	{"GB", "EU", 5},
+	{"KR", "XY", 3},
+	{"AU", "XY", 3},
+	{"CN", "XY", 3}, /* input ISO "CN" to : XY regrev 03 */
+	{"TW", "XY", 3},
+	{"AR", "XY", 3},
+	{"MX", "XY", 3},
+	{"IL", "IL", 0},
+	{"CH", "CH", 0},
+	{"TR", "TR", 0},
+	{"NO", "NO", 0},
 #endif /* EXMAPLE_TABLE */
 };
 
@@ -232,11 +262,17 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec)
 		 return;
 
 	for (i = 0; i < size; i++) {
-	if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
-		memcpy(cspec->ccode,  translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
-		cspec->rev = translate_custom_table[i].custom_locale_rev;
-			break;
+		if (strcmp(country_iso_code, translate_custom_table[i].iso_abbrev) == 0) {
+			memcpy(cspec->ccode,
+				translate_custom_table[i].custom_locale, WLC_CNTRY_BUF_SZ);
+			cspec->rev = translate_custom_table[i].custom_locale_rev;
+			return;
 		}
 	}
+#ifdef EXAMPLE_TABLE
+	/* if no country code matched return first universal code from translate_custom_table */
+	memcpy(cspec->ccode, translate_custom_table[0].custom_locale, WLC_CNTRY_BUF_SZ);
+	cspec->rev = translate_custom_table[0].custom_locale_rev;
+#endif /* EXMAPLE_TABLE */
 	return;
 }
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index facf6c0b79e8..c51b8320294a 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -936,7 +936,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
 	int ret;
 	osl_t *osh;
 	uint8 *frame;
-	uint16 len, pad = 0;
+	uint16 len, pad1 = 0;
 	uint32 swheader;
 	uint retries = 0;
 	bcmsdh_info_t *sdh;
@@ -972,10 +972,10 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
 #endif /* WLMEDIA_HTSF */
 
 	/* Add alignment padding, allocate new packet if needed */
-	if ((pad = ((uintptr)frame % DHD_SDALIGN))) {
-		if (PKTHEADROOM(osh, pkt) < pad) {
-			DHD_INFO(("%s: insufficient headroom %d for %d pad\n",
-			          __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad));
+	if ((pad1 = ((uintptr)frame % DHD_SDALIGN))) {
+		if (PKTHEADROOM(osh, pkt) < pad1) {
+			DHD_INFO(("%s: insufficient headroom %d for %d pad1\n",
+			          __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad1));
 			bus->dhd->tx_realloc++;
 			new = PKTGET(osh, (PKTLEN(osh, pkt) + DHD_SDALIGN), TRUE);
 			if (!new) {
@@ -994,16 +994,16 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
 			pkt = new;
 			frame = (uint8*)PKTDATA(osh, pkt);
 			ASSERT(((uintptr)frame % DHD_SDALIGN) == 0);
-			pad = 0;
+			pad1 = 0;
 		} else {
-			PKTPUSH(osh, pkt, pad);
+			PKTPUSH(osh, pkt, pad1);
 			frame = (uint8*)PKTDATA(osh, pkt);
 
-			ASSERT((pad + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
-			bzero(frame, pad + SDPCM_HDRLEN);
+			ASSERT((pad1 + SDPCM_HDRLEN) <= (int) PKTLEN(osh, pkt));
+			bzero(frame, pad1 + SDPCM_HDRLEN);
 		}
 	}
-	ASSERT(pad < DHD_SDALIGN);
+	ASSERT(pad1 < DHD_SDALIGN);
 
 	/* Hardware tag: 2 byte len followed by 2 byte ~len check (all LE) */
 	len = (uint16)PKTLEN(osh, pkt);
@@ -1012,7 +1012,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
 
 	/* Software tag: channel, sequence number, data offset */
 	swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq |
-	        (((pad + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
+	        (((pad1 + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK);
 	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
 	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
@@ -1029,12 +1029,12 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
 
 	/* Raise len to next SDIO block to eliminate tail command */
 	if (bus->roundup && bus->blocksize && (len > bus->blocksize)) {
-		uint16 pad = bus->blocksize - (len % bus->blocksize);
-		if ((pad <= bus->roundup) && (pad < bus->blocksize))
+		uint16 pad2 = bus->blocksize - (len % bus->blocksize);
+		if ((pad2 <= bus->roundup) && (pad2 < bus->blocksize))
 #ifdef NOTUSED
-			if (pad <= PKTTAILROOM(osh, pkt))
+			if (pad2 <= PKTTAILROOM(osh, pkt))
 #endif /* NOTUSED */
-				len += pad;
+				len += pad2;
 	} else if (len % DHD_SDALIGN) {
 		len += DHD_SDALIGN - (len % DHD_SDALIGN);
 	}
@@ -1087,7 +1087,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt)
 
 done:
 	/* restore pkt buffer pointer before calling tx complete routine */
-	PKTPULL(osh, pkt, SDPCM_HDRLEN + pad);
+	PKTPULL(osh, pkt, SDPCM_HDRLEN + pad1);
 #ifdef PROP_TXSTATUS
 	if (bus->dhd->wlfc_state) {
 		dhd_os_sdunlock(bus->dhd);
@@ -5791,7 +5791,7 @@ dhdsdio_download_code_array(struct dhd_bus *bus)
 
 	/* Download image */
 	while ((offset + MEMBLOCK) < sizeof(dlarray)) {
-		bcmerror = dhdsdio_membytes(bus, TRUE, offset, dlarray + offset, MEMBLOCK);
+		bcmerror = dhdsdio_membytes(bus, TRUE, offset, (uint8 *) (dlarray + offset), MEMBLOCK);
 		if (bcmerror) {
 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
 			        __FUNCTION__, bcmerror, MEMBLOCK, offset));
@@ -5803,7 +5803,7 @@ dhdsdio_download_code_array(struct dhd_bus *bus)
 
 	if (offset < sizeof(dlarray)) {
 		bcmerror = dhdsdio_membytes(bus, TRUE, offset,
-			dlarray + offset, sizeof(dlarray) - offset);
+			(uint8 *) (dlarray + offset), sizeof(dlarray) - offset);
 		if (bcmerror) {
 			DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n",
 			        __FUNCTION__, bcmerror, sizeof(dlarray) - offset, offset));
diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h
index 1b8a3e8a5421..9a79a1e358c5 100644
--- a/drivers/net/wireless/bcmdhd/include/epivers.h
+++ b/drivers/net/wireless/bcmdhd/include/epivers.h
@@ -33,17 +33,17 @@
 
 #define	EPI_RC_NUMBER		125
 
-#define	EPI_INCREMENTAL_NUMBER	14
+#define	EPI_INCREMENTAL_NUMBER	22
 
 #define	EPI_BUILD_NUMBER	0
 
-#define	EPI_VERSION		5, 90, 125, 14
+#define	EPI_VERSION		5, 90, 125, 22
 
-#define	EPI_VERSION_NUM		0x055a7d0e
+#define	EPI_VERSION_NUM		0x055a7d16
 
 #define EPI_VERSION_DEV		5.90.125
 
 
-#define	EPI_VERSION_STR		"5.90.125.14"
+#define	EPI_VERSION_STR		"5.90.125.22"
 
 #endif 
diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h
index ddcf8df60a39..fd399cbf2772 100644
--- a/drivers/net/wireless/bcmdhd/include/linuxver.h
+++ b/drivers/net/wireless/bcmdhd/include/linuxver.h
@@ -136,7 +136,7 @@ typedef irqreturn_t(*FN_ISR) (int irq, void *dev_id, struct pt_regs *ptregs);
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
 #include <net/lib80211.h>
 #endif
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 30)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 29)
 #include <linux/ieee80211.h>
 #else
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 14)
diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h
index c824692b394b..d78ecfc2726b 100644
--- a/drivers/net/wireless/bcmdhd/include/wlioctl.h
+++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h
@@ -633,8 +633,17 @@ typedef struct _pmkid_cand_list {
 	pmkid_cand_t    pmkid_cand[1];
 } pmkid_cand_list_t;
 
-
-
+typedef struct wl_assoc_info {
+	uint32      req_len;
+	uint32      resp_len;
+	uint32      flags;
+	struct dot11_assoc_req req;
+	struct ether_addr reassoc_bssid; /* used in reassoc's */
+	struct dot11_assoc_resp resp;
+} wl_assoc_info_t;
+
+/* flags */
+#define WLC_ASSOC_REQ_IS_REASSOC 0x01 /* assoc req was actually a reassoc */
 
 #define WLC_TXFILTER_OVERRIDE_DISABLED  0
 #define WLC_TXFILTER_OVERRIDE_ENABLED   1
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index ce28a050728d..f2480e9c1016 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -29,6 +29,10 @@
 #include <osl.h>
 #include <linux/kernel.h>
 
+#ifdef CONFIG_SYSCTL
+#include <linux/sysctl.h>
+#endif
+
 #include <bcmutils.h>
 #include <bcmwifi.h>
 #include <bcmendian.h>
@@ -62,13 +66,14 @@
 #include <bcmsdbus.h>
 
 #include <wlioctl.h>
+#include <wldev_common.h>
 #include <wl_cfg80211.h>
 #include <wl_cfgp2p.h>
 
 static struct sdio_func *cfg80211_sdio_func;
 static struct wl_dev *wl_cfg80211_dev;
 
-u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
+u32 wl_dbg_level = WL_DBG_ERR;
 
 #define WL_4329_FW_FILE "brcm/bcm4329-fullmac-4-218-248-5.bin"
 #define WL_4329_NVRAM_FILE "brcm/bcm4329-fullmac-4-218-248-5.txt"
@@ -76,7 +81,44 @@ u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
 #define MAC2STR(a) (a)[0], (a)[1], (a)[2], (a)[3], (a)[4], (a)[5]
 #define MACSTR "%02x:%02x:%02x:%02x:%02x:%02x"
 #define MAX_WAIT_TIME 3000
+static s8 ioctlbuf[WLC_IOCTL_MAXLEN];
+
+#ifdef CONFIG_SYSCTL
+#define MAC_STRING_LEN (sizeof(u8) * 17)
+u8 wl_sysctl_macstring[2][MAC_STRING_LEN];
 
+static ctl_table wl_sysctl_child[] = {
+	{
+	.procname = "p2p_dev_addr",
+	.data = &wl_sysctl_macstring[0],
+	.maxlen = MAC_STRING_LEN,
+	.mode =  0444,
+	.child = NULL,
+	.proc_handler = proc_dostring,
+	},
+	{
+	.procname = "p2p_int_addr",
+	.data = &wl_sysctl_macstring[1],
+	.maxlen = MAC_STRING_LEN,
+	.mode =  0444,
+	.child = NULL,
+	.proc_handler = proc_dostring,
+	},
+	{0}
+};
+static ctl_table wl_sysctl_table[] = {
+	{
+	.procname = "wifi",
+	.data = NULL,
+	.maxlen = 0,
+	.mode =  0555,
+	.child = wl_sysctl_child,
+	.proc_handler = proc_dostring,
+	},
+	{0}
+};
+static struct ctl_table_header *wl_sysctl_hdr;
+#endif /* CONFIG_SYSCTL */ 
 
 /* Data Element Definitions */
 #define WPS_ID_CONFIG_METHODS     0x1008
@@ -90,7 +132,9 @@ u32 wl_dbg_level = WL_DBG_ERR | WL_DBG_INFO;
 /*
  * cfg80211_ops api/callback list
  */
-
+static s32 wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
+	const struct ether_addr *sa, const struct ether_addr *bssid,
+	u8 **pheader, u32 *body_len, u8 *pbody);
 static s32 __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	struct cfg80211_scan_request *request,
 	struct cfg80211_ssid *this_ssid);
@@ -119,15 +163,9 @@ static s32 wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 	enum nl80211_tx_power_setting type,
 	s32 dbm);
 static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm);
-#ifdef NEW_COMPAT_WIRELESS
 static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
 	struct net_device *dev,
 	u8 key_idx, bool unicast, bool multicast);
-#else
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-	struct net_device *dev,
-	u8 key_idx);
-#endif /* NEW_COMPAT_WIRELESS */
 static s32 wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	u8 key_idx, bool pairwise, const u8 *mac_addr,
 	struct key_params *params);
@@ -161,7 +199,7 @@ static void wl_init_eq_lock(struct wl_priv *wl);
 static void wl_init_event_handler(struct wl_priv *wl);
 static struct wl_event_q *wl_deq_event(struct wl_priv *wl);
 static s32 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 type,
-	const wl_event_msg_t *msg, void *data);
+	const wl_event_msg_t *msg, void *data, gfp_t gfp);
 static void wl_put_event(struct wl_event_q *e);
 static void wl_wakeup_event(struct wl_priv *wl);
 static s32 wl_notify_connect_status(struct wl_priv *wl,
@@ -195,8 +233,6 @@ static __used s32 wl_dev_bufvar_set(struct net_device *dev, s8 *name,
 static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val);
 static s32 wl_dev_intvar_get(struct net_device *dev, s8 *name,
 	s32 *retval);
-static s32 wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg,
-	u32 len);
 
 /*
  * cfg80211 set_wiphy_params utilities
@@ -275,18 +311,18 @@ static void *wl_get_drvdata(struct wl_dev *dev);
 /*
  * ibss mode utilities
  */
-static bool wl_is_ibssmode(struct wl_priv *wl);
+static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev);
 static __used bool wl_is_ibssstarter(struct wl_priv *wl);
 
 /*
  * dongle up/down , default configuration utilities
  */
 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e);
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e);
+static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev);
 static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e);
 static void wl_link_up(struct wl_priv *wl);
 static void wl_link_down(struct wl_priv *wl);
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype);
+static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype);
 static s32 __wl_cfg80211_up(struct wl_priv *wl);
 static s32 __wl_cfg80211_down(struct wl_priv *wl);
 static s32 wl_dongle_probecap(struct wl_priv *wl);
@@ -297,7 +333,6 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev);
  * dongle configuration utilities
  */
 #ifndef EMBEDDED_PLATFORM
-/* static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype); */
 static s32 wl_dongle_country(struct net_device *ndev, u8 ccode);
 static s32 wl_dongle_up(struct net_device *ndev, u32 up);
 static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode);
@@ -325,12 +360,6 @@ static void wl_iscan_timer(unsigned long data);
 static void wl_term_iscan(struct wl_priv *wl);
 static s32 wl_init_iscan(struct wl_priv *wl);
 static s32 wl_iscan_thread(void *data);
-static s32 wl_dev_iovar_setbuf(struct net_device *dev, s8 *iovar,
-	void *param, s32 paramlen, void *bufptr,
-	s32 buflen);
-static s32 wl_dev_iovar_getbuf(struct net_device *dev, s8 *iovar,
-	void *param, s32 paramlen, void *bufptr,
-	s32 buflen);
 static s32 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid,
 	u16 action);
 static s32 wl_do_iscan(struct wl_priv *wl);
@@ -344,11 +373,7 @@ static s32 wl_iscan_done(struct wl_priv *wl);
 static s32 wl_iscan_pending(struct wl_priv *wl);
 static s32 wl_iscan_inprogress(struct wl_priv *wl);
 static s32 wl_iscan_aborted(struct wl_priv *wl);
-#ifdef NOT_YET
-static s32 wl_dongle_save_eventmsg(struct wl_priv *wl);
-static s32 wl_dongle_disable_eventmsg(struct wl_priv *wl);
-static s32 wl_dongle_restore_eventmsg(struct wl_priv *wl);
-#endif /* NOT_YET */
+
 /*
  * fw/nvram downloading handler
  */
@@ -365,7 +390,7 @@ static __used u32 wl_find_msb(u16 bit16);
 static __used s32 wl_update_pmklist(struct net_device *dev,
 	struct wl_pmk_list *pmk_list, s32 err);
 
-static void wl_set_mpc(struct net_device *ndev, int mpc);
+static void wl_set_mpc(struct net_device *ndev, s32 mpc);
 
 /*
  * debufs support
@@ -469,7 +494,7 @@ static struct ieee80211_rate __wl_rates[] = {
 	RATETAB_ENT(WLC_RATE_24M, 0),
 	RATETAB_ENT(WLC_RATE_36M, 0),
 	RATETAB_ENT(WLC_RATE_48M, 0),
-	RATETAB_ENT(WLC_RATE_54M, 0),
+	RATETAB_ENT(WLC_RATE_54M, 0)
 };
 
 #define wl_a_rates		(__wl_rates + 4)
@@ -491,7 +516,7 @@ static struct ieee80211_channel __wl_2ghz_channels[] = {
 	CHAN2G(11, 2462, 0),
 	CHAN2G(12, 2467, 0),
 	CHAN2G(13, 2472, 0),
-	CHAN2G(14, 2484, 0),
+	CHAN2G(14, 2484, 0)
 };
 
 static struct ieee80211_channel __wl_5ghz_a_channels[] = {
@@ -513,7 +538,7 @@ static struct ieee80211_channel __wl_5ghz_a_channels[] = {
 	CHAN5G(192, 0), CHAN5G(196, 0),
 	CHAN5G(200, 0), CHAN5G(204, 0),
 	CHAN5G(208, 0), CHAN5G(212, 0),
-	CHAN5G(216, 0),
+	CHAN5G(216, 0)
 };
 
 static struct ieee80211_channel __wl_5ghz_n_channels[] = {
@@ -571,7 +596,7 @@ static struct ieee80211_channel __wl_5ghz_n_channels[] = {
 	CHAN5G(214, 0), CHAN5G(216, 0),
 	CHAN5G(218, 0), CHAN5G(220, 0),
 	CHAN5G(222, 0), CHAN5G(224, 0),
-	CHAN5G(226, 0), CHAN5G(228, 0),
+	CHAN5G(226, 0), CHAN5G(228, 0)
 };
 
 static struct ieee80211_supported_band __wl_band_2ghz = {
@@ -579,7 +604,7 @@ static struct ieee80211_supported_band __wl_band_2ghz = {
 	.channels = __wl_2ghz_channels,
 	.n_channels = ARRAY_SIZE(__wl_2ghz_channels),
 	.bitrates = wl_g_rates,
-	.n_bitrates = wl_g_rates_size,
+	.n_bitrates = wl_g_rates_size
 };
 
 static struct ieee80211_supported_band __wl_band_5ghz_a = {
@@ -587,7 +612,7 @@ static struct ieee80211_supported_band __wl_band_5ghz_a = {
 	.channels = __wl_5ghz_a_channels,
 	.n_channels = ARRAY_SIZE(__wl_5ghz_a_channels),
 	.bitrates = wl_a_rates,
-	.n_bitrates = wl_a_rates_size,
+	.n_bitrates = wl_a_rates_size
 };
 
 static struct ieee80211_supported_band __wl_band_5ghz_n = {
@@ -595,7 +620,7 @@ static struct ieee80211_supported_band __wl_band_5ghz_n = {
 	.channels = __wl_5ghz_n_channels,
 	.n_channels = ARRAY_SIZE(__wl_5ghz_n_channels),
 	.bitrates = wl_a_rates,
-	.n_bitrates = wl_a_rates_size,
+	.n_bitrates = wl_a_rates_size
 };
 
 static const u32 __wl_cipher_suites[] = {
@@ -603,7 +628,7 @@ static const u32 __wl_cipher_suites[] = {
 	WLAN_CIPHER_SUITE_WEP104,
 	WLAN_CIPHER_SUITE_TKIP,
 	WLAN_CIPHER_SUITE_CCMP,
-	WLAN_CIPHER_SUITE_AES_CMAC,
+	WLAN_CIPHER_SUITE_AES_CMAC
 };
 
 /* There isn't a lot of sense in it, but you can transmit anything you like */
@@ -653,7 +678,7 @@ wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
 		BIT(IEEE80211_STYPE_AUTH >> 4) |
 		BIT(IEEE80211_STYPE_DEAUTH >> 4) |
 		BIT(IEEE80211_STYPE_ACTION >> 4)
-	},
+	}
 };
 
 static void swap_key_from_BE(struct wl_wsec_key *key)
@@ -678,33 +703,6 @@ static void swap_key_to_BE(struct wl_wsec_key *key)
 	key->iv_initialized = dtoh32(key->iv_initialized);
 }
 
-static s32
-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len)
-{
-	struct ifreq ifr;
-	struct wl_ioctl ioc;
-	mm_segment_t fs;
-	s32 err = 0;
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = cmd;
-	ioc.buf = arg;
-	ioc.len = len;
-	strcpy(ifr.ifr_name, dev->name);
-	ifr.ifr_data = (caddr_t)&ioc;
-
-	fs = get_fs();
-	set_fs(get_ds());
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
-	err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#else
-	err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
-	set_fs(fs);
-
-	return err;
-}
-
 /* For debug: Dump the contents of the encoded wps ie buffe */
 static void
 wl_dbg_dump_wps_ie(char *wps_ie)
@@ -777,13 +775,14 @@ wl_dbg_dump_wps_ie(char *wps_ie)
 
 static struct net_device *
 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
-                              enum nl80211_iftype type, u32 *flags,
-                              struct vif_params *params)
+	enum nl80211_iftype type, u32 *flags,
+	struct vif_params *params)
 {
 	s32 err;
 	s32 timeout = -1;
 	s32 wlif_type;
 	s32 index = 0;
+	s32 mode = 0;
 	chanspec_t chspec;
 	struct wl_priv *wl = WL_PRIV_GET();
 	struct net_device *_ndev;
@@ -796,19 +795,19 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 	case NL80211_IFTYPE_WDS:
 	case NL80211_IFTYPE_MESH_POINT:
 		WL_ERR(("Unsupported interface type\n"));
-		wl->conf->mode = WL_MODE_IBSS;
+		mode = WL_MODE_IBSS;
 		return NULL;
 	case NL80211_IFTYPE_MONITOR:
 		return  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
-	    wlif_type = WL_P2P_IF_CLIENT;
-		wl->conf->mode = WL_MODE_BSS;
+		wlif_type = WL_P2P_IF_CLIENT;
+		mode = WL_MODE_BSS;
 		break;
 	case NL80211_IFTYPE_P2P_GO:
 	case NL80211_IFTYPE_AP:
 		wlif_type = WL_P2P_IF_GO;
-		wl->conf->mode = WL_MODE_AP;
+		mode = WL_MODE_AP;
 		break;
 	default:
 		WL_ERR(("Unsupported interface type\n"));
@@ -821,6 +820,26 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 		return NULL;
 	}
 
+	if (test_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status) == 1) {
+		/* wait till IF_DEL is complete
+		 * release the lock for the unregister to proceed
+		 */
+		rtnl_unlock();
+		WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", __func__));
+		timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
+			(test_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status) == FALSE),
+			msecs_to_jiffies(MAX_WAIT_TIME));
+
+		/* put back the rtnl_lock again */
+		rtnl_lock();
+		if (timeout > 0) {
+			WL_ERR(("IF DEL is Success\n"));
+
+		} else {
+			WL_ERR(("%s: timeount < 0, return -EAGAIN\n", __func__));
+			return ERR_PTR(-EAGAIN);
+		}
+	}
 	if (!wl->p2p_on && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
 		wl->p2p_on = true;
 		wl_cfgp2p_init_discovery(wl);
@@ -836,16 +855,16 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 	/* For P2P mode, use P2P-specific driver features to create the
 	 * bss: "wl p2p_ifadd"
 	 */
-	clear_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
+	set_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
 	err = wl_cfgp2p_ifadd(wl, &wl->p2p_int_addr, htod32(wlif_type), chspec);
 
 	if (unlikely(err))
 		return ERR_PTR(-ENOMEM);
 
 	timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
-		(test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status) == TRUE),
+		(test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status) == FALSE),
 		msecs_to_jiffies(MAX_WAIT_TIME));
-	if (timeout > 0 && test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status)) {
+	if (timeout > 0 && (!test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status))) {
 
 		struct wireless_dev *vwdev;
 		vwdev = kzalloc(sizeof(*vwdev), GFP_KERNEL);
@@ -859,17 +878,17 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 		wl->vwdev[index] = vwdev;
 		vwdev->iftype =
 			(wlif_type == WL_P2P_IF_CLIENT) ? NL80211_IFTYPE_STATION
-			                                 : NL80211_IFTYPE_AP;
+			: NL80211_IFTYPE_AP;
 		_ndev =  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
 		_ndev->ieee80211_ptr = vwdev;
 		SET_NETDEV_DEV(_ndev, wiphy_dev(vwdev->wiphy));
 		vwdev->netdev = _ndev;
 		set_bit(WL_STATUS_READY, &wl->status);
 		wl->p2p_vif_created = TRUE;
+		set_mode_by_netdev(wl, _ndev, mode);
 		wl = wdev_to_wl(vwdev);
 		return _ndev;
 
-
 	} else {
 		clear_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
 		WL_ERR((" virtual interface(%s) is not created \n", wl->p2p_vir_ifname));
@@ -892,6 +911,9 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
 			wl_cfg80211_scan_abort(wl, dev);
 		}
 		wl_cfgp2p_ifdel(wl, &p2p_mac);
+		WL_ERR(("ifdel command sent to Firmware.. "
+				"and we just come out without waiting.."));
+		set_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status);
 
 	}
 
@@ -901,15 +923,16 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
 
 static s32
 wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
-                                enum nl80211_iftype type, u32 *flags,
-                                struct vif_params *params)
+	enum nl80211_iftype type, u32 *flags,
+	struct vif_params *params)
 {
 	s32 ap = 0;
 	s32 infra = 0;
 	s32 err = BCME_OK;
-	chanspec_t chspec;
 	s32 timeout = -1;
 	s32 wlif_type;
+	s32 mode = 0;
+	chanspec_t chspec;
 	struct wl_priv *wl = WL_PRIV_GET();
 	CHECK_SYS_UP();
 	switch (type) {
@@ -921,17 +944,17 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
 			type));
 		break;
 	case NL80211_IFTYPE_ADHOC:
-		wl->conf->mode = WL_MODE_IBSS;
+		mode = WL_MODE_IBSS;
 		break;
 	case NL80211_IFTYPE_STATION:
 	case NL80211_IFTYPE_P2P_CLIENT:
-		wl->conf->mode = WL_MODE_BSS;
+		mode = WL_MODE_BSS;
 		infra = 1;
 		break;
 	case NL80211_IFTYPE_AP:
 	case NL80211_IFTYPE_AP_VLAN:
 	case NL80211_IFTYPE_P2P_GO:
-		wl->conf->mode = WL_MODE_AP;
+		mode = WL_MODE_AP;
 		ap = 1;
 		break;
 	default:
@@ -951,7 +974,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
 		timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
 			(test_bit(WLP2P_STATUS_IF_CHANGED, &wl->p2p_status) == TRUE),
 			msecs_to_jiffies(MAX_WAIT_TIME));
-
+		set_mode_by_netdev(wl, ndev, mode);
 		clear_bit(WLP2P_STATUS_IF_CHANGING, &wl->p2p_status);
 		clear_bit(WLP2P_STATUS_IF_CHANGED, &wl->p2p_status);
 	}
@@ -971,12 +994,12 @@ wl_cfg80211_notify_ifadd(struct net_device *net)
 	}
 
 	WL_DBG(("IF_ADD event called from dongle, old interface name: %s, new name: %s\n",
-	                                 net->name, wl->p2p_vir_ifname));
+		net->name, wl->p2p_vir_ifname));
 	/* Assign the net device to CONNECT BSSCFG */
 	strncpy(net->name, wl->p2p_vir_ifname, IFNAMSIZ - 1);
 	wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = net;
 	wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = P2PAPI_BSSCFG_CONNECTION;
-	set_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
+	clear_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status);
 	wake_up_interruptible(&wl->dongle_event_wait);
 	return ret;
 }
@@ -992,7 +1015,7 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
 	}
 
 	WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n",
-	                                 net->name, wl->p2p_vir_ifname));
+		net->name, wl->p2p_vir_ifname));
 	if (wl->p2p_vif_created) {
 		s32 index = 0;
 		memset(wl->p2p_vir_ifname, '\0', IFNAMSIZ);
@@ -1000,6 +1023,7 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
 		wl_to_p2p_bss_ndev(wl, index) = NULL;
 		wl_to_p2p_bss_bssidx(wl, index) = 0;
 		wl->p2p_vif_created = FALSE;
+		set_mode_by_netdev(wl, net, -1);
 		wl_cfgp2p_clear_management_ie(wl,
 			index);
 		index = get_idx_vwdev_by_netdev(wl, net);
@@ -1007,10 +1031,24 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
 		if (index >= 0) {
 				free_vwdev_by_index(wl, index);
 		}
+		/* Another option.. Make the IF_ADD wait, if the IF_DEL is not complete.. */
+		clear_bit(WLP2P_STATUS_IF_DELETING, &wl->p2p_status);
+		WL_ERR(("Cleared IF_DELETING status bit\n"));
+		wake_up_interruptible(&wl->dongle_event_wait);
+		WL_ERR(("Cleared IF_DELETING status bit DONE WAKEUP Interruptible\n"));
 	}
 	return 0;
 }
 
+s32
+wl_cfg80211_is_progress_ifadd(void)
+{
+	s32 is_progress = 0;
+	struct wl_priv *wl = WL_PRIV_GET();
+	if (test_bit(WLP2P_STATUS_IF_ADD, &wl->p2p_status))
+		is_progress = 1;
+	return is_progress;
+}
 
 s32
 wl_cfg80211_is_progress_ifchange(void)
@@ -1054,43 +1092,19 @@ static void wl_iscan_prep(struct wl_scan_params *params, struct wlc_ssid *ssid)
 
 }
 
-static s32
-wl_dev_iovar_setbuf(struct net_device *dev, s8 * iovar, void *param,
-	s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 iolen;
-
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(unlikely(!iolen));
-
-	return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen);
-}
-
-static s32
-wl_dev_iovar_getbuf(struct net_device *dev, s8 * iovar, void *param,
-	s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 iolen;
-
-	iolen = bcm_mkiovar(iovar, param, paramlen, bufptr, buflen);
-	BUG_ON(unlikely(!iolen));
-
-	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen);
-}
-
 static s32
 wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
 {
 	s32 params_size =
-	    (WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
+		(WL_SCAN_PARAMS_FIXED_SIZE + offsetof(wl_iscan_params_t, params));
 	struct wl_iscan_params *params;
 	s32 err = 0;
 
 	if (ssid && ssid->SSID_len)
-	    params_size += sizeof(struct wlc_ssid);
+		params_size += sizeof(struct wlc_ssid);
 	params = (struct wl_iscan_params *)kzalloc(params_size, GFP_KERNEL);
 	if (unlikely(!params))
-	    return -ENOMEM;
+		return -ENOMEM;
 	memset(params, 0, params_size);
 	BUG_ON(unlikely(params_size >= WLC_IOCTL_SMLEN));
 
@@ -1101,13 +1115,13 @@ wl_run_iscan(struct wl_iscan_ctrl *iscan, struct wlc_ssid *ssid, u16 action)
 	params->scan_duration = htod16(0);
 
 	/* params_size += offsetof(wl_iscan_params_t, params); */
-	err = wl_dev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
+	err = wldev_iovar_setbuf(iscan->dev, "iscan", params, params_size,
 		iscan->ioctl_buf, WLC_IOCTL_SMLEN);
 	if (unlikely(err)) {
-	    if (err == -EBUSY) {
+		if (err == -EBUSY) {
 		WL_INFO(("system busy : iscan canceled\n"));
 		} else {
-		    WL_ERR(("error (%d)\n", err));
+			WL_ERR(("error (%d)\n", err));
 		}
 	}
 	kfree(params);
@@ -1128,8 +1142,8 @@ static s32 wl_do_iscan(struct wl_priv *wl)
 	iscan->state = WL_ISCAN_STATE_SCANING;
 
 	passive_scan = wl->active_scan ? 0 : 1;
-	err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-		&passive_scan, sizeof(passive_scan));
+	err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+		&passive_scan, sizeof(passive_scan), FALSE);
 	if (unlikely(err)) {
 		WL_DBG(("error (%d)\n", err));
 		return err;
@@ -1185,8 +1199,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
 		params->version = htod32(ESCAN_REQ_VERSION);
 		params->action =  htod16(action);
 		params->sync_id = htod16(0x1234);
-		wl_dev_iovar_setbuf(ndev, "escan", params, params_size,
-		                    wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN);
+		wldev_iovar_setbuf(ndev, "escan", params, params_size,
+			wl->escan_ioctl_buf, WLC_IOCTL_MEDLEN);
 		kfree(params);
 	}
 	else if (wl->p2p_on && wl->p2p_scan) {
@@ -1195,7 +1209,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
 			num_chans = scan_request->n_channels;
 			WL_INFO((" chann number : %d\n", num_chans));
 			default_chan_list = kzalloc(num_chans * sizeof(*default_chan_list),
-			                             GFP_KERNEL);
+				GFP_KERNEL);
 			if (default_chan_list == NULL) {
 				WL_ERR(("channel list allocation failed \n"));
 				err = -ENOMEM;
@@ -1205,7 +1219,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
 			{
 				default_chan_list[i] =
 				ieee80211_frequency_to_channel(
-				         scan_request->channels[i]->center_freq);
+					scan_request->channels[i]->center_freq);
 			}
 			if (num_chans == 3 && (
 						(default_chan_list[0] == SOCIAL_CHAN_1) &&
@@ -1219,8 +1233,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
 			}
 
 		}
-		err = wl_cfgp2p_escan(wl, wl->active_scan, num_chans, default_chan_list,
-		        search_state, action,
+		err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list,
+			search_state, action,
 			wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
 		kfree(default_chan_list);
 	}
@@ -1242,8 +1256,8 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl
 	wl->escan_info.wiphy = wiphy;
 	wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
 	passive_scan = wl->active_scan ? 0 : 1;
-	err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-	        &passive_scan, sizeof(passive_scan));
+	err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+		&passive_scan, sizeof(passive_scan), FALSE);
 	if (unlikely(err)) {
 		WL_DBG(("error (%d)\n", err));
 		return err;
@@ -1346,7 +1360,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
 		if (wl->p2p_on && wl->p2p_scan) {
 
-			err = wl_cfgp2p_enable_discovery(wl, request->ie, request->ie_len);
+			err = wl_cfgp2p_enable_discovery(wl, ndev, request->ie, request->ie_len);
 
 			if (unlikely(err)) {
 				goto scan_out;
@@ -1374,15 +1388,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 		}
 		WL_DBG(("sr->ssid.SSID_len (%d)\n", sr->ssid.SSID_len));
 		passive_scan = wl->active_scan ? 0 : 1;
-		err = wl_dev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-			&passive_scan, sizeof(passive_scan));
+		err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
+			&passive_scan, sizeof(passive_scan), FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
 			goto scan_out;
 		}
 		wl_set_mpc(ndev, 0);
-		err = wl_dev_ioctl(ndev, WLC_SCAN, &sr->ssid,
-			sizeof(sr->ssid));
+		err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
+			sizeof(sr->ssid), FALSE);
 		if (err) {
 			if (err == -EBUSY) {
 				WL_INFO(("system busy : scan for \"%s\" "
@@ -1430,7 +1444,7 @@ static s32 wl_dev_intvar_set(struct net_device *dev, s8 *name, s32 val)
 	len = bcm_mkiovar(name, (char *)(&val), sizeof(val), buf, sizeof(buf));
 	BUG_ON(unlikely(!len));
 
-	err = wl_dev_ioctl(dev, WLC_SET_VAR, buf, len);
+	err = wldev_ioctl(dev, WLC_SET_VAR, buf, len, FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 	}
@@ -1452,7 +1466,7 @@ wl_dev_intvar_get(struct net_device *dev, s8 *name, s32 *retval)
 	len = bcm_mkiovar(name, (char *)(&data_null), 0,
 		(char *)(&var), sizeof(var.buf));
 	BUG_ON(unlikely(!len));
-	err = wl_dev_ioctl(dev, WLC_GET_VAR, &var, len);
+	err = wldev_ioctl(dev, WLC_GET_VAR, &var, len, FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 	}
@@ -1491,7 +1505,7 @@ static s32 wl_set_retry(struct net_device *dev, u32 retry, bool l)
 	u32 cmd = (l ? WLC_SET_LRL : WLC_SET_SRL);
 
 	retry = htod32(retry);
-	err = wl_dev_ioctl(dev, cmd, &retry, sizeof(retry));
+	err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
 		return err;
@@ -1507,14 +1521,14 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed)
 
 	CHECK_SYS_UP();
 	if (changed & WIPHY_PARAM_RTS_THRESHOLD &&
-	    (wl->conf->rts_threshold != wiphy->rts_threshold)) {
+		(wl->conf->rts_threshold != wiphy->rts_threshold)) {
 		wl->conf->rts_threshold = wiphy->rts_threshold;
 		err = wl_set_rts(ndev, wl->conf->rts_threshold);
 		if (!err)
 			return err;
 	}
 	if (changed & WIPHY_PARAM_FRAG_THRESHOLD &&
-	    (wl->conf->frag_threshold != wiphy->frag_threshold)) {
+		(wl->conf->frag_threshold != wiphy->frag_threshold)) {
 		wl->conf->frag_threshold = wiphy->frag_threshold;
 		err = wl_set_frag(ndev, wl->conf->frag_threshold);
 		if (!err)
@@ -1563,14 +1577,14 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 		ssid.ssid_len = params->ssid_len;
 		do {
 			if (unlikely
-			    (__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
-			     -EBUSY)) {
+				(__wl_cfg80211_scan(wiphy, dev, NULL, &ssid) ==
+				 -EBUSY)) {
 				wl_delay(150);
 			} else {
 				break;
 			}
 		} while (++scan_retry < WL_SCAN_RETRY_MAX);
-		/* to allow scan_inform to paropagate to cfg80211 plane */
+		/* to allow scan_inform to propagate to cfg80211 plane */
 		rtnl_unlock();
 
 		/* wait 4 secons till scan done.... */
@@ -1602,8 +1616,8 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 	else
 		memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
 
-	err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params,
-		sizeof(join_params));
+	err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
+		sizeof(join_params), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("Error (%d)\n", err));
 		return err;
@@ -1642,7 +1656,7 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme)
 		val = WPA_AUTH_DISABLED;
 
 	WL_DBG(("setting wpa_auth to 0x%0x\n", val));
-	err = wl_cfgp2p_bssiovar_setint(dev, "wpa_auth", bssidx, val);
+	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("set wpa_auth failed (%d)\n", err));
 		return err;
@@ -1681,7 +1695,7 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
 		break;
 	}
 
-	err = wl_cfgp2p_bssiovar_setint(dev, "auth", bssidx, val);
+	err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("set auth failed (%d)\n", err));
 		return err;
@@ -1747,9 +1761,9 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
 	WL_DBG(("pval (%d) gval (%d)\n", pval, gval));
 
 	if (is_wps_conn(sme)) {
-		err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, 4);
+		err = wldev_iovar_setint_bsscfg(dev, "wsec", 4, bssidx);
 	} else {
-		err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, pval | gval);
+		err = wldev_iovar_setint_bsscfg(dev, "wsec", pval | gval, bssidx);
 	}
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
@@ -1808,7 +1822,7 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
 
 		WL_DBG(("setting wpa_auth to %d\n", val));
 
-		err = wl_cfgp2p_bssiovar_setint(dev, "wpa_auth", bssidx, val);
+		err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx);
 		if (unlikely(err)) {
 			WL_ERR(("could not set wpa_auth (%d)\n", err));
 			return err;
@@ -1866,7 +1880,8 @@ wl_set_set_sharedkey(struct net_device *dev,
 				key.len, key.index, key.algo));
 			WL_DBG(("key \"%s\"\n", key.data));
 			swap_key_from_BE(&key);
-			err = wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+			err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key),
+				ioctlbuf, sizeof(ioctlbuf), bssidx);
 			if (unlikely(err)) {
 				WL_ERR(("WLC_SET_KEY error (%d)\n", err));
 				return err;
@@ -1874,7 +1889,7 @@ wl_set_set_sharedkey(struct net_device *dev,
 			if (sec->auth_type == NL80211_AUTHTYPE_OPEN_SYSTEM) {
 				WL_DBG(("set auth_type to shared key\n"));
 				val = 1;	/* shared key */
-				err = wl_cfgp2p_bssiovar_setint(dev, "auth", bssidx, val);
+				err = wldev_iovar_setint_bsscfg(dev, "auth", val, bssidx);
 				if (unlikely(err)) {
 					WL_ERR(("set auth failed (%d)\n", err));
 					return err;
@@ -1896,10 +1911,10 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 	s32 err = 0;
 
 	WL_TRACE(("In\n"));
+	CHECK_SYS_UP();
 	if (IS_P2P_SSID(sme->ssid) && (dev != wl_to_prmry_ndev(wl))) {
 		/* we only allow to connect using virtual interface in case of P2P */
 		if (wl->p2p_on && is_wps_conn(sme)) {
-
 			WL_DBG(("p2p index : %d\n", wl_cfgp2p_find_idx(wl, dev)));
 			/* Have to apply WPS IE + P2P IE in assoc req frame */
 			wl_cfgp2p_set_managment_ie(wl, dev,
@@ -1909,13 +1924,21 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 				P2PAPI_BSSCFG_DEVICE).p2p_probe_req_ie_len);
 			wl_cfgp2p_set_managment_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
 				VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
+		} else if (wl->p2p_on && (sme->crypto.wpa_versions & NL80211_WPA_VERSION_2)) {
+			/* This is the connect req after WPS is done [credentials exchanged] 
+			 * currently identified with WPA_VERSION_2 .
+			 * Update the previously set IEs with
+			 * the newly received IEs from Supplicant. This will remove the WPS IE from
+			 * the Assoc Req.
+			 */
+			wl_cfgp2p_set_managment_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev),
+				VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len);
 		}
+
 	} else {
 		WL_ERR(("No P2PIE in beacon \n"));
 	}
 
-
-	CHECK_SYS_UP();
 	if (unlikely(!sme->ssid)) {
 		WL_ERR(("Invalid ssid\n"));
 		return -EOPNOTSUPP;
@@ -1967,7 +1990,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
 		WL_ERR(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID,
 			join_params.ssid.SSID_len));
 	}
-	err = wl_dev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size);
+	err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 		return err;
@@ -1993,8 +2016,8 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 		scbval.val = reason_code;
 		memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
 		scbval.val = htod32(scbval.val);
-		err = wl_dev_ioctl(dev, WLC_DISASSOC, &scbval,
-			sizeof(scb_val_t));
+		err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
+			sizeof(scb_val_t), FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("error (%d)\n", err));
 			return err;
@@ -2035,7 +2058,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy,
 	/* Make sure radio is off or on as far as software is concerned */
 	disable = WL_RADIO_SW_DISABLE << 16;
 	disable = htod32(disable);
-	err = wl_dev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable));
+	err = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_SET_RADIO error (%d)\n", err));
 		return err;
@@ -2076,15 +2099,9 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm)
 	return err;
 }
 
-#ifdef NEW_COMPAT_WIRELESS
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-	struct net_device *dev,
+static s32
+wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
 	u8 key_idx, bool unicast, bool multicast)
-#else
-static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
-	struct net_device *dev,
-	u8 key_idx)
-#endif /* NEW_COMPAT_WIRELESS */
 {
 	struct wl_priv *wl = WL_PRIV_GET();
 	u32 index;
@@ -2094,23 +2111,17 @@ static s32 wl_cfg80211_config_default_key(struct wiphy *wiphy,
 
 	WL_DBG(("key index (%d)\n", key_idx));
 	CHECK_SYS_UP();
-	/* TODO: wl_cfgp2p_bssiovar_get seems to have a problem here
-	 * roll back to old way
-	 err = wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
-	 */
-	UNUSED_PARAMETER(bssidx);
-	err = wl_dev_ioctl(dev, WLC_GET_WSEC, &wsec, sizeof(wsec));
+	err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
 		return err;
 	}
-	wsec = dtoh32(wsec);
 	if (wsec & WEP_ENABLED) {
 		/* Just select a new current key */
 		index = (u32) key_idx;
 		index = htod32(index);
-		err = wl_dev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
-			sizeof(index));
+		err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
+			sizeof(index), FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("error (%d)\n", err));
 		}
@@ -2138,7 +2149,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 	if (key.len == 0) {
 		/* key delete */
 		swap_key_from_BE(&key);
-		wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+		wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+			sizeof(ioctlbuf), bssidx);
 		if (unlikely(err)) {
 			WL_ERR(("key delete error (%d)\n", err));
 			return err;
@@ -2165,7 +2177,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 			u8 *ivptr;
 			ivptr = (u8 *) params->seq;
 			key.rxiv.hi = (ivptr[5] << 24) | (ivptr[4] << 16) |
-			    (ivptr[3] << 8) | ivptr[2];
+				(ivptr[3] << 8) | ivptr[2];
 			key.rxiv.lo = (ivptr[1] << 8) | ivptr[0];
 			key.iv_initialized = true;
 		}
@@ -2199,7 +2211,8 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 #ifdef CONFIG_WIRELESS_EXT
 		dhd_wait_pend8021x(dev);
 #endif
-		wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+		wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+			sizeof(ioctlbuf), bssidx);
 		if (unlikely(err)) {
 			WL_ERR(("WLC_SET_KEY error (%d)\n", err));
 			return err;
@@ -2227,12 +2240,8 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	bssidx = wl_cfgp2p_find_idx(wl, dev);
 
 	if (mac_addr) {
-#if defined(P2P_CONFLICT_GONE)
 		wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
 		goto exit;
-#else
-		return wl_add_keyext(wiphy, dev, key_idx, mac_addr, params);
-#endif /* defined(P2P_CONFLICT_GONE) */
 	}
 	memset(&key, 0, sizeof(key));
 
@@ -2283,23 +2292,22 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 
 	/* Set the new key/index */
 	swap_key_from_BE(&key);
-	err = wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+	err = wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+		sizeof(ioctlbuf), bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_SET_KEY error (%d)\n", err));
 		return err;
 	}
-#if defined(P2P_CONFLICT_GONE)
+
 exit:
-#endif
-	val = WEP_ENABLED;
-	err = wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
+	err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("get wsec error (%d)\n", err));
 		return err;
 	}
-	wsec &= ~(WEP_ENABLED);
+
 	wsec |= val;
-	err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, wsec);
+	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("set wsec error (%d)\n", err));
 		return err;
@@ -2309,7 +2317,7 @@ exit:
 	/* TODO: Removed in P2P, check later --lm */
 	val = 1;		/* assume shared key. otherwise 0 */
 	val = htod32(val);
-	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
+	err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
 		return err;
@@ -2325,8 +2333,6 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	struct wl_wsec_key key;
 	struct wl_priv *wl = WL_PRIV_GET();
 	s32 err = 0;
-	s32 val;
-	s32 wsec = 0;
 	s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
 
 	WL_DBG(("Enter\n"));
@@ -2340,7 +2346,8 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	WL_DBG(("key index (%d)\n", key_idx));
 	/* Set the new key/index */
 	swap_key_from_BE(&key);
-	wl_cfgp2p_bssiovar_set(dev, "wsec_key", bssidx, &key, sizeof(key));
+	wldev_iovar_setbuf_bsscfg(dev, "wsec_key", &key, sizeof(key), ioctlbuf,
+		sizeof(ioctlbuf), bssidx);
 	if (unlikely(err)) {
 		if (err == -EINVAL) {
 			if (key.index >= DOT11_MAX_DEFAULT_KEYS) {
@@ -2353,26 +2360,11 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 		return err;
 	}
 
-	val = 0;
-	err = wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
-	if (unlikely(err)) {
-		WL_ERR(("get wsec error (%d)\n", err));
-		return err;
-	}
-
-	wsec &= ~(WEP_ENABLED);
-	wsec |= val;
-	err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, wsec);
-	if (unlikely(err)) {
-		WL_ERR(("set wsec error (%d)\n", err));
-		return err;
-	}
-
 #ifdef NOT_YET
 	/* TODO: Removed in P2P twig, check later --lin */
 	val = 0;		/* assume open key. otherwise 1 */
 	val = htod32(val);
-	err = wl_dev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val));
+	err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_SET_AUTH error (%d)\n", err));
 		return err;
@@ -2403,12 +2395,11 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 	params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len);
 	memcpy(params.key, key.data, params.key_len);
 
-	wl_cfgp2p_bssiovar_get(dev, "wsec", bssidx, &wsec, sizeof(wsec));
+	wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
 		return err;
 	}
-	wsec = dtoh32(wsec);
 	switch (wsec) {
 	case WEP_ENABLED:
 		sec = wl_read_prof(wl, WL_PROF_SEC);
@@ -2458,13 +2449,13 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 
 	CHECK_SYS_UP();
 	if (unlikely
-	    (memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
+		(memcmp(mac, wl_read_prof(wl, WL_PROF_BSSID), ETHER_ADDR_LEN))) {
 		WL_ERR(("Wrong Mac address\n"));
 		return -ENOENT;
 	}
 
 	/* Report the current tx rate */
-	err = wl_dev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate));
+	err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), FALSE);
 	if (err) {
 		WL_ERR(("Could not get rate (%d)\n", err));
 	} else {
@@ -2477,8 +2468,8 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 	if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
 		memset(&scb_val, 0, sizeof(scb_val));
 		scb_val.val = 0;
-		err = wl_dev_ioctl(dev, WLC_GET_RSSI, &scb_val,
-			sizeof(scb_val_t));
+		err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
+			sizeof(scb_val_t), FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("Could not get rssi (%d)\n", err));
 			return err;
@@ -2490,7 +2481,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 #if defined(ANDROID_WIRELESS_PATCH)
-	err = wl_dev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed));
+	err = wldev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed), FALSE);
 	sinfo->link_speed = sinfo->link_speed / 2; /* Convert internal 500Kbps to Mpbs */
 	if (!err)
 		sinfo->filled |= STATION_LINK_SPEED;
@@ -2512,7 +2503,7 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev,
 	pm = enabled ? PM_FAST : PM_OFF;
 	pm = htod32(pm);
 	WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled")));
-	err = wl_dev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm));
+	err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE);
 	if (unlikely(err)) {
 		if (err == -ENODEV)
 			WL_DBG(("net_device is not ready yet\n"));
@@ -2566,8 +2557,8 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 	CHECK_SYS_UP();
 	/* addr param is always NULL. ignore it */
 	/* Get current rateset */
-	err = wl_dev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
-		sizeof(rateset));
+	err = wldev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
+		sizeof(rateset), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("could not get current rateset (%d)\n", err));
 		return err;
@@ -2808,14 +2799,20 @@ wl_cfg80211_scan_abort(struct wl_priv *wl, struct net_device *ndev)
 		err = -ENOMEM;
 	}
 	/* Do a scan abort to stop the driver's scan engine */
-	err = wl_dev_ioctl(ndev, WLC_SCAN, params, params_size);
+	err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, FALSE);
 	if (err < 0) {
 		WL_ERR(("scan abort  failed \n"));
 	}
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
+	/* Report the scan abort to CFG driver too 
+	 * We will report it from the thread context, not from this context.
+	 */
 
-	if (wl->p2p_on && test_bit(WLP2P_STATUS_SCANNING, &wl->p2p_status))
-	clear_bit(WLP2P_STATUS_SCANNING, &wl->p2p_status);
+	{
+		wl_event_msg_t msg;
+		msg.event_type =  hton32(WLC_E_ESCAN_RESULT);
+		msg.status = WLC_E_STATUS_ABORT;
+		wl_cfg80211_event(ndev, &msg, NULL, GFP_ATOMIC);
+	}
 	return err;
 }
 static s32
@@ -2847,7 +2844,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
 		 * without turning on P2P
 		 */
 
-		err = wl_cfgp2p_enable_discovery(wl, NULL, 0);
+		err = wl_cfgp2p_enable_discovery(wl, dev, NULL, 0);
 
 		if (unlikely(err)) {
 			goto exit;
@@ -2892,9 +2889,12 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 	u32 p2pie_len = 0;
 	u32 wpsie_len = 0;
 	u16 fc;
+	bool ack = FALSE;
 	WL_DBG(("Enter \n"));
 	/* find bssidx based on ndev */
 	bssidx = wl_cfgp2p_find_idx(wl, dev);
+	/* cookie generation */
+	*cookie = (unsigned long) buf;
 
 	if (bssidx == -1) {
 
@@ -2908,47 +2908,16 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 		* channel.
 		*/
 		wl_cfgp2p_discover_enable_search(wl, FALSE);
+	    /* Abort the dwell time of any previous off-channel action frame that may
+	     * be still in effect.  Sending off-channel action frames relies on the
+	     * driver's scan engine.  If a previous off-channel action frame tx is
+	     * still in progress (including the dwell time), then this new action
+	     * frame will not be sent out.
+	     */
+		wl_cfg80211_scan_abort(wl, dev);
 	}
 	mgmt = (const struct ieee80211_mgmt *) buf;
 	fc = mgmt->frame_control;
-	switch (fc & IEEE80211_FCTL_STYPE) {
-	case IEEE80211_STYPE_ASSOC_REQ:
-		WL_DBG(("packet type: IEEE80211_STYPE_ASSOC_REQ, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_ASSOC_RESP:
-		WL_DBG(("packet type: IEEE80211_STYPE_ASSOC_RESP, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_REASSOC_REQ:
-		WL_DBG(("packet type: IEEE80211_STYPE_REASSOC_REQ, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_REASSOC_RESP:
-		WL_DBG(("packet type: IEEE80211_STYPE_REASSOC_RESP, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_PROBE_REQ:
-		WL_DBG(("packet type: IEEE80211_STYPE_PROBE_REQ, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_PROBE_RESP:
-		WL_DBG(("packet type: IEEE80211_STYPE_PROBE_RESP, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_BEACON:
-		WL_DBG(("packet type: IEEE80211_STYPE_BEACON, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_ATIM:
-		WL_DBG(("packet type: IEEE80211_STYPE_ATIM, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_DISASSOC:
-		WL_DBG(("packet type: IEEE80211_STYPE_DISASSOC, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_AUTH:
-		WL_DBG(("packet type: IEEE80211_STYPE_AUTH, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_DEAUTH:
-		WL_DBG(("packet type: IEEE80211_STYPE_DEAUTH, bssidx : %d\n", bssidx));
-		break;
-	case IEEE80211_STYPE_ACTION:
-		WL_DBG(("packet type: IEEE80211_STYPE_ACTION, bssidx : %d\n", bssidx));
-		break;
-	}
 	if (fc != IEEE80211_STYPE_ACTION) {
 		if (wl->p2p_on && (fc == IEEE80211_STYPE_PROBE_RESP)) {
 			s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
@@ -2960,8 +2929,10 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 				/* Have to change p2p device address in dev_info attribute
 				 * because Supplicant use primary eth0 address
 				 */
+			#ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */
 				wl_cfg80211_change_ifaddr((u8 *)p2p_ie,
 					&wl->p2p_dev_addr, P2P_SEID_DEV_INFO);
+			#endif
 			}
 			if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)(buf + ie_offset), ie_len))
 				!= NULL) {
@@ -3011,7 +2982,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 	 * Dwell time to stay off-channel to wait for a response action frame
 	 * after transmitting an GO Negotiation action frame
 	 */
-	af_params->dwell_time = 200;
+	af_params->dwell_time = WL_DWELL_TIME;
 
 	memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
 
@@ -3019,21 +2990,28 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 		wifi_p2p_pub_act_frame_t *act_frm =
 			(wifi_p2p_pub_act_frame_t *) (action_frame->data);
 		/*
-		 *  Have to change intented address from GO REQ or GO RSP
+		 *  Have to change intented address from GO REQ or GO RSP and INVITE REQ
 		 *  because wpa-supplicant use eth0 primary address
 		 */
-		if (act_frm->subtype == P2P_PAF_GON_REQ || act_frm->subtype == P2P_PAF_GON_RSP) {
+		if ((act_frm->subtype == P2P_PAF_GON_REQ)||
+		  (act_frm->subtype == P2P_PAF_GON_RSP)||
+		  (act_frm->subtype == P2P_PAF_GON_CONF)||
+		  (act_frm->subtype == P2P_PAF_INVITE_REQ)) {
 			p2p_ie = wl_cfgp2p_find_p2pie(act_frm->elts,
 				action_frame->len - P2P_PUB_AF_FIXED_LEN);
+		#ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */
 			wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_int_addr,
 				P2P_SEID_INTINTADDR);
 			wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr,
 				P2P_SEID_DEV_INFO);
+			wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr,
+				P2P_SEID_GROUP_ID);
+		#endif
 		}
 	}
 
-	err = wl_cfgp2p_tx_action_frame(wl, af_params, bssidx);
-	cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL);
+	ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? FALSE : TRUE;
+	cfg80211_mgmt_tx_status(dev, *cookie, buf, len, ack, GFP_KERNEL);
 
 	kfree(af_params);
 exit:
@@ -3092,7 +3070,7 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
 	channel = ieee80211_frequency_to_channel(chan->center_freq);
 	WL_DBG(("netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
 		dev->ifindex, channel_type, channel));
-	wl_dev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel));
+	wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), FALSE);
 
 	return err;
 }
@@ -3179,17 +3157,17 @@ wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
 			break;
 	}
 	/* set auth */
-	err = wl_cfgp2p_bssiovar_setint(dev, "auth", bssidx, auth);
+	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
 	if (err < 0) {
 		WL_ERR(("auth error %d\n", err));
 	}
 	/* set wsec */
-	err = wl_cfgp2p_bssiovar_setint(dev, "wsec", bssidx, wsec);
+	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
 	if (err < 0) {
 		WL_ERR(("wsec error %d\n", err));
 	}
 	/* set upper-layer auth */
-	err = wl_cfgp2p_bssiovar_setint(dev, "wpa_auth", bssidx, wpa_auth);
+	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
 	if (err < 0) {
 		WL_ERR(("wpa_auth error %d\n", err));
 	}
@@ -3230,62 +3208,70 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 
 	WL_DBG(("interval (%d) dtim_period (%d) head_len (%d) tail_len (%d)\n",
 		info->interval, info->dtim_period, info->head_len, info->tail_len));
+
+	/*
+	 * !!! The following code was NOT indented properly, PLEASE merge your code
+	 * to SVN verion becuase your merger tool may IGNORE tabs/spaces
+	 */
 	if (wl->p2p_on && (bssidx >= wl_to_p2p_bss_bssidx(wl,
 		P2PAPI_BSSCFG_CONNECTION))) {
-	/* We don't need to set beacon for P2P_GO,
-	 * but need to parse ssid from beacon_parameters
-	 * because there is no way to set ssid
-	 */
-	ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
-	/* find the SSID */
-	if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset], info->head_len - ie_offset,
-		DOT11_MNG_SSID_ID)) != NULL) {
-		memcpy(wl->p2p_ssid.SSID, ssid_ie->data, ssid_ie->len);
-		wl->p2p_ssid.SSID_len = ssid_ie->len;
-		WL_DBG(("SSID (%s) in Head \n", ssid_ie->data));
+		/* We don't need to set beacon for P2P_GO,
+		 * but need to parse ssid from beacon_parameters
+		 * because there is no way to set ssid
+		 */
+		ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
+		/* find the SSID */
+		if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
+			info->head_len - ie_offset,
+			DOT11_MNG_SSID_ID)) != NULL) {
+			memcpy(wl->p2p_ssid.SSID, ssid_ie->data, ssid_ie->len);
+			wl->p2p_ssid.SSID_len = ssid_ie->len;
+			WL_DBG(("SSID (%s) in Head \n", ssid_ie->data));
 
-	} else {
-		WL_ERR(("No SSID in beacon \n"));
-	}
+		} else {
+			WL_ERR(("No SSID in beacon \n"));
+		}
 
-	/* find the WPSIE */
-	if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
-		wpsie_len = wps_ie->length + sizeof(wps_ie->tag) + sizeof(wps_ie->length);
-		/*
-		 * Should be compared with saved ie before saving it
-		 */
+		/* find the WPSIE */
+		if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
+			wpsie_len = wps_ie->length + sizeof(wps_ie->tag) + sizeof(wps_ie->length);
+			/*
+			 * Should be compared with saved ie before saving it
+			 */
 			if (wl_dbg_level & WL_DBG_INFO)
 				wl_dbg_dump_wps_ie((char *) wps_ie);
-		memcpy(beacon_ie, wps_ie, wpsie_len);
-	} else {
-		WL_ERR(("No WPSIE in beacon \n"));
-	}
+			memcpy(beacon_ie, wps_ie, wpsie_len);
+		} else {
+			WL_ERR(("No WPSIE in beacon \n"));
+		}
 
 
-	/* find the P2PIE */
-	if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)info->tail, info->tail_len)) != NULL) {
-		/* Total length of P2P Information Element */
-		p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
-		/* Have to change device address in dev_id attribute because Supplicant
-		 * use primary eth0 address
-		 */
-		wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr, P2P_SEID_DEV_ID);
-		memcpy(&beacon_ie[wpsie_len], p2p_ie, p2pie_len);
+		/* find the P2PIE */
+		if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)info->tail, info->tail_len)) != NULL) {
+			/* Total length of P2P Information Element */
+			p2pie_len = p2p_ie->len + sizeof(p2p_ie->len) + sizeof(p2p_ie->id);
+		#ifdef ENABLE_DRIVER_CHANGE_IFADDR /* We are now doing this in supplicant */
+			/* Have to change device address in dev_id attribute because Supplicant
+			 * use primary eth0 address
+			 */
+			wl_cfg80211_change_ifaddr((u8 *)p2p_ie, &wl->p2p_dev_addr, P2P_SEID_DEV_ID);
+		#endif
+			memcpy(&beacon_ie[wpsie_len], p2p_ie, p2pie_len);
 
-	} else {
-		WL_ERR(("No P2PIE in beacon \n"));
-	}
+		} else {
+			WL_ERR(("No P2PIE in beacon \n"));
+		}
 		wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
-		     beacon_ie, wpsie_len + p2pie_len);
+			beacon_ie, wpsie_len + p2pie_len);
 		wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG,
-		     beacon_ie, wpsie_len + p2pie_len);
+			beacon_ie, wpsie_len + p2pie_len);
 		/* find the WPA_IE */
 		if ((wpa_ie = wl_cfgp2p_find_wpaie((u8 *)info->tail, info->tail_len)) != NULL) {
 			WL_DBG((" WPA IE is found\n"));
 		}
 		/* find the RSN_IE */
 		if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
-		     DOT11_MNG_RSN_ID)) != NULL) {
+			DOT11_MNG_RSN_ID)) != NULL) {
 			WL_DBG((" WPA2 IE is found\n"));
 		}
 		is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
@@ -3294,16 +3280,16 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 			wl_check_wpa2ie(dev, wpa2_ie, bssidx);
 			wl_check_wpaie(dev, (bcm_tlv_t *)wpa_ie, bssidx);
 
-			err = wl_dev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32));
-		if (err < 0) {
+			err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), FALSE);
+			if (err < 0) {
 				WL_ERR(("SET INFRA error %d\n", err));
-		}
+			}
 
-		err = wl_cfgp2p_bssiovar_set(dev, "ssid", bssidx, &wl->p2p_ssid,
-			sizeof(wl->p2p_ssid));
+			err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p_ssid,
+				sizeof(wl->p2p_ssid), ioctlbuf, sizeof(ioctlbuf), bssidx);
 
-		wl_cfgp2p_bss(dev, bssidx, 1);
-	}
+			wl_cfgp2p_bss(dev, bssidx, 1);
+		}
 	}
 	return 0;
 }
@@ -3364,7 +3350,7 @@ static struct cfg80211_ops wl_cfg80211_ops = {
 	.set_beacon = wl_cfg80211_set_beacon,
 #if defined(ANDROID_WIRELESS_PATCH)
 	.drv_start = wl_cfg80211_drv_start,
-	.drv_stop = wl_cfg80211_drv_stop,
+	.drv_stop = wl_cfg80211_drv_stop
 #endif
 };
 
@@ -3410,23 +3396,24 @@ static struct wireless_dev *wl_alloc_wdev(s32 sizeof_iface,
 	wdev->wiphy->max_scan_ssids = WL_NUM_SCAN_MAX;
 	wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX;
 	wdev->wiphy->interface_modes =
-	    BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP) |
-	    (BIT(NL80211_IFTYPE_P2P_CLIENT) | BIT(NL80211_IFTYPE_P2P_GO));
+	    BIT(NL80211_IFTYPE_STATION) | BIT(NL80211_IFTYPE_ADHOC) | BIT(NL80211_IFTYPE_AP);
+
 	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
 	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
 	wdev->wiphy->signal_type = CFG80211_SIGNAL_TYPE_MBM;
 	wdev->wiphy->cipher_suites = __wl_cipher_suites;
 	wdev->wiphy->n_cipher_suites = ARRAY_SIZE(__wl_cipher_suites);
-#ifdef NEW_COMPAT_WIRELESS
 	wdev->wiphy->max_remain_on_channel_duration = 5000;
-#endif
 	wdev->wiphy->mgmt_stypes = wl_cfg80211_default_mgmt_stypes;
 #ifndef WL_POWERSAVE_DISABLED
 	wdev->wiphy->flags |= WIPHY_FLAG_PS_ON_BY_DEFAULT;
 #else
 	wdev->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT;
 #endif				/* !WL_POWERSAVE_DISABLED */
-
+	wdev->wiphy->flags |= WIPHY_FLAG_NETNS_OK |
+		WIPHY_FLAG_4ADDR_AP |
+		WIPHY_FLAG_4ADDR_STATION |
+		WIPHY_FLAG_SUPPORTS_SEPARATE_DEFAULT_KEYS;
 	err = wiphy_register(wdev->wiphy);
 	if (unlikely(err < 0)) {
 		WL_ERR(("Couldn not register wiphy device (%d)\n", err));
@@ -3490,7 +3477,7 @@ static s32 wl_inform_bss(struct wl_priv *wl)
 
 static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 {
-	struct wiphy *wiphy = wl_to_wiphy(wl);
+	struct wiphy *wiphy = wiphy_from_scan(wl);
 	struct ieee80211_mgmt *mgmt;
 	struct ieee80211_channel *channel;
 	struct ieee80211_supported_band *band;
@@ -3548,7 +3535,11 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 		offsetof(struct wl_cfg80211_bss_info, frame_buf));
 	notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
 		u.beacon.variable) + wl_get_ielen(wl);
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(COMPAT_WIRELESS)
+	freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
+#else
 	freq = ieee80211_channel_to_frequency(notif_bss_info->channel, band->band);
+#endif
 	channel = ieee80211_get_channel(wiphy, freq);
 
 	WL_DBG(("SSID : \"%s\", rssi %d, channel %d, capability : 0x04%x, bssid %pM\n",
@@ -3570,42 +3561,21 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi)
 	return err;
 }
 
-static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e)
+static bool wl_is_linkup(struct wl_priv *wl, const wl_event_msg_t *e, struct net_device *ndev)
 {
-	/* To SK, chagne NOT_YET to 1 if you don't like this
-	 * But in general WLC_E_SET_SSID is more reliable --lin
-	 */
-#ifdef NOT_YET
-	u32 event = ntoh32(e->event_type);
-	u16 flags = ntoh16(e->flags);
-
-	if (event == WLC_E_LINK) {
-		if (flags & WLC_EVENT_MSG_LINK) {
-			if (wl_is_ibssmode(wl)) {
-				if (wl_is_ibssstarter(wl)) {
-				}
-			} else {
-				return true;
-			}
-		}
-	}
-	return false;
-#else
 	u32 event = ntoh32(e->event_type);
 	uint32 status =  ntoh32(e->status);
 
-	WL_DBG(("event %d\n", event));
-	/* was WLC_E_LINK here, changed as WLC_E_SET_SSID is more reliable -- lin */
+	WL_DBG(("event %d, status %d\n", event, status));
 	if (event == WLC_E_SET_SSID) {
 		if (status == WLC_E_STATUS_SUCCESS) {
-			if (!wl_is_ibssmode(wl))
+			if (!wl_is_ibssmode(wl, ndev))
 				return true;
 		}
 	}
 
 	WL_DBG(("wl_is_linkup false\n"));
 	return false;
-#endif /* NOT_YET */
 }
 
 static bool wl_is_linkdown(struct wl_priv *wl, const wl_event_msg_t *e)
@@ -3636,39 +3606,91 @@ static bool wl_is_nonetwork(struct wl_priv *wl, const wl_event_msg_t *e)
 	return false;
 }
 
-static bool wl_is_newsta(struct wl_priv *wl, const wl_event_msg_t *e)
-{
-	u32 event = ntoh32(e->event_type);
-	u32 status = ntoh32(e->status);
-
-	if (event == WLC_E_ASSOC_IND && (status == WLC_E_STATUS_SUCCESS)) {
-		return true;
-	}
-	return false;
-}
-
 static s32
 wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 	const wl_event_msg_t *e, void *data)
 {
 	bool act;
+	bool isfree = FALSE;
 	s32 err = 0;
+	s32 freq;
+	s32 channel;
 	u8 body[200];
+	u32 event = ntoh32(e->event_type);
+	u32 reason = ntoh32(e->reason);
+	u32 len = ntoh32(e->datalen);
+	u16 fc = 0;
+	u8 *mgmt_frame;
+	u8 bsscfgidx = e->bsscfgidx;
+	struct ieee80211_supported_band *band;
+	struct ether_addr da;
+	struct ether_addr bssid;
+	struct wiphy *wiphy = wl_to_wiphy(wl);
+	channel_info_t ci;
 
+	memset(body, 0, sizeof(body));
 	WL_DBG(("Enter \n"));
 
-	if (wl->conf->mode == WL_MODE_AP) {
-		if (wl_is_newsta(wl, e)) {
-			u32 len = ntoh32(e->datalen);
-			memcpy(body, e->addr.octet, ETHER_ADDR_LEN);
-			memcpy(&body[ETHER_ADDR_LEN], data, len);
-			cfg80211_send_rx_assoc(ndev, body, len + ETHER_ADDR_LEN);
+	if (get_mode_by_netdev(wl, ndev) == WL_MODE_AP) {
+		memcpy(body, data, len);
+		wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+		&da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
+		wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE);
+		switch (event) {
+			case WLC_E_ASSOC_IND:
+				fc = FC_ASSOC_REQ;
+				break;
+			case WLC_E_REASSOC_IND:
+				fc = FC_REASSOC_REQ;
+				break;
+			case WLC_E_DISASSOC_IND:
+				fc = FC_DISASSOC;
+				break;
+			case WLC_E_DEAUTH_IND:
+				fc = FC_DEAUTH;
+				break;
+			case WLC_E_DEAUTH:
+				fc = FC_DEAUTH;
+				break;
+			default:
+				fc = 0;
+				goto exit;
 		}
+		if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), FALSE)))
+			return err;
+
+		channel = dtoh32(ci.hw_channel);
+		if (channel <= CH_MAX_2G_CHANNEL)
+			band = wiphy->bands[IEEE80211_BAND_2GHZ];
+		else
+			band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(COMPAT_WIRELESS)
+		freq = ieee80211_channel_to_frequency(channel);
+#else
+		freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+
+		err = wl_frame_get_mgmt(fc, &da, &e->addr, &bssid,
+		&mgmt_frame, &len, body);
+		if (err < 0)
+				goto exit;
+		isfree = TRUE;
+
+		if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
+			cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+		} else if (event == WLC_E_DISASSOC_IND) {
+				cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+		} else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+			cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+		}
+
 	} else {
-		WL_ERR(("event %d ",  ntoh32(e->event_type)));
-		if (wl_is_linkup(wl, e)) {
+		WL_DBG(("wl_notify_connect_status : event %d status : %d \n",
+			ntoh32(e->event_type), ntoh32(e->status)));
+		if (wl_is_linkup(wl, e, ndev)) {
 			wl_link_up(wl);
-			if (wl_is_ibssmode(wl)) {
+			if (wl_is_ibssmode(wl, ndev)) {
 				printk("cfg80211_ibss_joined");
 				cfg80211_ibss_joined(ndev, (s8 *)&e->addr,
 					GFP_KERNEL);
@@ -3684,14 +3706,14 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 			wl_update_prof(wl, e, &act, WL_PROF_ACT);
 		} else if (wl_is_linkdown(wl, e)) {
 			if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
-				printk("link down, call cfg80211_disconnected");
+				printk("link down, call cfg80211_disconnected ");
 				cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
 				clear_bit(WL_STATUS_CONNECTED, &wl->status);
 				wl_link_down(wl);
 				wl_init_prof(wl->profile);
 			}
 		} else if (wl_is_nonetwork(wl, e)) {
-			printk("connect failed wl->status 0x%x", (int)wl->status);
+			printk("connect failed e->status 0x%x", (int)ntoh32(e->status));
 			if (test_bit(WL_STATUS_CONNECTING, &wl->status))
 				wl_bss_connect_done(wl, ndev, e, data, false);
 		} else {
@@ -3699,6 +3721,9 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 		}
 		printk("\n");
 	}
+exit:
+	if (isfree)
+		kfree(mgmt_frame);
 	return err;
 }
 
@@ -3726,7 +3751,7 @@ wl_dev_bufvar_set(struct net_device *dev, s8 *name, s8 *buf, s32 len)
 	buflen = bcm_mkiovar(name, buf, len, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
 	BUG_ON(unlikely(!buflen));
 
-	return wl_dev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen);
+	return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, FALSE);
 }
 
 static s32
@@ -3739,8 +3764,8 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
 
 	len = bcm_mkiovar(name, NULL, 0, wl->ioctl_buf, WL_IOCTL_LEN_MAX);
 	BUG_ON(unlikely(!len));
-	err = wl_dev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
-		WL_IOCTL_LEN_MAX);
+	err = wldev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
+		WL_IOCTL_LEN_MAX, FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 		return err;
@@ -3752,10 +3777,8 @@ wl_dev_bufvar_get(struct net_device *dev, s8 *name, s8 *buf,
 
 static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
 {
-	struct wl_assoc_ielen *assoc_info;
+	wl_assoc_info_t assoc_info;
 	struct wl_connect_info *conn_info = wl_to_conn(wl);
-	u32 req_len;
-	u32 resp_len;
 	s32 err = 0;
 
 	WL_DBG(("Enter \n"));
@@ -3765,31 +3788,35 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
 		WL_ERR(("could not get assoc info (%d)\n", err));
 		return err;
 	}
-	assoc_info = (struct wl_assoc_ielen *)wl->extra_buf;
-	req_len = assoc_info->req_len;
-	resp_len = assoc_info->resp_len;
-	if (req_len) {
+	memcpy(&assoc_info, wl->extra_buf, sizeof(wl_assoc_info_t));
+	assoc_info.req_len = htod32(assoc_info.req_len);
+	assoc_info.resp_len = htod32(assoc_info.resp_len);
+	assoc_info.flags = htod32(assoc_info.flags);
+	if (assoc_info.req_len) {
 		err = wl_dev_bufvar_get(ndev, "assoc_req_ies", wl->extra_buf,
 			WL_ASSOC_INFO_MAX);
 		if (unlikely(err)) {
 			WL_ERR(("could not get assoc req (%d)\n", err));
 			return err;
 		}
-		conn_info->req_ie_len = req_len;
+		conn_info->req_ie_len = assoc_info.req_len - sizeof(struct dot11_assoc_req);
+		if (assoc_info.flags & WLC_ASSOC_REQ_IS_REASSOC) {
+			conn_info->req_ie_len -= ETHER_ADDR_LEN;
+		}
 		conn_info->req_ie =
 		    kmemdup(wl->extra_buf, conn_info->req_ie_len, GFP_KERNEL);
 	} else {
 		conn_info->req_ie_len = 0;
 		conn_info->req_ie = NULL;
 	}
-	if (resp_len) {
+	if (assoc_info.resp_len) {
 		err = wl_dev_bufvar_get(ndev, "assoc_resp_ies", wl->extra_buf,
 			WL_ASSOC_INFO_MAX);
 		if (unlikely(err)) {
 			WL_ERR(("could not get assoc resp (%d)\n", err));
 			return err;
 		}
-		conn_info->resp_ie_len = resp_len;
+		conn_info->resp_ie_len = assoc_info.resp_len -sizeof(struct dot11_assoc_resp);
 		conn_info->resp_ie =
 		    kmemdup(wl->extra_buf, conn_info->resp_ie_len, GFP_KERNEL);
 	} else {
@@ -3803,7 +3830,7 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev)
 }
 
 static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
-	size_t *join_params_size)
+        size_t *join_params_size)
 {
 	chanspec_t chanspec = 0;
 
@@ -3832,6 +3859,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params,
 
 		WL_DBG(("%s  join_params->params.chanspec_list[0]= %X\n",
 			__FUNCTION__, join_params->params.chanspec_list[0]));
+
 	}
 }
 
@@ -3849,7 +3877,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
 	struct wiphy *wiphy;
 	wiphy = wl_to_wiphy(wl);
 
-	if (wl_is_ibssmode(wl))
+	if (wl_is_ibssmode(wl, ndev))
 		return err;
 
 	ssid = (struct wlc_ssid *)wl_read_prof(wl, WL_PROF_SSID);
@@ -3861,8 +3889,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
 	if (unlikely(!bss)) {
 		WL_DBG(("Could not find the AP\n"));
 		*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
-		err = wl_dev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BSS_INFO,
-			wl->extra_buf, WL_EXTRA_BUF_MAX);
+		err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BSS_INFO,
+			wl->extra_buf, WL_EXTRA_BUF_MAX, FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("Could not get bss info %d\n", err));
 			goto update_bss_info_out;
@@ -3896,8 +3924,8 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
 		* information out of probe response.
 		* so we speficially query dtim information to dongle.
 		*/
-		err = wl_dev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_DTIMPRD,
-			&dtim_period, sizeof(dtim_period));
+		err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_DTIMPRD,
+			&dtim_period, sizeof(dtim_period), FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
 			goto update_bss_info_out;
@@ -4009,8 +4037,8 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 	if (unlikely(!wl->scan_request)) {
 	}
 	rtnl_lock();
-	err = wl_dev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
-		sizeof(channel_inform));
+	err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
+		sizeof(channel_inform), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("scan busy (%d)\n", err));
 		goto scan_done_out;
@@ -4025,7 +4053,7 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 	bss_list = wl->bss_list;
 	memset(bss_list, 0, len);
 	bss_list->buflen = htod32(len);
-	err = wl_dev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len);
+	err = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("%s Scan_results error (%d)\n", ndev->name, err));
 		err = -EINVAL;
@@ -4049,40 +4077,111 @@ scan_done_out:
 	rtnl_unlock();
 	return err;
 }
+static s32
+wl_frame_get_mgmt(u16 fc, const struct ether_addr *da,
+	const struct ether_addr *sa, const struct ether_addr *bssid,
+	u8 **pheader, u32 *body_len, u8 *pbody)
+{
+	struct dot11_management_header *hdr;
+	u32 totlen = 0;
+	s32 err = 0;
+	u8 *offset;
+	u32 prebody_len = *body_len;
+	switch (fc) {
+		case FC_ASSOC_REQ:
+			/* capability , listen interval */
+			totlen = DOT11_ASSOC_REQ_FIXED_LEN;
+			*body_len += DOT11_ASSOC_REQ_FIXED_LEN;
+			break;
 
+		case FC_REASSOC_REQ:
+			/* capability, listen inteval, ap address */
+			totlen = DOT11_REASSOC_REQ_FIXED_LEN;
+			*body_len += DOT11_REASSOC_REQ_FIXED_LEN;
+			break;
+	}
+	totlen += DOT11_MGMT_HDR_LEN + prebody_len;
+	*pheader = kzalloc(totlen, GFP_KERNEL);
+	if (*pheader == NULL) {
+		WL_ERR(("memory alloc failed \n"));
+		return -ENOMEM;
+	}
+	hdr = (struct dot11_management_header *) (*pheader);
+	hdr->fc = htol16(fc);
+	hdr->durid = 0;
+	hdr->seq = 0;
+	offset = (u8*)(hdr + 1) + (totlen - DOT11_MGMT_HDR_LEN - prebody_len);
+	bcopy((const char*)da, (u8*)&hdr->da, ETHER_ADDR_LEN);
+	bcopy((const char*)sa, (u8*)&hdr->sa, ETHER_ADDR_LEN);
+	bcopy((const char*)bssid, (u8*)&hdr->bssid, ETHER_ADDR_LEN);
+	bcopy((const char*)pbody, offset, prebody_len);
+	*body_len = totlen;
+	return err;
+}
 static s32
 wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
 	const wl_event_msg_t *e, void *data)
 {
 	struct ieee80211_supported_band *band;
-	s32 freq;
 	struct wiphy *wiphy = wl_to_wiphy(wl);
-
+	struct ether_addr da;
+	struct ether_addr bssid;
+	bool isfree = FALSE;
+	s32 err = 0;
+	s32 freq;
 	wl_event_rx_frame_data_t *rxframe =
 		(wl_event_rx_frame_data_t*)data;
-
-	u8 *mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
+	u32 event = ntoh32(e->event_type);
+	u8 *mgmt_frame;
+	u8 bsscfgidx = e->bsscfgidx;
 	u32 mgmt_frame_len = ntoh32(e->datalen) - sizeof(wl_event_rx_frame_data_t);
-
 	u16 channel = ((ntoh16(rxframe->channel) & WL_CHANSPEC_CHAN_MASK) & 0x0f);
-
 	if (channel <= CH_MAX_2G_CHANNEL)
 		band = wiphy->bands[IEEE80211_BAND_2GHZ];
 	else
 		band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
+#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(COMPAT_WIRELESS)
+	freq = ieee80211_channel_to_frequency(channel);
+#else
 	freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+	if (event == WLC_E_ACTION_FRAME_RX) {
+		wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+		&da, sizeof(struct ether_addr), ioctlbuf, sizeof(ioctlbuf), bsscfgidx);
+		wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, FALSE);
+		err = wl_frame_get_mgmt(FC_ACTION, &da, &e->addr, &bssid,
+			&mgmt_frame, &mgmt_frame_len,
+			(u8 *)((wl_event_rx_frame_data_t *)rxframe + 1));
+		if (err < 0) {
+			WL_ERR(("%s: Error in receiving action frame len %d channel %d freq %d\n",
+				__func__, mgmt_frame_len, channel, freq));
+			goto exit;
+		}
+		isfree = TRUE;
+	} else {
+		mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
+	}
 
 	cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC);
 
 	WL_DBG(("%s: mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", __func__,
 		mgmt_frame_len, ntoh32(e->datalen), channel, freq));
+
+	if (isfree)
+		kfree(mgmt_frame);
+exit:
 	return 0;
 }
 
 static void wl_init_conf(struct wl_conf *conf)
 {
+	s32 i = 0;
 	WL_DBG(("Enter \n"));
-	conf->mode = (u32)-1;
+	for (i = 0; i <= VWDEV_CNT; i++) {
+		conf->mode[i].type = -1;
+		conf->mode[i].ndev = NULL;
+	}
 	conf->frag_threshold = (u32)-1;
 	conf->rts_threshold = (u32)-1;
 	conf->retry_short = (u32)-1;
@@ -4100,9 +4199,10 @@ static void wl_init_event_handler(struct wl_priv *wl)
 	memset(wl->evt_handler, 0, sizeof(wl->evt_handler));
 
 	wl->evt_handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
-	wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status;
+	/* wl->evt_handler[WLC_E_JOIN] = wl_notify_connect_status; */
 	wl->evt_handler[WLC_E_LINK] = wl_notify_connect_status;
 	wl->evt_handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
+	wl->evt_handler[WLC_E_DEAUTH] = wl_notify_connect_status;
 	wl->evt_handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
 	wl->evt_handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
 	wl->evt_handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
@@ -4115,18 +4215,6 @@ static void wl_init_event_handler(struct wl_priv *wl)
 	wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
 	wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete;
 
-	/* Used to be like this...
-	el->handler[WLC_E_SCAN_COMPLETE] = wl_notify_scan_status;
-	el->handler[WLC_E_JOIN] = wl_notify_connect_status;
-	el->handler[WLC_E_LINK] = wl_notify_connect_status;
-	el->handler[WLC_E_DEAUTH_IND] = wl_notify_connect_status;
-	el->handler[WLC_E_DISASSOC_IND] = wl_notify_connect_status;
-	el->handler[WLC_E_ASSOC_IND] = wl_notify_connect_status;
-	el->handler[WLC_E_REASSOC_IND] = wl_notify_connect_status;
-	el->handler[WLC_E_ROAM] = wl_notify_roaming_status;
-	el->handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
-	el->handler[WLC_E_SET_SSID] = wl_notify_connect_status;
-	*/
 }
 
 static s32 wl_init_priv_mem(struct wl_priv *wl)
@@ -4307,7 +4395,7 @@ wl_get_iscan_results(struct wl_iscan_ctrl *iscan, u32 *status,
 
 	memset(&list, 0, sizeof(list));
 	list.results.buflen = htod32(WL_ISCAN_BUF_MAX);
-	err = wl_dev_iovar_getbuf(iscan->dev, "iscanresults", &list,
+	err = wldev_iovar_getbuf(iscan->dev, "iscanresults", &list,
 		WL_ISCAN_RESULTS_FIXED_SIZE, iscan->scan_buf,
 		WL_ISCAN_BUF_MAX);
 	if (unlikely(err)) {
@@ -4557,6 +4645,15 @@ static s32 wl_escan_handler(struct wl_priv *wl,
 			rtnl_unlock();
 		}
 	}
+	else if (status == WLC_E_STATUS_ABORT) {
+		wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+		if (likely(wl->scan_request)) {
+			rtnl_lock();
+			WL_INFO(("ESCAN COMPLETED\n"));
+			wl_notify_escan_complete(wl, true);
+			rtnl_unlock();
+		}
+	}
 exit:
 	return err;
 }
@@ -4603,8 +4700,8 @@ static s32 wl_init_priv(struct wl_priv *wl)
 
 	wl->scan_request = NULL;
 	wl->pwr_save = !!(wiphy->flags & WIPHY_FLAG_PS_ON_BY_DEFAULT);
-	wl->iscan_on = true;
-	wl->escan_on = false;
+	wl->iscan_on = false;
+	wl->escan_on = true;
 	wl->roam_on = false;
 	wl->iscan_kickstart = false;
 	wl->active_scan = true;
@@ -4645,6 +4742,48 @@ static void wl_deinit_priv(struct wl_priv *wl)
 	wl_deinit_priv_mem(wl);
 }
 
+#ifdef CONFIG_SYSCTL
+s32 wl_cfg80211_sysctl_export_devaddr(void *data)
+{
+	/* Export the p2p_dev_addr via sysctl interface
+	 * so that wpa_supplicant can access it
+	 */
+	dhd_pub_t *dhd = (dhd_pub_t *)data;
+	struct wl_priv *wl = WL_PRIV_GET();
+
+	wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p_dev_addr, &wl->p2p_int_addr);
+
+	sprintf((char *)&wl_sysctl_macstring[0], MACSTR, MAC2STR(wl->p2p_dev_addr.octet));
+	sprintf((char *)&wl_sysctl_macstring[1], MACSTR, MAC2STR(wl->p2p_int_addr.octet));
+
+	return 0;
+}
+#endif /* CONFIG_SYSCTL */
+
+s32 wl_cfg80211_attach_post(struct net_device *ndev)
+{
+	struct wl_priv * wl = NULL;
+	s32 err = 0;
+	WL_TRACE(("In\n"));
+	if (unlikely(!ndev)) {
+		WL_ERR(("ndev is invaild\n"));
+		return -ENODEV;
+	}
+	wl = WL_PRIV_GET();
+	if (wl && !test_bit(WL_STATUS_READY, &wl->status)) {
+			if (wl->wdev &&
+				wl_cfgp2p_is_p2p_supported(wl, ndev)) {
+				WL_INFO(("P2P is supported on Firmware \n"));
+				wl->wdev->wiphy->interface_modes |=
+					(BIT(NL80211_IFTYPE_P2P_CLIENT)|
+					BIT(NL80211_IFTYPE_P2P_GO));
+			}
+	} else
+		return -ENODEV;
+
+	set_bit(WL_STATUS_READY, &wl->status);
+	return err;
+}
 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
 {
 	struct wireless_dev *wdev;
@@ -4690,9 +4829,13 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
 		goto cfg80211_attach_out;
 	}
 
+#ifdef CONFIG_SYSCTL
+	if (!(wl_sysctl_hdr = register_sysctl_table(wl_sysctl_table))) {
+		WL_ERR(("%s: sysctl register failed!! \n", __func__));
+		goto cfg80211_attach_out;
+	}
+#endif
 	wl_set_drvdata(wl_cfg80211_dev, ci);
-	set_bit(WL_STATUS_READY, &wl->status);
-
 	return err;
 
 cfg80211_attach_out:
@@ -4709,6 +4852,10 @@ void wl_cfg80211_detach(void)
 
 	WL_TRACE(("In\n"));
 
+#ifdef CONFIG_SYSCTL
+	if (wl_sysctl_hdr)
+		unregister_sysctl_table(wl_sysctl_hdr);
+#endif
 	rfkill_unregister(wl->rfkill);
 	rfkill_destroy(wl->rfkill);
 
@@ -4758,7 +4905,7 @@ static s32 wl_event_handler(void *data)
 }
 
 void
-wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data, gfp_t gfp)
 {
 	u32 event_type = ntoh32(e->event_type);
 	struct wl_priv *wl = WL_PRIV_GET();
@@ -4769,7 +4916,7 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
 	WL_DBG(("event_type (%d):" "WLC_E_" "%s\n", event_type, estr));
 #endif /* (WL_DBG_LEVEL > 0) */
 
-	if (likely(!wl_enq_event(wl, ndev, event_type, e, data)))
+	if (likely(!wl_enq_event(wl, ndev, event_type, e, data, gfp)))
 		wl_wakeup_event(wl);
 }
 
@@ -4816,7 +4963,7 @@ static struct wl_event_q *wl_deq_event(struct wl_priv *wl)
 
 static s32
 wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_event_msg_t *msg,
-	void *data)
+	void *data, gfp_t gfp)
 {
 	struct wl_event_q *e;
 	s32 err = 0;
@@ -4827,7 +4974,7 @@ wl_enq_event(struct wl_priv *wl, struct net_device *ndev, u32 event, const wl_ev
 	if (data)
 		data_len = ntoh32(msg->datalen);
 	evtq_size = sizeof(struct wl_event_q) + data_len;
-	e = kzalloc(evtq_size, GFP_KERNEL);
+	e = kzalloc(evtq_size, gfp);
 	if (unlikely(!e)) {
 		WL_ERR(("event alloc failed\n"));
 		return -ENOMEM;
@@ -4866,12 +5013,11 @@ struct sdio_func *wl_cfg80211_get_sdio_func(void)
 	return cfg80211_sdio_func;
 }
 
-static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
+static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftype)
 {
 	s32 infra = 0;
-	s32 ap = 0;
 	s32 err = 0;
-
+	s32 mode = 0;
 	switch (iftype) {
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_WDS:
@@ -4880,8 +5026,10 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
 		err = -EINVAL;
 		return err;
 	case NL80211_IFTYPE_ADHOC:
+		mode = WL_MODE_IBSS;
 		break;
 	case NL80211_IFTYPE_STATION:
+		mode = WL_MODE_BSS;
 		infra = 1;
 		break;
 	default:
@@ -4890,69 +5038,16 @@ static s32 wl_dongle_mode(struct net_device *ndev, s32 iftype)
 		return err;
 	}
 	infra = htod32(infra);
-	ap = htod32(ap);
-	WL_DBG(("%s ap (%d), infra (%d)\n", ndev->name, ap, infra));
-	err = wl_dev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra));
+	err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_SET_INFRA error (%d)\n", err));
 		return err;
 	}
-	err = wl_dev_ioctl(ndev, WLC_SET_AP, &ap, sizeof(ap));
-	if (unlikely(err)) {
-		WL_ERR(("WLC_SET_AP error (%d)\n", err));
-		return err;
-	}
-
-	return -EINPROGRESS;
-}
-#ifdef NOT_YET
-static s32 wl_dongle_save_eventmsg(struct wl_priv *wl)
-{
-	s8 eventmask[WL_EVENTING_MASK_LEN];
-	s32 err = 0;
-	struct net_device *ndev = wl_to_prmry_ndev(wl);
-	/*  Room for "event_msgs" + '\0' + bitvec  */
-	err = wl_cfgp2p_bssiovar_get(ndev, "event_msgs", 0,
-	           eventmask, WL_EVENTING_MASK_LEN);
-	if (unlikely(err)) {
-		WL_ERR(("Get event_msgs error (%d)\n", err));
-	} else {
-		memcpy(wl->last_eventmask, eventmask, WL_EVENTING_MASK_LEN);
-	}
-	return err;
-}
-
-static s32 wl_dongle_disable_eventmsg(struct wl_priv *wl)
-{
-	s8 eventmask[WL_EVENTING_MASK_LEN];
-	s32 err = 0;
-	struct net_device *ndev = wl_to_prmry_ndev(wl);
-	/* Only Enable IF EVENT */
-	setbit(eventmask, WLC_E_IF);
-
-	err = wl_cfgp2p_bssiovar_set(ndev, "event_msgs", 0,
-	           eventmask, WL_EVENTING_MASK_LEN);
-	if (unlikely(err)) {
-		WL_ERR(("Get event_msgs error (%d)\n", err));
-	}
 
-	return err;
-}
+	set_mode_by_netdev(wl, ndev, mode);
 
-
-static s32 wl_dongle_restore_eventmsg(struct wl_priv *wl)
-{
-	s32 err = 0;
-	struct net_device *ndev = wl_to_prmry_ndev(wl);
-	err = wl_cfgp2p_bssiovar_set(ndev, "event_msgs", 0,
-	            wl->last_eventmask, WL_EVENTING_MASK_LEN);
-	if (unlikely(err)) {
-		WL_ERR(("Get event_msgs error (%d)\n", err));
-	}
-
-	return err;
+	return 0;
 }
-#endif /* NOT_YET */
 
 static s32 wl_dongle_eventmsg(struct net_device *ndev)
 {
@@ -4964,7 +5059,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
 	/* Setup event_msgs */
 	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
 		sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("Get event_msgs error (%d)\n", err));
 		goto dongle_eventmsg_out;
@@ -4977,6 +5072,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
 	setbit(eventmask, WLC_E_REASSOC);
 	setbit(eventmask, WLC_E_REASSOC_IND);
 	setbit(eventmask, WLC_E_DEAUTH_IND);
+	setbit(eventmask, WLC_E_DEAUTH);
 	setbit(eventmask, WLC_E_DISASSOC_IND);
 	setbit(eventmask, WLC_E_DISASSOC);
 	setbit(eventmask, WLC_E_JOIN);
@@ -4991,12 +5087,13 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
 	setbit(eventmask, WLC_E_SCAN_COMPLETE);
 	setbit(eventmask, WLC_E_ACTION_FRAME_RX);
 	setbit(eventmask, WLC_E_ACTION_FRAME_COMPLETE);
+	setbit(eventmask, WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE);
 	setbit(eventmask, WLC_E_P2P_PROBREQ_MSG);
 	setbit(eventmask, WLC_E_P2P_DISC_LISTEN_COMPLETE);
 	setbit(eventmask, WLC_E_ESCAN_RESULT);
 	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
 		sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("Set event_msgs error (%d)\n", err));
 		goto dongle_eventmsg_out;
@@ -5019,7 +5116,7 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
 {
 	s32 err = 0;
 
-	err = wl_dev_ioctl(ndev, WLC_UP, &up, sizeof(up));
+	err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_UP error (%d)\n", err));
 	}
@@ -5031,7 +5128,7 @@ static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
 	s32 err = 0;
 
 	WL_TRACE(("In\n"));
-	err = wl_dev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode));
+	err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_SET_PM error (%d)\n", err));
 	}
@@ -5048,14 +5145,14 @@ wl_dongle_glom(struct net_device *ndev, u32 glom, u32 dongle_align)
 	/* Match Host and Dongle rx alignment */
 	bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf,
 		sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("txglomalign error (%d)\n", err));
 		goto dongle_glom_out;
 	}
 	/* disable glom option per default */
 	bcm_mkiovar("bus:txglom", (char *)&glom, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("txglom error (%d)\n", err));
 		goto dongle_glom_out;
@@ -5075,7 +5172,7 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	if (roamvar) {
 		bcm_mkiovar("bcn_timeout", (char *)&bcn_timeout, 4, iovbuf,
 			sizeof(iovbuf));
-		err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+		err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 		if (unlikely(err)) {
 			WL_ERR(("bcn_timeout error (%d)\n", err));
 			goto dongle_rom_out;
@@ -5083,7 +5180,7 @@ wl_dongle_roam(struct net_device *ndev, u32 roamvar, u32 bcn_timeout)
 	}
 	/* Enable/Disable built-in roaming to allow supplicant to take care of roaming */
 	bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("roam_off error (%d)\n", err));
 		goto dongle_rom_out;
@@ -5098,8 +5195,8 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 {
 	s32 err = 0;
 
-	err = wl_dev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
-		sizeof(scan_assoc_time));
+	err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
+		sizeof(scan_assoc_time), FALSE);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("Scan assoc time is not supported\n"));
@@ -5108,8 +5205,8 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		}
 		goto dongle_scantime_out;
 	}
-	err = wl_dev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
-		sizeof(scan_unassoc_time));
+	err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
+		sizeof(scan_unassoc_time), FALSE);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("Scan unassoc time is not supported\n"));
@@ -5133,7 +5230,7 @@ wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
 
 	/* Set ARP offload */
 	bcm_mkiovar("arpoe", (char *)&arpoe, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO(("arpoe is not supported\n"));
@@ -5143,7 +5240,7 @@ wl_dongle_offload(struct net_device *ndev, s32 arpoe, s32 arp_ol)
 		goto dongle_offload_out;
 	}
 	bcm_mkiovar("arp_ol", (char *)&arp_ol, 4, iovbuf, sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO(("arp_ol is not supported\n"));
@@ -5242,7 +5339,7 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
 	memcpy((char *)pkt_filterp, &pkt_filter,
 		WL_PKT_FILTER_FIXED_LEN + WL_PKT_FILTER_PATTERN_FIXED_LEN);
 
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, buf, buf_len);
+	err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, FALSE);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("filter not supported\n"));
@@ -5255,7 +5352,7 @@ static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode)
 	/* set mode to allow pattern */
 	bcm_mkiovar("pkt_filter_mode", (char *)&filter_mode, 4, iovbuf,
 		sizeof(iovbuf));
-	err = wl_dev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf));
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("filter_mode not supported\n"));
@@ -5315,8 +5412,7 @@ s32 wl_config_dongle(struct wl_priv *wl, bool need_lock)
 	wl_dongle_filter(ndev, 1);
 #endif				/* !EMBEDDED_PLATFORM */
 
-	/* TODO: Check if this is ever needed */
-	err = wl_dongle_mode(ndev, wdev->iftype);
+	err = wl_dongle_mode(wl, ndev, wdev->iftype);
 	if (unlikely(err && err != -EINPROGRESS))
 		goto default_conf_out;
 	err = wl_dongle_probecap(wl);
@@ -5342,8 +5438,8 @@ static s32 wl_update_wiphybands(struct wl_priv *wl)
 	s8 phy;
 	s32 err = 0;
 
-	err = wl_dev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, &phy_list,
-		sizeof(phy_list));
+	err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, &phy_list,
+		sizeof(phy_list), FALSE);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 		return err;
@@ -5402,6 +5498,8 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
 	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
 	clear_bit(WL_STATUS_CONNECTED, &wl->status);
 
+	wl_cfgp2p_down(wl);
+
 	wl_debugfs_remove_netdev(wl);
 
 	return err;
@@ -5515,9 +5613,9 @@ void wl_cfg80211_dbg_level(u32 level)
 	/* wl_dbg_level = level; */
 }
 
-static bool wl_is_ibssmode(struct wl_priv *wl)
+static bool wl_is_ibssmode(struct wl_priv *wl, struct net_device *ndev)
 {
-	return wl->conf->mode == WL_MODE_IBSS;
+	return get_mode_by_netdev(wl, ndev) == WL_MODE_IBSS;
 }
 
 static __used bool wl_is_ibssstarter(struct wl_priv *wl)
@@ -5594,6 +5692,7 @@ static void wl_link_down(struct wl_priv *wl)
 {
 	struct wl_connect_info *conn_info = wl_to_conn(wl);
 
+	WL_DBG(("In\n"));
 	wl->link_up = false;
 	kfree(conn_info->req_ie);
 	conn_info->req_ie = NULL;
@@ -5731,8 +5830,19 @@ s8 *wl_cfg80211_get_nvramname(void)
 	return wl->fw->nvram_name;
 }
 
-static void wl_set_mpc(struct net_device *ndev, int mpc)
+static void wl_set_mpc(struct net_device *ndev, s32 mpc)
 {
+
+	s32 err = 0;
+
+	WL_TRACE(("In\n"));
+	err = wl_dev_intvar_set(ndev, "mpc", mpc);
+	if (unlikely(err)) {
+		WL_ERR(("fail to set mpc\n"));
+		return;
+	}
+	WL_DBG(("MPC : %d\n", mpc));
+
 }
 
 static int wl_debugfs_add_netdev_params(struct wl_priv *wl)
@@ -5798,7 +5908,7 @@ static __used void wl_dongle_poweroff(struct wl_priv *wl)
 }
 
 static const struct rfkill_ops wl_rfkill_ops = {
-	.set_block = wl_rfkill_set,
+	.set_block = wl_rfkill_set
 };
 
 static int wl_rfkill_set(void *data, bool blocked)
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index bb2f0e40729c..4ec91e84de8f 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -110,13 +110,14 @@ do {									\
 				 * as kernel memory allows
 				 */
 #define WL_FILE_NAME_MAX		256
+#define WL_DWELL_TIME 	200
 
 /* WiFi Direct */
 #define WL_P2P_WILDCARD_SSID "DIRECT-"
 #define WL_P2P_WILDCARD_SSID_LEN 7
 #define WL_P2P_INTERFACE_PREFIX "p2p"
 #define WL_P2P_TEMP_CHAN "11"
-
+#define VWDEV_CNT 3
 /* dongle status */
 enum wl_status {
 	WL_STATUS_READY = 0,
@@ -169,16 +170,12 @@ enum wl_cfgp2p_status {
 	WLP2P_STATUS_SEARCH_ENABLED,
 	WLP2P_STATUS_IF_ADD,
 	WLP2P_STATUS_IF_DEL,
+	WLP2P_STATUS_IF_DELETING,
 	WLP2P_STATUS_IF_CHANGING,
 	WLP2P_STATUS_IF_CHANGED,
 	WLP2P_STATUS_LISTEN_EXPIRED,
 	WLP2P_STATUS_ACTION_TX_COMPLETED,
-	WLP2P_STATUS_GROUP_OWNER,
-	WLP2P_STATUS_GROUP_CLIENT,
-	WLP2P_STATUS_SCANNING,
-	WLP2P_STATUS_SCAN_ABORTING,
-	WLP2P_STATUS_CONNECTING,
-	WLP2P_STATUS_CONNECTED
+	WLP2P_STATUS_SCANNING
 };
 /* beacon / probe_response */
 struct beacon_proberesp {
@@ -190,7 +187,10 @@ struct beacon_proberesp {
 
 /* dongle configuration */
 struct wl_conf {
-	u32 mode;		/* adhoc , infrastructure or ap */
+	struct net_mode {
+		struct net_device *ndev;
+		s32 type;
+	} mode [VWDEV_CNT + 1];		/* adhoc , infrastructure or ap */
 	u32 frag_threshold;
 	u32 rts_threshold;
 	u32 retry_short;
@@ -354,7 +354,7 @@ struct escan_info {
     u8 escan_buf[ESCAN_BUF_SIZE];
     struct wiphy *wiphy;
 };
-#define VWDEV_CNT 3
+
 /* dongle private data of cfg80211 interface */
 struct wl_priv {
 	struct wireless_dev *wdev;	/* representing wl cfg80211 device */
@@ -457,9 +457,9 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct
 	return bss = bss ?
 		(struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
 }
-static inline int alloc_idx_vwdev(struct wl_priv *wl)
+static inline s32 alloc_idx_vwdev(struct wl_priv *wl)
 {
-	int i = 0;
+	s32 i = 0;
 	for (i = 0; i < VWDEV_CNT; i++) {
 		if (wl->vwdev[i] == NULL)
 				return i;
@@ -467,9 +467,9 @@ static inline int alloc_idx_vwdev(struct wl_priv *wl)
 	return -1;
 }
 
-static inline int get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device *ndev)
+static inline s32 get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device *ndev)
 {
-	int i = 0;
+	s32 i = 0;
 	for (i = 0; i < VWDEV_CNT; i++) {
 		if ((wl->vwdev[i] != NULL) && (wl->vwdev[i]->netdev == ndev))
 				return i;
@@ -477,6 +477,43 @@ static inline int get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device
 	return -1;
 }
 
+static inline s32 get_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev)
+{
+	s32 i = 0;
+	for (i = 0; i <= VWDEV_CNT; i++) {
+		if (wl->conf->mode[i].ndev != NULL && (wl->conf->mode[i].ndev == ndev))
+			return wl->conf->mode[i].type;
+	}
+	return -1;
+}
+static inline void set_mode_by_netdev(struct wl_priv *wl, struct net_device *ndev, s32 type)
+{
+	s32 i = 0;
+	for (i = 0; i <= VWDEV_CNT; i++) {
+		if (type == -1) {
+			/* free the info of netdev */
+			if (wl->conf->mode[i].ndev == ndev) {
+				wl->conf->mode[i].ndev = NULL;
+				wl->conf->mode[i].type = -1;
+				break;
+			}
+
+		} else {
+			if ((wl->conf->mode[i].ndev != NULL)&&
+			(wl->conf->mode[i].ndev == ndev)) {
+				/* update type of ndev */
+				wl->conf->mode[i].type = type;
+				break;
+			}
+			else if ((wl->conf->mode[i].ndev == NULL)&&
+			(wl->conf->mode[i].type == -1)) {
+				wl->conf->mode[i].ndev = ndev;
+				wl->conf->mode[i].type = type;
+				break;
+			}
+		}
+	}
+}
 #define free_vwdev_by_index(wl, __i) do {      \
 						if (wl->vwdev[__i] != NULL) \
 							kfree(wl->vwdev[__i]); \
@@ -494,16 +531,20 @@ static inline int get_idx_vwdev_by_netdev(struct wl_priv *wl, struct net_device
 	 (!_sme->crypto.n_ciphers_pairwise) && \
 	 (!_sme->crypto.cipher_group))
 extern s32 wl_cfg80211_attach(struct net_device *ndev, void *data);
+extern s32 wl_cfg80211_attach_post(struct net_device *ndev);
 extern void wl_cfg80211_detach(void);
 /* event handler from dongle */
-extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e, void *data);
+extern void wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t *e,
+            void *data, gfp_t gfp);
 extern void wl_cfg80211_set_sdio_func(void *func);	/* set sdio function info */
 extern struct sdio_func *wl_cfg80211_get_sdio_func(void);	/* set sdio function info */
 extern s32 wl_cfg80211_up(void);	/* dongle up */
 extern s32 wl_cfg80211_down(void);	/* dongle down */
 extern s32 wl_cfg80211_notify_ifadd(struct net_device *net);
 extern s32 wl_cfg80211_notify_ifdel(struct net_device *net);
+extern s32 wl_cfg80211_is_progress_ifadd(void);
 extern s32 wl_cfg80211_is_progress_ifchange(void);
+extern s32 wl_cfg80211_is_progress_ifadd(void);
 extern s32 wl_cfg80211_notify_ifchange(void);
 extern void wl_cfg80211_dbg_level(u32 level);
 extern void *wl_cfg80211_request_fw(s8 *file_name);
@@ -511,6 +552,9 @@ extern s32 wl_cfg80211_read_fw(s8 *buf, u32 size);
 extern void wl_cfg80211_release_fw(void);
 extern s8 *wl_cfg80211_get_fwname(void);
 extern s8 *wl_cfg80211_get_nvramname(void);
+#ifdef CONFIG_SYSCTL
+extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);
+#endif
 
 /* do scan abort */
 extern s32
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index a87631ccd21d..730a25f45342 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -21,6 +21,7 @@
  * software in any way with any other Broadcom software provided under a license
  * other than the GPL, without Broadcom's express prior written consent.
  *
+ * $Id: wl_cfg80211.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
  * $Id$
  */
 
@@ -47,6 +48,7 @@
 
 #include <wl_cfg80211.h>
 #include <wl_cfgp2p.h>
+#include <wldev_common.h>
 
 
 /* dword align allocation */
@@ -96,350 +98,12 @@ static s8 ioctlbuf[WLC_IOCTL_MAXLEN];
 static s8 scanparambuf[WLC_IOCTL_SMLEN];
 static s8 *smbuf = ioctlbuf;
 
+static bool
+wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type);
 
 static s32
 wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag,
             s8 *oui, s32 ie_id, s8 *data, s32 data_len, s32 delete);
-static s32
-wl_dev_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
-{
-	struct ifreq ifr;
-	struct wl_ioctl ioc;
-	mm_segment_t fs;
-	s32 err = 0;
-
-	memset(&ioc, 0, sizeof(ioc));
-	ioc.cmd = cmd;
-	ioc.buf = arg;
-	ioc.len = len;
-	ioc.set = set;
-	strcpy(ifr.ifr_name, dev->name);
-	ifr.ifr_data = (caddr_t)&ioc;
-	fs = get_fs();
-	set_fs(get_ds());
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
-	err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#else
-	err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
-#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
-	set_fs(fs);
-
-	return err;
-}
-
-/*
- * Format an iovar buffer.
- * iovar name is converted to lower case
- */
-static s32
-wl_cfgp2p_iovar_mkbuf(const s8 *name, s8 *data, u32 datalen,
-            s8 *iovar_buf, u32 buflen, u32 *perr)
-{
-	u32 iovar_len;
-	iovar_len = (u32) strlen(name) + 1;
-
-	if ((iovar_len + datalen) > buflen) {
-
-		CFGP2P_ERR(("buf too short, %u < %u\n", buflen, (iovar_len + datalen)));
-		*perr = BCME_BUFTOOSHORT;
-		return 0;
-	}
-
-	/* copy data to the buffer past the end of the iovar name string */
-	if (datalen > 0) {
-		memmove(&iovar_buf[iovar_len], data, datalen);
-	}
-
-	/* copy the name to the beginning of the buffer */
-	strcpy(iovar_buf, name);
-
-
-	*perr = 0;
-	return (iovar_len + datalen);
-}
-
-/*
- * Format a bsscfg indexed iovar buffer.
- * This is a common implementation called by most OSL implementations of
- * p2posl_bssiovar_mkbuf().  DO NOT call this function directly from the
- * common code -- call p2posl_bssiovar_mkbuf() instead to allow the OSL to
- * override the common implementation if necessary.
- */
-static s32
-wl_cfgp2p_bssiovar_mkbuf(const s8 *iovar, s32 bssidx,
-            void *param, s32 paramlen, void *bufptr, s32 buflen, s32 *perr)
-{
-	const s8 *prefix = "bsscfg:";
-	s8 *p;
-	u32 prefixlen;
-	u32 namelen;
-	u32 iolen;
-
-	if (bssidx == 0) {
-		return wl_cfgp2p_iovar_mkbuf(iovar, (s8 *)param, paramlen,
-		                    (s8 *) bufptr, buflen, perr);
-	}
-
-	prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
-	namelen = (u32) strlen(iovar) + 1; /* lengh of iovar  name + null */
-	iolen = prefixlen + namelen + sizeof(u32) + paramlen;
-
-	if (buflen < 0 || iolen > (u32)buflen) {
-		CFGP2P_ERR(("buf too short, %u < %u\n", buflen, iolen));
-		*perr = BCME_BUFTOOSHORT;
-		return 0;
-	}
-	p = (s8 *)bufptr;
-
-	/* copy prefix, no null */
-	memcpy(p, prefix, prefixlen);
-	p += prefixlen;
-
-	/* copy iovar name including null */
-	memcpy(p, iovar, namelen);
-	p += namelen;
-
-	/* bss config index as first param */
-	bssidx = htod32(bssidx);
-	memcpy(p, &bssidx, sizeof(u32));
-	p += sizeof(u32);
-
-	/* parameter buffer follows */
-	if (paramlen)
-		memcpy(p, param, paramlen);
-
-	*perr = 0;
-
-	return iolen;
-
-}
-
-/*
- * Set a bss-indexed iovar on the primary ioctl interface, providing both
- * parameter and i/o buffers.
- */
-
-static s32
-wl_cfgp2p_bssiovar_setbuf(struct net_device *dev, const s8 *iovar, s32 bssidx,
-            void *param, s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 iolen;
-	s32  err;
-	iolen = wl_cfgp2p_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr,
-	                    buflen, &err);
-
-	if (err)
-		return err;
-
-	return wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen, TRUE);
-}
-/*
- * Get a named & bss indexed driver iovar using the primary ioctl interface.
- */
-static s32
-wl_cfgp2p_bssiovar_getbuf(struct net_device *dev, const s8 *iovar, int bssidx,
-            void *param, s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 err;
-	s32 iolen;
-	iolen = wl_cfgp2p_bssiovar_mkbuf(iovar, bssidx, param, paramlen, bufptr, buflen, &err);
-
-	if (unlikely(err))
-		return err;
-
-	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, iolen, FALSE);
-}
-
-
-/*
- * Get named & bss indexed driver variable to buffer value
- * using the primary ioctl interface.
- */
-s32
-wl_cfgp2p_bssiovar_get(struct net_device *dev, const s8 *iovar, s32 bssidx,
-            void *outbuf, s32 len)
-{
-	s32 err;
-
-	if (len > (s32)sizeof(ioctlbuf)) {
-		err = wl_cfgp2p_bssiovar_getbuf(dev, iovar, bssidx, NULL, 0,
-		            outbuf, len);
-	} else {
-		memset(smbuf, 0, sizeof(ioctlbuf));
-
-		err = wl_cfgp2p_bssiovar_getbuf(dev, iovar, bssidx, NULL, 0,
-		            smbuf, sizeof(ioctlbuf));
-
-		if (err == 0)
-			memcpy(outbuf, smbuf, len);
-	}
-	return err;
-}
-/*
- * Set named & bss indexed driver variable to buffer value
- * on the primary ioctl interface.
- */
-s32
-wl_cfgp2p_bssiovar_set(struct net_device *dev, const s8 *iovar, s32 bssidx,
-            void *param, s32 paramlen)
-{
-
-	memset(smbuf, 0, sizeof(ioctlbuf));
-
-	return wl_cfgp2p_bssiovar_setbuf(dev, iovar, bssidx, param, paramlen, smbuf,
-	            sizeof(ioctlbuf));
-}
-
-
-/*
- * Set named & bsscfg indexed driver variable to int value
- * on the primary ioctl interface.
- */
-
-s32
-wl_cfgp2p_bssiovar_setint(struct net_device *dev, const s8 *iovar, s32 bssidx,
-            s32 val)
-{
-
-	val = htod32(val);
-
-	return wl_cfgp2p_bssiovar_set(dev, iovar, bssidx, &val, sizeof(int));
-}
-
-
-s32
-wl_cfgp2p_set_int_bss(struct net_device *dev, s32 ioctl_cmd, s32 val, s32 bssidx)
-{
-	s32 setval = htod32(val);
-	return wl_dev_ioctl(dev, WLC_SET_VAR, &setval, sizeof(setval), TRUE);
-}
-
-
-s32
-wl_cfgp2p_get_int_bss(struct net_device *dev, s32 ioctl_cmd, s32 *val, s32 bssidx)
-{
-	s32 ret;
-	ret = wl_dev_ioctl(dev, WLC_GET_VAR, val, sizeof(*val), FALSE);
-	if (ret >= 0) {
-		val = dtoh32(val);
-	}
-	return ret;
-}
-
-s32
-wl_cfgp2p_iovar_getbuf_bss(struct net_device *dev, const s8 *iovar, void *param,
-            s32 paramlen, void *bufptr, s32 buflen, s32 bssidx)
-{
-	s32 err;
-
-	wl_cfgp2p_iovar_mkbuf(iovar, (s8 *)param, paramlen, (s8 *) bufptr, buflen,
-	            &err);
-
-	if (unlikely(err)) {
-		CFGP2P_ERR((" mkbuf err %d\n", err));
-	}
-
-	return wl_dev_ioctl(dev, WLC_GET_VAR, bufptr, buflen, FALSE);
-}
-/*
- * Set a named iovar on a specified BSS, providing both parameter and i/o
- * buffers.  The iovar name is converted to lower case.
- */
-s32
-wl_cfgp2p_iovar_setbuf_bss(struct net_device *dev, const s8 *iovar,
-            void *param, s32 paramlen, void *bufptr, s32 buflen)
-{
-	s32 err = BCME_OK;
-	s32 iolen;
-	CFGP2P_DBG((" enter\n"));
-
-	iolen = wl_cfgp2p_iovar_mkbuf(iovar, (char *) param, paramlen, (s8 *)bufptr,
-	                    buflen, &err);
-
-	if (unlikely(err)) {
-		CFGP2P_ERR(("iovar = %s\n", iovar));
-		return err;
-	}
-	err = wl_dev_ioctl(dev, WLC_SET_VAR, bufptr, iolen, TRUE);
-	CFGP2P_DBG((" leave\n"));
-	return err;
-}
-
-/*
- * Set a named iovar given the parameter buffer, on a specified BSS.
- * The iovar name is converted to lower case.
- */
-s32
-wl_cfgp2p_iovar_set_bss(struct net_device *dev, const s8 *iovar, void *param,
-            s32 paramlen)
-{
-
-	s32 ret;
-	memset(smbuf, 0, sizeof(ioctlbuf));
-	CFGP2P_DBG((" enter\n"));
-	ret = wl_cfgp2p_iovar_setbuf_bss(dev, iovar, param, paramlen, smbuf,
-	                    sizeof(ioctlbuf));
-
-	if (unlikely(ret != 0)) {
-		CFGP2P_ERR(("set iovar %s failed (%d)\n",
-		    iovar, ret));
-	}
-	CFGP2P_DBG((" leave\n"));
-	return ret;
-}
-/*
- * Get a parameterless iovar into a given buffer.
- * iovar name is converted to lower case
- */
-s32
-wl_cfgp2p_iovar_get_bss(struct net_device *dev, const s8 *iovar, void *outbuf, s32 len,
-            s32 bssidx)
-{
-	s32 err;
-
-	/* use the return buffer if it is bigger than what we have on the stack */
-	if (len > (s32)sizeof(ioctlbuf)) {
-		err = wl_cfgp2p_iovar_getbuf_bss(dev, iovar, NULL, 0, outbuf, len, bssidx);
-	} else {
-		memset(smbuf, 0, sizeof(ioctlbuf));
-		err = wl_cfgp2p_iovar_getbuf_bss(dev, iovar, NULL, 0, smbuf, sizeof(ioctlbuf),
-		                    bssidx);
-		if (err == 0)
-			memcpy(outbuf, smbuf, len);
-	}
-
-	return err;
-}
-
-/*
- * Set named iovar given an integer parameter, on the specified BSS.
- * iovar name is converted to lower case
- */
-s32
-wl_cfgp2p_iovar_setint_bss(struct net_device *dev, const s8 *iovar, s32 val)
-{
-	CFGP2P_DBG((" enter\n"));
-	val = htod32(val);
-	return wl_cfgp2p_iovar_set_bss(dev, iovar, &val, sizeof(int));
-}
-
-/*
- * Get the named integer iovar on the specified BSS.
- * iovar name is converted to lower case
- */
-s32
-wl_cfgp2p_iovar_getint_bss(struct net_device *dev, const s8*iovar, s32 *pval, s32 bssidx)
-{
-	s32 ret;
-
-	ret = wl_cfgp2p_iovar_get_bss(dev, iovar, pval, sizeof(s32), bssidx);
-	if (ret >= 0)
-	{
-		*pval = dtoh32(*pval);
-	}
-	return ret;
-}
-
 /* 
  *  Initialize variables related to P2P
  *
@@ -521,7 +185,8 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 		(if_type == WL_P2P_IF_GO) ? "go" : "client",
 	        (chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
 
-	err = wl_cfgp2p_iovar_set_bss(netdev, "p2p_ifadd", &ifreq, sizeof(ifreq));
+	err = wldev_iovar_setbuf(netdev, "p2p_ifadd", &ifreq, sizeof(ifreq),
+		ioctlbuf, sizeof(ioctlbuf));
 	return err;
 }
 
@@ -540,7 +205,8 @@ wl_cfgp2p_ifdel(struct wl_priv *wl, struct ether_addr *mac)
 	    mac->octet[0], mac->octet[1], mac->octet[2],
 	    mac->octet[3], mac->octet[4], mac->octet[5]));
 
-	ret = wl_cfgp2p_iovar_set_bss(netdev, "p2p_ifdel", mac, sizeof(*mac));
+	ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
+		ioctlbuf, sizeof(ioctlbuf));
 
 	if (unlikely(ret < 0)) {
 		printk("'wl p2p_ifdel' error %d\n", ret);
@@ -571,7 +237,8 @@ wl_cfgp2p_ifchange(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 	    (if_type == WL_P2P_IF_GO) ? "go" : "client",
 		(chspec & WL_CHANSPEC_CHAN_MASK) >> WL_CHANSPEC_CHAN_SHIFT));
 
-	err = wl_cfgp2p_iovar_set_bss(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq));
+	err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
+		ioctlbuf, sizeof(ioctlbuf));
 
 	if (unlikely(err < 0)) {
 		printk("'wl p2p_ifupd' error %d\n", err);
@@ -597,7 +264,7 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index)
 	    mac->octet[0], mac->octet[1], mac->octet[2],
 	    mac->octet[3], mac->octet[4], mac->octet[5]));
 
-	ret = wl_cfgp2p_iovar_getbuf_bss(dev, "p2p_if", mac, sizeof(*mac),
+	ret = wldev_iovar_getbuf_bsscfg(dev, "p2p_if", mac, sizeof(*mac),
 	            getbuf, sizeof(getbuf), wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY));
 
 	if (ret == 0) {
@@ -615,7 +282,7 @@ wl_cfgp2p_set_discovery(struct wl_priv *wl, s32 on)
 	struct net_device *ndev = wl_to_prmry_ndev(wl);
 	CFGP2P_DBG(("enter\n"));
 
-	ret = wl_cfgp2p_iovar_setint_bss(ndev, "p2p_disc", on);
+	ret = wldev_iovar_setint(ndev, "p2p_disc", on);
 
 	if (unlikely(ret < 0)) {
 		CFGP2P_ERR(("p2p_disc %d error %d\n", on, ret));
@@ -656,8 +323,8 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms,
 	discovery_mode.state = mode;
 	discovery_mode.chspec = CH20MHZ_CHSPEC(channel);
 	discovery_mode.dwell = listen_ms;
-	ret = wl_cfgp2p_bssiovar_set(dev, "p2p_state", bssidx, &discovery_mode,
-	            sizeof(discovery_mode));
+	ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_state", &discovery_mode,
+	            sizeof(discovery_mode), ioctlbuf, sizeof(ioctlbuf), bssidx);
 
 	return ret;
 }
@@ -669,7 +336,7 @@ wl_cfgp2p_get_disc_idx(struct wl_priv *wl, s32 *index)
 	s32 ret;
 	struct net_device *dev = wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY);
 
-	ret = wl_cfgp2p_iovar_getint_bss(dev, "p2p_dev", index, 0);
+	ret = wldev_iovar_getint(dev, "p2p_dev", index);
 	CFGP2P_INFO(("p2p_dev bsscfg_idx=%d ret=%d\n", *index, ret));
 
 	if (unlikely(ret <  0)) {
@@ -765,7 +432,7 @@ wl_cfgp2p_deinit_discovery(struct wl_priv *wl)
  * Returns 0 if success.
  */
 s32
-wl_cfgp2p_enable_discovery(struct wl_priv *wl, const u8 *ie, u32 ie_len)
+wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len)
 {
 	s32 ret = BCME_OK;
 	if (test_bit(WLP2P_STATUS_DISCOVERY_ON, &wl->p2p_status)) {
@@ -786,13 +453,13 @@ wl_cfgp2p_enable_discovery(struct wl_priv *wl, const u8 *ie, u32 ie_len)
 	 * P2P probe responses have the privacy bit set in the 802.11 WPA IE.
 	 * Some peer devices may not initiate WPS with us if this bit is not set.
 	 */
-	ret = wl_cfgp2p_bssiovar_setint(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
-			"wsec", wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), AES_ENABLED);
+	ret = wldev_iovar_setint_bsscfg(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
+			"wsec", AES_ENABLED, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
 	if (unlikely(ret < 0)) {
 		CFGP2P_ERR((" wsec error %d\n", ret));
 	}
 set_ie:
-	ret = wl_cfgp2p_set_managment_ie(wl, wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
+	ret = wl_cfgp2p_set_managment_ie(wl, dev,
 	            wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE),
 	            VNDR_IE_PRBREQ_FLAG, ie, ie_len);
 
@@ -844,7 +511,8 @@ exit:
 }
 
 s32
-wl_cfgp2p_escan(struct wl_priv *wl, u16 active, u32 num_chans, u16 *channels,
+wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
+	u32 num_chans, u16 *channels,
 	s32 search_state, u16 action, u32 bssidx)
 {
 	s32 ret = BCME_OK;
@@ -933,10 +601,19 @@ wl_cfgp2p_escan(struct wl_priv *wl, u16 active, u32 num_chans, u16 *channels,
 
 	CFGP2P_INFO(("\n"));
 
-	ret = wl_cfgp2p_bssiovar_setbuf(wl_to_p2p_bss_ndev(wl, bssidx), "p2p_scan", bssidx,
-	            memblk, memsize, smbuf, sizeof(ioctlbuf));
+	ret = wldev_iovar_setbuf_bsscfg(dev, "p2p_scan",
+	            memblk, memsize, smbuf, sizeof(ioctlbuf), bssidx);
 	return ret;
 }
+/* Check whether pointed-to IE looks like WPA. */
+#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
+		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
+/* Check whether pointed-to IE looks like WPS. */
+#define wl_cfgp2p_is_wps_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
+		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
+/* Check whether the given IE looks like WFA P2P IE. */
+#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
+		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
 /* Delete and Set a management ie to firmware
  * Parameters:
  * @wl       : wl_private data
@@ -965,7 +642,8 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
 	u8 delete = 0;
 #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie)
 #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len)
-
+	if (bssidx == -1)
+		return BCME_BADARG;
 	if (bssidx == P2PAPI_BSSCFG_PRIMARY)
 		bssidx =  wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
 	switch (pktflag) {
@@ -1019,9 +697,9 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
 				while (pos < *mgmt_ie_len) {
 					ie_id = ie_buf[pos++];
 					ie_len = ie_buf[pos++];
-					CFGP2P_INFO(("DELELED ID(%d), Len(%d),\
-						OUI(%02x:%02x:%02x)\n",\
-						ie_id, ie_len, ie_buf[pos],\
+					CFGP2P_INFO(("DELELED ID(%d), Len(%d),"
+						"OUI(%02x:%02x:%02x)\n",
+						ie_id, ie_len, ie_buf[pos],
 						ie_buf[pos+1], ie_buf[pos+2]));
 					ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag,
 					    ie_buf+pos, VNDR_SPEC_ELEMENT_ID,
@@ -1039,10 +717,15 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
 			while (pos < p2p_ie_len) {
 				ie_id = ie_buf[pos++];
 				ie_len = ie_buf[pos++];
-				CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI : %02x:%02x:%02x\n",
-				        ie_id, ie_len, ie_buf[pos], ie_buf[pos+1], ie_buf[pos+2]));
-				ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos,
-				        VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete);
+				if ((ie_id == DOT11_MNG_VS_ID) &&
+				   (wl_cfgp2p_is_wps_ie(&ie_buf[pos-2], NULL, 0) ||
+					wl_cfgp2p_is_p2p_ie(&ie_buf[pos-2], NULL, 0))) {
+					CFGP2P_INFO(("ADDED ID : %d, Len : %d , OUI :"
+						"%02x:%02x:%02x\n", ie_id, ie_len, ie_buf[pos],
+						ie_buf[pos+1], ie_buf[pos+2]));
+					ret = wl_cfgp2p_vndr_ie(ndev, bssidx, pktflag, ie_buf+pos,
+					    VNDR_SPEC_ELEMENT_ID, ie_buf+pos+3, ie_len-3, delete);
+				}
 				pos += ie_len;
 			}
 		}
@@ -1083,15 +766,7 @@ wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx)
 
 	return BCME_OK;
 }
-/* Check whether pointed-to IE looks like WPA. */
-#define wl_cfgp2p_is_wpa_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPA_OUI_TYPE)
-/* Check whether pointed-to IE looks like WPS. */
-#define wl_cfgp2p_is_wps_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WPS_OUI, WPS_OUI_LEN, WPS_OUI_TYPE)
-/* Check whether the given IE looks like WFA P2P IE. */
-#define wl_cfgp2p_is_p2p_ie(ie, tlvs, len)	wl_cfgp2p_has_ie(ie, tlvs, len, \
-		(const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P)
+
 
 /* Is any of the tlvs the expected entry? If
  * not update the tlvs buffer pointer/length.
@@ -1106,6 +781,8 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u
 		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 */
@@ -1196,7 +873,9 @@ wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag,
 	        = (uchar)(data_len + VNDR_IE_MIN_LEN);
 	memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui, oui, 3);
 	memcpy(ie_setbuf->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.data, data, data_len);
-	err = wl_cfgp2p_bssiovar_set(ndev, "vndr_ie", bssidx, ie_setbuf, buf_len);
+	err = wldev_iovar_setbuf_bsscfg(ndev, "vndr_ie", ie_setbuf, buf_len,
+		ioctlbuf, sizeof(ioctlbuf), bssidx);
+
 	CFGP2P_INFO(("vndr_ie iovar returns %d\n", err));
 	kfree(ie_setbuf);
 	return err;
@@ -1255,24 +934,18 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev,
 
 /*
  *  Timer expire callback function for LISTEN
+ *  We can't report cfg80211_remain_on_channel_expired from Timer ISR context, 
+ *  so lets do it from thread context.
  */
 static void
 wl_cfgp2p_listen_expired(unsigned long data)
 {
+	wl_event_msg_t msg;
 	struct wl_priv *wl = (struct wl_priv *) data;
 
 	CFGP2P_DBG((" Enter\n"));
-
-	if (test_bit(WLP2P_STATUS_LISTEN_EXPIRED, &wl->p2p_status) == 0) {
-		CFGP2P_ERR((" WLC_E_P2P_DISC_LISTEN_COMPLETE does not occur\n"));
-		set_bit(WLP2P_STATUS_LISTEN_EXPIRED, &wl->p2p_status);
-
-		cfg80211_remain_on_channel_expired(
-		    wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE),
-		    wl->cache_cookie, &wl->remain_on_chan,
-		    wl->remain_on_chan_type, GFP_KERNEL);
-	}
-
+	msg.event_type =  hton32(WLC_E_P2P_DISC_LISTEN_COMPLETE);
+	wl_cfg80211_event(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE), &msg, NULL, GFP_ATOMIC);
 }
 
 /* 
@@ -1300,6 +973,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
 
 	s32 ret = BCME_OK;
 	CFGP2P_DBG((" Enter\n"));
+	CFGP2P_INFO(("Channel : %d, Duration : %d\n", channel, duration_ms));
 	if (unlikely(test_bit(WLP2P_STATUS_DISCOVERY_ON, &wl->p2p_status) == 0)) {
 
 		CFGP2P_ERR((" Discovery is not set, so we have noting to do\n"));
@@ -1371,19 +1045,21 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
 {
 	s32 ret = BCME_OK;
 	u32 event_type = ntoh32(e->event_type);
-
+	u32 status = ntoh32(e->status);
 	CFGP2P_DBG((" Enter\n"));
 	if (event_type == WLC_E_ACTION_FRAME_COMPLETE) {
 
-		CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received\n"));
+		CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status));
+		if (status == WLC_E_STATUS_SUCCESS)
+			set_bit(WLP2P_STATUS_ACTION_TX_COMPLETED, &wl->p2p_status);
+		else
+			CFGP2P_ERR(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n"));
+		wake_up_interruptible(&wl->dongle_event_wait);
+	} else {
+		CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received,"
+					"status : %d\n", status));
 
-	}else {
-		CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received\n"));
 	}
-	set_bit(WLP2P_STATUS_ACTION_TX_COMPLETED, &wl->p2p_status);
-
-	wake_up_interruptible(&wl->dongle_event_wait);
-
 
 	return ret;
 }
@@ -1396,7 +1072,8 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
  * 802.11 ack has been received for the sent action frame.
  */
 s32
-wl_cfgp2p_tx_action_frame(struct wl_priv *wl, wl_af_params_t *af_params, s32 bssidx)
+wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
+	wl_af_params_t *af_params, s32 bssidx)
 {
 	s32 ret = BCME_OK;
 	s32 timeout = 0;
@@ -1411,8 +1088,9 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, wl_af_params_t *af_params, s32 bss
 	if (bssidx == P2PAPI_BSSCFG_PRIMARY)
 		bssidx =  wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
 
-	ret = wl_cfgp2p_bssiovar_setbuf(wl_to_p2p_bss_ndev(wl, bssidx), "actframe",
-	            bssidx, af_params, sizeof(*af_params), ioctlbuf, sizeof(ioctlbuf));
+	ret = wldev_iovar_setbuf_bsscfg(dev, "actframe",
+	           af_params, sizeof(*af_params), ioctlbuf, sizeof(ioctlbuf), bssidx);
+
 	if (ret < 0) {
 
 		CFGP2P_ERR((" sending action frame is failed\n"));
@@ -1499,9 +1177,11 @@ wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_i
 				CFGP2P_INFO(("Device ID ATTR FOUND\n"));
 			} else if (subelt_id == P2P_SEID_DEV_INFO) {
 				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
-				CFGP2P_INFO(("Device ID ATTR FOUND\n"));
-			}
-			return;
+				CFGP2P_INFO(("Device INFO ATTR FOUND\n"));
+			} else if (subelt_id == P2P_SEID_GROUP_ID) {
+				memcpy(subel, p2p_int_addr->octet, ETHER_ADDR_LEN);
+				CFGP2P_INFO(("GROUP ID ATTR FOUND\n"));
+			}			return;
 		} else {
 			CFGP2P_DBG(("OTHER id : %d\n", subelt_id));
 		}
@@ -1524,7 +1204,7 @@ wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx)
 
 	/* Check if the BSS is up */
 	*(int*)getbuf = -1;
-	result = wl_cfgp2p_iovar_getbuf_bss(ndev, "bss", &bsscfg_idx,
+	result = wldev_iovar_getbuf_bsscfg(ndev, "bss", &bsscfg_idx,
 	                    sizeof(bsscfg_idx), getbuf, sizeof(getbuf), 0);
 	if (result != 0) {
 		CFGP2P_ERR(("'wl bss -C %d' failed: %d\n", bsscfg_idx, result));
@@ -1555,7 +1235,8 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up)
 	bss_setbuf.cfg = htod32(bsscfg_idx);
 	bss_setbuf.val = htod32(val);
 	CFGP2P_INFO(("---wl bss -C %d %s\n", bsscfg_idx, up ? "up" : "down"));
-	ret = wl_cfgp2p_iovar_set_bss(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf));
+	ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+		ioctlbuf, sizeof(ioctlbuf));
 
 	if (ret != 0) {
 		CFGP2P_ERR(("'bss %d' failed with %d\n", up, ret));
@@ -1566,12 +1247,12 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up)
 
 /* Check if 'p2p' is supported in the driver */
 s32
-wl_cfgp2p_is_p2p_supported(struct wl_priv *wl)
+wl_cfgp2p_is_p2p_supported(struct wl_priv *wl, struct net_device *ndev)
 {
 	s32 ret = BCME_OK;
 	s32 is_p2p_supported = 0;
-	ret = wl_cfgp2p_iovar_getint_bss(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_PRIMARY), "p2p",
-	               &is_p2p_supported, wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY));
+	ret = wldev_iovar_getint(ndev, "p2p",
+	               &is_p2p_supported);
 	if (ret < 0) {
 	    CFGP2P_ERR(("wl p2p error %d\n", ret));
 		return 0;
@@ -1581,3 +1262,11 @@ wl_cfgp2p_is_p2p_supported(struct wl_priv *wl)
 
 	return is_p2p_supported;
 }
+
+s32
+wl_cfgp2p_down(struct wl_priv *wl)
+{
+	if (wl->listen_timer)
+		del_timer_sync(wl->listen_timer);
+	return 0;
+}
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index b208f255f90d..9fb2c9e53ab3 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -23,7 +23,6 @@
  *
  * $Id: wl_cfg80211.h,v 1.1.4.1.2.8 2011/02/09 01:37:52 Exp $
  */
-
 #ifndef _wl_cfgp2p_h_
 #define _wl_cfgp2p_h_
 #include <proto/802.11.h>
@@ -50,12 +49,13 @@ wl_cfgp2p_ifidx(struct wl_priv *wl, struct ether_addr *mac, s32 *index);
 extern s32
 wl_cfgp2p_init_discovery(struct wl_priv *wl);
 extern s32
-wl_cfgp2p_enable_discovery(struct wl_priv *wl, const u8 *ie, u32 ie_len);
+wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len);
 extern s32
 wl_cfgp2p_disable_discovery(struct wl_priv *wl);
 extern s32
-wl_cfgp2p_escan(struct wl_priv *wl, u16 active, u32 num_chans, u16 *channels,
-   s32 search_state, u16 action, u32 bssidx);
+wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_chans,
+	u16 *channels,
+	s32 search_state, u16 action, u32 bssidx);
 
 extern wpa_ie_fixed_t *
 wl_cfgp2p_find_wpaie(u8 *parse, u32 len);
@@ -89,7 +89,8 @@ extern s32
 wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev,
             const wl_event_msg_t *e, void *data);
 extern s32
-wl_cfgp2p_tx_action_frame(struct wl_priv *wl, wl_af_params_t *af_params, s32 bssidx);
+wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev,
+	wl_af_params_t *af_params, s32 bssidx);
 
 extern void
 wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, struct ether_addr *out_dev_addr,
@@ -97,20 +98,6 @@ wl_cfgp2p_generate_bss_mac(struct ether_addr *primary_addr, struct ether_addr *o
 
 extern void
 wl_cfg80211_change_ifaddr(u8* buf, struct ether_addr *p2p_int_addr, u8 element_id);
-
-extern s32
-wl_cfgp2p_bssiovar_set(struct net_device *dev, const s8 *iovar, s32 bssidx,
-            void *param, s32 paramlen);
-extern s32
-wl_cfgp2p_bssiovar_get(struct net_device *dev, const s8 *iovar, s32 bssidx,
-            void *outbuf, s32 len);
-extern s32
-wl_cfgp2p_bssiovar_setint(struct net_device *dev, const s8 *iovar, s32 bssidx, s32 val);
-extern s32
-wl_cfgp2p_iovar_set_bss(struct net_device *dev, const s8 *iovar, void *param, s32 paramlen);
-extern s32
-wl_cfgp2p_iovar_get_bss(struct net_device *dev, const s8 *iovar, void *outbuf, s32 len, s32 bssidx);
-
 extern bool
 wl_cfgp2p_bss_isup(struct net_device *ndev, int bsscfg_idx);
 
@@ -119,7 +106,10 @@ wl_cfgp2p_bss(struct net_device *ndev, s32 bsscfg_idx, s32 up);
 
 
 extern s32
-wl_cfgp2p_is_p2p_supported(struct wl_priv *wl);
+wl_cfgp2p_is_p2p_supported(struct wl_priv *wl, struct net_device *ndev);
+
+extern s32
+wl_cfgp2p_down(struct wl_priv *wl);
 
 /* WiFi Direct */
 #define SOCIAL_CHAN_1 1
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.c b/drivers/net/wireless/bcmdhd/wldev_common.c
new file mode 100644
index 000000000000..c81fccad6c2d
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.c
@@ -0,0 +1,238 @@
+/*
+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers
+ *
+ * Copyright (C) 1999-2011, 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
+ * you also meet, for each linked independent module, the terms and conditions of
+ * 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.
+ *
+ * $Id: wldev_common.c,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
+ */
+
+#include <wlioctl.h>
+#include <bcmutils.h>
+
+#define htod32(i) i
+#define htod16(i) i
+#define dtoh32(i) i
+#define dtoh16(i) i
+#define htodchanspec(i) i
+#define dtohchanspec(i) i
+
+s32 wldev_ioctl(
+	struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
+{
+	s32 ret = 0;
+	struct ifreq ifr;
+	struct wl_ioctl ioc;
+	mm_segment_t fs;
+	s32 err = 0;
+
+	memset(&ioc, 0, sizeof(ioc));
+	ioc.cmd = cmd;
+	ioc.buf = arg;
+	ioc.len = len;
+	ioc.set = set;
+	strcpy(ifr.ifr_name, dev->name);
+	ifr.ifr_data = (caddr_t)&ioc;
+
+	fs = get_fs();
+	set_fs(get_ds());
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31)
+	err = dev->do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#else
+	err = dev->netdev_ops->ndo_do_ioctl(dev, &ifr, SIOCDEVPRIVATE);
+#endif /* LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) */
+	set_fs(fs);
+
+	return ret;
+}
+
+/* Format a iovar buffer, not bsscfg indexed. The bsscfg index will be
+ * taken care of in dhd_ioctl_entry. Internal use only, not exposed to
+ * wl_iw, wl_cfg80211 and wl_cfgp2p
+ */
+s32 wldev_mkiovar(
+	s8 *iovar_name, s8 *param, s32 paramlen,
+	s8 *iovar_buf, u32 buflen)
+{
+	s32 iolen = 0;
+
+	iolen = bcm_mkiovar(iovar_name, param, paramlen, iovar_buf, buflen);
+	return iolen;
+}
+
+s32 wldev_iovar_getbuf(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen)
+{
+	s32 ret = 0;
+	s32 iovar_len = 0;
+
+	iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
+	ret = wldev_ioctl(dev, WLC_GET_VAR, buf, iovar_len, FALSE);
+	return ret;
+}
+
+
+s32 wldev_iovar_setbuf(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen)
+{
+	s32 ret = 0;
+	s32 iovar_len;
+
+	iovar_len = wldev_mkiovar(iovar_name, param, paramlen, buf, buflen);
+	ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+	return ret;
+}
+
+s32 wldev_iovar_setint(
+	struct net_device *dev, s8 *iovar, s32 val)
+{
+	s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+	val = htod32(val);
+	memset(iovar_buf, 0, sizeof(iovar_buf));
+	return wldev_iovar_setbuf(dev, iovar, &val, sizeof(val), iovar_buf,
+		sizeof(iovar_buf));
+}
+
+
+s32 wldev_iovar_getint(
+	struct net_device *dev, s8 *iovar, s32 *pval)
+{
+	s8 iovar_buf[WLC_IOCTL_SMLEN];
+	s32 err;
+
+	memset(iovar_buf, 0, sizeof(iovar_buf));
+	err = wldev_iovar_getbuf(dev, iovar, pval, sizeof(*pval), iovar_buf,
+		sizeof(iovar_buf));
+	if (err == 0)
+	{
+		memcpy(pval, iovar_buf, sizeof(*pval));
+		*pval = dtoh32(*pval);
+	}
+	return err;
+}
+
+/** Format a bsscfg indexed iovar buffer. The bsscfg index will be
+ *  taken care of in dhd_ioctl_entry. Internal use only, not exposed to
+ *  wl_iw, wl_cfg80211 and wl_cfgp2p
+ */
+s32 wldev_mkiovar_bsscfg(
+	const s8 *iovar_name, s8 *param, s32 paramlen,
+	s8 *iovar_buf, s32 buflen, s32 bssidx)
+{
+	const s8 *prefix = "bsscfg:";
+	s8 *p;
+	u32 prefixlen;
+	u32 namelen;
+	u32 iolen;
+
+	if (bssidx == 0) {
+		return wldev_mkiovar((s8*)iovar_name, (s8 *)param, paramlen,
+			(s8 *) iovar_buf, buflen);
+	}
+
+	prefixlen = (u32) strlen(prefix); /* lengh of bsscfg prefix */
+	namelen = (u32) strlen(iovar_name) + 1; /* lengh of iovar  name + null */
+	iolen = prefixlen + namelen + sizeof(u32) + paramlen;
+
+	if (buflen < 0 || iolen > (u32)buflen)
+	{
+		printk("wldev_mkiovar_bsscfg buffer is too short\n");
+		return BCME_BUFTOOSHORT;
+	}
+
+	p = (s8 *)iovar_buf;
+
+	/* copy prefix, no null */
+	memcpy(p, prefix, prefixlen);
+	p += prefixlen;
+
+	/* copy iovar name including null */
+	memcpy(p, iovar_name, namelen);
+	p += namelen;
+
+	/* bss config index as first param */
+	bssidx = htod32(bssidx);
+	memcpy(p, &bssidx, sizeof(u32));
+	p += sizeof(u32);
+
+	/* parameter buffer follows */
+	if (paramlen)
+		memcpy(p, param, paramlen);
+
+	return iolen;
+
+}
+
+s32 wldev_iovar_getbuf_bsscfg(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx)
+{
+	s32 ret = 0;
+	s32 iovar_len = 0;
+
+	iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
+	ret = wldev_ioctl(dev, WLC_GET_VAR, buf, iovar_len, FALSE);
+	return ret;
+
+}
+
+s32 wldev_iovar_setbuf_bsscfg(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx)
+{
+	s32 ret = 0;
+	s32 iovar_len;
+
+	iovar_len = wldev_mkiovar_bsscfg(iovar_name, param, paramlen, buf, buflen, bsscfg_idx);
+	ret = wldev_ioctl(dev, WLC_SET_VAR, buf, iovar_len, TRUE);
+	return ret;
+}
+
+s32 wldev_iovar_setint_bsscfg(
+	struct net_device *dev, s8 *iovar, s32 val, s32 bssidx)
+{
+	s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+	val = htod32(val);
+	memset(iovar_buf, 0, sizeof(iovar_buf));
+	return wldev_iovar_setbuf_bsscfg(dev, iovar, &val, sizeof(val), iovar_buf,
+		sizeof(iovar_buf), bssidx);
+}
+
+
+s32 wldev_iovar_getint_bsscfg(
+	struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx)
+{
+	s8 iovar_buf[WLC_IOCTL_SMLEN];
+	s32 err;
+
+	memset(iovar_buf, 0, sizeof(iovar_buf));
+	err = wldev_iovar_getbuf_bsscfg(dev, iovar, pval, sizeof(*pval), iovar_buf,
+		sizeof(iovar_buf), bssidx);
+	if (err == 0)
+	{
+		memcpy(pval, iovar_buf, sizeof(*pval));
+		*pval = dtoh32(*pval);
+	}
+	return err;
+}
diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h
new file mode 100644
index 000000000000..eae7d24f9e38
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/wldev_common.h
@@ -0,0 +1,91 @@
+/*
+ * Common function shared by Linux WEXT, cfg80211 and p2p drivers
+ *
+ * Copyright (C) 1999-2011, 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
+ * you also meet, for each linked independent module, the terms and conditions of
+ * 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.
+ *
+ * $Id: wldev_common.h,v 1.1.4.1.2.14 2011-02-09 01:40:07 Exp $
+ */
+#ifndef __WLDEV_COMMON_H__
+#define __WLDEV_COMMON_H__
+
+/** wl_dev_ioctl - get/set IOCTLs, will call net_device's do_ioctl (or 
+ *  netdev_ops->ndo_do_ioctl in new kernels)
+ *  @dev: the net_device handle
+ */
+
+s32 wldev_ioctl(
+	struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set);
+
+/** Retrieve named IOVARs, this function calls wl_dev_ioctl with 
+    WLC_GET_VAR IOCTL code
+ */
+s32 wldev_iovar_getbuf(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen);
+
+/** Set named IOVARs, this function calls wl_dev_ioctl with
+    WLC_SET_VAR IOCTL code
+ */
+s32 wldev_iovar_setbuf(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen);
+
+s32 wldev_iovar_setint(
+	struct net_device *dev, s8 *iovar, s32 val);
+
+s32 wldev_iovar_getint(
+	struct net_device *dev, s8 *iovar, s32 *pval);
+
+
+s32 wldev_mkiovar(
+	s8 *iovar_name, s8 *param, s32 paramlen,
+	s8 *iovar_buf, u32 buflen);
+
+
+/** The following function can be implemented if there is a need for bsscfg
+    indexed IOVARs
+ */
+
+s32 wldev_mkiovar_bsscfg(
+	const s8 *iovar_name, s8 *param, s32 paramlen,
+	s8 *iovar_buf, s32 buflen, s32 bssidx);
+
+/** Retrieve named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
+    WLC_GET_VAR IOCTL code
+ */
+s32 wldev_iovar_getbuf_bsscfg(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx);
+
+/** Set named and bsscfg indexed IOVARs, this function calls wl_dev_ioctl with
+    WLC_SET_VAR IOCTL code
+ */
+s32 wldev_iovar_setbuf_bsscfg(
+	struct net_device *dev, s8 *iovar_name,
+	void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx);
+
+s32 wldev_iovar_getint_bsscfg(
+	struct net_device *dev, s8 *iovar, s32 *pval, s32 bssidx);
+
+s32 wldev_iovar_setint_bsscfg(
+	struct net_device *dev, s8 *iovar, s32 val, s32 bssidx);
+
+#endif /* __WLDEV_COMMON_H__ */
-- 
2.34.1