Update to 5.90.125.40
authorLin Ma <linm@broadcom.com>
Mon, 18 Jul 2011 18:42:36 +0000 (11:42 -0700)
committermgross <mark.gross@intel.com>
Wed, 9 Nov 2011 20:21:43 +0000 (12:21 -0800)
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
drivers/net/wireless/bcmdhd/dhd_linux_mon.c [new file with mode: 0644]
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/wl_android.c
drivers/net/wireless/bcmdhd/wl_cfg80211.c
drivers/net/wireless/bcmdhd/wl_cfg80211.h
drivers/net/wireless/bcmdhd/wl_cfgp2p.c
drivers/net/wireless/bcmdhd/wl_cfgp2p.h
drivers/net/wireless/bcmdhd/wl_iw.c

index e952ee1..ff9f9fa 100644 (file)
@@ -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 (file)
index 0000000..a51db01
--- /dev/null
@@ -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;
+}
index ce9d26b..2dbb802 100644 (file)
@@ -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__));
 
index 432e253..fa6e305 100644 (file)
@@ -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");
index 22b636d..69180b5 100644 (file)
 #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;
 }
 
index 4c05987..f9de60f 100644 (file)
@@ -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
index 0a5a8a8..fa88d4b 100644 (file)
@@ -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;
 }
index 27aef59..1b28fa9 100644 (file)
@@ -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_ */
index 1f811a9..75022a4 100644 (file)
@@ -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;