Update to 5.90.125.22:
authorHoward M. Harte <hharte@broadcom.com>
Fri, 27 May 2011 23:07:36 +0000 (16:07 -0700)
committerColin Cross <ccross@android.com>
Tue, 14 Jun 2011 16:10:01 +0000 (09:10 -0700)
    * Add support for SoftAP, keepalive, ARP offload.
    * Clean up cfg80211 and p2p code.
    * Update Makefile to support new features.
Change-Id: I1e7a16acd400d7baf5625ca8ba6552a6f1c80661
Signed-off-by: Howard M. Harte <hharte@broadcom.com>
15 files changed:
drivers/net/wireless/bcmdhd/Makefile
drivers/net/wireless/bcmdhd/dhd.h
drivers/net/wireless/bcmdhd/dhd_cdc.c
drivers/net/wireless/bcmdhd/dhd_common.c
drivers/net/wireless/bcmdhd/dhd_custom_gpio.c
drivers/net/wireless/bcmdhd/dhd_sdio.c
drivers/net/wireless/bcmdhd/include/epivers.h
drivers/net/wireless/bcmdhd/include/linuxver.h
drivers/net/wireless/bcmdhd/include/wlioctl.h
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/wldev_common.c [new file with mode: 0644]
drivers/net/wireless/bcmdhd/wldev_common.h [new file with mode: 0644]

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