From 2f66cb426e32ac6c731e4eda09aded204a800d64 Mon Sep 17 00:00:00 2001
From: Lin Ma <linm@broadcom.com>
Date: Mon, 18 Jul 2011 11:42:36 -0700
Subject: [PATCH 494/696] Update to 5.90.125.40

Add monitor interface support and fix cfg80211 management frame isses
Add support for hostapd
Use private command to get p2p device address

Change-Id: Ie490e38f1af9f259ff4a96b2f7d367119c65c377
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
Signed-off-by: Dmitry Shmidt <dimitrysh@google.com>
---
 drivers/net/wireless/bcmdhd/dhd_linux.c     |   68 ++-
 drivers/net/wireless/bcmdhd/dhd_linux_mon.c |  331 ++++++++
 drivers/net/wireless/bcmdhd/dhd_sdio.c      |  119 ++--
 drivers/net/wireless/bcmdhd/wl_android.c    |   19 +-
 drivers/net/wireless/bcmdhd/wl_cfg80211.c   | 1143 ++++++++++++++++++++-------
 drivers/net/wireless/bcmdhd/wl_cfg80211.h   |   32 +-
 drivers/net/wireless/bcmdhd/wl_cfgp2p.c     |  190 +++--
 drivers/net/wireless/bcmdhd/wl_cfgp2p.h     |   32 +-
 drivers/net/wireless/bcmdhd/wl_iw.c         |   26 +-
 9 files changed, 1488 insertions(+), 472 deletions(-)
 create mode 100644 drivers/net/wireless/bcmdhd/dhd_linux_mon.c

diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c
index e952ee1..ff9f9fa 100644
--- a/drivers/net/wireless/bcmdhd/dhd_linux.c
+++ b/drivers/net/wireless/bcmdhd/dhd_linux.c
@@ -91,6 +91,7 @@ static histo_t vi_d1, vi_d2, vi_d3, vi_d4;
 
 #if defined(SOFTAP)
 extern bool ap_cfg_running;
+extern bool ap_fw_loaded;
 #endif
 
 /* enable HOSTIP cache update from the host side when an eth0:N is up */
@@ -442,6 +443,12 @@ static void dhd_htsf_addrxts(dhd_pub_t *dhdp, void *pktbuf);
 static void dhd_dump_htsfhisto(histo_t *his, char *s);
 #endif /* WLMEDIA_HTSF */
 
+extern s32 wl_cfg80211_ifdel_ops(struct net_device *net);
+
+/* Monitor interface */
+extern int dhd_monitor_init(void *dhd_pub);
+extern int dhd_monitor_uninit(void);
+
 
 #if defined(CONFIG_WIRELESS_EXT)
 struct iw_statistics *dhd_get_wireless_stats(struct net_device *dev);
@@ -491,6 +498,7 @@ extern int register_pm_notifier(struct notifier_block *nb);
 extern int unregister_pm_notifier(struct notifier_block *nb);
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */
 	/* && defined(DHD_GPL) */
+
 static void dhd_set_packet_filter(int value, dhd_pub_t *dhd)
 {
 #ifdef PKT_FILTER_SUPPORT
@@ -972,7 +980,7 @@ dhd_op_if(dhd_if_t *ifp)
 				ret = -EOPNOTSUPP;
 			} else {
 #if defined(SOFTAP)
-		if (ap_cfg_running && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
+		if (ap_fw_loaded && !(dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)) {
 				 /* semaphore that the soft AP CODE waits on */
 				flags = dhd_os_spin_lock(&dhd->pub);
 
@@ -992,6 +1000,9 @@ dhd_op_if(dhd_if_t *ifp)
 	case WLC_E_IF_DEL:
 		if (ifp->net != NULL) {
 			DHD_TRACE(("\n%s: got 'WLC_E_IF_DEL' state\n", __FUNCTION__));
+#ifdef WL_CFG80211
+			wl_cfg80211_ifdel_ops(ifp->net);
+#endif
 			netif_stop_queue(ifp->net);
 			unregister_netdev(ifp->net);
 			ret = DHD_DEL_IF;	/* Make sure the free_netdev() is called */
@@ -1234,7 +1245,7 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
 	return ret;
 }
 
-static int
+int
 dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
 {
 	int ret;
@@ -1462,7 +1473,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
 			}
 		}
 
-
 		ASSERT(ifidx < DHD_MAX_IFS && dhd->iflist[ifidx]);
 		if (dhd->iflist[ifidx] && !dhd->iflist[ifidx]->state)
 			ifp = dhd->iflist[ifidx];
@@ -1473,6 +1483,14 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
 		dhdp->dstats.rx_bytes += skb->len;
 		dhdp->rx_packets++; /* Local count */
 
+		/* Dropping packets before registering net device to avoid kernel panic */
+		if (!ifp->net || ifp->net->reg_state != NETREG_REGISTERED) {
+			DHD_ERROR(("%s: net device is NOT registered yet. drop [%s] packet\n",
+			__FUNCTION__, (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) ? "event" : "data"));
+			PKTFREE(dhdp->osh, pktbuf, TRUE);
+			continue;
+		}
+
 		if (in_interrupt()) {
 			netif_rx(skb);
 		} else {
@@ -2363,7 +2381,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 	dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
-
 	/* updates firmware nvram path if it was provided as module parameters */
 	if ((firmware_path != NULL) && (firmware_path[0] != '\0'))
 		strcpy(fw_path, firmware_path);
@@ -2469,6 +2486,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 		DHD_ERROR(("wl_cfg80211_attach failed\n"));
 		goto fail;
 	}
+
+	dhd_monitor_init(&dhd->pub);
 	dhd_state |= DHD_ATTACH_STATE_CFG80211;
 #endif
 #if defined(CONFIG_WIRELESS_EXT)
@@ -2563,7 +2582,6 @@ fail:
 		dhd_free(&dhd->pub);
 	}
 
-
 	return NULL;
 }
 
@@ -2665,7 +2683,11 @@ dhd_bus_start(dhd_pub_t *dhdp)
 	setbit(dhdp->eventmask, WLC_E_TXFAIL);
 	setbit(dhdp->eventmask, WLC_E_JOIN_START);
 	setbit(dhdp->eventmask, WLC_E_SCAN_COMPLETE);
-
+	setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_RX);
+	setbit(dhdp->eventmask, WLC_E_ACTION_FRAME_COMPLETE);
+#if defined(WLP2P)
+	setbit(dhdp->eventmask, WLC_E_P2P_PROBREQ_MSG);
+#endif /* WLP2P */
 #ifdef PNO_SUPPORT
 	setbit(dhdp->eventmask, WLC_E_PFN_NET_FOUND);
 #endif /* PNO_SUPPORT */
@@ -2694,10 +2716,6 @@ dhd_bus_start(dhd_pub_t *dhdp)
 	dhd_write_macaddr(dhd->pub.mac.octet);
 #endif
 
-#if defined(CONFIG_SYSCTL) && defined(WL_CFG80211)
-	wl_cfg80211_sysctl_export_devaddr(&dhd->pub);
-#endif
-
 	return 0;
 }
 
@@ -2724,6 +2742,7 @@ dhd_iovar(dhd_pub_t *pub, int ifidx, char *name, char *cmd_buf, uint cmd_len, in
 
 	return ret;
 }
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31))
 static struct net_device_ops dhd_ops_pri = {
 	.ndo_open = dhd_open,
@@ -2848,6 +2867,8 @@ static int dhd_device_event(struct notifier_block *this,
 					__FUNCTION__));
 				aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
 			}
+			else
+				aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE);
 #endif
 			break;
 
@@ -2923,12 +2944,18 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
 	 * We have to use the primary MAC for virtual interfaces
 	 */
 		memcpy(temp_addr, dhd->iflist[ifidx]->mac_addr, ETHER_ADDR_LEN);
-		if (ifidx == 1) {
-			DHD_TRACE(("%s ACCESS POINT MAC: \n", __FUNCTION__));
-			/*  ACCESSPOINT INTERFACE CASE */
-			temp_addr[0] |= 0x02;  /* set bit 2 , - Locally Administered address  */
+		/*
+		 * Android sets the locally administered bit to indicate that this is a
+		 * portable hotspot.  This will not work in simultaneous AP/STA mode,
+		 * nor with P2P.  Need to set the Donlge's MAC address, and then use that.
+		 */
+		if (ifidx > 0) {
+			DHD_ERROR(("%s interface [%s]: set locally administered bit in MAC\n",
+			__func__, net->name));
+			temp_addr[0] |= 0x02;
 		}
 	}
+
 	net->hard_header_len = ETH_HLEN + dhd->pub.hdrlen;
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 24)
 	net->ethtool_ops = &dhd_ethtool_ops;
@@ -2951,11 +2978,11 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx)
 		DHD_ERROR(("couldn't register the net device, err %d\n", err));
 		goto fail;
 	}
-
-	printf("%s: Driver up: Broadcom Dongle Host Driver mac=%.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
+	printf("Broadcom Dongle Host Driver: register interface [%s]"
+		" MAC: %.2x:%.2x:%.2x:%.2x:%.2x:%.2x\n",
 		net->name,
-	       dhd->pub.mac.octet[0], dhd->pub.mac.octet[1], dhd->pub.mac.octet[2],
-	       dhd->pub.mac.octet[3], dhd->pub.mac.octet[4], dhd->pub.mac.octet[5]);
+		net->dev_addr[0], net->dev_addr[1], net->dev_addr[2],
+		net->dev_addr[3], net->dev_addr[4], net->dev_addr[5]);
 
 #if defined(SOFTAP) && defined(CONFIG_WIRELESS_EXT) && !defined(WL_CFG80211)
 		wl_iw_iscan_set_scan_broadcast_prep(net, 1);
@@ -3106,8 +3133,10 @@ void dhd_detach(dhd_pub_t *dhdp)
 	}
 
 #ifdef WL_CFG80211
-	if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211)
+	if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
 		wl_cfg80211_detach();
+		dhd_monitor_uninit();
+	}
 #endif
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP)
@@ -3120,6 +3149,7 @@ void dhd_detach(dhd_pub_t *dhdp)
 		wake_lock_destroy(&dhd->wl_rxwake);
 #endif
 	}
+
 }
 
 
diff --git a/drivers/net/wireless/bcmdhd/dhd_linux_mon.c b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c
new file mode 100644
index 0000000..a51db01
--- /dev/null
+++ b/drivers/net/wireless/bcmdhd/dhd_linux_mon.c
@@ -0,0 +1,331 @@
+/*
+ * Broadcom Dongle Host Driver (DHD), Linux monitor network interface
+ *
+ * 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: dhd_linux_mon.c,v 1.131.2.55 2011-02-09 05:31:56 Exp $
+ */
+
+#include <linux/string.h>
+#include <linux/module.h>
+#include <linux/netdevice.h>
+#include <linux/etherdevice.h>
+#include <linux/if_arp.h>
+#include <linux/ieee80211.h>
+#include <net/ieee80211_radiotap.h>
+
+#include <wlioctl.h>
+#include <bcmutils.h>
+#include <linux_osl.h>
+#include <dhd_dbg.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+
+/*
+ * Some external functions, TODO: move them to dhd_linux.h
+ */
+int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
+
+/**
+ * Local declarations and defintions (not exposed)
+ */
+#define MON_PRINT(format, ...) printk("DHD-MON: %s " format, __func__, ##__VA_ARGS__)
+#define MON_TRACE MON_PRINT
+
+typedef struct monitor_interface {
+	int radiotap_enabled;
+	struct net_device* real_ndev;	/* The real interface that the monitor is on */
+	struct net_device* mon_ndev;
+} monitor_interface;
+
+typedef struct dhd_linux_monitor {
+	void *dhd_pub;
+	monitor_interface mon_if[DHD_MAX_IFS];
+	int count;			/* Number of total monitor interface */
+	struct mutex lock;		/* lock to protect count and mon_if */
+} dhd_linux_monitor_t;
+
+static dhd_linux_monitor_t g_monitor;
+
+static struct net_device* lookup_real_netdev(char *name);
+static monitor_interface* ndev_to_monif(struct net_device *ndev);
+static int dhd_mon_if_open(struct net_device *ndev);
+static int dhd_mon_if_stop(struct net_device *ndev);
+static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+static void dhd_mon_if_set_multicast_list(struct net_device *ndev);
+static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr);
+
+static const struct net_device_ops dhd_mon_if_ops = {
+	.ndo_open		= dhd_mon_if_open,
+	.ndo_stop		= dhd_mon_if_stop,
+	.ndo_start_xmit		= dhd_mon_if_subif_start_xmit,
+	.ndo_set_multicast_list = dhd_mon_if_set_multicast_list,
+	.ndo_set_mac_address 	= dhd_mon_if_change_mac,
+};
+
+/**
+ * Local static function defintions
+ */
+
+/* Look up dhd's net device table to find a match (e.g. interface "eth0" is a match for "mon.eth0"
+ * "p2p-eth0-0" is a match for "mon.p2p-eth0-0")
+ */
+static struct net_device* lookup_real_netdev(char *name)
+{
+	int i;
+	int last_name_len = 0;
+	struct net_device *ndev;
+	struct net_device *ndev_found = NULL;
+
+	/* We want to find interface "p2p-eth0-0" for monitor interface "mon.p2p-eth0-0", so
+	 * we skip "eth0" even if "mon.p2p-eth0-0" contains "eth0"
+	 */
+	for (i = 0; i < DHD_MAX_IFS; i++) {
+		ndev = dhd_idx2net(g_monitor.dhd_pub, i);
+		if (ndev && strstr(name, ndev->name)) {
+			if (strlen(ndev->name) > last_name_len)
+				ndev_found = ndev;
+		}
+	}
+
+	return ndev_found;
+}
+
+static monitor_interface* ndev_to_monif(struct net_device *ndev)
+{
+	int i;
+
+	for (i = 0; i < DHD_MAX_IFS; i++) {
+		if (g_monitor.mon_if[i].mon_ndev == ndev)
+			return &g_monitor.mon_if[i];
+	}
+
+	return NULL;
+}
+
+static int dhd_mon_if_open(struct net_device *ndev)
+{
+	int ret = 0;
+
+	MON_PRINT("enter\n");
+	return ret;
+}
+
+static int dhd_mon_if_stop(struct net_device *ndev)
+{
+	int ret = 0;
+
+	MON_PRINT("enter\n");
+	return ret;
+}
+
+static int dhd_mon_if_subif_start_xmit(struct sk_buff *skb, struct net_device *ndev)
+{
+	int ret = 0;
+	int rtap_len;
+	int qos_len = 0;
+	int dot11_hdr_len = 24;
+	int snap_len = 6;
+	unsigned char *pdata;
+	unsigned char src_mac_addr[6];
+	unsigned char dst_mac_addr[6];
+	struct ieee80211_hdr *dot11_hdr;
+	struct ieee80211_radiotap_header *rtap_hdr;
+	monitor_interface* mon_if;
+
+	MON_PRINT("enter\n");
+
+	mon_if = ndev_to_monif(ndev);
+	if (mon_if == NULL || mon_if->real_ndev == NULL) {
+		MON_PRINT(" cannot find matched net dev, skip the packet\n");
+		goto fail;
+	}
+
+	if (unlikely(skb->len < sizeof(struct ieee80211_radiotap_header)))
+		goto fail;
+
+	rtap_hdr = (struct ieee80211_radiotap_header *)skb->data;
+	if (unlikely(rtap_hdr->it_version))
+		goto fail;
+
+	rtap_len = ieee80211_get_radiotap_len(skb->data);
+	if (unlikely(skb->len < rtap_len))
+		goto fail;
+
+	MON_PRINT("radiotap len (should be 14): %d\n", rtap_len);
+
+	/* Skip the ratio tap header */
+	skb_pull(skb, rtap_len);
+
+	dot11_hdr = (struct ieee80211_hdr *)skb->data;
+
+	/* Check if the QoS bit is set */
+	if (dot11_hdr->frame_control & 0x0080)
+		qos_len = 2;
+
+	/* Check if this ia a Wireless Distribution System (WDS) frame
+	 * which has 4 MAC addresses
+	 */
+	if ((dot11_hdr->frame_control & 0x0300) == 0x0300)
+		dot11_hdr_len += 6;
+
+	memcpy(dst_mac_addr, dot11_hdr->addr1, sizeof(dst_mac_addr));
+	memcpy(src_mac_addr, dot11_hdr->addr2, sizeof(src_mac_addr));
+
+	/* Skip the 802.11 header, QoS (if any) and SNAP, but leave spaces for
+	 * for two MAC addresses
+	 */
+	skb_pull(skb, dot11_hdr_len + qos_len + snap_len - sizeof(src_mac_addr) * 2);
+	pdata = (unsigned char*)skb->data;
+	memcpy(pdata, dst_mac_addr, sizeof(dst_mac_addr));
+	memcpy(pdata + sizeof(dst_mac_addr), src_mac_addr, sizeof(src_mac_addr));
+
+	MON_PRINT("if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
+
+	/* Use the real net device to transmit the packet */
+	ret = dhd_start_xmit(skb, mon_if->real_ndev);
+
+	return ret;
+
+fail:
+	dev_kfree_skb(skb);
+	return 0;
+}
+
+static void dhd_mon_if_set_multicast_list(struct net_device *ndev)
+{
+	monitor_interface* mon_if;
+
+	mon_if = ndev_to_monif(ndev);
+	if (mon_if == NULL || mon_if->real_ndev == NULL) {
+		MON_PRINT(" cannot find matched net dev, skip the packet\n");
+	}
+
+	MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
+}
+
+static int dhd_mon_if_change_mac(struct net_device *ndev, void *addr)
+{
+	int ret = 0;
+	monitor_interface* mon_if;
+
+	mon_if = ndev_to_monif(ndev);
+	if (mon_if == NULL || mon_if->real_ndev == NULL) {
+		MON_PRINT(" cannot find matched net dev, skip the packet\n");
+	}
+
+	MON_PRINT("enter, if name: %s, matched if name %s\n", ndev->name, mon_if->real_ndev->name);
+	return ret;
+}
+
+/**
+ * Global function definitions (declared in dhd_linux_mon.h)
+ */
+
+int dhd_add_monitor(char *name, struct net_device **new_ndev)
+{
+	int idx;
+	int ret = 0;
+	struct net_device* ndev = NULL;
+	dhd_linux_monitor_t **dhd_mon;
+
+	mutex_lock(&g_monitor.lock);
+
+	MON_TRACE("enter, if name: %s\n", name);
+	if (!name || !new_ndev) {
+		MON_PRINT("invalid parameters\n");
+		ret = -EINVAL;
+		goto out;
+	}
+
+	if (g_monitor.count >= DHD_MAX_IFS) {
+		MON_PRINT("exceeds maximum interfaces\n");
+		ret = -EFAULT;
+		goto out;
+	}
+
+	ndev = alloc_etherdev(sizeof(dhd_linux_monitor_t*));
+	if (!ndev) {
+		MON_PRINT("failed to allocate memory\n");
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	ndev->type = ARPHRD_IEEE80211_RADIOTAP;
+	strncpy(ndev->name, name, IFNAMSIZ);
+	ndev->name[IFNAMSIZ - 1] = 0;
+	ndev->netdev_ops = &dhd_mon_if_ops;
+
+	ret = register_netdevice(ndev);
+	if (ret) {
+		MON_PRINT(" register_netdevice failed (%d)\n", ret);
+		goto out;
+	}
+
+	*new_ndev = ndev;
+	idx = g_monitor.count;
+	g_monitor.mon_if[idx].radiotap_enabled = TRUE;
+	g_monitor.mon_if[idx].mon_ndev = ndev;
+	g_monitor.mon_if[idx].real_ndev = lookup_real_netdev(name);
+	g_monitor.count++;
+	dhd_mon = (dhd_linux_monitor_t **)netdev_priv(ndev);
+	*dhd_mon = &g_monitor;
+
+	MON_PRINT("net device returned: 0x%p\n", ndev);
+	MON_PRINT("found a matched net device, name %s\n", g_monitor.mon_if[idx].real_ndev->name);
+
+out:
+	if (ret && ndev)
+		free_netdev(ndev);
+
+	mutex_unlock(&g_monitor.lock);
+	return ret;
+
+}
+
+int dhd_monitor_init(void *dhd_pub)
+{
+	g_monitor.dhd_pub = dhd_pub;
+	mutex_init(&g_monitor.lock);
+	return 0;
+}
+
+int dhd_monitor_uninit(void)
+{
+	int i;
+	struct net_device *ndev;
+
+	mutex_lock(&g_monitor.lock);
+
+	for (i = 0; i < DHD_MAX_IFS; i++) {
+		ndev = g_monitor.mon_if[i].mon_ndev;
+		if (ndev) {
+			unregister_netdev(ndev);
+			free_netdev(ndev);
+			g_monitor.mon_if[i].real_ndev = NULL;
+			g_monitor.mon_if[i].mon_ndev = NULL;
+			g_monitor.count--;
+		}
+	}
+
+	mutex_unlock(&g_monitor.lock);
+	return 0;
+}
diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c
index ce9d26b..2dbb802 100644
--- a/drivers/net/wireless/bcmdhd/dhd_sdio.c
+++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c
@@ -392,6 +392,11 @@ static bool dhd_readahead;
 
 /* To check if there's window offered */
 #define DATAOK(bus) \
+	(((uint8)(bus->tx_max - bus->tx_seq) > 1) && \
+	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
+
+/* To check if there's window offered for ctrl frame*/
+#define TXCTLOK(bus) \
 	(((uint8)(bus->tx_max - bus->tx_seq) != 0) && \
 	(((uint8)(bus->tx_max - bus->tx_seq) & 0x80) == 0))
 
@@ -1364,7 +1369,7 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen)
 	htol32_ua_store(swheader, frame + SDPCM_FRAMETAG_LEN);
 	htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + sizeof(swheader));
 
-	if (!DATAOK(bus)) {
+	if (!TXCTLOK(bus)) {
 		DHD_INFO(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d\n",
 			__FUNCTION__, bus->tx_max, bus->tx_seq));
 		bus->ctrl_frame_stat = TRUE;
@@ -2602,46 +2607,44 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch
 
 		break;
 #ifdef SOFTAP
-        case IOV_GVAL(IOV_FWPATH):
-        {
-            uint32  fw_path_len;
-    
-            fw_path_len = strlen(bus->fw_path);
-    
-            DHD_INFO(("[softap] get fwpath, l=%d\n", len));
-    
-            if ( fw_path_len > len-1 ) {
-                bcmerror = BCME_BUFTOOSHORT;
-                break;
-            }
-    
-            if ( fw_path_len )
-                bcopy(bus->fw_path, arg, fw_path_len);
-    
-            ((uchar*)arg)[fw_path_len] = 0;
-        }
-        break;
-    
-        case IOV_SVAL(IOV_FWPATH):
-            {
-                DHD_INFO(("[softap] set fwpath, idx=%d\n", int_val));
-    
-                switch(int_val) {
-                case 1:
-                    bus->fw_path = fw_path; /* ordinary one */
-                    break;
-                case 2:
-                    bus->fw_path = fw_path2;
-                    break;
-                default:
-                    bcmerror = BCME_BADARG;
-                    return bcmerror;
-                }
-                
-                DHD_INFO(("[softap] new fw path: %s\n", (bus->fw_path[0]?bus->fw_path:"NULL")));
-            }
-            break;
-#endif
+	case IOV_GVAL(IOV_FWPATH):
+	{
+		uint32  fw_path_len;
+
+		fw_path_len = strlen(bus->fw_path);
+		DHD_INFO(("[softap] get fwpath, l=%d\n", len));
+
+		if (fw_path_len > len-1) {
+			bcmerror = BCME_BUFTOOSHORT;
+			break;
+		}
+
+		if (fw_path_len) {
+			bcopy(bus->fw_path, arg, fw_path_len);
+			((uchar*)arg)[fw_path_len] = 0;
+		}
+		break;
+	}
+
+	case IOV_SVAL(IOV_FWPATH):
+		DHD_INFO(("[softap] set fwpath, idx=%d\n", int_val));
+
+		switch (int_val) {
+		case 1:
+			bus->fw_path = fw_path; /* ordinary one */
+			break;
+		case 2:
+			bus->fw_path = fw_path2;
+			break;
+		default:
+			bcmerror = BCME_BADARG;
+			break;
+		}
+
+		DHD_INFO(("[softap] new fw path: %s\n", (bus->fw_path[0] ? bus->fw_path : "NULL")));
+		break;
+
+#endif /* SOFTAP */
 	case IOV_GVAL(IOV_DEVRESET):
 		DHD_TRACE(("%s: Called get IOV_DEVRESET\n", __FUNCTION__));
 
@@ -4386,6 +4389,12 @@ dhdsdio_dpc(dhd_bus_t *bus)
 
 	DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+	if (bus->dhd->busstate == DHD_BUS_DOWN) {
+		DHD_ERROR(("%s: Bus down, ret\n", __FUNCTION__));
+		bus->intstatus = 0;
+		return 0;
+	}
+
 	/* Start with leftover status bits */
 	intstatus = bus->intstatus;
 
@@ -4544,7 +4553,7 @@ clkwait:
 		bcmsdh_intr_enable(sdh);
 	}
 
-	if (DATAOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))  {
+	if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))  {
 		int ret, i;
 
 		ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC,
@@ -4589,6 +4598,9 @@ clkwait:
 		framecnt = dhdsdio_sendfromq(bus, framecnt);
 		txlimit -= framecnt;
 	}
+	/* Resched the DPC if ctrl cmd is pending on bus credit*/
+	if (bus->ctrl_frame_stat)
+		resched = TRUE;
 
 	/* Resched if events or tx frames are pending, else await next interrupt */
 	/* On failed register access, all bets are off: no resched or interrupts */
@@ -5176,7 +5188,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
 	sd1idle = TRUE;
 	dhd_readahead = TRUE;
 	retrydata = FALSE;
-	dhd_doflow = TRUE;
+	dhd_doflow = FALSE;
 	dhd_dongle_memsize = 0;
 	dhd_txminmax = DHD_TXMINMAX;
 
@@ -5291,15 +5303,20 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
 		goto fail;
 	}
 
-	/* Register interrupt callback, but mask it (not operational yet). */
-	DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
-	bcmsdh_intr_disable(sdh);
-	if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
-		DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
-		           __FUNCTION__, ret));
-		goto fail;
+	if (bus->intr) {
+		/* Register interrupt callback, but mask it (not operational yet). */
+		DHD_INTR(("%s: disable SDIO interrupts (not interested yet)\n", __FUNCTION__));
+		bcmsdh_intr_disable(sdh);
+		if ((ret = bcmsdh_intr_reg(sdh, dhdsdio_isr, bus)) != 0) {
+			DHD_ERROR(("%s: FAILED: bcmsdh_intr_reg returned %d\n",
+			           __FUNCTION__, ret));
+			goto fail;
+		}
+		DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
+	} else {
+		DHD_INFO(("%s: SDIO interrupt function is NOT registered due to polling mode\n",
+		           __FUNCTION__));
 	}
-	DHD_INTR(("%s: registered SDIO interrupt function ok\n", __FUNCTION__));
 
 	DHD_INFO(("%s: completed!!\n", __FUNCTION__));
 
diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c
index 432e253..fa6e305 100644
--- a/drivers/net/wireless/bcmdhd/wl_android.c
+++ b/drivers/net/wireless/bcmdhd/wl_android.c
@@ -65,6 +65,7 @@
 #define CMD_BTCOEXSCAN_STOP	"BTCOEXSCAN-STOP"
 #define CMD_BTCOEXMODE		"BTCOEXMODE"
 #define CMD_SETSUSPENDOPT	"SETSUSPENDOPT"
+#define CMD_P2P_DEV_ADDR	"P2P_DEV_ADDR"
 #define CMD_SETFWPATH		"SETFWPATH"
 #define CMD_SETBAND		"SETBAND"
 #define CMD_GETBAND		"GETBAND"
@@ -105,6 +106,7 @@ typedef struct android_wifi_priv_cmd {
 void dhd_customer_gpio_wlan_ctrl(int onoff);
 uint dhd_dev_reset(struct net_device *dev, uint8 flag);
 void dhd_dev_init_ioctl(struct net_device *dev);
+int wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
 
 extern bool ap_fw_loaded;
 #ifdef CUSTOMER_HW2
@@ -276,6 +278,18 @@ exit_proc:
 }
 #endif
 
+static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len)
+{
+	int ret;
+	int bytes_written = 0;
+
+	ret = wl_cfg80211_get_p2p_dev_addr(ndev, (struct ether_addr*)command);
+	if (ret)
+		return 0;
+	bytes_written = sizeof(struct ether_addr);
+	return bytes_written;
+}
+
 /**
  * Global function definitions (declared in wl_android.h)
  */
@@ -439,8 +453,8 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 	else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
 		char *country_code = command + strlen(CMD_COUNTRY) + 1;
 		bytes_written = wldev_set_country(net, country_code);
-#ifdef PNO_SUPPORT
 	}
+#ifdef PNO_SUPPORT
 	else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) {
 		bytes_written = dhd_dev_pno_reset(net);
 	}
@@ -450,7 +464,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 	else if (strnicmp(command, CMD_PNOENABLE_SET, strlen(CMD_PNOENABLE_SET)) == 0) {
 		uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0';
 		bytes_written = dhd_dev_pno_enable(net, pfn_enabled);
+	}
 #endif
+	else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
+		bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd->total_len);
 	} else {
 		DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
 		snprintf(command, 3, "OK");
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
index 22b636d..69180b5 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c
@@ -29,6 +29,11 @@
 #include <osl.h>
 #include <linux/kernel.h>
 
+/*
+ * sys proc file will be REMOVED in next release
+ */
+#undef CONFIG_SYSCTL
+
 #ifdef CONFIG_SYSCTL
 #include <linux/sysctl.h>
 #endif
@@ -189,6 +194,7 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
 	struct cfg80211_pmksa *pmksa);
 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
 	struct net_device *dev);
+static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted);
 /*
  * event & event Q handlers for cfg80211 interfaces
  */
@@ -331,6 +337,7 @@ 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);
 static void wl_init_conf(struct wl_conf *conf);
+static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add);
 static s32 wl_dongle_eventmsg(struct net_device *ndev);
 
 /*
@@ -353,6 +360,8 @@ static s32 wl_pattern_atoh(s8 *src, s8 *dst);
 static s32 wl_dongle_filter(struct net_device *ndev, u32 filter_mode);
 static s32 wl_update_wiphybands(struct wl_priv *wl);
 #endif				/* !EMBEDDED_PLATFORM */
+static __used void wl_dongle_poweron(struct wl_priv *wl);
+static __used void wl_dongle_poweroff(struct wl_priv *wl);
 static s32 wl_config_dongle(struct wl_priv *wl, bool need_lock);
 
 /*
@@ -404,6 +413,12 @@ static void wl_debugfs_remove_netdev(struct wl_priv *wl);
 static int wl_setup_rfkill(struct wl_priv *wl);
 static int wl_rfkill_set(void *data, bool blocked);
 
+/*
+ * Some external functions, TODO: move them to dhd_linux.h
+ */
+int dhd_add_monitor(char *name, struct net_device **new_ndev);
+int dhd_start_xmit(struct sk_buff *skb, struct net_device *net);
+
 #define WL_PRIV_GET() 							\
 	({								\
 	struct wl_iface *ci = NULL;					\
@@ -418,13 +433,17 @@ static int wl_rfkill_set(void *data, bool blocked);
 #define CHECK_SYS_UP()							\
 do {									\
 	struct wl_priv *wl = WL_PRIV_GET();			\
-	if (unlikely(!test_bit(WL_STATUS_READY, &wl->status))) {	\
+	if (unlikely(!wl_get_drv_status(wl, READY))) {	\
 		WL_INFO(("device is not ready : status (%d)\n",		\
 			(int)wl->status));				\
 		return -EIO;						\
 	}								\
 } while (0)
 
+#define IS_WPA_AKM(akm) ((akm) == RSN_AKM_NONE || \
+			 (akm) == RSN_AKM_UNSPECIFIED || \
+			 (akm) == RSN_AKM_PSK)
+
 extern int dhd_wait_pend8021x(struct net_device *dev);
 
 #if (WL_DBG_LEVEL > 0)
@@ -773,6 +792,16 @@ wl_dbg_dump_wps_ie(char *wps_ie)
 	}
 }
 
+static struct net_device* wl_cfg80211_add_monitor_if(char *name)
+{
+	int ret = 0;
+	struct net_device* ndev = NULL;
+
+	ret = dhd_add_monitor(name, &ndev);
+	WL_ERR(("wl_cfg80211_add_monitor_if net device returned: 0x%p\n", ndev));
+	return ndev;
+}
+
 static struct net_device *
 wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 	enum nl80211_iftype type, u32 *flags,
@@ -780,7 +809,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 {
 	s32 err;
 	s32 timeout = -1;
-	s32 wlif_type;
+	s32 wlif_type = -1;
 	s32 index = 0;
 	s32 mode = 0;
 	chanspec_t chspec;
@@ -798,7 +827,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 		mode = WL_MODE_IBSS;
 		return NULL;
 	case NL80211_IFTYPE_MONITOR:
-		return  wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION);
+		return wl_cfg80211_add_monitor_if(name);
 	case NL80211_IFTYPE_P2P_CLIENT:
 	case NL80211_IFTYPE_STATION:
 		wlif_type = WL_P2P_IF_CLIENT;
@@ -819,35 +848,37 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 		WL_ERR(("name is NULL\n"));
 		return NULL;
 	}
+	if (wl->p2p_supported && (wlif_type != -1)) {
+		if (wl_get_p2p_status(wl, IF_DELETING) == 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,
+				(wl_get_p2p_status(wl, IF_DELETING) == false),
+				msecs_to_jiffies(MAX_WAIT_TIME));
 
-	if (wl_get_p2p_status(wl, IF_DELETING) == 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,
-			(wl_get_p2p_status(wl, IF_DELETING) == 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"));
+			/* 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);
+			} else {
+				WL_ERR(("%s: timeount < 0, return -EAGAIN\n", __func__));
+				return ERR_PTR(-EAGAIN);
+			}
+		}
+		if (!p2p_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
+			p2p_on(wl) = true;
+			wl_cfgp2p_set_firm_p2p(wl);
+			wl_cfgp2p_init_discovery(wl);
 		}
-	}
-	if (!p2p_on(wl) && strstr(name, WL_P2P_INTERFACE_PREFIX)) {
-		p2p_on(wl) = true;
-		wl_cfgp2p_init_discovery(wl);
-	}
 
-	memset(wl->p2p.vir_ifname, 0, IFNAMSIZ);
-	strncpy(wl->p2p.vir_ifname, name, IFNAMSIZ - 1);
-	wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr);
+		memset(wl->p2p->vir_ifname, 0, IFNAMSIZ);
+		strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1);
+		wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
 
 	/* Temporary use channel 11, in case GO will be changed with set_channel API  */
 	chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
@@ -856,13 +887,13 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 	 * bss: "wl p2p_ifadd"
 	 */
 	wl_set_p2p_status(wl, IF_ADD);
-	err = wl_cfgp2p_ifadd(wl, &wl->p2p.int_addr, htod32(wlif_type), chspec);
+		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,
-		(wl_get_p2p_status(wl, IF_ADD) == FALSE),
+			(wl_get_p2p_status(wl, IF_ADD) == false),
 		msecs_to_jiffies(MAX_WAIT_TIME));
 	if (timeout > 0 && (!wl_get_p2p_status(wl, IF_ADD))) {
 
@@ -873,7 +904,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 			return ERR_PTR(-ENOMEM);
 		}
 		vwdev->wiphy = wl->wdev->wiphy;
-		WL_INFO((" virtual interface(%s) is created \n", wl->p2p.vir_ifname));
+			WL_INFO((" virtual interface(%s) is created \n", wl->p2p->vir_ifname));
 		index = alloc_idx_vwdev(wl);
 		wl->vwdev[index] = vwdev;
 		vwdev->iftype =
@@ -883,20 +914,19 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name,
 		_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;
+			wl_set_drv_status(wl, READY);
+			wl->p2p->vif_created = true;
 		set_mode_by_netdev(wl, _ndev, mode);
 		wl = wdev_to_wl(vwdev);
 		return _ndev;
 
 	} else {
 		wl_clr_p2p_status(wl, IF_ADD);
-		WL_ERR((" virtual interface(%s) is not created timeout=%d\n",
-			wl->p2p.vir_ifname, timeout));
-		memset(wl->p2p.vir_ifname, '\0', IFNAMSIZ);
-		wl->p2p.vif_created = FALSE;
+			WL_ERR((" virtual interface(%s) is not created \n", wl->p2p->vir_ifname));
+			memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
+			wl->p2p->vif_created = false;
+		}
 	}
-
 	return ERR_PTR(-ENODEV);
 }
 
@@ -906,19 +936,31 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev)
 {
 	struct ether_addr p2p_mac;
 	struct wl_priv *wl = WL_PRIV_GET();
-	memcpy(p2p_mac.octet, wl->p2p.int_addr.octet, ETHER_ADDR_LEN);
-	if (wl->p2p.vif_created) {
-		if (test_bit(WL_STATUS_SCANNING, &wl->status)) {
-			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.."));
-		wl_set_p2p_status(wl, IF_DELETING);
+	s32 timeout = -1;
+
+	if (wl->p2p_supported) {
+		memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN);
+		if (wl->p2p->vif_created) {
+			if (wl_get_drv_status(wl, SCANNING)) {
+				wl_cfg80211_scan_abort(wl, dev);
+			}
 
+			wl_cfgp2p_ifdel(wl, &p2p_mac);
+			wl_set_p2p_status(wl, IF_DELETING);
+
+			/* Wait for any pending scan req to get aborted from the sysioc context */
+			timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
+				(wl->scan_request == false),
+				msecs_to_jiffies(MAX_WAIT_TIME));
+
+			if (timeout > 0 && (!wl->scan_request)) {
+				WL_DBG(("IFDEL Operations Done"));
+			} else {
+				WL_ERR(("IFDEL didn't complete properly"));
+			}
+		}
 	}
 
-	WL_DBG(("Done\n"));
 	return 0;
 }
 
@@ -935,7 +977,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
 	s32 mode = 0;
 	chanspec_t chspec;
 	struct wl_priv *wl = WL_PRIV_GET();
-	CHECK_SYS_UP();
+	WL_DBG(("Enter \n"));
 	switch (type) {
 	case NL80211_IFTYPE_MONITOR:
 	case NL80211_IFTYPE_WDS:
@@ -963,21 +1005,36 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
 	}
 
 
-	if (ap && wl->p2p.vif_created) {
-		WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p.vif_created,
-			p2p_on(wl)));
-		chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
-		wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT;
-		WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n", ndev->name, ap, infra, type));
-		wl_set_p2p_status(wl, IF_CHANGING);
-		wl_clr_p2p_status(wl, IF_CHANGED);
-		err = wl_cfgp2p_ifchange(wl, &wl->p2p.int_addr, htod32(wlif_type), chspec);
-		timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
-			(wl_get_p2p_status(wl, IF_CHANGED) == TRUE),
-			msecs_to_jiffies(MAX_WAIT_TIME));
+	if (ap) {
 		set_mode_by_netdev(wl, ndev, mode);
-		wl_clr_p2p_status(wl, IF_CHANGING);
-		wl_clr_p2p_status(wl, IF_CHANGED);
+		if (wl->p2p_supported && wl->p2p->vif_created) {
+			WL_DBG(("p2p_vif_created (%d) p2p_on (%d)\n", wl->p2p->vif_created,
+			p2p_on(wl)));
+			chspec = wf_chspec_aton(WL_P2P_TEMP_CHAN);
+			wlif_type = ap ? WL_P2P_IF_GO : WL_P2P_IF_CLIENT;
+			WL_ERR(("%s : ap (%d), infra (%d), iftype: (%d)\n",
+				ndev->name, ap, infra, type));
+			wl_set_p2p_status(wl, IF_CHANGING);
+			wl_clr_p2p_status(wl, IF_CHANGED);
+			err = wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec);
+			timeout = wait_event_interruptible_timeout(wl->dongle_event_wait,
+				(wl_get_p2p_status(wl, IF_CHANGED) == true),
+				msecs_to_jiffies(MAX_WAIT_TIME));
+			set_mode_by_netdev(wl, ndev, mode);
+			wl_clr_p2p_status(wl, IF_CHANGING);
+			wl_clr_p2p_status(wl, IF_CHANGED);
+		} else if (ndev == wl_to_prmry_ndev(wl) &&
+			!wl_get_drv_status(wl, AP_CREATED)) {
+			wl_set_drv_status(wl, AP_CREATING);
+			if (!wl->ap_info &&
+				!(wl->ap_info = kzalloc(sizeof(struct ap_info), GFP_KERNEL))) {
+				WL_ERR(("struct ap_saved_ie allocation failed\n"));
+				return -ENOMEM;
+			}
+		} else {
+			WL_ERR(("Cannot change the interface for GO or SOFTAP\n"));
+			return -EINVAL;
+		}
 	}
 
 	ndev->ieee80211_ptr->iftype = type;
@@ -993,20 +1050,22 @@ wl_cfg80211_notify_ifadd(struct net_device *net)
 		WL_ERR(("net is NULL\n"));
 		return 0;
 	}
-
-	WL_DBG(("IF_ADD event called from dongle, old interface name: %s, new name: %s\n",
-		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;
-	wl_clr_p2p_status(wl, IF_ADD);
-	wake_up_interruptible(&wl->dongle_event_wait);
+	if (wl->p2p_supported) {
+		WL_DBG(("IF_ADD event called from dongle, old interface name: %s,"
+			"new name: %s\n", 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;
+		wl_clr_p2p_status(wl, IF_ADD);
+		wake_up_interruptible(&wl->dongle_event_wait);
+	}
 	return ret;
 }
 
 s32
-wl_cfg80211_notify_ifdel(struct net_device *net)
+wl_cfg80211_ifdel_ops(struct net_device *net)
 {
 	struct wl_priv *wl = WL_PRIV_GET();
 
@@ -1015,15 +1074,39 @@ wl_cfg80211_notify_ifdel(struct net_device *net)
 		return 0;
 	}
 
-	WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n",
-		net->name, wl->p2p.vir_ifname));
-	if (wl->p2p.vif_created) {
+	if ((wl->p2p->vif_created) && (wl->scan_request)) {
+
+		/* Abort any pending scan requests */
+		wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE;
+		rtnl_lock();
+		WL_INFO(("ESCAN COMPLETED\n"));
+		wl_notify_escan_complete(wl, true);
+		rtnl_unlock();
+	}
+
+	/* Wake up any waiting thread */
+	wake_up_interruptible(&wl->dongle_event_wait);
+
+	return 0;
+}
+
+s32
+wl_cfg80211_notify_ifdel(struct net_device *net)
+{
+	struct wl_priv *wl = WL_PRIV_GET();
+
+
+	if (wl->p2p->vif_created) {
 		s32 index = 0;
-		memset(wl->p2p.vir_ifname, '\0', IFNAMSIZ);
+
+	WL_DBG(("IF_DEL event called from dongle, _net name: %s, vif name: %s\n",
+			net->name, wl->p2p->vir_ifname));
+
+		memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ);
 		index = wl_cfgp2p_find_idx(wl, net);
 		wl_to_p2p_bss_ndev(wl, index) = NULL;
 		wl_to_p2p_bss_bssidx(wl, index) = 0;
-		wl->p2p.vif_created = FALSE;
+		wl->p2p->vif_created = false;
 		set_mode_by_netdev(wl, net, -1);
 		wl_cfgp2p_clear_management_ie(wl,
 			index);
@@ -1032,12 +1115,13 @@ 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.. */
+	}
+
 		wl_clr_p2p_status(wl, IF_DELETING);
-		WL_ERR(("Cleared IF_DELETING status bit\n"));
+
+	/* Wake up any waiting thread */
 		wake_up_interruptible(&wl->dongle_event_wait);
-		WL_ERR(("Cleared IF_DELETING status bit DONE WAKEUP Interruptible\n"));
-	}
+
 	return 0;
 }
 
@@ -1144,7 +1228,7 @@ static s32 wl_do_iscan(struct wl_priv *wl)
 
 	passive_scan = wl->active_scan ? 0 : 1;
 	err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-		&passive_scan, sizeof(passive_scan), FALSE);
+		&passive_scan, sizeof(passive_scan), false);
 	if (unlikely(err)) {
 		WL_DBG(("error (%d)\n", err));
 		return err;
@@ -1171,8 +1255,8 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, wlc_ssid_t *ssid, uint
 	WL_DBG(("Enter \n"));
 
 
-	if ((ndev == wl_to_prmry_ndev(wl)) &&
-		!p2p_scan(wl)) {
+	if (!wl->p2p_supported || ((ndev == wl_to_prmry_ndev(wl)) &&
+		!p2p_scan(wl))) {
 		/* LEGACY SCAN TRIGGER */
 		WL_DBG(("LEGACY SCAN START\n"));
 		if (ssid && ssid->SSID_len) {
@@ -1255,7 +1339,7 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl
 	wl->escan_info.escan_state = WL_ESCAN_STATE_SCANING;
 	passive_scan = wl->active_scan ? 0 : 1;
 	err = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-		&passive_scan, sizeof(passive_scan), FALSE);
+		&passive_scan, sizeof(passive_scan), false);
 	if (unlikely(err)) {
 		WL_DBG(("error (%d)\n", err));
 		return err;
@@ -1284,11 +1368,11 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	bool spec_scan;
 	s32 err = 0;
 
-	if (unlikely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (unlikely(wl_get_drv_status(wl, SCANNING))) {
 		WL_ERR(("Scanning already : status (%d)\n", (int)wl->status));
 		return -EAGAIN;
 	}
-	if (unlikely(test_bit(WL_STATUS_SCAN_ABORTING, &wl->status))) {
+	if (unlikely(wl_get_drv_status(wl, SCAN_ABORTING))) {
 		WL_ERR(("Scanning being aborted : status (%d)\n",
 			(int)wl->status));
 		return -EAGAIN;
@@ -1305,33 +1389,37 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 		} else if (wl->escan_on) {
 			escan_req = true;
 			if (ssids->ssid_len && IS_P2P_SSID(ssids->ssid)) {
-				/* p2p scan trigger */
-				if (p2p_on(wl) == false) {
-					/* p2p on at the first time */
-					p2p_on(wl) = true;
-					wl_cfgp2p_set_firm_p2p(wl);
+				if (wl->p2p_supported) {
+					/* p2p scan trigger */
+					if (p2p_on(wl) == false) {
+						/* p2p on at the first time */
+						p2p_on(wl) = true;
+						wl_cfgp2p_set_firm_p2p(wl);
+					}
+					p2p_scan(wl) = true;
 				}
 
-				p2p_scan(wl) = true;
-
 			} else {
 				/* legacy scan trigger
 				 * So, we have to disable p2p discovery if p2p discovery is on
 				 */
-				p2p_scan(wl) = false;
-				/* If Netdevice is not equals to primary and p2p is on
-				*  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
-							 */
-				if (p2p_on(wl) && (ndev != wl_to_prmry_ndev(wl)))
-					p2p_scan(wl) = true;
+				if (wl->p2p_supported) {
+					p2p_scan(wl) = false;
+					/* If Netdevice is not equals to primary and p2p is on
+					*  , we will do p2p scan using P2PAPI_BSSCFG_DEVICE.
+					*/
+					if (p2p_on(wl) && (ndev != wl_to_prmry_ndev(wl)))
+						p2p_scan(wl) = true;
+
+					if (p2p_scan(wl) == false) {
+						if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
+							err = wl_cfgp2p_discover_enable_search(wl,
+							false);
+							if (unlikely(err)) {
+								goto scan_out;
+							}
 
-				if (p2p_scan(wl) == false) {
-					if (wl_get_p2p_status(wl, DISCOVERY_ON)) {
-						err = wl_cfgp2p_discover_enable_search(wl, FALSE);
-						if (unlikely(err)) {
-							goto scan_out;
 						}
-
 					}
 				}
 			}
@@ -1341,7 +1429,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 		ssids = this_ssid;
 	}
 	wl->scan_request = request;
-	set_bit(WL_STATUS_SCANNING, &wl->status);
+	wl_set_drv_status(wl, SCANNING);
 	if (iscan_req) {
 		err = wl_do_iscan(wl);
 		if (likely(!err))
@@ -1354,13 +1442,15 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 
 		memcpy(ssid_info.SSID, ssids->ssid, ssids->ssid_len);
 		ssid_info.SSID_len = ssids->ssid_len;
+		if (wl->p2p_supported) {
+			if (p2p_on(wl) && p2p_scan(wl)) {
 
-		if (p2p_on(wl) && p2p_scan(wl)) {
-
-			err = wl_cfgp2p_enable_discovery(wl, ndev, request->ie, request->ie_len);
+				err = wl_cfgp2p_enable_discovery(wl, ndev,
+				request->ie, request->ie_len);
 
-			if (unlikely(err)) {
-				goto scan_out;
+				if (unlikely(err)) {
+					goto scan_out;
+				}
 			}
 		}
 		err = wl_do_escan(wl, wiphy, ndev, &ssid_info);
@@ -1386,13 +1476,13 @@ __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 = wldev_ioctl(ndev, WLC_SET_PASSIVE_SCAN,
-			&passive_scan, sizeof(passive_scan), FALSE);
+			&passive_scan, sizeof(passive_scan), false);
 		if (unlikely(err)) {
 			WL_ERR(("WLC_SET_PASSIVE_SCAN error (%d)\n", err));
 			goto scan_out;
 		}
 		err = wldev_ioctl(ndev, WLC_SCAN, &sr->ssid,
-			sizeof(sr->ssid), FALSE);
+			sizeof(sr->ssid), false);
 		if (err) {
 			if (err == -EBUSY) {
 				WL_INFO(("system busy : scan for \"%s\" "
@@ -1407,7 +1497,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
 	return 0;
 
 scan_out:
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
+	wl_clr_drv_status(wl, SCANNING);
 	wl->scan_request = NULL;
 	return err;
 }
@@ -1439,7 +1529,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 = wldev_ioctl(dev, WLC_SET_VAR, buf, len, FALSE);
+	err = wldev_ioctl(dev, WLC_SET_VAR, buf, len, false);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 	}
@@ -1461,7 +1551,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 = wldev_ioctl(dev, WLC_GET_VAR, &var, len, FALSE);
+	err = wldev_ioctl(dev, WLC_GET_VAR, &var, len, false);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 	}
@@ -1500,7 +1590,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 = wldev_ioctl(dev, cmd, &retry, sizeof(retry), FALSE);
+	err = wldev_ioctl(dev, cmd, &retry, sizeof(retry), false);
 	if (unlikely(err)) {
 		WL_ERR(("cmd (%d) , error (%d)\n", cmd, err));
 		return err;
@@ -1612,7 +1702,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
 		memset(&join_params.params.bssid, 0, ETHER_ADDR_LEN);
 
 	err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
-		sizeof(join_params), FALSE);
+		sizeof(join_params), false);
 	if (unlikely(err)) {
 		WL_ERR(("Error (%d)\n", err));
 		return err;
@@ -1985,12 +2075,12 @@ 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 = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, FALSE);
+	err = wldev_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, false);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 		return err;
 	}
-	set_bit(WL_STATUS_CONNECTING, &wl->status);
+	wl_set_drv_status(wl, CONNECTING);
 
 	return err;
 }
@@ -2012,7 +2102,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
 		memcpy(&scbval.ea, &wl->bssid, ETHER_ADDR_LEN);
 		scbval.val = htod32(scbval.val);
 		err = wldev_ioctl(dev, WLC_DISASSOC, &scbval,
-			sizeof(scb_val_t), FALSE);
+			sizeof(scb_val_t), false);
 		if (unlikely(err)) {
 			WL_ERR(("error (%d)\n", err));
 			return err;
@@ -2053,7 +2143,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 = wldev_ioctl(ndev, WLC_SET_RADIO, &disable, sizeof(disable), FALSE);
+	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;
@@ -2116,7 +2206,7 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev,
 		index = (u32) key_idx;
 		index = htod32(index);
 		err = wldev_ioctl(dev, WLC_SET_KEY_PRIMARY, &index,
-			sizeof(index), FALSE);
+			sizeof(index), false);
 		if (unlikely(err)) {
 			WL_ERR(("error (%d)\n", err));
 		}
@@ -2132,7 +2222,7 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 	struct wl_wsec_key key;
 	s32 err = 0;
 	s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
-
+	s32 mode = get_mode_by_netdev(wl, dev);
 	memset(&key, 0, sizeof(key));
 	key.index = (u32) key_idx;
 
@@ -2155,11 +2245,11 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev,
 			WL_ERR(("Invalid key length (%d)\n", key.len));
 			return -EINVAL;
 		}
-
 		WL_DBG(("Setting the key index %d\n", key.index));
 		memcpy(key.data, params->key, key.len);
 
-		if (params->cipher == WLAN_CIPHER_SUITE_TKIP) {
+		if ((mode == WL_MODE_BSS) &&
+			(params->cipher == WLAN_CIPHER_SUITE_TKIP)) {
 			u8 keybuf[8];
 			memcpy(keybuf, &key.data[24], sizeof(keybuf));
 			memcpy(&key.data[24], &key.data[16], sizeof(keybuf));
@@ -2225,10 +2315,10 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	s32 val = 0;
 	s32 wsec = 0;
 	s32 err = 0;
-	uint8 keybuf[8];
+	u8 keybuf[8];
 	s32 bssidx = 0;
 	struct wl_priv *wl = WL_PRIV_GET();
-
+	s32 mode = get_mode_by_netdev(wl, dev);
 	WL_DBG(("key index (%d)\n", key_idx));
 	CHECK_SYS_UP();
 
@@ -2264,10 +2354,12 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
 	case WLAN_CIPHER_SUITE_TKIP:
 		key.algo = CRYPTO_ALGO_TKIP;
 		val = TKIP_ENABLED;
-		/* wpa_supplicant switches the third and fourth quarters of the TKIP key, linm */
-		bcopy(&key.data[24], keybuf, sizeof(keybuf));
-		bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
-		bcopy(keybuf, &key.data[16], sizeof(keybuf));
+		/* wpa_supplicant switches the third and fourth quarters of the TKIP key */
+		if (mode == WL_MODE_BSS) {
+			bcopy(&key.data[24], keybuf, sizeof(keybuf));
+			bcopy(&key.data[16], &key.data[24], sizeof(keybuf));
+			bcopy(keybuf, &key.data[16], sizeof(keybuf));
+		}
 		WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
 		break;
 	case WLAN_CIPHER_SUITE_AES_CMAC:
@@ -2312,7 +2404,7 @@ exit:
 	/* TODO: Removed in P2P, check later --lm */
 	val = 1;		/* assume shared key. otherwise 0 */
 	val = htod32(val);
-	err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), FALSE);
+	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;
@@ -2359,7 +2451,7 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev,
 	/* TODO: Removed in P2P twig, check later --lin */
 	val = 0;		/* assume open key. otherwise 1 */
 	val = htod32(val);
-	err = wldev_ioctl(dev, WLC_SET_AUTH, &val, sizeof(val), FALSE);
+	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;
@@ -2395,28 +2487,28 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
 		WL_ERR(("WLC_GET_WSEC error (%d)\n", err));
 		return err;
 	}
-	switch (wsec) {
-	case WEP_ENABLED:
-		sec = wl_read_prof(wl, WL_PROF_SEC);
-		if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
-			params.cipher = WLAN_CIPHER_SUITE_WEP40;
-			WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
-		} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
-			params.cipher = WLAN_CIPHER_SUITE_WEP104;
-			WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
-		}
-		break;
-	case TKIP_ENABLED:
-		params.cipher = WLAN_CIPHER_SUITE_TKIP;
-		WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
-		break;
-	case AES_ENABLED:
-		params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
-		WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
-		break;
-	default:
-		WL_ERR(("Invalid algo (0x%x)\n", wsec));
-		return -EINVAL;
+	switch (wsec & ~SES_OW_ENABLED) {
+		case WEP_ENABLED:
+			sec = wl_read_prof(wl, WL_PROF_SEC);
+			if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP40) {
+				params.cipher = WLAN_CIPHER_SUITE_WEP40;
+				WL_DBG(("WLAN_CIPHER_SUITE_WEP40\n"));
+			} else if (sec->cipher_pairwise & WLAN_CIPHER_SUITE_WEP104) {
+				params.cipher = WLAN_CIPHER_SUITE_WEP104;
+				WL_DBG(("WLAN_CIPHER_SUITE_WEP104\n"));
+			}
+			break;
+		case TKIP_ENABLED:
+			params.cipher = WLAN_CIPHER_SUITE_TKIP;
+			WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+			break;
+		case AES_ENABLED:
+			params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+			WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
+			break;
+		default:
+			WL_ERR(("Invalid algo (0x%x)\n", wsec));
+			return -EINVAL;
 	}
 
 	callback(cookie, &params);
@@ -2450,7 +2542,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 	/* Report the current tx rate */
-	err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), FALSE);
+	err = wldev_ioctl(dev, WLC_GET_RATE, &rate, sizeof(rate), false);
 	if (err) {
 		WL_ERR(("Could not get rate (%d)\n", err));
 	} else {
@@ -2460,11 +2552,11 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 		WL_DBG(("Rate %d Mbps\n", (rate / 2)));
 	}
 
-	if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+	if (wl_get_drv_status(wl, CONNECTED)) {
 		memset(&scb_val, 0, sizeof(scb_val));
 		scb_val.val = 0;
 		err = wldev_ioctl(dev, WLC_GET_RSSI, &scb_val,
-			sizeof(scb_val_t), FALSE);
+			sizeof(scb_val_t), false);
 		if (unlikely(err)) {
 			WL_ERR(("Could not get rssi (%d)\n", err));
 			return err;
@@ -2476,7 +2568,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
 	}
 
 #if defined(ANDROID_WIRELESS_PATCH)
-	err = wldev_ioctl(dev, WLC_GET_RATE, &sinfo->link_speed, sizeof(sinfo->link_speed), FALSE);
+	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;
@@ -2498,7 +2590,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 = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE);
+	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"));
@@ -2553,7 +2645,7 @@ wl_cfg80211_set_bitrate_mask(struct wiphy *wiphy, struct net_device *dev,
 	/* addr param is always NULL. ignore it */
 	/* Get current rateset */
 	err = wldev_ioctl(dev, WLC_GET_CURR_RATESET, &rateset,
-		sizeof(rateset), FALSE);
+		sizeof(rateset), false);
 	if (unlikely(err)) {
 		WL_ERR(("could not get current rateset (%d)\n", err));
 		return err;
@@ -2623,14 +2715,14 @@ static s32 wl_cfg80211_suspend(struct wiphy *wiphy)
 		return 0;
 	}
 
-	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+	wl_set_drv_status(wl, SCAN_ABORTING);
 	wl_term_iscan(wl);
 	if (wl->scan_request) {
 		cfg80211_scan_done(wl->scan_request, true);
 		wl->scan_request = NULL;
 	}
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
-	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+	wl_clr_drv_status(wl, SCANNING);
+	wl_clr_drv_status(wl, SCAN_ABORTING);
 
 	return err;
 }
@@ -2640,6 +2732,18 @@ wl_update_pmklist(struct net_device *dev, struct wl_pmk_list *pmk_list,
 	s32 err)
 {
 	int i, j;
+	struct wl_priv *wl = WL_PRIV_GET();
+	struct net_device *primary_dev = wl_to_prmry_ndev(wl);
+
+	/* Firmware is supporting pmk list only for STA interface i.e. primary interface
+	  * Refer code wlc_bsscfg.c->wlc_bsscfg_sta_init
+	  * Do we really need to support PMK cache in P2P in firmware?
+	*/
+	if (primary_dev != dev) {
+		WL_ERR(("Not supporting Flushing pmklist on virtual"
+			" interfaces than primary interface\n"));
+		return err;
+	}
 
 	WL_DBG(("No of elements %d\n", pmk_list->pmkids.npmkid));
 	for (i = 0; i < pmk_list->pmkids.npmkid; i++) {
@@ -2745,7 +2849,6 @@ wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev)
 {
 	struct wl_priv *wl = WL_PRIV_GET();
 	s32 err = 0;
-
 	CHECK_SYS_UP();
 	memset(wl->pmk_list, 0, sizeof(*wl->pmk_list));
 	err = wl_update_pmklist(dev, wl->pmk_list, err);
@@ -2806,20 +2909,11 @@ 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 = wldev_ioctl(ndev, WLC_SCAN, params, params_size, FALSE);
+	err = wldev_ioctl(ndev, WLC_SCAN, params, params_size, false);
 	if (err < 0) {
 		WL_ERR(("scan abort  failed \n"));
 	}
-	/* Report the scan abort to CFG driver too 
-	 * We will report it from the thread context, not from this context.
-	 */
 
-	{
-		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);
-	}
 	return err;
 }
 static s32
@@ -2834,7 +2928,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
 	struct wl_priv *wl = WL_PRIV_GET();
 	dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub);
 	WL_DBG(("Enter, netdev_ifidx: %d \n", dev->ifindex));
-	if (likely(test_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (likely(wl_get_drv_status(wl, SCANNING))) {
 		wl_cfg80211_scan_abort(wl, dev);
 	}
 
@@ -2845,7 +2939,7 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
 	cfg80211_ready_on_channel(dev, *cookie, channel,
 		channel_type, duration, GFP_KERNEL);
 	if (!p2p_on(wl)) {
-		wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr);
+		wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
 
 		/* In case of p2p_listen command, supplicant send remain_on_channel
 		 * without turning on P2P
@@ -2867,13 +2961,11 @@ exit:
 }
 
 static s32
-wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, u64 cookie)
+wl_cfg80211_cancel_remain_on_channel(struct wiphy *wiphy, struct net_device *dev,
+	u64 cookie)
 {
-
 	s32 err = 0;
 	WL_DBG((" enter ) netdev_ifidx: %d \n", dev->ifindex));
-
-
 	return err;
 }
 
@@ -2896,7 +2988,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 	u32 p2pie_len = 0;
 	u32 wpsie_len = 0;
 	u16 fc;
-	bool ack = FALSE;
+	bool ack = false;
 	WL_DBG(("Enter \n"));
 	/* find bssidx based on ndev */
 	bssidx = wl_cfgp2p_find_idx(wl, dev);
@@ -2909,24 +3001,20 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 		return -ENODEV;
 	}
 	if (p2p_on(wl)) {
-		wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p.dev_addr, &wl->p2p.int_addr);
-
+		wl_cfgp2p_generate_bss_mac(&dhd->mac, &wl->p2p->dev_addr, &wl->p2p->int_addr);
 	   /* Suspend P2P discovery search-listen to prevent it from changing the
 		* 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);
+		if ((err = wl_cfgp2p_discover_enable_search(wl, false)) < 0) {
+			WL_ERR(("Can not disable discovery mode\n"));
+			return -EFAULT;
+		}
 	}
+
 	mgmt = (const struct ieee80211_mgmt *) buf;
 	fc = mgmt->frame_control;
 	if (fc != IEEE80211_STYPE_ACTION) {
-		if (p2p_on(wl) && (fc == IEEE80211_STYPE_PROBE_RESP)) {
+		if (fc == IEEE80211_STYPE_PROBE_RESP) {
 			s32 ie_offset =  DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
 			s32 ie_len = len - ie_offset;
 			if ((p2p_ie = wl_cfgp2p_find_p2pie((u8 *)(buf + ie_offset), ie_len))
@@ -2953,12 +3041,23 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 				wl_cfgp2p_set_managment_ie(wl, dev, bssidx,
 					VNDR_IE_PRBRSP_FLAG,
 					(u8 *)wps_ie, wpsie_len + p2pie_len);
-
+				/* remove WLC_E_PROBREQ_MSG event to prevent HOSTAPD
+				 * from responding many probe request
+				 */
+				wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, false);
 			}
 		}
 		cfg80211_mgmt_tx_status(dev, *cookie, buf, len, true, GFP_KERNEL);
 
 		goto exit;
+	} else {
+	    /* 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);
 	}
 	af_params = (wl_af_params_t *) kzalloc(WL_WIFI_AF_PARAMS_SIZE, GFP_KERNEL);
 
@@ -2993,7 +3092,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 
 	memcpy(action_frame->data, &buf[DOT11_MGMT_HDR_LEN], action_frame->len);
 
-	if (wl->p2p.vif_created) {
+	if (wl->p2p->vif_created) {
 		wifi_p2p_pub_act_frame_t *act_frm =
 			(wifi_p2p_pub_act_frame_t *) (action_frame->data);
 		/*
@@ -3017,7 +3116,7 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *dev,
 		}
 	}
 
-	ack = (wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx)) ? FALSE : TRUE;
+	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);
@@ -3077,28 +3176,31 @@ 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));
-	wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), FALSE);
+	wldev_ioctl(dev, WLC_SET_CHANNEL, &channel, sizeof(channel), false);
 
 	return err;
 }
 
 static s32
-wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
+wl_validate_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
 {
-	s32 len = wpa2ie->len;
+	s32 len = 0;
 	s32 err = BCME_OK;
 	u16 auth = 0; /* d11 open authentication */
-	u16 wpa_auth = 0;
 	u16 count;
 	u32 wsec;
 	u32 pval = 0;
 	u32 gval = 0;
+	u32 wpa_auth = 0;
 	u8* tmp;
 	wpa_suite_mcast_t *mcast;
 	wpa_suite_ucast_t *ucast;
 	wpa_suite_auth_key_mgmt_t *mgmt;
 	if (wpa2ie == NULL)
 		goto exit;
+
+	WL_DBG(("Enter \n"));
+	len =  wpa2ie->len;
 	/* check the mcast cipher */
 	mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
 	tmp = mcast->oui;
@@ -3141,7 +3243,6 @@ wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
 			break;
 		default:
 			WL_ERR(("No Security Info\n"));
-			break;
 	}
 	/* FOR WPS , set SEC_OW_ENABLED */
 	wsec = (pval | gval | SES_OW_ENABLED);
@@ -3161,33 +3262,171 @@ wl_check_wpa2ie(struct net_device *dev, bcm_tlv_t *wpa2ie, s32 bssidx)
 			break;
 		default:
 			WL_ERR(("No Key Mgmt Info\n"));
-			break;
 	}
 	/* set auth */
 	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
 	if (err < 0) {
 		WL_ERR(("auth error %d\n", err));
+		return BCME_ERROR;
 	}
 	/* set wsec */
 	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
 	if (err < 0) {
 		WL_ERR(("wsec error %d\n", err));
+		return BCME_ERROR;
 	}
 	/* set upper-layer auth */
 	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
 	if (err < 0) {
 		WL_ERR(("wpa_auth error %d\n", err));
+		return BCME_ERROR;
 	}
 exit:
 	return 0;
 }
 
 static s32
-wl_check_wpaie(struct net_device *dev, bcm_tlv_t *wpaie, s32 bssidx)
+wl_validate_wpaie(struct net_device *dev, wpa_ie_fixed_t *wpaie, s32 bssidx)
 {
+	wpa_suite_mcast_t *mcast;
+	wpa_suite_ucast_t *ucast;
+	wpa_suite_auth_key_mgmt_t *mgmt;
+	u16 auth = 0; /* d11 open authentication */
+	u16 count;
+	s32 err = BCME_OK;
+	s32 len = 0;
+	u32 i;
+	u32 wsec;
+	u32 pval = 0;
+	u32 gval = 0;
+	u32 wpa_auth = 0;
+	u32 tmp = 0;
+
 	if (wpaie == NULL)
 		goto exit;
+	WL_DBG(("Enter \n"));
+	len = wpaie->length;    /* value length */
+	len -= WPA_IE_TAG_FIXED_LEN;
+	/* check for multicast cipher suite */
+	if (len < WPA_SUITE_LEN) {
+		WL_INFO(("no multicast cipher suite\n"));
+		goto exit;
+	}
 
+	/* pick up multicast cipher */
+	mcast = (wpa_suite_mcast_t *)&wpaie[1];
+	len -= WPA_SUITE_LEN;
+	if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
+		if (IS_WPA_CIPHER(mcast->type)) {
+			tmp = 0;
+			switch (mcast->type) {
+				case WPA_CIPHER_NONE:
+					tmp = 0;
+					break;
+				case WPA_CIPHER_WEP_40:
+				case WPA_CIPHER_WEP_104:
+					tmp = WEP_ENABLED;
+					break;
+				case WPA_CIPHER_TKIP:
+					tmp = TKIP_ENABLED;
+					break;
+				case WPA_CIPHER_AES_CCM:
+					tmp = AES_ENABLED;
+					break;
+				default:
+					WL_ERR(("No Security Info\n"));
+			}
+			gval |= tmp;
+		}
+	}
+	/* Check for unicast suite(s) */
+	if (len < WPA_IE_SUITE_COUNT_LEN) {
+		WL_INFO(("no unicast suite\n"));
+		goto exit;
+	}
+	/* walk thru unicast cipher list and pick up what we recognize */
+	ucast = (wpa_suite_ucast_t *)&mcast[1];
+	count = ltoh16_ua(&ucast->count);
+	len -= WPA_IE_SUITE_COUNT_LEN;
+	for (i = 0; i < count && len >= WPA_SUITE_LEN;
+		i++, len -= WPA_SUITE_LEN) {
+		if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
+			if (IS_WPA_CIPHER(ucast->list[i].type)) {
+				tmp = 0;
+				switch (ucast->list[i].type) {
+					case WPA_CIPHER_NONE:
+						tmp = 0;
+						break;
+					case WPA_CIPHER_WEP_40:
+					case WPA_CIPHER_WEP_104:
+						tmp = WEP_ENABLED;
+						break;
+					case WPA_CIPHER_TKIP:
+						tmp = TKIP_ENABLED;
+						break;
+					case WPA_CIPHER_AES_CCM:
+						tmp = AES_ENABLED;
+						break;
+					default:
+						WL_ERR(("No Security Info\n"));
+				}
+				pval |= tmp;
+			}
+		}
+	}
+	len -= (count - i) * WPA_SUITE_LEN;
+	/* Check for auth key management suite(s) */
+	if (len < WPA_IE_SUITE_COUNT_LEN) {
+		WL_INFO((" no auth key mgmt suite\n"));
+		goto exit;
+	}
+	/* walk thru auth management suite list and pick up what we recognize */
+	mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
+	count = ltoh16_ua(&mgmt->count);
+	len -= WPA_IE_SUITE_COUNT_LEN;
+	for (i = 0; i < count && len >= WPA_SUITE_LEN;
+		i++, len -= WPA_SUITE_LEN) {
+		if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
+			if (IS_WPA_AKM(mgmt->list[i].type)) {
+				tmp = 0;
+				switch (mgmt->list[i].type) {
+					case RSN_AKM_NONE:
+						tmp = WPA_AUTH_NONE;
+						break;
+					case RSN_AKM_UNSPECIFIED:
+						tmp = WPA_AUTH_UNSPECIFIED;
+						break;
+					case RSN_AKM_PSK:
+						tmp = WPA_AUTH_PSK;
+						break;
+					default:
+						WL_ERR(("No Key Mgmt Info\n"));
+				}
+				wpa_auth |= tmp;
+			}
+		}
+
+	}
+	/* FOR WPS , set SEC_OW_ENABLED */
+	wsec = (pval | gval | SES_OW_ENABLED);
+	/* set auth */
+	err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
+	if (err < 0) {
+		WL_ERR(("auth error %d\n", err));
+		return BCME_ERROR;
+	}
+	/* set wsec */
+	err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
+	if (err < 0) {
+		WL_ERR(("wsec error %d\n", err));
+		return BCME_ERROR;
+	}
+	/* set upper-layer auth */
+	err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
+	if (err < 0) {
+		WL_ERR(("wpa_auth error %d\n", err));
+		return BCME_ERROR;
+	}
 exit:
 	return 0;
 }
@@ -3198,27 +3437,29 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 {
 	s32 err = BCME_OK;
 	bcm_tlv_t *ssid_ie;
+	wlc_ssid_t ssid;
+	struct wl_priv *wl = WL_PRIV_GET();
+	struct wl_join_params join_params;
 	wpa_ie_fixed_t *wps_ie;
 	wpa_ie_fixed_t *wpa_ie;
 	bcm_tlv_t *wpa2_ie;
 	wifi_p2p_ie_t *p2p_ie;
-	struct wl_priv *wl = WL_PRIV_GET();
 	bool is_bssup = false;
+	bool update_bss = false;
 	u16 wpsie_len = 0;
 	u16 p2pie_len = 0;
 	u8 beacon_ie[IE_MAX_LEN];
 	s32 ie_offset = 0;
 	s32 bssidx = wl_cfgp2p_find_idx(wl, dev);
 	s32 infra = 1;
-
-	memset(beacon_ie, 0, sizeof(beacon_ie));
-
+	s32 join_params_size = 0;
+	s32 ap = 0;
 	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));
-
-
-	if (p2p_on(wl) && (bssidx >= wl_to_p2p_bss_bssidx(wl,
+	if (wl->p2p_supported && p2p_on(wl) &&
+		(bssidx >= wl_to_p2p_bss_bssidx(wl,
 		P2PAPI_BSSCFG_CONNECTION))) {
+		memset(beacon_ie, 0, sizeof(beacon_ie));
 		/* 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
@@ -3228,8 +3469,8 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 		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;
+			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 {
@@ -3238,7 +3479,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 
 		/* 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);
+			wpsie_len = wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
 			/*
 			 * Should be compared with saved ie before saving it
 			 */
@@ -3269,10 +3510,7 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 			beacon_ie, wpsie_len + p2pie_len);
 		wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_ASSOCRSP_FLAG,
 			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) {
@@ -3280,19 +3518,209 @@ wl_cfg80211_set_beacon(struct wiphy *wiphy, struct net_device *dev,
 		}
 		is_bssup = wl_cfgp2p_bss_isup(dev, bssidx);
 
-		if (!is_bssup && (wpa_ie != NULL || wpa2_ie != NULL)) {
-			wl_check_wpa2ie(dev, wpa2_ie, bssidx);
-			wl_check_wpaie(dev, (bcm_tlv_t *)wpa_ie, bssidx);
-
-			err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), FALSE);
+		if (!is_bssup && (wpa2_ie != NULL)) {
+			if ((err = wl_validate_wpa2ie(dev, wpa2_ie, bssidx)) < 0) {
+					WL_ERR(("WPA2 IE parsing error"));
+					return BCME_ERROR;
+			}
+			err = wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false);
 			if (err < 0) {
 				WL_ERR(("SET INFRA error %d\n", err));
+				return err;
 			}
-
-			err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p.ssid,
-				sizeof(wl->p2p.ssid), ioctlbuf, sizeof(ioctlbuf), bssidx);
-
-			wl_cfgp2p_bss(dev, bssidx, 1);
+			err = wldev_iovar_setbuf_bsscfg(dev, "ssid", &wl->p2p->ssid,
+				sizeof(wl->p2p->ssid), ioctlbuf, sizeof(ioctlbuf), bssidx);
+			if (err < 0) {
+				WL_ERR(("GO SSID setting error %d\n", err));
+				return err;
+			}
+			if ((err = wl_cfgp2p_bss(dev, bssidx, 1)) < 0) {
+				WL_ERR(("GO Bring up error %d\n", err));
+				return err;
+			}
+		}
+	} else if (wl_get_drv_status(wl, AP_CREATING)) {
+		ie_offset = DOT11_MGMT_HDR_LEN + DOT11_BCN_PRB_FIXED_LEN;
+		ap = 1;
+		/* find the SSID */
+		if ((ssid_ie = bcm_parse_tlvs((u8 *)&info->head[ie_offset],
+			info->head_len - ie_offset,
+			DOT11_MNG_SSID_ID)) != NULL) {
+			memset(&ssid, 0, sizeof(wlc_ssid_t));
+			memcpy(ssid.SSID, ssid_ie->data, ssid_ie->len);
+			WL_DBG(("SSID is (%s) in Head \n", ssid.SSID));
+			ssid.SSID_len = ssid_ie->len;
+			wldev_iovar_setint(dev, "mpc", 0);
+			wldev_ioctl(dev, WLC_DOWN, &ap, sizeof(s32), false);
+			wldev_ioctl(dev, WLC_SET_INFRA, &infra, sizeof(s32), false);
+			wldev_ioctl(dev, WLC_SET_AP, &ap, sizeof(s32), false);
+			/* find the RSN_IE */
+			if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
+				DOT11_MNG_RSN_ID)) != NULL) {
+				WL_DBG((" WPA2 IE is found\n"));
+			}
+			/* 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"));
+			}
+			if ((wpa_ie != NULL || wpa2_ie != NULL)) {
+				if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx)  < 0 ||
+					wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) {
+					wl->ap_info->security_mode = false;
+					return BCME_ERROR;
+				}
+				wl->ap_info->security_mode = true;
+				kfree(wl->ap_info->rsn_ie);
+				kfree(wl->ap_info->wpa_ie);
+				kfree(wl->ap_info->wps_ie);
+				if (wpa_ie != NULL) {
+					/* WPAIE */
+					wl->ap_info->rsn_ie = NULL;
+					wl->ap_info->wpa_ie = kmemdup(wpa_ie,
+						wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+				} else {
+					/* RSNIE */
+					wl->ap_info->wpa_ie = NULL;
+					wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
+						wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+				}
+			} else
+				wl->ap_info->security_mode = false;
+			/* find the WPSIE */
+			if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail,
+				info->tail_len)) != NULL) {
+				wpsie_len = wps_ie->length +WPA_RSN_IE_TAG_FIXED_LEN;
+				/*
+				* 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);
+				wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
+				beacon_ie, wpsie_len);
+				wl->ap_info->wps_ie = kmemdup(wps_ie, 	wpsie_len, GFP_KERNEL);
+				/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
+				wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
+			} else {
+				WL_ERR(("No WPSIE in beacon \n"));
+			}
+			wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), false);
+
+			memset(&join_params, 0, sizeof(join_params));
+			/* join parameters starts with ssid */
+			join_params_size = sizeof(join_params.ssid);
+			memcpy(join_params.ssid.SSID, ssid.SSID, ssid.SSID_len);
+			join_params.ssid.SSID_len = htod32(ssid.SSID_len);
+			/* create softap */
+			if ((err = wldev_ioctl(dev, WLC_SET_SSID, &join_params,
+				join_params_size, false)) == 0) {
+				wl_clr_drv_status(wl, AP_CREATING);
+				wl_set_drv_status(wl, AP_CREATED);
+			}
+		}
+	} else if (wl_get_drv_status(wl, AP_CREATED)) {
+		ap = 1;
+		/* find the WPSIE */
+		if ((wps_ie = wl_cfgp2p_find_wpsie((u8 *)info->tail, info->tail_len)) != NULL) {
+			wpsie_len = wps_ie->length + WPA_RSN_IE_TAG_FIXED_LEN;
+			/*
+			 * 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);
+			wl_cfgp2p_set_managment_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG,
+			beacon_ie, wpsie_len);
+			if (wl->ap_info->wps_ie &&
+				memcmp(wl->ap_info->wps_ie, wps_ie, wpsie_len)) {
+				WL_DBG((" WPS IE is changed\n"));
+				kfree(wl->ap_info->wps_ie);
+				wl->ap_info->wps_ie = kmemdup(wps_ie, 	wpsie_len, GFP_KERNEL);
+				/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
+				wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
+			} else if (wl->ap_info->wps_ie == NULL) {
+				WL_DBG((" WPS IE is added\n"));
+				wl->ap_info->wps_ie = kmemdup(wps_ie, 	wpsie_len, GFP_KERNEL);
+				/* add WLC_E_PROBREQ_MSG event to respose probe_request from STA */
+				wl_dongle_add_remove_eventmsg(dev, WLC_E_PROBREQ_MSG, true);
+			}
+			/* find the RSN_IE */
+			if ((wpa2_ie = bcm_parse_tlvs((u8 *)info->tail, info->tail_len,
+				DOT11_MNG_RSN_ID)) != NULL) {
+				WL_DBG((" WPA2 IE is found\n"));
+			}
+			/* 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"));
+			}
+			if ((wpa_ie != NULL || wpa2_ie != NULL)) {
+				if (!wl->ap_info->security_mode) {
+					/* change from open mode to security mode */
+					update_bss = true;
+					if (wpa_ie != NULL) {
+						wl->ap_info->wpa_ie = kmemdup(wpa_ie,
+						wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+					} else {
+						wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
+						wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+					}
+				} else if (wl->ap_info->wpa_ie) {
+					/* change from WPA mode to WPA2 mode */
+					if (wpa2_ie != NULL) {
+						update_bss = true;
+						kfree(wl->ap_info->wpa_ie);
+						wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
+						wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+						wl->ap_info->wpa_ie = NULL;
+					}
+					else if (memcmp(wl->ap_info->wpa_ie,
+						wpa_ie, wpa_ie->length +
+						WPA_RSN_IE_TAG_FIXED_LEN)) {
+						kfree(wl->ap_info->wpa_ie);
+						update_bss = true;
+						wl->ap_info->wpa_ie = kmemdup(wpa_ie,
+						wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+						wl->ap_info->rsn_ie = NULL;
+					}
+				} else {
+					/* change from WPA2 mode to WPA mode */
+					if (wpa_ie != NULL) {
+						update_bss = true;
+						kfree(wl->ap_info->rsn_ie);
+						wl->ap_info->rsn_ie = NULL;
+						wl->ap_info->wpa_ie = kmemdup(wpa_ie,
+						wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+					} else if (memcmp(wl->ap_info->rsn_ie,
+						wpa2_ie, wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN)) {
+						update_bss = true;
+						kfree(wl->ap_info->rsn_ie);
+						wl->ap_info->rsn_ie = kmemdup(wpa2_ie,
+						wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+						GFP_KERNEL);
+						wl->ap_info->wpa_ie = NULL;
+					}
+				}
+				if (update_bss) {
+					wl->ap_info->security_mode = true;
+					wl_cfgp2p_bss(dev, bssidx, 0);
+					if (wl_validate_wpa2ie(dev, wpa2_ie, bssidx)  < 0 ||
+						wl_validate_wpaie(dev, wpa_ie, bssidx) < 0) {
+						return BCME_ERROR;
+					}
+					wl_cfgp2p_bss(dev, bssidx, 1);
+				}
+			}
+		} else {
+			WL_ERR(("No WPSIE in beacon \n"));
 		}
 	}
 	return 0;
@@ -3400,7 +3828,8 @@ 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_STATION) | BIT(NL80211_IFTYPE_ADHOC)
+	    | BIT(NL80211_IFTYPE_AP) | BIT(NL80211_IFTYPE_MONITOR);
 
 	wdev->wiphy->bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz;
 	wdev->wiphy->bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a;
@@ -3455,6 +3884,7 @@ static void wl_free_wdev(struct wl_priv *wl)
 	wiphy_unregister(wdev->wiphy);
 	wiphy_free(wdev->wiphy);
 	kfree(wdev);
+	wl_to_wdev(wl) = NULL;
 }
 
 static s32 wl_inform_bss(struct wl_priv *wl)
@@ -3465,13 +3895,11 @@ static s32 wl_inform_bss(struct wl_priv *wl)
 	s32 i;
 
 	bss_list = wl->bss_list;
-	/*
 	if (unlikely(bss_list->version != WL_BSS_INFO_VERSION)) {
-		WL_ERR(("Version %d != %d\n",
-			bss_list->version, WL_BSS_INFO_VERSION));
+		WL_ERR(("Version %d != WL_BSS_INFO_VERSION\n",
+			bss_list->version));
 		return -EOPNOTSUPP;
 	}
-	*/
 	WL_DBG(("scanned AP count (%d)\n", bss_list->count));
 	bi = next_bss(bss_list, bi);
 	for_each_bss(bss_list, bi, i) {
@@ -3618,7 +4046,7 @@ 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;
+	bool isfree = false;
 	s32 err = 0;
 	s32 freq;
 	s32 channel;
@@ -3642,7 +4070,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 		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);
+		wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false);
 		switch (event) {
 			case WLC_E_ASSOC_IND:
 				fc = FC_ASSOC_REQ;
@@ -3663,7 +4091,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 				fc = 0;
 				goto exit;
 		}
-		if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), FALSE)))
+		if ((err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci), false)))
 			return err;
 
 		channel = dtoh32(ci.hw_channel);
@@ -3682,14 +4110,14 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 		&mgmt_frame, &len, body);
 		if (err < 0)
 				goto exit;
-		isfree = TRUE;
+		isfree = true;
 
 		if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) {
-			cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+			cfg80211_send_rx_assoc(ndev, mgmt_frame, len);
 		} else if (event == WLC_E_DISASSOC_IND) {
-				cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+			cfg80211_send_disassoc(ndev, mgmt_frame, len);
 		} else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
-			cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+			cfg80211_send_deauth(ndev, mgmt_frame, len);
 		}
 
 	} else {
@@ -3712,16 +4140,16 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev,
 			act = true;
 			wl_update_prof(wl, e, &act, WL_PROF_ACT);
 		} else if (wl_is_linkdown(wl, e)) {
-			if (test_bit(WL_STATUS_CONNECTED, &wl->status)) {
+			if (wl_get_drv_status(wl, CONNECTED)) {
 				printk("link down, call cfg80211_disconnected ");
 				cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL);
-				clear_bit(WL_STATUS_CONNECTED, &wl->status);
+				wl_clr_drv_status(wl, CONNECTED);
 				wl_link_down(wl);
 				wl_init_prof(wl->profile);
 			}
 		} else if (wl_is_nonetwork(wl, e)) {
 			printk("connect failed e->status 0x%x", (int)ntoh32(e->status));
-			if (test_bit(WL_STATUS_CONNECTING, &wl->status))
+			if (wl_get_drv_status(wl, CONNECTING))
 				wl_bss_connect_done(wl, ndev, e, data, false);
 		} else {
 			printk("%s nothing\n", __FUNCTION__);
@@ -3758,7 +4186,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 wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, FALSE);
+	return wldev_ioctl(dev, WLC_SET_VAR, wl->ioctl_buf, buflen, false);
 }
 
 static s32
@@ -3772,7 +4200,7 @@ 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 = wldev_ioctl(dev, WLC_GET_VAR, (void *)wl->ioctl_buf,
-		WL_IOCTL_LEN_MAX, FALSE);
+		WL_IOCTL_LEN_MAX, false);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 		return err;
@@ -3897,7 +4325,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
 		WL_DBG(("Could not find the AP\n"));
 		*(u32 *) wl->extra_buf = htod32(WL_EXTRA_BUF_MAX);
 		err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_BSS_INFO,
-			wl->extra_buf, WL_EXTRA_BUF_MAX, FALSE);
+			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;
@@ -3932,7 +4360,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev)
 		* so we speficially query dtim information to dongle.
 		*/
 		err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_DTIMPRD,
-			&dtim_period, sizeof(dtim_period), FALSE);
+			&dtim_period, sizeof(dtim_period), false);
 		if (unlikely(err)) {
 			WL_ERR(("WLC_GET_DTIMPRD error (%d)\n", err));
 			goto update_bss_info_out;
@@ -3966,7 +4394,7 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev,
 		conn_info->resp_ie, conn_info->resp_ie_len, GFP_KERNEL);
 	WL_DBG(("Report roaming result\n"));
 
-	set_bit(WL_STATUS_CONNECTED, &wl->status);
+	wl_set_drv_status(wl, CONNECTED);
 
 	return err;
 }
@@ -3982,7 +4410,8 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
 	wl_get_assoc_ies(wl, ndev);
 	memcpy(&wl->bssid, &e->addr, ETHER_ADDR_LEN);
 	wl_update_bss_info(wl, ndev);
-	if (test_and_clear_bit(WL_STATUS_CONNECTING, &wl->status)) {
+	if (wl_get_drv_status(wl, CONNECTING)) {
+		wl_clr_drv_status(wl, CONNECTING);
 		cfg80211_connect_result(ndev,
 			(u8 *)&wl->bssid,
 			conn_info->req_ie,
@@ -3994,6 +4423,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
 		WL_DBG(("Report connect result - connection %s\n",
 			completed ? "succeeded" : "failed"));
 	} else {
+		wl_clr_drv_status(wl, CONNECTING);
 		cfg80211_roamed(ndev,
 #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39)
 			NULL,
@@ -4004,7 +4434,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev,
 			GFP_KERNEL);
 		WL_DBG(("Report roaming result\n"));
 	}
-	set_bit(WL_STATUS_CONNECTED, &wl->status);
+	wl_set_drv_status(wl, CONNECTED);
 
 	return err;
 }
@@ -4038,20 +4468,21 @@ wl_notify_scan_status(struct wl_priv *wl, struct net_device *ndev,
 	u32 len = WL_SCAN_BUF_MAX;
 	s32 err = 0;
 
-
 	WL_DBG(("Enter \n"));
 	if (wl->iscan_on && wl->iscan_kickstart)
 		return wl_wakeup_iscan(wl_to_iscan(wl));
 
-	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (unlikely(!wl_get_drv_status(wl, SCANNING))) {
+		wl_clr_drv_status(wl, SCANNING);
 		WL_DBG(("Scan complete while device not scanning\n"));
 		return -EINVAL;
 	}
+	wl_clr_drv_status(wl, SCANNING);
 	if (unlikely(!wl->scan_request)) {
 	}
 	rtnl_lock();
 	err = wldev_ioctl(ndev, WLC_GET_CHANNEL, &channel_inform,
-		sizeof(channel_inform), FALSE);
+		sizeof(channel_inform), false);
 	if (unlikely(err)) {
 		WL_ERR(("scan busy (%d)\n", err));
 		goto scan_done_out;
@@ -4066,7 +4497,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 = wldev_ioctl(ndev, WLC_SCAN_RESULTS, bss_list, len, FALSE);
+	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;
@@ -4138,7 +4569,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
 	struct wiphy *wiphy = wl_to_wiphy(wl);
 	struct ether_addr da;
 	struct ether_addr bssid;
-	bool isfree = FALSE;
+	bool isfree = false;
 	s32 err = 0;
 	s32 freq;
 	wl_event_rx_frame_data_t *rxframe =
@@ -4152,6 +4583,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
 		band = wiphy->bands[IEEE80211_BAND_2GHZ];
 	else
 		band = wiphy->bands[IEEE80211_BAND_5GHZ];
+
 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS)
 	freq = ieee80211_channel_to_frequency(channel);
 #else
@@ -4160,7 +4592,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
 	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);
+		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));
@@ -4169,7 +4601,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev,
 				__func__, mgmt_frame_len, channel, freq));
 			goto exit;
 		}
-		isfree = TRUE;
+		isfree = true;
 	} else {
 		mgmt_frame = (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1);
 	}
@@ -4221,6 +4653,7 @@ static void wl_init_event_handler(struct wl_priv *wl)
 	wl->evt_handler[WLC_E_MIC_ERROR] = wl_notify_mic_status;
 	wl->evt_handler[WLC_E_SET_SSID] = wl_notify_connect_status;
 	wl->evt_handler[WLC_E_ACTION_FRAME_RX] = wl_notify_rx_mgmt_frame;
+	wl->evt_handler[WLC_E_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
 	wl->evt_handler[WLC_E_P2P_PROBREQ_MSG] = wl_notify_rx_mgmt_frame;
 	wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete;
 	wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete;
@@ -4320,6 +4753,13 @@ static void wl_deinit_priv_mem(struct wl_priv *wl)
 	wl->fw = NULL;
 	kfree(wl->pmk_list);
 	wl->pmk_list = NULL;
+	if (wl->ap_info) {
+		kfree(wl->ap_info->wpa_ie);
+		kfree(wl->ap_info->rsn_ie);
+		kfree(wl->ap_info->wps_ie);
+		kfree(wl->ap_info);
+		wl->ap_info = NULL;
+	}
 }
 
 static s32 wl_create_event_handler(struct wl_priv *wl)
@@ -4352,7 +4792,7 @@ static void wl_term_iscan(struct wl_priv *wl)
 		iscan->state = WL_ISCAN_STATE_IDLE;
 		WL_INFO(("SIGTERM\n"));
 		send_sig(SIGTERM, iscan->tsk, 1);
-		printk("kthread_stop\n");
+		WL_DBG(("kthread_stop\n"));
 		kthread_stop(iscan->tsk);
 		iscan->tsk = NULL;
 	}
@@ -4363,10 +4803,12 @@ static void wl_notify_iscan_complete(struct wl_iscan_ctrl *iscan, bool aborted)
 	struct wl_priv *wl = iscan_to_wl(iscan);
 
 	WL_DBG(("Enter \n"));
-	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (unlikely(!wl_get_drv_status(wl, SCANNING))) {
+		wl_clr_drv_status(wl, SCANNING);
 		WL_ERR(("Scan complete while device not scanning\n"));
 		return;
 	}
+	wl_clr_drv_status(wl, SCANNING);
 	if (likely(wl->scan_request)) {
 		cfg80211_scan_done(wl->scan_request, aborted);
 		wl->scan_request = NULL;
@@ -4556,11 +4998,13 @@ static void wl_init_iscan_handler(struct wl_iscan_ctrl *iscan)
 static void wl_notify_escan_complete(struct wl_priv *wl, bool aborted)
 {
 	WL_DBG(("Enter \n"));
-	if (unlikely(!test_and_clear_bit(WL_STATUS_SCANNING, &wl->status))) {
+	if (unlikely(!wl_get_drv_status(wl, SCANNING))) {
+		wl_clr_drv_status(wl, SCANNING);
 		WL_ERR(("Scan complete while device not scanning\n"));
 		return;
 	}
-	if (p2p_on(wl))
+	wl_clr_drv_status(wl, SCANNING);
+	if (wl->p2p_supported && p2p_on(wl))
 	   wl_clr_p2p_status(wl, SCANNING);
 
 	if (likely(wl->scan_request)) {
@@ -4584,7 +5028,7 @@ static s32 wl_escan_handler(struct wl_priv *wl,
 	WL_DBG((" enter event type : %d, status : %d \n",
 		ntoh32(e->event_type), ntoh32(e->status)));
 	if (!wl->escan_on &&
-		!test_bit(WL_STATUS_SCANNING, &wl->status)) {
+		!wl_get_drv_status(wl, SCANNING)) {
 		WL_ERR(("escan is not ready \n"));
 		return err;
 	}
@@ -4733,7 +5177,6 @@ static s32 wl_init_priv(struct wl_priv *wl)
 	wl_init_conf(wl->conf);
 	wl_init_prof(wl->profile);
 	wl_link_down(wl);
-	wl_cfgp2p_init_priv(wl);
 
 	return err;
 }
@@ -4757,10 +5200,10 @@ s32 wl_cfg80211_sysctl_export_devaddr(void *data)
 	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);
+	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));
+	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;
 }
@@ -4776,18 +5219,24 @@ s32 wl_cfg80211_attach_post(struct net_device *ndev)
 		return -ENODEV;
 	}
 	wl = WL_PRIV_GET();
-	if (wl && !test_bit(WL_STATUS_READY, &wl->status)) {
+	if (wl && !wl_get_drv_status(wl, READY)) {
 			if (wl->wdev &&
 				wl_cfgp2p_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));
+				if ((err = wl_cfgp2p_init_priv(wl)) != 0)
+					goto fail;
+#ifdef CONFIG_SYSCTL
+				wl_cfg80211_sysctl_export_devaddr(wl->pub);
+#endif
+				wl->p2p_supported = true;
 			}
 	} else
 		return -ENODEV;
 
-	set_bit(WL_STATUS_READY, &wl->status);
+	wl_set_drv_status(wl, READY);
+fail:
 	return err;
 }
 s32 wl_cfg80211_attach(struct net_device *ndev, void *data)
@@ -4864,7 +5313,8 @@ void wl_cfg80211_detach(void)
 #endif
 	rfkill_unregister(wl->rfkill);
 	rfkill_destroy(wl->rfkill);
-
+	if (wl->p2p_supported)
+		wl_cfgp2p_deinit_priv(wl);
 	wl_deinit_priv(wl);
 	wl_free_wdev(wl);
 	wl_set_drvdata(wl_cfg80211_dev, NULL);
@@ -5001,9 +5451,6 @@ static void wl_put_event(struct wl_event_q *e)
 	kfree(e);
 }
 
-/* TODO: this has been changed to wl_cfg80211_set_sdio_func in FALCON
- * Keep is as-is in P2P Twig
- */
 void wl_cfg80211_set_sdio_func(void *func)
 {
 	cfg80211_sdio_func = (struct sdio_func *)func;
@@ -5035,16 +5482,22 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp
 		mode = WL_MODE_IBSS;
 		break;
 	case NL80211_IFTYPE_STATION:
+	case NL80211_IFTYPE_P2P_CLIENT:
 		mode = WL_MODE_BSS;
 		infra = 1;
 		break;
+	case NL80211_IFTYPE_AP:
+	case NL80211_IFTYPE_P2P_GO:
+		mode = WL_MODE_AP;
+		infra = 1;
+		break;
 	default:
 		err = -EINVAL;
 		WL_ERR(("invalid type (%d)\n", iftype));
 		return err;
 	}
 	infra = htod32(infra);
-	err = wldev_ioctl(ndev, WLC_SET_INFRA, &infra, sizeof(infra), FALSE);
+	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;
@@ -5054,6 +5507,39 @@ static s32 wl_dongle_mode(struct wl_priv *wl, struct net_device *ndev, s32 iftyp
 
 	return 0;
 }
+static s32 wl_dongle_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add)
+{
+	s8 iovbuf[WL_EVENTING_MASK_LEN + 12];
+
+	s8 eventmask[WL_EVENTING_MASK_LEN];
+	s32 err = 0;
+
+	/* Setup event_msgs */
+	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, 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;
+	}
+	memcpy(eventmask, iovbuf, WL_EVENTING_MASK_LEN);
+	if (add) {
+		setbit(eventmask, event);
+	} else {
+		clrbit(eventmask, event);
+	}
+	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, 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;
+	}
+
+dongle_eventmsg_out:
+	return err;
+
+}
 
 static s32 wl_dongle_eventmsg(struct net_device *ndev)
 {
@@ -5065,7 +5551,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 = wldev_ioctl(ndev, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	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;
@@ -5099,7 +5585,7 @@ static s32 wl_dongle_eventmsg(struct net_device *ndev)
 	setbit(eventmask, WLC_E_ESCAN_RESULT);
 	bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf,
 		sizeof(iovbuf));
-	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	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;
@@ -5122,7 +5608,7 @@ static s32 wl_dongle_up(struct net_device *ndev, u32 up)
 {
 	s32 err = 0;
 
-	err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), FALSE);
+	err = wldev_ioctl(ndev, WLC_UP, &up, sizeof(up), false);
 	if (unlikely(err)) {
 		WL_ERR(("WLC_UP error (%d)\n", err));
 	}
@@ -5134,7 +5620,7 @@ static s32 wl_dongle_power(struct net_device *ndev, u32 power_mode)
 	s32 err = 0;
 
 	WL_TRACE(("In\n"));
-	err = wldev_ioctl(ndev, WLC_SET_PM, &power_mode, sizeof(power_mode), FALSE);
+	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));
 	}
@@ -5151,14 +5637,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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	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;
@@ -5178,7 +5664,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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+		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;
@@ -5186,7 +5672,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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	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;
@@ -5202,7 +5688,7 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 	s32 err = 0;
 
 	err = wldev_ioctl(ndev, WLC_SET_SCAN_CHANNEL_TIME, &scan_assoc_time,
-		sizeof(scan_assoc_time), FALSE);
+		sizeof(scan_assoc_time), false);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("Scan assoc time is not supported\n"));
@@ -5212,7 +5698,7 @@ wl_dongle_scantime(struct net_device *ndev, s32 scan_assoc_time,
 		goto dongle_scantime_out;
 	}
 	err = wldev_ioctl(ndev, WLC_SET_SCAN_UNASSOC_TIME, &scan_unassoc_time,
-		sizeof(scan_unassoc_time), FALSE);
+		sizeof(scan_unassoc_time), false);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("Scan unassoc time is not supported\n"));
@@ -5236,7 +5722,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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO(("arpoe is not supported\n"));
@@ -5246,7 +5732,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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
 	if (err) {
 		if (err == -EOPNOTSUPP)
 			WL_INFO(("arp_ol is not supported\n"));
@@ -5345,7 +5831,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 = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, FALSE);
+	err = wldev_ioctl(ndev, WLC_SET_VAR, buf, buf_len, false);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("filter not supported\n"));
@@ -5358,7 +5844,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 = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), FALSE);
+	err = wldev_ioctl(ndev, WLC_SET_VAR, iovbuf, sizeof(iovbuf), false);
 	if (err) {
 		if (err == -EOPNOTSUPP) {
 			WL_INFO(("filter_mode not supported\n"));
@@ -5445,7 +5931,7 @@ static s32 wl_update_wiphybands(struct wl_priv *wl)
 	s32 err = 0;
 
 	err = wldev_ioctl(wl_to_prmry_ndev(wl), WLC_GET_PHYLIST, &phy_list,
-		sizeof(phy_list), FALSE);
+		sizeof(phy_list), false);
 	if (unlikely(err)) {
 		WL_ERR(("error (%d)\n", err));
 		return err;
@@ -5473,7 +5959,7 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl)
 		return err;
 
 	wl_invoke_iscan(wl);
-	set_bit(WL_STATUS_READY, &wl->status);
+	wl_set_drv_status(wl, READY);
 	return err;
 }
 
@@ -5483,25 +5969,32 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl)
 
 	WL_TRACE(("In\n"));
 	/* Check if cfg80211 interface is already down */
-	if (!test_bit(WL_STATUS_READY, &wl->status))
+	if (!wl_get_drv_status(wl, READY))
 		return err;	/* it is even not ready */
 
-	set_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
+	wl_set_drv_status(wl, SCAN_ABORTING);
+
 	wl_term_iscan(wl);
 	if (wl->scan_request) {
 		cfg80211_scan_done(wl->scan_request, true);
-
 		wl->scan_request = NULL;
 	}
-	clear_bit(WL_STATUS_READY, &wl->status);
-	clear_bit(WL_STATUS_SCANNING, &wl->status);
-	clear_bit(WL_STATUS_SCAN_ABORTING, &wl->status);
-	clear_bit(WL_STATUS_CONNECTED, &wl->status);
-
+	wl_clr_drv_status(wl, READY);
+	wl_clr_drv_status(wl, SCANNING);
+	wl_clr_drv_status(wl, SCAN_ABORTING);
+	wl_clr_drv_status(wl, CONNECTED);
+	if (wl_get_drv_status(wl, AP_CREATED)) {
+		wl_clr_drv_status(wl, AP_CREATED);
+		wl_clr_drv_status(wl, AP_CREATING);
+		wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype =
+		NL80211_IFTYPE_STATION;
+	}
 	wl->dongle_up = false;
 	wl_flush_eq(wl);
 	wl_link_down(wl);
-	wl_cfgp2p_down(wl);
+	if (wl->p2p_supported)
+		wl_cfgp2p_down(wl);
+
 	wl_debugfs_remove_netdev(wl);
 
 	return err;
@@ -5833,6 +6326,47 @@ s8 *wl_cfg80211_get_nvramname(void)
 	return wl->fw->nvram_name;
 }
 
+s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr)
+{
+	struct wl_priv *wl;
+	dhd_pub_t *dhd_pub;
+	struct ether_addr p2pif_addr;
+
+	wl = WL_PRIV_GET();
+	dhd_pub = (dhd_pub_t *)wl->pub;
+	wl_cfgp2p_generate_bss_mac(&dhd_pub->mac, p2pdev_addr, &p2pif_addr);
+
+	return 0;
+}
+
+static __used void wl_dongle_poweron(struct wl_priv *wl)
+{
+
+	WL_DBG(("Enter \n"));
+	dhd_customer_gpio_wlan_ctrl(WLAN_RESET_ON);
+
+#if defined(BCMLXSDMMC)
+	sdioh_start(NULL, 0);
+#endif
+#if defined(BCMLXSDMMC)
+	sdioh_start(NULL, 1);
+#endif
+	wl_cfg80211_resume(wl_to_wiphy(wl));
+}
+
+static __used void wl_dongle_poweroff(struct wl_priv *wl)
+{
+
+
+	WL_DBG(("Enter \n"));
+	wl_cfg80211_suspend(wl_to_wiphy(wl));
+
+#if defined(BCMLXSDMMC)
+	sdioh_stop(NULL);
+#endif
+	/* clean up dtim_skip setting */
+	dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF);
+}
 static int wl_debugfs_add_netdev_params(struct wl_priv *wl)
 {
 	char buf[10+IFNAMSIZ];
@@ -5872,6 +6406,13 @@ static const struct rfkill_ops wl_rfkill_ops = {
 
 static int wl_rfkill_set(void *data, bool blocked)
 {
+	struct wl_priv *wl = (struct wl_priv *)data;
+
+	WL_DBG(("Enter \n"));
+	WL_DBG(("RF %s\n", blocked ? "blocked" : "unblocked"));
+
+	wl->rf_blocked = blocked;
+
 	return 0;
 }
 
diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
index 4c05987..f9de60f 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h
@@ -114,12 +114,6 @@ do {									\
 				 */
 #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 {
@@ -127,7 +121,9 @@ enum wl_status {
 	WL_STATUS_SCANNING,
 	WL_STATUS_SCAN_ABORTING,
 	WL_STATUS_CONNECTING,
-	WL_STATUS_CONNECTED
+	WL_STATUS_CONNECTED,
+	WL_STATUS_AP_CREATING,
+	WL_STATUS_AP_CREATED
 };
 
 /* wi-fi mode */
@@ -315,6 +311,17 @@ struct escan_info {
     struct wiphy *wiphy;
 };
 
+struct ap_info {
+/* Structure to hold WPS, WPA IEs for a AP */
+	u8   probe_res_ie[IE_MAX_LEN];
+	u8   beacon_ie[IE_MAX_LEN];
+	u32 probe_res_ie_len;
+	u32 beacon_ie_len;
+	u8 *wpa_ie;
+	u8 *rsn_ie;
+	u8 *wps_ie;
+	bool security_mode;
+};
 /* dongle private data of cfg80211 interface */
 struct wl_priv {
 	struct wireless_dev *wdev;	/* representing wl cfg80211 device */
@@ -373,12 +380,13 @@ struct wl_priv {
 	struct dentry *debugfsdir;
 	struct rfkill *rfkill;
 	bool rf_blocked;
-
 	struct ieee80211_channel remain_on_chan;
 	enum nl80211_channel_type remain_on_chan_type;
 	u64 cache_cookie;
 	wait_queue_head_t dongle_event_wait;
-	struct p2p_info p2p;
+	struct ap_info *ap_info;
+	struct p2p_info *p2p;
+	bool p2p_supported;
 	s8 last_eventmask[WL_EVENTING_MASK_LEN];
 	u8 ci[0] __attribute__ ((__aligned__(NETDEV_ALIGN)));
 };
@@ -398,6 +406,10 @@ struct wl_priv {
 #define wl_to_iscan(w) (w->iscan)
 #define wl_to_conn(w) (&w->conn_info)
 #define wiphy_from_scan(w) (w->escan_info.wiphy)
+#define wl_get_drv_status(wl, stat)   (test_bit(WL_STATUS_ ## stat, &(wl)->status))
+#define wl_set_drv_status(wl, stat)   (set_bit(WL_STATUS_ ## stat, &(wl)->status))
+#define wl_clr_drv_status(wl, stat)   (clear_bit(WL_STATUS_ ## stat, &(wl)->status))
+#define wl_chg_drv_status(wl, stat)   (change_bit(WL_STATUS_ ## stat, &(wl)->status))
 
 static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
 {
@@ -488,6 +500,7 @@ extern struct sdio_func *wl_cfg80211_get_sdio_func(void);	/* set sdio function i
 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_ifdel_ops(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);
@@ -499,6 +512,7 @@ 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);
+extern s32 wl_cfg80211_get_p2p_dev_addr(struct net_device *net, struct ether_addr *p2pdev_addr);
 #ifdef CONFIG_SYSCTL
 extern s32 wl_cfg80211_sysctl_export_devaddr(void *data);
 #endif
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
index 0a5a8a8..fa88d4b 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c
@@ -65,14 +65,13 @@ wl_cfgp2p_vndr_ie(struct net_device *ndev, s32 bssidx, s32 pktflag,
  *  Initialize variables related to P2P
  *
  */
-void
+s32
 wl_cfgp2p_init_priv(struct wl_priv *wl)
 {
-	wl->p2p.on = 0;
-	wl->p2p.scan = 0; /* by default , legacy scan */
-	wl->p2p.status = 0;
-	wl->p2p.listen_timer = NULL;
-
+	if (!(wl->p2p = kzalloc(sizeof(struct p2p_info), GFP_KERNEL))) {
+		CFGP2P_ERR(("struct p2p_info allocation failed\n"));
+		return -ENOMEM;
+	}
 #define INIT_IE(IE_TYPE, BSS_TYPE)		\
 	do {							\
 		memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \
@@ -103,17 +102,38 @@ wl_cfgp2p_init_priv(struct wl_priv *wl)
 	wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION) = NULL;
 	wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION) = 0;
 
-}
+	return BCME_OK;
 
+}
+/*
+ *  Deinitialize variables related to P2P
+ *
+ */
+void
+wl_cfgp2p_deinit_priv(struct wl_priv *wl)
+{
+	if (wl->p2p) {
+		kfree(wl->p2p);
+	}
+	wl->p2p_supported = 0;
+}
 /*
  * Set P2P functions into firmware
  */
 s32
 wl_cfgp2p_set_firm_p2p(struct wl_priv *wl)
 {
+	struct net_device *ndev = wl_to_prmry_ndev(wl);
 	s32 ret = BCME_OK;
-
-	/* TODO : Do we have to check whether APSTA is enabled or not ? */
+	s32 val = 0;
+	/* Do we have to check whether APSTA is enabled or not ? */
+	wldev_iovar_getint(ndev, "apsta", &val);
+	if (val == 0) {
+		val = 1;
+		wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), false);
+		wldev_iovar_setint(ndev, "apsta", val);
+		wldev_ioctl(ndev, WLC_UP, &val, sizeof(s32), false);
+	}
 	return ret;
 }
 
@@ -130,7 +150,7 @@ wl_cfgp2p_ifadd(struct wl_priv *wl, struct ether_addr *mac, u8 if_type,
 {
 	wl_p2p_if_t ifreq;
 	s32 err;
-	struct net_device *netdev = wl_to_prmry_ndev(wl);
+	struct net_device *ndev = wl_to_prmry_ndev(wl);
 
 	ifreq.type = if_type;
 	ifreq.chspec = chspec;
@@ -142,7 +162,7 @@ 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 = wldev_iovar_setbuf(netdev, "p2p_ifadd", &ifreq, sizeof(ifreq),
+	err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
 		ioctlbuf, sizeof(ioctlbuf));
 	return err;
 }
@@ -571,21 +591,21 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active,
 /* 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
+/* Delete and Set a management vndr ie to firmware
  * Parameters:
  * @wl       : wl_private data
  * @ndev     : net device for bssidx
  * @bssidx   : bssidx for BSS
  * @pktflag  : packet flag for IE (VNDR_IE_PRBREQ_FLAG,VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG,
  *                                 VNDR_IE_ASSOCREQ_FLAG)
- * @ie       : probe request ie (WPS IE + P2P IE)
- * @ie_len   : probe request ie length
+ * @ie       :  VNDR IE (such as P2P IE , WPS IE)
+ * @ie_len   : VNDR IE Length
  * Returns 0 if success.
  */
 
 s32
 wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
-    s32 pktflag, const u8 *p2p_ie, u32 p2p_ie_len)
+    s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len)
 {
 	/* Vendor-specific Information Element ID */
 #define VNDR_SPEC_ELEMENT_ID 0xdd
@@ -601,50 +621,70 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
 #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) {
-		case VNDR_IE_PRBREQ_FLAG :
-			mgmt_ie_buf = IE_TYPE(probe_req, bssidx);
-			mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx);
-			mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx));
-			break;
-		case VNDR_IE_PRBRSP_FLAG :
-			mgmt_ie_buf = IE_TYPE(probe_res, bssidx);
-			mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx);
-			mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx));
-			break;
-		case VNDR_IE_ASSOCREQ_FLAG :
-			mgmt_ie_buf = IE_TYPE(assoc_req, bssidx);
-			mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx);
-			mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx));
-			break;
-		case VNDR_IE_ASSOCRSP_FLAG :
-			mgmt_ie_buf = IE_TYPE(assoc_res, bssidx);
-			mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx);
-			mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx));
-			break;
-		case VNDR_IE_BEACON_FLAG :
-			mgmt_ie_buf = IE_TYPE(beacon, bssidx);
-			mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx);
-			mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx));
-			break;
-		default:
-			mgmt_ie_buf = NULL;
-			mgmt_ie_len = NULL;
-			CFGP2P_ERR(("not suitable type\n"));
-			return -1;
+	if (wl->p2p_supported && p2p_on(wl)) {
+		if (bssidx == P2PAPI_BSSCFG_PRIMARY)
+			bssidx =  wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE);
+		switch (pktflag) {
+			case VNDR_IE_PRBREQ_FLAG :
+				mgmt_ie_buf = IE_TYPE(probe_req, bssidx);
+				mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx);
+				mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx));
+				break;
+			case VNDR_IE_PRBRSP_FLAG :
+				mgmt_ie_buf = IE_TYPE(probe_res, bssidx);
+				mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx);
+				mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx));
+				break;
+			case VNDR_IE_ASSOCREQ_FLAG :
+				mgmt_ie_buf = IE_TYPE(assoc_req, bssidx);
+				mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx);
+				mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx));
+				break;
+			case VNDR_IE_ASSOCRSP_FLAG :
+				mgmt_ie_buf = IE_TYPE(assoc_res, bssidx);
+				mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx);
+				mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx));
+				break;
+			case VNDR_IE_BEACON_FLAG :
+				mgmt_ie_buf = IE_TYPE(beacon, bssidx);
+				mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx);
+				mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx));
+				break;
+			default:
+				mgmt_ie_buf = NULL;
+				mgmt_ie_len = NULL;
+				CFGP2P_ERR(("not suitable type\n"));
+				return -1;
+		}
+	} else {
+		switch (pktflag) {
+			case VNDR_IE_PRBRSP_FLAG :
+				mgmt_ie_buf = wl->ap_info->probe_res_ie;
+				mgmt_ie_len = &wl->ap_info->probe_res_ie_len;
+				mgmt_ie_buf_len = sizeof(wl->ap_info->probe_res_ie);
+				break;
+			case VNDR_IE_BEACON_FLAG :
+				mgmt_ie_buf = wl->ap_info->beacon_ie;
+				mgmt_ie_len = &wl->ap_info->beacon_ie_len;
+				mgmt_ie_buf_len = sizeof(wl->ap_info->beacon_ie);
+				break;
+			default:
+				mgmt_ie_buf = NULL;
+				mgmt_ie_len = NULL;
+				CFGP2P_ERR(("not suitable type\n"));
+				return -1;
+		}
 	}
 	/* Add if there is any extra IE */
-	if (p2p_ie && p2p_ie_len) {
-		CFGP2P_INFO(("Request has extra IE"));
-		if (p2p_ie_len > mgmt_ie_buf_len) {
+	if (vndr_ie && vndr_ie_len) {
+		CFGP2P_ERR(("Request has extra IE"));
+		if (vndr_ie_len > mgmt_ie_buf_len) {
 			CFGP2P_ERR(("extra IE size too big\n"));
 			ret = -ENOMEM;
 		} else {
 			if (mgmt_ie_buf != NULL) {
-				if ((p2p_ie_len == *mgmt_ie_len) &&
-				     (memcmp(mgmt_ie_buf, p2p_ie, p2p_ie_len) == 0)) {
+				if ((vndr_ie_len == *mgmt_ie_len) &&
+				     (memcmp(mgmt_ie_buf, vndr_ie, vndr_ie_len) == 0)) {
 					CFGP2P_INFO(("Previous mgmt IE is equals to current IE"));
 					goto exit;
 				}
@@ -666,12 +706,12 @@ wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssi
 
 			}
 			/* save the current IE in wl struct */
-			memcpy(mgmt_ie_buf, p2p_ie, p2p_ie_len);
-			*mgmt_ie_len = p2p_ie_len;
+			memcpy(mgmt_ie_buf, vndr_ie, vndr_ie_len);
+			*mgmt_ie_len = vndr_ie_len;
 			pos = 0;
-			ie_buf = (u8 *) p2p_ie;
+			ie_buf = (u8 *) vndr_ie;
 			delete = 0;
-			while (pos < p2p_ie_len) {
+			while (pos < vndr_ie_len) {
 				ie_id = ie_buf[pos++];
 				ie_len = ie_buf[pos++];
 				if ((ie_id == DOT11_MNG_VS_ID) &&
@@ -719,8 +759,6 @@ wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx)
 	INIT_IE(assoc_req, bssidx);
 	INIT_IE(assoc_res, bssidx);
 	INIT_IE(beacon, bssidx);
-
-
 	return BCME_OK;
 }
 
@@ -749,6 +787,7 @@ wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u
 
 	return FALSE;
 }
+
 wpa_ie_fixed_t *
 wl_cfgp2p_find_wpaie(u8 *parse, u32 len)
 {
@@ -855,12 +894,17 @@ wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev)
 		CFGP2P_ERR((" ndev is NULL\n"));
 		goto exit;
 	}
+	if (!wl->p2p_supported) {
+		return P2PAPI_BSSCFG_PRIMARY;
+	}
 	for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) {
 	    if (ndev == wl_to_p2p_bss_ndev(wl, i)) {
 			index = wl_to_p2p_bss_bssidx(wl, i);
 			break;
 		}
 	}
+	if (index == -1)
+		return P2PAPI_BSSCFG_PRIMARY;
 exit:
 	return index;
 }
@@ -874,12 +918,11 @@ wl_cfgp2p_listen_complete(struct wl_priv *wl, struct net_device *ndev,
 	s32 ret = BCME_OK;
 
 	CFGP2P_DBG((" Enter\n"));
-	/* TODO : have to acquire bottom half lock ? */
 	if (wl_get_p2p_status(wl, LISTEN_EXPIRED) == 0) {
 		wl_set_p2p_status(wl, LISTEN_EXPIRED);
 
-		if (wl->p2p.listen_timer)
-			del_timer_sync(wl->p2p.listen_timer);
+		if (wl->p2p->listen_timer)
+			del_timer_sync(wl->p2p->listen_timer);
 
 		cfg80211_remain_on_channel_expired(ndev, wl->cache_cookie, &wl->remain_on_chan,
 		    wl->remain_on_chan_type, GFP_KERNEL);
@@ -944,12 +987,12 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
 	wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_LISTEN, channel, (u16) duration_ms,
 	            wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
 
-	if (wl->p2p.listen_timer)
-		del_timer_sync(wl->p2p.listen_timer);
+	if (wl->p2p->listen_timer)
+		del_timer_sync(wl->p2p->listen_timer);
 
-	wl->p2p.listen_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
+	wl->p2p->listen_timer = kmalloc(sizeof(struct timer_list), GFP_KERNEL);
 
-	if (wl->p2p.listen_timer == NULL) {
+	if (wl->p2p->listen_timer == NULL) {
 		CFGP2P_ERR(("listen_timer allocation failed\n"));
 		return -ENOMEM;
 	}
@@ -957,7 +1000,7 @@ wl_cfgp2p_discover_listen(struct wl_priv *wl, s32 channel, u32 duration_ms)
 	/*  We will wait to receive WLC_E_P2P_DISC_LISTEN_COMPLETE from dongle , 
 	 *  otherwise we will wait up to duration_ms + 10ms
 	 */
-	INIT_TIMER(wl->p2p.listen_timer, wl_cfgp2p_listen_expired, duration_ms, 20);
+	INIT_TIMER(wl->p2p->listen_timer, wl_cfgp2p_listen_expired, duration_ms, 20);
 
 #undef INIT_TIMER
 exit:
@@ -986,7 +1029,7 @@ wl_cfgp2p_discover_enable_search(struct wl_priv *wl, u8 enable)
 	 */
 	if (!enable) {
 		wl_clr_p2p_status(wl, SCANNING);
-		(void) wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0,
+		ret = wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0,
 		            wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE));
 	}
 
@@ -1214,16 +1257,19 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev)
 	    CFGP2P_ERR(("wl p2p error %d\n", ret));
 		return 0;
 	}
-	if (p2p_supported)
+	if (p2p_supported == 1) {
 		CFGP2P_INFO(("p2p is supported\n"));
-
+	} else {
+		CFGP2P_INFO(("p2p is unsupported\n"));
+		p2p_supported = 0;
+	}
 	return p2p_supported;
 }
 /* Cleanup P2P resources */
 s32
 wl_cfgp2p_down(struct wl_priv *wl)
 {
-	if (wl->p2p.listen_timer)
-		del_timer_sync(wl->p2p.listen_timer);
+	if (wl->p2p->listen_timer)
+		del_timer_sync(wl->p2p->listen_timer);
 	return 0;
 }
diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
index 27aef59..1b28fa9 100644
--- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
+++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h
@@ -91,16 +91,20 @@ enum wl_cfgp2p_status {
 };
 
 
-#define wl_to_p2p_bss_ndev(w, type) 	((wl)->p2p.bss_idx[type].dev)
-#define wl_to_p2p_bss_bssidx(w, type) 	((wl)->p2p.bss_idx[type].bssidx)
-#define wl_to_p2p_bss_saved_ie(w, type) 	((wl)->p2p.bss_idx[type].saved_ie)
-#define wl_to_p2p_bss(wl, type) ((wl)->p2p.bss_idx[type])
-#define wl_get_p2p_status(wl, stat)   (test_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
-#define wl_set_p2p_status(wl, stat)   (set_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
-#define wl_clr_p2p_status(wl, stat)   (clear_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
-#define wl_chg_p2p_status(wl, stat)   (change_bit(WLP2P_STATUS_ ## stat, &(wl)->p2p.status))
-#define p2p_on(wl) ((wl)->p2p.on)
-#define p2p_scan(wl) ((wl)->p2p.scan)
+#define wl_to_p2p_bss_ndev(w, type) 	((wl)->p2p->bss_idx[type].dev)
+#define wl_to_p2p_bss_bssidx(w, type) 	((wl)->p2p->bss_idx[type].bssidx)
+#define wl_to_p2p_bss_saved_ie(w, type) 	((wl)->p2p->bss_idx[type].saved_ie)
+#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type])
+#define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \
+									&(wl)->p2p->status))
+#define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : set_bit(WLP2P_STATUS_ ## stat, \
+									&(wl)->p2p->status))
+#define wl_clr_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : clear_bit(WLP2P_STATUS_ ## stat, \
+									&(wl)->p2p->status))
+#define wl_chg_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? : change_bit(WLP2P_STATUS_ ## stat, \
+									&(wl)->p2p->status))
+#define p2p_on(wl) ((wl)->p2p->on)
+#define p2p_scan(wl) ((wl)->p2p->scan)
 
 
 /* dword align allocation */
@@ -131,8 +135,10 @@ enum wl_cfgp2p_status {
 	} while (0)
 
 
-extern void
+extern s32
 wl_cfgp2p_init_priv(struct wl_priv *wl);
+extern void
+wl_cfgp2p_deinit_priv(struct wl_priv *wl);
 extern s32
 wl_cfgp2p_set_firm_p2p(struct wl_priv *wl);
 extern s32
@@ -171,7 +177,7 @@ wl_cfgp2p_find_p2pie(u8 *parse, u32 len);
 
 extern s32
 wl_cfgp2p_set_managment_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx,
-            s32 pktflag, const u8 *p2p_ie, u32 p2p_ie_len);
+            s32 pktflag, const u8 *vndr_ie, u32 vndr_ie_len);
 extern s32
 wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx);
 
@@ -220,5 +226,7 @@ wl_cfgp2p_down(struct wl_priv *wl);
 #define SOCIAL_CHAN_3 11
 #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 IS_P2P_SSID(ssid) (memcmp(ssid, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN) == 0)
 #endif				/* _wl_cfgp2p_h_ */
diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c
index 1f811a9..75022a4 100644
--- a/drivers/net/wireless/bcmdhd/wl_iw.c
+++ b/drivers/net/wireless/bcmdhd/wl_iw.c
@@ -1889,6 +1889,12 @@ iwpriv_set_ap_config(struct net_device *dev,
 		info->cmd, info->flags,
 		wrqu->data.pointer, wrqu->data.length));
 
+	if (!ap_fw_loaded) {
+		WL_ERROR(("Can't execute %s(), SOFTAP fw is not Loaded\n",
+			__FUNCTION__));
+		return -1;
+	}
+
 	if (wrqu->data.length != 0) {
 
 		char *str_ptr;
@@ -1955,13 +1961,14 @@ static int iwpriv_get_assoc_list(struct net_device *dev,
 
 	iw = *(wl_iw_t **)netdev_priv(dev);
 
-	MUTEX_LOCK_SOFTAP_SET(iw->pub);
-	DHD_OS_WAKE_LOCK(iw->pub);
+	net_os_wake_lock(dev);
+	DHD_OS_MUTEX_LOCK(&wl_softap_lock);
 
 	WL_TRACE(("\n %s: IWPRIV IOCTL: cmd:%hx, flags:%hx, extra:%p, iwp.len:%d,"
 		"iwp.len:%p, iwp.flags:%x  \n", __FUNCTION__, info->cmd, info->flags,
 		extra, p_iwrq->data.length, p_iwrq->data.pointer, p_iwrq->data.flags));
 
+
 	memset(sta_maclist, 0, sizeof(mac_buf));
 
 	sta_maclist->count = 8;
@@ -2028,8 +2035,9 @@ static int iwpriv_get_assoc_list(struct net_device *dev,
 	}
 
 func_exit:
-	DHD_OS_WAKE_UNLOCK(iw->pub);
-	MUTEX_UNLOCK_SOFTAP_SET(iw->pub);
+
+	DHD_OS_MUTEX_UNLOCK(&wl_softap_lock);
+	net_os_wake_unlock(dev);
 
 	WL_SOFTAP(("%s: Exited\n", __FUNCTION__));
 	return ret;
@@ -4320,6 +4328,10 @@ wl_iw_iscan_get_scan(
 
 	WL_TRACE(("%s return to WE %d bytes APs=%d\n", __FUNCTION__, dwrq->length, counter));
 
+
+	if (!dwrq->length)
+		return -EAGAIN;
+
 	return 0;
 }
 #endif 
@@ -6266,7 +6278,7 @@ thr_wait_for_2nd_eth_dev(void *data)
 	}
 	DHD_OS_WAKE_LOCK(iw->pub);
 	complete(&tsk_ctl->completed);
-	if (down_timeout(&tsk_ctl->sema,  msecs_to_jiffies(5000)) != 0) {
+	if (down_timeout(&tsk_ctl->sema,  msecs_to_jiffies(1000)) != 0) {
 #else
 	if (down_interruptible(&tsk_ctl->sema) != 0) {
 #endif 
@@ -6289,7 +6301,7 @@ thr_wait_for_2nd_eth_dev(void *data)
 		goto fail;
 	}
 
-	WL_TRACE(("\n>%s: Thread:'softap ethdev IF:%s is detected !!!'\n\n",
+	WL_SOFTAP(("\n>%s: Thread:'softap ethdev IF:%s is detected!'\n\n",
 		__FUNCTION__, ap_net_dev->name));
 
 	ap_cfg_running = TRUE;
@@ -6304,7 +6316,7 @@ fail:
 
 	DHD_OS_WAKE_UNLOCK(iw->pub);
 
-	WL_TRACE(("\n>%s, thread completed\n", __FUNCTION__));
+	WL_SOFTAP(("\n>%s, thread completed\n", __FUNCTION__));
 
 	complete_and_exit(&tsk_ctl->completed, 0);
 	return ret;
-- 
1.7.1


