update dhd to 100.10.545.11 [1/1]
authorLiang Ji <liang.ji@amlogic.com>
Tue, 30 Jun 2020 13:07:22 +0000 (21:07 +0800)
committerLiang Ji <liang.ji@amlogic.com>
Fri, 3 Jul 2020 03:11:51 +0000 (11:11 +0800)
PD#SWPL-28928

Problem:
cmd:
 iw --debug phy0 interface add test type managed
failed on adt3

Solution:
update dhd
Driver: 100.10.545.11 (r826445-20200610-1)

Verify:
deadpool + R

Signed-off-by: Liang Ji <liang.ji@amlogic.com>
Change-Id: I0073b34edacdb0fe69a6a0517b9be7e782afa572

53 files changed:
bcmdhd.100.10.315.x/Makefile
bcmdhd.100.10.315.x/bcmsdh_linux.c
bcmdhd.100.10.315.x/bcmsdh_sdmmc.c
bcmdhd.100.10.315.x/bcmstdlib_s.c
bcmdhd.100.10.315.x/bcmutils.c
bcmdhd.100.10.315.x/dbus.c
bcmdhd.100.10.315.x/dhd.h
bcmdhd.100.10.315.x/dhd_bus.h
bcmdhd.100.10.315.x/dhd_ccode.c [new file with mode: 0644]
bcmdhd.100.10.315.x/dhd_common.c
bcmdhd.100.10.315.x/dhd_config.c
bcmdhd.100.10.315.x/dhd_config.h
bcmdhd.100.10.315.x/dhd_csi.c [new file with mode: 0644]
bcmdhd.100.10.315.x/dhd_csi.h [new file with mode: 0644]
bcmdhd.100.10.315.x/dhd_custom_gpio.c
bcmdhd.100.10.315.x/dhd_gpio.c
bcmdhd.100.10.315.x/dhd_linux.c
bcmdhd.100.10.315.x/dhd_linux.h
bcmdhd.100.10.315.x/dhd_linux_exportfs.c
bcmdhd.100.10.315.x/dhd_linux_pktdump.c
bcmdhd.100.10.315.x/dhd_linux_platdev.c
bcmdhd.100.10.315.x/dhd_msgbuf.c
bcmdhd.100.10.315.x/dhd_pcie.c
bcmdhd.100.10.315.x/dhd_pcie_linux.c
bcmdhd.100.10.315.x/dhd_pno.c
bcmdhd.100.10.315.x/dhd_sdio.c
bcmdhd.100.10.315.x/dhd_static_buf.c
bcmdhd.100.10.315.x/dhd_wlfc.c
bcmdhd.100.10.315.x/dhd_wlfc.h
bcmdhd.100.10.315.x/include/bcmdevs.h
bcmdhd.100.10.315.x/include/bcmevent.h
bcmdhd.100.10.315.x/include/dhdioctl.h
bcmdhd.100.10.315.x/include/epivers.h
bcmdhd.100.10.315.x/include/linux_osl.h
bcmdhd.100.10.315.x/include/wlioctl.h
bcmdhd.100.10.315.x/include/wlioctl_defs.h
bcmdhd.100.10.315.x/linux_osl.c
bcmdhd.100.10.315.x/siutils.c
bcmdhd.100.10.315.x/wl_android.c
bcmdhd.100.10.315.x/wl_android.h
bcmdhd.100.10.315.x/wl_android_ext.c
bcmdhd.100.10.315.x/wl_cfg80211.c
bcmdhd.100.10.315.x/wl_cfg80211.h
bcmdhd.100.10.315.x/wl_cfgp2p.c
bcmdhd.100.10.315.x/wl_cfgp2p.h
bcmdhd.100.10.315.x/wl_cfgscan.c
bcmdhd.100.10.315.x/wl_cfgvendor.c
bcmdhd.100.10.315.x/wl_escan.c
bcmdhd.100.10.315.x/wl_escan.h
bcmdhd.100.10.315.x/wl_event.c
bcmdhd.100.10.315.x/wl_iw.c
bcmdhd.100.10.315.x/wl_iw.h
bcmdhd.100.10.315.x/wldev_common.c

index 88d5475a59c765337060cb581bcb4fc4bafe397f..8461a5b46156bdb3ccf15a991db3c84456aac9d8 100644 (file)
@@ -9,7 +9,11 @@ endif
 ifeq ($(CONFIG_BCMDHD_SDIO),y)
 MODULE_NAME := dhd
 else
+ifeq ($(CONFIG_BCMDHD_USB),y)
 MODULE_NAME := bcmdhd
+else
+MODULE_NAME := dhdpci
+endif
 endif
 #CONFIG_BCMDHD := m
 #CONFIG_BCMDHD_SDIO := y
@@ -34,9 +38,9 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER                 \
        -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY             \
        -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DDHDTCPACK_SUPPRESS                \
        -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT                           \
-       -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP                          \
+       -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP -DDHD_8021X_DUMP         \
        -DPOWERUP_MAX_RETRY=0 -DIFACE_HANG_FORCE_DEV_CLOSE -DWAIT_DEQUEUE     \
-       -DWL_EXT_IAPSTA -DWL_ESCAN                                            \
+       -DWL_EXT_IAPSTA -DWL_ESCAN -DCCODE_LIST                               \
        -DENABLE_INSMOD_NO_FW_LOAD                                            \
        -I$(src) -I$(src)/include
 
@@ -46,15 +50,39 @@ DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o   \
        bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o           \
        dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o dhd_dbg_ring.o            \
        hnd_pktq.o hnd_pktpool.o bcmxtlv.o linux_pkt.o bcmstdlib_s.o frag.o   \
-       dhd_linux_exportfs.o dhd_linux_pktdump.o \
-       dhd_config.o wl_event.o wl_android_ext.o wl_escan.o
+       dhd_linux_exportfs.o dhd_linux_pktdump.o                              \
+       dhd_config.o dhd_ccode.o wl_event.o wl_android_ext.o wl_escan.o
+
+ifneq ($(CONFIG_WIRELESS_EXT),)
+       DHDOFILES += wl_iw.o
+       DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW
+endif
+ifneq ($(CONFIG_CFG80211),)
+       DHDOFILES += wl_cfg80211.o wl_cfgscan.o wl_cfgp2p.o
+       DHDOFILES += wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o
+       DHDOFILES += dhd_cfg80211.o
+       DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
+       DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
+       DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
+       DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL
+       DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES
+       DHDCFLAGS += -DESCAN_RESULT_PATCH -DESCAN_BUF_OVERFLOW_MGMT
+       DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
+       DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8
+       DHDCFLAGS += -DWL_VIRTUAL_APSTA
+       DHDCFLAGS += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP
+       DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK
+       DHDCFLAGS += -DWL_STATIC_IF
+#      DHDCFLAGS += -DWL_SAE
+endif
 
 #BCMDHD_SDIO
 ifneq ($(CONFIG_BCMDHD_SDIO),)
 DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \
        -DSDTEST -DBDC -DDHD_USE_IDLECOUNT -DCUSTOM_SDIO_F2_BLKSIZE=256       \
        -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD              \
-       -DBCMSDIO_RXLIM_POST
+       -DDHDENABLE_TAILPAD -DSUPPORT_P2P_GO_PS                               \
+       -DBCMSDIO_RXLIM_POST -DCONSOLE_DPC
 ifeq ($(CONFIG_BCMDHD_OOB),y)
        DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB
 ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y)
@@ -73,9 +101,19 @@ DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1    \
        -DDONGLE_ENABLE_ISOLATION
 DHDCFLAGS += -DDHD_LB -DDHD_LB_RXP -DDHD_LB_STATS -DDHD_LB_TXP
 DHDCFLAGS += -DDHD_PKTID_AUDIT_ENABLED
+ifeq ($(CONFIG_BCMDHD_OOB),y)
+       DHDCFLAGS += -DCUSTOMER_OOB -DBCMPCIE_OOB_HOST_WAKE
+endif
 ifneq ($(CONFIG_PCI_MSI),)
-       DHDCFLAGS += -DDHD_USE_MSI
+       DHDCFLAGS += -DDHD_MSI_SUPPORT
 endif
+DHDCFLAGS += -DDHD_LB_TXP_DEFAULT_ENAB
+DHDCFLAGS += -DSET_RPS_CPUS -DSET_XPS_CPUS
+DHDCFLAGS += -DCUSTOM_TCPACK_SUPP_RATIO=15
+DHDCFLAGS += -DCUSTOM_TCPACK_DELAY_TIME=10
+DHDCFLAGS += -DDHDTCPACK_SUPPRESS
+DHDCFLAGS += -DDHD_DISABLE_ASPM
+
 DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o       \
        dhd_msgbuf.o dhd_linux_lb.o
 endif
@@ -99,7 +137,7 @@ ifneq ($(CONFIG_BCMDHD_USB),)
        DHDCFLAGS += -DPROP_TXSTATUS
 endif
 ifneq ($(CONFIG_BCMDHD_SDIO),)
-       DHDCFLAGS += -DPROP_TXSTATUS
+       DHDCFLAGS += -DPROP_TXSTATUS -DPROPTX_MAXCOUNT
 endif
 ifneq ($(CONFIG_CFG80211),)
        DHDCFLAGS += -DPROP_TXSTATUS_VSDB
@@ -145,13 +183,19 @@ ifneq ($(CONFIG_BCMDHD_PCIE),)
 endif
        DHDCFLAGS += -DDHD_UPDATE_INTF_MAC
        DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS))
-       DHDCFLAGS :=$(filter-out -DSET_RANDOM_MAC_SOFTAP,$(DHDCFLAGS))
+       DHDCFLAGS :=$(filter-out -DWL_STATIC_IF,$(DHDCFLAGS))
 endif
 
 ifeq ($(CONFIG_WL_EASYMESH),y)
        DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS))
        DHDCFLAGS :=$(filter-out -DDHD_LOG_DUMP,$(DHDCFLAGS))
-DHDCFLAGS += -DWLEASYMESH -DWL_STATIC_IF -DWLDWDS -DFOURADDR_AUTO_BRG
+       DHDCFLAGS += -DWLEASYMESH -DWL_STATIC_IF -DWLDWDS -DFOURADDR_AUTO_BRG
+endif
+
+#CSI_SUPPORT
+ifneq ($(CONFIG_CSI_SUPPORT),)
+       DHDCFLAGS += -DCSI_SUPPORT
+       DHDOFILES += dhd_csi.o
 endif
 
 obj-$(CONFIG_BCMDHD) += $(MODULE_NAME).o
@@ -165,6 +209,13 @@ else
        DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT
 endif
        DHDCFLAGS += -DCUSTOMER_HW_AMLOGIC
+
+# for config custom MAC
+#      DHDCFLAGS += -DGET_CUSTOM_MAC_ENABLE -DCUSTOM_MULTI_MAC
+# if also need config AP MAC
+#      DHDCFLAGS += -DCUSTOM_AP_MAC
+#
+
 #      DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI
 endif
 
@@ -175,30 +226,10 @@ endif
 ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
 #      obj-m += dhd_static_buf.o
        DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF
-       DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP -DCONFIG_DHD_USE_STATIC_BUF
+       DHDCFLAGS += -DCONFIG_DHD_USE_STATIC_BUF
+       DHDCFLAGS += -DDHD_USE_STATIC_MEMDUMP
 endif
 
-ifneq ($(CONFIG_WIRELESS_EXT),)
-       DHDOFILES += wl_iw.o
-       DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW
-endif
-ifneq ($(CONFIG_CFG80211),)
-       DHDOFILES += wl_cfg80211.o wl_cfgscan.o wl_cfgp2p.o
-       DHDOFILES += wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o
-       DHDOFILES += dhd_cfg80211.o
-       DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT
-       DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
-       DHDCFLAGS += -DCUSTOM_PNO_EVENT_LOCK_xTIME=10
-       DHDCFLAGS += -DWL_SUPPORT_AUTO_CHANNEL
-       DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES
-       DHDCFLAGS += -DESCAN_RESULT_PATCH -DESCAN_BUF_OVERFLOW_MGMT
-       DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
-       DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8
-       DHDCFLAGS += -DWL_VIRTUAL_APSTA
-       DHDCFLAGS += -DPNO_SUPPORT -DEXPLICIT_DISCIF_CLEANUP
-       DHDCFLAGS += -DDHD_USE_SCAN_WAKELOCK
-       DHDCFLAGS += -DWL_STATIC_IF
-endif
 EXTRA_CFLAGS = $(DHDCFLAGS)
 ifeq ($(CONFIG_BCMDHD),m)
 EXTRA_LDFLAGS += --strip-debug
index ed611897cdc58a9bd328f8fd2f375ddbfcaf8115..54b05435c90739cee4594eda34a8dc9ff89da718 100644 (file)
@@ -81,6 +81,7 @@ typedef struct bcmsdh_os_info {
 } bcmsdh_os_info_t;
 
 /* debugging macros */
+#define SDLX_ERR(x) printf x
 #define SDLX_MSG(x) printf x
 
 /**
@@ -143,12 +144,12 @@ void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint
 
        bcmsdh = bcmsdh_attach(osh, sdioh, &regs);
        if (bcmsdh == NULL) {
-               SDLX_MSG(("%s: bcmsdh_attach failed\n", __FUNCTION__));
+               SDLX_ERR(("%s: bcmsdh_attach failed\n", __FUNCTION__));
                goto err;
        }
        bcmsdh_osinfo = MALLOC(osh, sizeof(bcmsdh_os_info_t));
        if (bcmsdh_osinfo == NULL) {
-               SDLX_MSG(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
+               SDLX_ERR(("%s: failed to allocate bcmsdh_os_info_t\n", __FUNCTION__));
                goto err;
        }
        bzero((char *)bcmsdh_osinfo, sizeof(bcmsdh_os_info_t));
@@ -168,7 +169,7 @@ void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint
        bcmsdh_osinfo->oob_irq_num = wifi_platform_get_irq_number(adapter_info,
                &bcmsdh_osinfo->oob_irq_flags);
        if  (bcmsdh_osinfo->oob_irq_num < 0) {
-               SDLX_MSG(("%s: Host OOB irq is not defined\n", __FUNCTION__));
+               SDLX_ERR(("%s: Host OOB irq is not defined\n", __FUNCTION__));
                goto err;
        }
 #endif /* defined(BCMLXSDMMC) */
@@ -179,7 +180,7 @@ void* bcmsdh_probe(osl_t *osh, void *dev, void *sdioh, void *adapter_info, uint
        bcmsdh_osinfo->context = drvinfo.probe((vendevid >> 16), (vendevid & 0xFFFF), bus_num,
                slot_num, 0, bus_type, (void *)regs, osh, bcmsdh);
        if (bcmsdh_osinfo->context == NULL) {
-               SDLX_MSG(("%s: device attach failed\n", __FUNCTION__));
+               SDLX_ERR(("%s: device attach failed\n", __FUNCTION__));
                goto err;
        }
 
@@ -282,7 +283,7 @@ bcmsdh_register(bcmsdh_driver_t *driver)
        SDLX_MSG(("%s: register client driver\n", __FUNCTION__));
        error = bcmsdh_register_client_driver();
        if (error)
-               SDLX_MSG(("%s: failed %d\n", __FUNCTION__, error));
+               SDLX_ERR(("%s: failed %d\n", __FUNCTION__, error));
 
        return error;
 }
@@ -362,15 +363,15 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl
        bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
 
        if (bcmsdh_osinfo->oob_irq_registered) {
-               SDLX_MSG(("%s: irq is already registered\n", __FUNCTION__));
+               SDLX_ERR(("%s: irq is already registered\n", __FUNCTION__));
                return -EBUSY;
        }
 #ifdef HW_OOB
-       printf("%s: HW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
-               (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags);
+       SDLX_MSG(("%s: HW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
+               (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
 #else
-       printf("%s: SW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
-               (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags);
+       SDLX_MSG(("%s: SW_OOB irq=%d flags=0x%X\n", __FUNCTION__,
+               (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
 #endif
        bcmsdh_osinfo->oob_irq_handler = oob_irq_handler;
        bcmsdh_osinfo->oob_irq_handler_context = oob_irq_handler_context;
@@ -379,7 +380,7 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl
        err = request_irq(bcmsdh_osinfo->oob_irq_num, wlan_oob_irq,
                bcmsdh_osinfo->oob_irq_flags, "bcmsdh_sdmmc", bcmsdh);
        if (err) {
-               SDLX_MSG(("%s: request_irq failed with %d\n", __FUNCTION__, err));
+               SDLX_ERR(("%s: request_irq failed with %d\n", __FUNCTION__, err));
                bcmsdh_osinfo->oob_irq_enabled = FALSE;
                bcmsdh_osinfo->oob_irq_registered = FALSE;
                return err;
@@ -394,7 +395,7 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl
 #endif /* CONFIG_ARCH_RHEA || CONFIG_ARCH_CAPRI */
                err = enable_irq_wake(bcmsdh_osinfo->oob_irq_num);
                if (err)
-                       SDLX_MSG(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err));
+                       SDLX_ERR(("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err));
                else
                        bcmsdh_osinfo->oob_irq_wake_enabled = TRUE;
 #if defined(CONFIG_ARCH_RHEA) || defined(CONFIG_ARCH_CAPRI)
index 89b2c9f9a77f192d5ea906b37108557cb3e623d2..aa9a36bfabb5d8fda0da9293c1cccec7306e7f09 100644 (file)
@@ -1180,6 +1180,9 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func
                         * a restriction on max tx/glom count (based on host->max_segs).
                         */
                        if (sg_count >= ARRAYSIZE(sd->sg_list)) {
+                               sd_err(("%s: sg list entries(%u) exceed limit(%zu),"
+                                       " sd blk_size=%u\n",
+                                       __FUNCTION__, sg_count, (size_t)ARRAYSIZE(sd->sg_list), blk_size));
                                return (SDIOH_API_RC_FAIL);
                        }
                        pdata += pkt_offset;
@@ -1274,21 +1277,13 @@ txglomfail:
                                pkt_len += blk_size - (pkt_len % blk_size);
 
                        if ((write) && (!fifo))
-                               err_ret = sdio_memcpy_toio(
-                                               sd->func[func],
-                                               addr, buf, pkt_len);
+                               err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, pkt_len);
                        else if (write)
-                               err_ret = sdio_memcpy_toio(
-                                               sd->func[func],
-                                               addr, buf, pkt_len);
+                               err_ret = sdio_memcpy_toio(sd->func[func], addr, buf, pkt_len);
                        else if (fifo)
-                               err_ret = sdio_readsb(
-                                               sd->func[func],
-                                               buf, addr, pkt_len);
+                               err_ret = sdio_readsb(sd->func[func], buf, addr, pkt_len);
                        else
-                               err_ret = sdio_memcpy_fromio(
-                                               sd->func[func],
-                                               buf, addr, pkt_len);
+                               err_ret = sdio_memcpy_fromio(sd->func[func], buf, addr, pkt_len);
 
                        if (err_ret)
                                sd_err(("%s: %s FAILED %p[%d], addr=0x%05x, pkt_len=%d, ERR=%d\n",
index 42e74c17b142c014e6862da53fb0303c399cbee6..05c3e483199b87300c587ffe27f2c91e013702de 100644 (file)
@@ -185,7 +185,7 @@ exit:
 }
 #endif /* !__STDC_WANT_SECURE_LIB__ && !(__STDC_LIB_EXT1__ && __STDC_WANT_LIB_EXT1__) */
 
-#if !defined(FREEBSD) && !defined(BCM_USE_PLATFORM_STRLCPY)
+#if 0
 /**
  * strlcpy - Copy a %NUL terminated string into a sized buffer
  * @dest: Where to copy the string to
index 3cdad7b59b9543192bf11cb6d439f958c62ed2fb..2e9253afdab5647a4060dffe5cba161863697073 100644 (file)
@@ -3179,7 +3179,7 @@ bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len)
                if ((flags & mask) == bit) {
                        if (len > (int)strlen(name)) {
                                slen = (int)strlen(name);
-                               strncpy(buf, name, (size_t)slen+1);
+                               strncpy(buf, name, (size_t)len);
                        }
                        break;
                }
@@ -3222,7 +3222,7 @@ bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len)
                if (len <= slen)
                        break;
                /* copy NULL char but don't count it */
-               strncpy(p, name, (size_t)nlen + 1);
+               strncpy(p, name, (size_t)len);
                p += nlen;
                /* copy btwn flag space and NULL char */
                if (flags != 0)
index baacbfc648260b925663e9fdf6953e71f267aad7..a62642e9b117a8248fc2624bb3ecf16259095466 100644 (file)
@@ -2703,7 +2703,7 @@ dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path,
        bus->dhd->clm_path = pclm_path;
        bus->dhd->conf_path = pconf_path;
 
-       dhd_conf_set_path_params(bus->dhd, NULL, NULL, bus->fw_path, bus->nv_path);
+       dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
 
 }
 
index 97b05987bdc5ab1e7b947152e1e3e477c4dfad94..f4a7f529cf8086f75d9e6238edd0e412b98b56ae 100644 (file)
@@ -53,7 +53,9 @@
 #if defined(CONFIG_HAS_WAKELOCK)
 #include <linux/wakelock.h>
 #endif /* defined CONFIG_HAS_WAKELOCK */
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 4, 0)
+#include <uapi/linux/sched/types.h>
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0)
 #include <linux/sched/types.h>
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(4, 11, 0) */
 /* The kernel threading is sdio-specific */
@@ -1387,6 +1389,10 @@ typedef struct dhd_pub {
        void *pktcnts;
 #endif /* DHD_PKTDUMP_ROAM */
        bool disable_dtim_in_suspend;   /* Disable set bcn_li_dtim in suspend */
+#ifdef CSI_SUPPORT
+       struct list_head csi_list;
+       int csi_count;
+#endif /* CSI_SUPPORT */
        char *clm_path;         /* module_param: path to clm vars file */
        char *conf_path;                /* module_param: path to config vars file */
        struct dhd_conf *conf;  /* Bus module handle */
@@ -2358,6 +2364,7 @@ extern uint dhd_console_ms;
 extern uint android_msg_level;
 extern uint config_msg_level;
 extern uint sd_msglevel;
+extern uint dump_msg_level;
 #ifdef BCMDBUS
 extern uint dbus_msglevel;
 #endif /* BCMDBUS */
@@ -2925,6 +2932,12 @@ extern void *dhd_pub_shim(dhd_pub_t *dhd_pub);
 void* dhd_get_fwdump_buf(dhd_pub_t *dhd_pub, uint32 length);
 #endif /* DHD_FW_COREDUMP */
 
+#if defined(SET_XPS_CPUS)
+int dhd_xps_cpus_enable(struct net_device *net, int enable);
+int custom_xps_map_set(struct net_device *net, char *buf, size_t len);
+void custom_xps_map_clear(struct net_device *net);
+#endif
+
 #if defined(SET_RPS_CPUS)
 int dhd_rps_cpus_enable(struct net_device *net, int enable);
 int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len);
@@ -2937,9 +2950,9 @@ void custom_rps_map_clear(struct netdev_rx_queue *queue);
 #define RPS_CPUS_MASK_IBSS "10"
 #define RPS_CPUS_WLAN_CORE_ID 4
 #else
-#define RPS_CPUS_MASK "6"
-#define RPS_CPUS_MASK_P2P "6"
-#define RPS_CPUS_MASK_IBSS "6"
+#define RPS_CPUS_MASK "f"
+#define RPS_CPUS_MASK_P2P "f"
+#define RPS_CPUS_MASK_IBSS "f"
 #endif /* CONFIG_MACH_UNIVERSAL7420 || CONFIG_SOC_EXYNOS8890 */
 #endif // endif
 
index 72e9d913e8242c8ede9213793d944c5455adb2d6..d020783af738bd65b04d6d8bf85451013c95c347 100644 (file)
@@ -96,6 +96,9 @@ extern bool dhd_bus_dev_pm_enabled(dhd_pub_t *dhdpub);
 
 /* Device console input function */
 extern int dhd_bus_console_in(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#ifdef CONSOLE_DPC
+extern int dhd_bus_txcons(dhd_pub_t *dhd, uchar *msg, uint msglen);
+#endif
 
 /* Deferred processing for the bus, return TRUE requests reschedule */
 extern bool dhd_bus_dpc(struct dhd_bus *bus);
diff --git a/bcmdhd.100.10.315.x/dhd_ccode.c b/bcmdhd.100.10.315.x/dhd_ccode.c
new file mode 100644 (file)
index 0000000..763e92d
--- /dev/null
@@ -0,0 +1,234 @@
+\r
+#ifdef CCODE_LIST\r
+#ifdef CONFIG_COMPAT\r
+#include <linux/compat.h>\r
+#endif /* COMFIG_COMPAT */\r
+#include <typedefs.h>\r
+#include <dhd_config.h>\r
+\r
+#ifdef BCMSDIO\r
+#define CCODE_43438\r
+#define CCODE_43455C0\r
+#define CCODE_43456C5\r
+#endif\r
+#if defined(BCMSDIO) || defined(BCMPCIE)\r
+#define CCODE_4356A2\r
+#define CCODE_4359C0\r
+#endif\r
+#ifdef BCMDBUS\r
+#define CCODE_4358U\r
+#endif\r
+\r
+#ifdef BCMSDIO\r
+#ifdef CCODE_43438\r
+const char ccode_43438[] = "RU/13";\r
+#else\r
+const char ccode_43438 = "";\r
+#endif\r
+\r
+#ifdef CCODE_43455C0\r
+const char ccode_43455c0[] = \\r
+"AE/6 AG/2 AI/1 AL/2 AS/12 AT/4 AU/6 AW/2 AZ/2 "\\r
+"BA/2 BD/1 BE/4 BG/4 BH/4 BM/12 BN/4 BR/2 BS/2 BY/3 "\\r
+"CA/2 CA/31 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\\r
+"DE/3 DE/7 DK/4 "\\r
+"EC/21 EE/4 EG/13 ES/4 ET/2 "\\r
+"FI/4 FR/5 "\\r
+"GB/1 GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/30 "\\r
+"HK/2 HR/4 HU/4 "\\r
+"ID/1 IE/5 IL/14 IN/3 IS/4 IT/4 "\\r
+"JO/3 JP/45 JP/58 "\\r
+"KH/2 KR/45 KR/48 KR/49 KR/70 KR/71 KR/96 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\\r
+"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MQ/2 MR/2 MT/4 MU/2 MV/3 MW/1 MX/44 MY/3 "\\r
+"NI/2 NL/4 NO/4 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PH/5 PL/4 PR/38 PT/4 PY/2 "\\r
+"Q2/993 "\\r
+"RE/2 RO/4 RS/2 RU/13 "\\r
+"SE/4 SI/4 SK/4 SV/25 "\\r
+"TH/5 TN/1 TR/7 TT/3 TW/1 "\\r
+"UA/8 US/988 "\\r
+"VA/2 VE/3 VG/2 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZA/6";\r
+#else\r
+const char ccode_43455c0[] = "";\r
+#endif\r
+\r
+#ifdef CCODE_43456C5\r
+const char ccode_43456c5[] = \\r
+"AE/6 AG/2 AI/1 AL/2 AS/12 AT/4 AU/6 AW/2 AZ/2 "\\r
+"BA/2 BD/1 BE/4 BG/4 BH/4 BM/12 BN/4 BR/4 BS/2 BY/3 "\\r
+"CA/2 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\\r
+"DE/7 DK/4 "\\r
+"EC/21 EE/4 EG/13 ES/4 ET/2 "\\r
+"FI/4 FR/5 "\\r
+"GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/30 "\\r
+"HK/2 HR/4 HU/4 "\\r
+"ID/1 IE/5 IL/14 IN/3 IS/4 IT/4 "\\r
+"JO/3 JP/58 "\\r
+"KH/2 KR/96 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\\r
+"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MQ/2 MR/2 MT/4 MU/2 MV/3 MW/1 MX/44 MY/3 "\\r
+"NI/2 NL/4 NO/4 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PH/5 PL/4 PR/38 PT/4 PY/2 "\\r
+"Q2/993 "\\r
+"RE/2 RO/4 RS/2 RU/13 "\\r
+"SE/4 SI/4 SK/4 SV/25 "\\r
+"TH/5 TN/1 TR/7 TT/3 TW/65 "\\r
+"UA/8 US/988 "\\r
+"VA/2 VE/3 VG/2 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZA/6";\r
+#else\r
+const char ccode_43456c5[] = "";\r
+#endif\r
+#endif\r
+\r
+#ifdef CCODE_4356A2\r
+const char ccode_4356a2[] = \\r
+"AE/6 AG/2 AI/1 AL/2 AN/2 AR/21 AS/12 AT/4 AU/6 AW/2 AZ/2 "\\r
+"BA/2 BD/2 BE/4 BG/4 BH/4 BM/12 BN/4 BR/4 BS/2 BY/3 "\\r
+"CA/31 CH/4 CN/38 CO/17 CR/17 CY/4 CZ/4 "\\r
+"DE/7 DK/4 DZ/1 "\\r
+"EC/21 EE/4 ES/4 ET/2 "\\r
+"FI/4 FR/5 "\\r
+"GB/6 GD/2 GF/2 GP/2 GR/4 GT/1 GU/12 "\\r
+"HK/2 HR/4 HU/4 "\\r
+"ID/13 IE/5 IL/7 IN/28 IS/4 IT/4 "\\r
+"JO/3 JP/58 "\\r
+"KH/2 KR/57 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/4 LK/1 LS/2 LT/4 LU/3 LV/4 "\\r
+"MA/2 MC/1 MD/2 ME/2 MK/2 MN/1 MO/2 MR/2 MT/4 MQ/2 MU/2 MV/3 MW/1 MX/20 MY/16 "\\r
+"NI/2 NL/4 NO/4 NP/3 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PG/2 PH/5 PL/4 PR/20 PT/4 PY/2 "\\r
+"RE/2 RO/4 RS/2 RU/986 "\\r
+"SE/4 SG/4 SG/19 SI/4 SK/4 SN/2 SV/19 "\\r
+"TH/9 TN/1 TR/7 TT/3 TW/1 "\\r
+"UA/8 UG/2 US/1 UY/1 "\\r
+"VA/2 UA/16 VE/3 VG/2 VI/13 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZM/2 "\\r
+"E0/32";\r
+#else\r
+const char ccode_4356a2[] = "";\r
+#endif\r
+\r
+#ifdef CCODE_4359C0\r
+const char ccode_4359c0[] = \\r
+"AD/1 AE/6 AG/2 AI/1 AL/3 AS/12 AT/21 AU/6 AW/2 AZ/8 "\\r
+"BA/4 BD/1 BE/19 BG/18 BH/4 BM/12 BN/4 BR/2 BS/2 BY/3 "\\r
+"CN/38 CO/17 CR/17 CY/18 CZ/18 "\\r
+"DE/30 DK/19 "\\r
+"E0/32 EC/21 EE/18 EG/13 ES/21 ET/2 "\\r
+"FI/19 FR/21 "\\r
+"GB/996 GD/2 GE/1 GF/2 GP/2 GR/18 GT/1 GU/30 "\\r
+"HK/2 HR/18 HU/18 "\\r
+"ID/1 IE/21 IL/14 IN/3 IS/17 IT/20 "\\r
+"JO/3 JP/967 "\\r
+"KH/2 KR/70 KW/5 KY/3 "\\r
+"LA/2 LB/5 LI/17 LI/4 LK/1 LS/2 LT/18 LU/18 LV/18 "\\r
+"MA/2 MC/2 MD/3 ME/5 MK/4 MN/1 MQ/2 MR/2 MT/18 MU/2 MV/3 MW/1 MX/44 MY/3 "\\r
+"NI/2 NL/19 NO/18 NZ/4 "\\r
+"OM/4 "\\r
+"PA/17 PE/20 PH/5 PL/18 PR/38 PT/20 PY/2 "\\r
+"Q1/947 Q2/993 "\\r
+"RE/2 RO/18 RS/4 RU/986 "\\r
+"SE/19 SI/18 SK/18 SM/1 SV/25 "\\r
+"TH/5 TN/1 TR/18 TT/3 TW/1 "\\r
+"UA/16 US/988 "\\r
+"VA/3 VE/3 VG/2 VN/4 "\\r
+"XZ/11 "\\r
+"YT/2 "\\r
+"ZA/6";\r
+#else\r
+const char ccode_4359c0[] = "";\r
+#endif\r
+\r
+#ifdef CCODE_4358U\r
+const char ccode_4358u[] = \\r
+"BE/4 BR/4 CA/2 CH/4 CN/38 CY/4 DE/7 DK/4 ES/4 "\\r
+"FI/4 FR/5 GB/6 GR/4 HK/2 HU/4 IE/5 IL/7 IS/4 "\\r
+"IT/4 JP/72 KE/0 MY/3 NL/4 PT/4 SA/5 SE/4 SG/0 "\\r
+"SZ/0 TH/5 TR/7 TW/230 US/0 VN/4";\r
+#else\r
+const char ccode_4358u[] = "";\r
+#endif\r
+\r
+typedef struct ccode_list_map_t {\r
+       uint chip;\r
+       uint chiprev;\r
+       const char *ccode_list;\r
+       const char *ccode_ww;\r
+} ccode_list_map_t;\r
+\r
+extern const char ccode_43438[];\r
+extern const char ccode_43455c0[];\r
+extern const char ccode_43456c5[];\r
+extern const char ccode_4356a2[];\r
+extern const char ccode_4359c0[];\r
+extern const char ccode_4358u[];\r
+\r
+const ccode_list_map_t ccode_list_map[] = {\r
+       /* ChipID               Chiprev         ccode  */\r
+#ifdef BCMSDIO\r
+       {BCM43430_CHIP_ID,      0,      ccode_43438, ""},\r
+       {BCM43430_CHIP_ID,      1,      ccode_43438, ""},\r
+       {BCM4345_CHIP_ID,       6,      ccode_43455c0, "XZ/11"},\r
+       {BCM43454_CHIP_ID,      6,      ccode_43455c0, "XZ/11"},\r
+       {BCM4345_CHIP_ID,       9,      ccode_43456c5, "XZ/11"},\r
+       {BCM43454_CHIP_ID,      9,      ccode_43456c5, "XZ/11"},\r
+       {BCM4354_CHIP_ID,       2,      ccode_4356a2, "XZ/11"},\r
+       {BCM4356_CHIP_ID,       2,      ccode_4356a2, "XZ/11"},\r
+       {BCM4371_CHIP_ID,       2,      ccode_4356a2, "XZ/11"},\r
+       {BCM4359_CHIP_ID,       9,      ccode_4359c0, "XZ/11"},\r
+#endif\r
+#ifdef BCMPCIE\r
+       {BCM4354_CHIP_ID,       2,      ccode_4356a2, "XZ/11"},\r
+       {BCM4356_CHIP_ID,       2,      ccode_4356a2, "XZ/11"},\r
+       {BCM4359_CHIP_ID,       9,      ccode_4359c0, "XZ/11"},\r
+#endif\r
+#ifdef BCMDBUS\r
+       {BCM43569_CHIP_ID,      2,      ccode_4358u, "XW/0"},\r
+#endif\r
+};\r
+\r
+int\r
+dhd_ccode_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)\r
+{\r
+       int bcmerror = -1, i;\r
+       uint chip = dhd->conf->chip, chiprev = dhd->conf->chiprev; \r
+       const char *ccode_list = NULL, *ccode_ww = NULL;\r
+       char *pch;\r
+\r
+       for (i=0;  i<sizeof(ccode_list_map)/sizeof(ccode_list_map[0]);  i++) {\r
+               const ccode_list_map_t* row = &ccode_list_map[i];\r
+               if (row->chip == chip && row->chiprev == chiprev) {\r
+                       ccode_list = row->ccode_list;\r
+                       ccode_ww = row->ccode_ww;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       if (ccode_list) {\r
+               pch = strstr(ccode_list, cspec->ccode);\r
+               if (pch) {\r
+                       cspec->rev = (int)simple_strtol(pch+strlen(cspec->ccode)+1, NULL, 0);\r
+                       bcmerror = 0;\r
+               }\r
+       }\r
+\r
+       if (bcmerror && ccode_ww && strlen(ccode_ww)>=4) {\r
+               memcpy(cspec->ccode, ccode_ww, 2);\r
+               cspec->rev = (int)simple_strtol(ccode_ww+3, NULL, 0);\r
+       }\r
+\r
+       return bcmerror;\r
+}\r
+#endif\r
index c5f62fb623383f2edc0d51833ba1e4e9cf2c5c93..813833d35e52140190729e3af556aa20f0fd75c0 100644 (file)
 #ifdef DHD_LOG_PRINT_RATE_LIMIT
 int log_print_threshold = 0;
 #endif /* DHD_LOG_PRINT_RATE_LIMIT */
-int dhd_msg_level = DHD_ERROR_VAL;// | DHD_FWLOG_VAL | DHD_EVENT_VAL
+int dhd_msg_level = DHD_ERROR_VAL | DHD_FWLOG_VAL;// | DHD_EVENT_VAL
        /* For CUSTOMER_HW4 do not enable DHD_IOVAR_MEM_VAL by default */
 //     | DHD_PKT_MON_VAL;
 
@@ -133,6 +133,10 @@ int dhd_msg_level = DHD_ERROR_VAL;// | DHD_FWLOG_VAL | DHD_EVENT_VAL
 #include <linux/pm_runtime.h>
 #endif /* DHD_PCIE_NATIVE_RUNTIMEPM */
 
+#ifdef CSI_SUPPORT
+#include <dhd_csi.h>
+#endif /* CSI_SUPPORT */
+
 #ifdef SOFTAP
 char fw_path2[MOD_PARAM_PATHLEN];
 extern bool softap_enabled;
@@ -1634,8 +1638,13 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
 
 #if defined(DHD_DEBUG)
        case IOV_SVAL(IOV_CONS):
-               if (len > 0)
+               if (len > 0) {
+#ifdef CONSOLE_DPC
+                       bcmerror = dhd_bus_txcons(dhd_pub, arg, len - 1);
+#else
                        bcmerror = dhd_bus_console_in(dhd_pub, arg, len - 1);
+#endif
+               }
                break;
 #endif /* DHD_DEBUG */
 #endif /* !BCMDBUS */
@@ -3071,7 +3080,7 @@ wl_show_host_event(dhd_pub_t *dhd_pub, wl_event_msg_t *event, void *event_data,
                        break;
                }
        default:
-               DHD_INFO(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
+               DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n",
                       event_name, event_type, eabuf, (int)status, (int)reason,
                       (int)auth_type));
                break;
@@ -3663,6 +3672,11 @@ wl_process_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, uint pktlen
                }
                break;
 #endif /* DHD_POST_EAPOL_M1_AFTER_ROAM_EVT */
+#if defined(CSI_SUPPORT)
+       case WLC_E_CSI:
+               dhd_csi_event_handler(dhd_pub, event, (void *)event_data);
+               break;
+#endif /* CSI_SUPPORT */
        case WLC_E_LINK:
 #ifdef PCIE_FULL_DONGLE
                if (dhd_update_interface_link_status(dhd_pub, (uint8)dhd_ifname2idx(dhd_pub->info,
@@ -5068,6 +5082,8 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd, int *dtim_period, int *bcn_interval)
                }
        }
 
+       if (dhd->conf->suspend_bcn_li_dtim >= 0)
+               bcn_li_dtim = dhd->conf->suspend_bcn_li_dtim;
        DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n",
                __FUNCTION__, *bcn_interval, bcn_li_dtim, *dtim_period, CUSTOM_LISTEN_INTERVAL));
 
@@ -5120,7 +5136,6 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd)
                if (bcn_li_dtim == 0) {
                        bcn_li_dtim = 1;
                }
-               bcn_li_dtim = MAX(dhd->suspend_bcn_li_dtim, bcn_li_dtim);
        } else {
                /* attemp to use platform defined dtim skip interval */
                bcn_li_dtim = dhd->suspend_bcn_li_dtim;
index 3d33ea4757474d1fb7166ef15f179223e4025b4e..c308fd0125539ca6bd88091ca476e7726718b172 100644 (file)
 /* message levels */\r
 #define CONFIG_ERROR_LEVEL     (1 << 0)\r
 #define CONFIG_TRACE_LEVEL     (1 << 1)\r
-#define CONFIG_MSG_LEVEL       (1 << 15)\r
+#define CONFIG_MSG_LEVEL       (1 << 0)\r
 \r
 uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL;\r
+uint dump_msg_level = 0;\r
 \r
 #define CONFIG_MSG(x, args...) \\r
        do { \\r
@@ -42,12 +43,12 @@ uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL;
 #define CONFIG_TRACE(x, args...) \\r
        do { \\r
                if (config_msg_level & CONFIG_TRACE_LEVEL) { \\r
-                       printk(KERN_ERR "[dhd] CONFIG-TRACE) %s : " x, __func__, ## args); \\r
+                       printk(KERN_INFO "[dhd] CONFIG-TRACE) %s : " x, __func__, ## args); \\r
                } \\r
        } while (0)\r
 \r
-#define MAXSZ_BUF              1000\r
-#define        MAXSZ_CONFIG    4096\r
+#define MAXSZ_BUF              4096\r
+#define MAXSZ_CONFIG   8192\r
 \r
 #ifndef WL_CFG80211\r
 #define htod32(i) i\r
@@ -58,11 +59,9 @@ uint config_msg_level = CONFIG_ERROR_LEVEL | CONFIG_MSG_LEVEL;
 #define dtohchanspec(i) i\r
 #endif\r
 \r
-#if defined(SUSPEND_EVENT) && defined(PROP_TXSTATUS)\r
-#if defined(BCMSDIO) || defined(BCMDBUS)\r
+#if defined(PROP_TXSTATUS)\r
 #include <dhd_wlfc.h>\r
-#endif /* BCMSDIO || BCMDBUS */\r
-#endif /* SUSPEND_EVENT && PROP_TXSTATUS */\r
+#endif /* PROP_TXSTATUS */\r
 \r
 #define MAX_EVENT_BUF_NUM 16\r
 typedef struct eventmsg_buf {\r
@@ -95,6 +94,7 @@ const cihp_name_map_t chip_name_map[] = {
        {BCM43430_CHIP_ID,      2,      DONT_CARE,      "bcm43436b0",           "ap6236"},\r
        {BCM43012_CHIP_ID,      1,      FW_TYPE_G,      "bcm43013b0",           ""},\r
        {BCM43012_CHIP_ID,      1,      FW_TYPE_AG,     "bcm43013c0_ag",        ""},\r
+       {BCM43012_CHIP_ID,      2,      DONT_CARE,      "bcm43013c1_ag",        ""},\r
        {BCM4334_CHIP_ID,       3,      DONT_CARE,      "bcm4334b1_ag",         ""},\r
        {BCM43340_CHIP_ID,      2,      DONT_CARE,      "bcm43341b0_ag",        ""},\r
        {BCM43341_CHIP_ID,      2,      DONT_CARE,      "bcm43341b0_ag",        ""},\r
@@ -133,6 +133,18 @@ const cihp_name_map_t chip_name_map[] = {
 #endif\r
 };\r
 \r
+void\r
+dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)\r
+{\r
+       CONFIG_TRACE("called\n");\r
+\r
+       if (chip_nv_list->m_chip_nv_path_head) {\r
+               CONFIG_TRACE("Free %p\n", chip_nv_list->m_chip_nv_path_head);\r
+               kfree(chip_nv_list->m_chip_nv_path_head);\r
+       }\r
+       chip_nv_list->count = 0;\r
+}\r
+\r
 #ifdef BCMSDIO\r
 void\r
 dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)\r
@@ -153,18 +165,6 @@ dhd_conf_free_mac_list(wl_mac_list_ctrl_t *mac_list)
        mac_list->count = 0;\r
 }\r
 \r
-void\r
-dhd_conf_free_chip_nv_path_list(wl_chip_nv_path_list_ctrl_t *chip_nv_list)\r
-{\r
-       CONFIG_TRACE("called\n");\r
-\r
-       if (chip_nv_list->m_chip_nv_path_head) {\r
-               CONFIG_TRACE("Free %p\n", chip_nv_list->m_chip_nv_path_head);\r
-               kfree(chip_nv_list->m_chip_nv_path_head);\r
-       }\r
-       chip_nv_list->count = 0;\r
-}\r
-\r
 #if defined(HW_OOB) || defined(FORCE_WOWLAN)\r
 void\r
 dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih)\r
@@ -185,73 +185,30 @@ dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih)
 #endif\r
 \r
 #define SBSDIO_CIS_SIZE_LIMIT          0x200\r
-#define F0_BLOCK_SIZE 32\r
-int\r
-dhd_conf_set_blksize(bcmsdh_info_t *sdh)\r
-{\r
-       int err = 0;\r
-       uint fn, numfn;\r
-       int32 blksize = 0, cur_blksize = 0;\r
-       uint8 cisd;\r
-\r
-       numfn = bcmsdh_query_iofnum(sdh);\r
-\r
-       for (fn = 0; fn <= numfn; fn++) {\r
-               if (!fn)\r
-                       blksize = F0_BLOCK_SIZE;\r
-               else {\r
-                       bcmsdh_cisaddr_read(sdh, fn, &cisd, 24);\r
-                       blksize = cisd;\r
-                       bcmsdh_cisaddr_read(sdh, fn, &cisd, 25);\r
-                       blksize |= cisd << 8;\r
-               }\r
-#ifdef CUSTOM_SDIO_F2_BLKSIZE\r
-               if (fn == 2 && blksize > CUSTOM_SDIO_F2_BLKSIZE) {\r
-                       blksize = CUSTOM_SDIO_F2_BLKSIZE;\r
-               }\r
-#endif\r
-               bcmsdh_iovar_op(sdh, "sd_blocksize", &fn, sizeof(int32),\r
-                       &cur_blksize, sizeof(int32), FALSE);\r
-               if (cur_blksize != blksize) {\r
-                       CONFIG_MSG("fn=%d, blksize=%d, cur_blksize=%d\n",\r
-                               fn, blksize, cur_blksize);\r
-                       blksize |= (fn<<16);\r
-                       if (bcmsdh_iovar_op(sdh, "sd_blocksize", NULL, 0, &blksize,\r
-                               sizeof(blksize), TRUE) != BCME_OK) {\r
-                               CONFIG_ERROR("fail on get sd_blocksize");\r
-                               err = -1;\r
-                       }\r
-               }\r
-       }\r
-\r
-       return err;\r
-}\r
-\r
-int\r
-dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac)\r
+void\r
+dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih)\r
 {\r
        int i, err = -1;\r
-       uint8 *ptr = 0;\r
+       uint8 *ptr = 0, *ptpl_code = NULL;\r
        unsigned char tpl_code, tpl_link='\0';\r
-       uint8 header[3] = {0x80, 0x07, 0x19};\r
+       uint8 mac_header[3] = {0x80, 0x07, 0x19};\r
        uint8 *cis;\r
 \r
        if (!(cis = MALLOC(dhd->osh, SBSDIO_CIS_SIZE_LIMIT))) {\r
                CONFIG_ERROR("cis malloc failed\n");\r
-               return err;\r
        }\r
        bzero(cis, SBSDIO_CIS_SIZE_LIMIT);\r
 \r
        if ((err = bcmsdh_cis_read(sdh, 0, cis, SBSDIO_CIS_SIZE_LIMIT))) {\r
                CONFIG_ERROR("cis read err %d\n", err);\r
                MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
-               return err;\r
+               return;\r
        }\r
-       err = -1; // reset err;\r
        ptr = cis;\r
        do {\r
                /* 0xff means we're done */\r
                tpl_code = *ptr;\r
+               ptpl_code = ptr;\r
                ptr++;\r
                if (tpl_code == 0xff)\r
                        break;\r
@@ -266,35 +223,35 @@ dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac)
                if (tpl_link == 0xff)\r
                        break;\r
                if (config_msg_level & CONFIG_TRACE_LEVEL) {\r
-                       CONFIG_MSG("tpl_code=0x%02x, tpl_link=0x%02x, tag=0x%02x\n",\r
-                               tpl_code, tpl_link, *ptr);\r
-                       printk("%s: value:", __FUNCTION__);\r
-                       for (i=0; i<tpl_link-1; i++) {\r
-                               printk("%02x ", ptr[i+1]);\r
-                               if ((i+1) % 16 == 0)\r
-                                       printk("\n");\r
-                       }\r
-                       printk("\n");\r
+                       prhex("TPL", ptpl_code, tpl_link+2);\r
                }\r
 \r
-               if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19)\r
-                       break;\r
+               if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {\r
+                       memcpy(&dhd->conf->otp_mac, ptr+1, 6);\r
+               }\r
+#ifdef GET_OTP_MODULE_NAME\r
+               else if (tpl_code == 0x8e && *ptr == 0x41) {\r
+                       int len = tpl_link - 1;\r
+                       if (len <= sizeof(dhd->conf->module_name) - 1) {\r
+                               strncpy(dhd->conf->module_name, ptr+1, len);\r
+                               CONFIG_MSG("module_name=%s\n", dhd->conf->module_name);\r
+                       } else {\r
+                               CONFIG_ERROR("len is too long %d >= %d\n",\r
+                                       len, (int)sizeof(dhd->conf->module_name) - 1);\r
+                       }\r
+               }\r
+#endif\r
 \r
                ptr += tpl_link;\r
        } while (1);\r
 \r
-       if (tpl_code == 0x80 && tpl_link == 0x07 && *ptr == 0x19) {\r
-               /* Normal OTP */\r
-               memcpy(mac, ptr+1, 6);\r
-               err = 0;\r
-       } else {\r
+       if (!memcmp(&ether_null, &dhd->conf->otp_mac, ETHER_ADDR_LEN)) {\r
                ptr = cis;\r
                /* Special OTP */\r
                if (bcmsdh_reg_read(sdh, SI_ENUM_BASE(sih), 4) == 0x16044330) {\r
                        for (i=0; i<SBSDIO_CIS_SIZE_LIMIT; i++) {\r
-                               if (!memcmp(header, ptr, 3)) {\r
-                                       memcpy(mac, ptr+3, 6);\r
-                                       err = 0;\r
+                               if (!memcmp(mac_header, ptr, 3)) {\r
+                                       memcpy(&dhd->conf->otp_mac, ptr+3, 6);\r
                                        break;\r
                                }\r
                                ptr++;\r
@@ -304,16 +261,13 @@ dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac)
 \r
        ASSERT(cis);\r
        MFREE(dhd->osh, cis, SBSDIO_CIS_SIZE_LIMIT);\r
-\r
-       return err;\r
 }\r
 \r
 void\r
-dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,\r
-       si_t *sih, char *fw_path)\r
+dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, char *fw_path)\r
 {\r
        int i, j;\r
-       uint8 mac[6]={0};\r
+       uint8 *mac = (uint8 *)&dhd->conf->otp_mac;\r
        int fw_num=0, mac_num=0;\r
        uint32 oui, nic;\r
        wl_mac_list_t *mac_list;\r
@@ -326,10 +280,6 @@ dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,
        if (!mac_list || !fw_num)\r
                return;\r
 \r
-       if (dhd_conf_get_mac(dhd, sdh, sih, mac)) {\r
-               CONFIG_ERROR("Can not read MAC address\n");\r
-               return;\r
-       }\r
        oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
        nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
 \r
@@ -390,11 +340,10 @@ dhd_conf_set_fw_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,
 }\r
 \r
 void\r
-dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,\r
-       si_t *sih, char *nv_path)\r
+dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, char *nv_path)\r
 {\r
        int i, j;\r
-       uint8 mac[6]={0};\r
+       uint8 *mac = (uint8 *)&dhd->conf->otp_mac;\r
        int nv_num=0, mac_num=0;\r
        uint32 oui, nic;\r
        wl_mac_list_t *mac_list;\r
@@ -406,10 +355,6 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,
        if (!mac_list || !nv_num)\r
                return;\r
 \r
-       if (dhd_conf_get_mac(dhd, sdh, sih, mac)) {\r
-               CONFIG_ERROR("Can not read MAC address\n");\r
-               return;\r
-       }\r
        oui = (mac[0] << 16) | (mac[1] << 8) | (mac[2]);\r
        nic = (mac[3] << 16) | (mac[4] << 8) | (mac[5]);\r
 \r
@@ -439,18 +384,37 @@ dhd_conf_set_nv_name_by_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh,
 #endif\r
 \r
 void\r
-dhd_conf_free_country_list(conf_country_list_t *country_list)\r
+dhd_conf_free_country_list(struct dhd_conf *conf)\r
 {\r
-       int i;\r
+       country_list_t *country = conf->country_head;\r
+       int count = 0;\r
 \r
        CONFIG_TRACE("called\n");\r
-       for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
-               if (country_list->cspec[i]) {\r
-                       CONFIG_TRACE("Free cspec %p\n", country_list->cspec[i]);\r
-                       kfree(country_list->cspec[i]);\r
-                       country_list->cspec[i] = NULL;\r
-               }\r
+       while (country) {\r
+               CONFIG_TRACE("Free cspec %s\n", country->cspec.country_abbrev);\r
+               conf->country_head = country->next;\r
+               kfree(country);\r
+               country = conf->country_head;\r
+               count++;\r
+       }\r
+       CONFIG_TRACE("%d country released\n", count);\r
+}\r
+\r
+void\r
+dhd_conf_free_mchan_list(struct dhd_conf *conf)\r
+{\r
+       mchan_params_t *mchan = conf->mchan;\r
+       int count = 0;\r
+\r
+       CONFIG_TRACE("called\n");\r
+       while (mchan) {\r
+               CONFIG_TRACE("Free cspec %p\n", mchan);\r
+               conf->mchan = mchan->next;\r
+               kfree(mchan);\r
+               mchan = conf->mchan;\r
+               count++;\r
        }\r
+       CONFIG_TRACE("%d mchan released\n", count);\r
 }\r
 \r
 int\r
@@ -475,7 +439,7 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
                }\r
        }\r
 #ifndef FW_PATH_AUTO_SELECT\r
-       return;\r
+       return DONT_CARE;\r
 #endif\r
 \r
        /* find out the last '/' */\r
@@ -610,10 +574,18 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path, int ag_type)
        for (i = 0; i < sizeof(chip_name_map)/sizeof(chip_name_map[0]); i++) {\r
                const cihp_name_map_t* row = &chip_name_map[i];\r
                if (row->chip == chip && row->chiprev == chiprev &&\r
-                               (row->ag_type == ag_type || row->ag_type == DONT_CARE) &&\r
-                               strlen(row->module_name)) {\r
-                       strcpy(name_ptr, "nvram_");\r
-                       strcat(name_ptr, row->module_name);\r
+                               (row->ag_type == ag_type || row->ag_type == DONT_CARE)) {\r
+#ifdef GET_OTP_MODULE_NAME\r
+                       if (strlen(dhd->conf->module_name)) {\r
+                               strcpy(name_ptr, "nvram_");\r
+                               strcat(name_ptr, dhd->conf->module_name);\r
+                       } else\r
+#endif\r
+                       if (strlen(row->module_name)){\r
+                               strcpy(name_ptr, "nvram_");\r
+                               strcat(name_ptr, row->module_name);\r
+                       } else\r
+                               continue;\r
 #ifdef BCMUSBDEV_COMPOSITE\r
                        strcat(name_ptr, "_cusb");\r
 #endif\r
@@ -698,8 +670,7 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path)
 #endif\r
 \r
 void\r
-dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih,\r
-       char *fw_path, char *nv_path)\r
+dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path)\r
 {\r
        int ag_type;\r
 \r
@@ -722,8 +693,8 @@ dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih,
        dhd_conf_set_nv_name_by_chip(dhd, nv_path, ag_type);\r
        dhd_conf_set_clm_name_by_chip(dhd, dhd->clm_path, ag_type);\r
 #ifdef BCMSDIO\r
-       dhd_conf_set_fw_name_by_mac(dhd, (bcmsdh_info_t *)sdh, (si_t *)sih, fw_path);\r
-       dhd_conf_set_nv_name_by_mac(dhd, (bcmsdh_info_t *)sdh, (si_t *)sih, nv_path);\r
+       dhd_conf_set_fw_name_by_mac(dhd, fw_path);\r
+       dhd_conf_set_nv_name_by_mac(dhd, nv_path);\r
 #endif\r
 \r
        CONFIG_MSG("Final fw_path=%s\n", fw_path);\r
@@ -815,6 +786,196 @@ dhd_conf_get_iovar(dhd_pub_t *dhd, int ifidx, int cmd, char *name,
        return ret;\r
 }\r
 \r
+static int\r
+dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf)\r
+{\r
+       wl_config_t rsdb_mode_cfg = {1, 0};\r
+\r
+       if (buf) {\r
+               rsdb_mode_cfg.config = (int)simple_strtol(buf, NULL, 0);\r
+               CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config);\r
+               dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,\r
+                       sizeof(rsdb_mode_cfg), TRUE);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+typedef struct sub_cmd_t {\r
+       char *name;\r
+       uint16 id;              /* id for the dongle f/w switch/case  */\r
+       uint16 type;            /* base type of argument IOVT_XXXX */\r
+} sub_cmd_t;\r
+\r
+/* wl he sub cmd list */\r
+static const sub_cmd_t he_cmd_list[] = {\r
+       {"enab", WL_HE_CMD_ENAB, IOVT_UINT8},\r
+       {"features", WL_HE_CMD_FEATURES, IOVT_UINT32},\r
+       {"bsscolor", WL_HE_CMD_BSSCOLOR, IOVT_UINT8},\r
+       {"partialbsscolor", WL_HE_CMD_PARTIAL_BSSCOLOR, IOVT_UINT8},\r
+       {"cap", WL_HE_CMD_CAP, IOVT_UINT8},\r
+       {"staid", WL_HE_CMD_STAID, IOVT_UINT16},\r
+       {"rtsdurthresh", WL_HE_CMD_RTSDURTHRESH, IOVT_UINT16},\r
+       {"peduration", WL_HE_CMD_PEDURATION, IOVT_UINT8},\r
+       {"testbed_mode", WL_HE_CMD_TESTBED_MODE, IOVT_UINT32},\r
+       {"omi_ulmu_throttle", WL_HE_CMD_OMI_ULMU_THROTTLE, IOVT_UINT16},\r
+       {"omi_dlmu_rr_mpf_map", WL_HE_CMD_OMI_DLMU_RSD_RCM_MPF_MAP, IOVT_UINT32},\r
+       {"ulmu_disable_policy", WL_HE_CMD_ULMU_DISABLE_POLICY, IOVT_UINT8},\r
+       {"sr_prohibit", WL_HE_CMD_SR_PROHIBIT, IOVT_UINT8},\r
+};\r
+\r
+static uint\r
+wl_he_iovt2len(uint iovt)\r
+{\r
+       switch (iovt) {\r
+       case IOVT_BOOL:\r
+       case IOVT_INT8:\r
+       case IOVT_UINT8:\r
+               return sizeof(uint8);\r
+       case IOVT_INT16:\r
+       case IOVT_UINT16:\r
+               return sizeof(uint16);\r
+       case IOVT_INT32:\r
+       case IOVT_UINT32:\r
+               return sizeof(uint32);\r
+       default:\r
+               /* ASSERT(0); */\r
+               return 0;\r
+       }\r
+}\r
+\r
+static int\r
+dhd_conf_he_cmd(dhd_pub_t * dhd, char *buf)\r
+{\r
+       int ret = BCME_OK, i;\r
+       bcm_xtlv_t *pxtlv = NULL;\r
+       uint8 mybuf[128];\r
+       uint16 he_id = -1, he_len = 0, mybuf_len = sizeof(mybuf);\r
+       uint32 he_val;\r
+       const sub_cmd_t *tpl = he_cmd_list;\r
+       char sub_cmd[32], he_val_str[10];\r
+\r
+       if (buf) {\r
+               sscanf(buf, "%s %s", sub_cmd, he_val_str);\r
+       }\r
+\r
+       for (i=0; i<ARRAY_SIZE(he_cmd_list); i++, tpl++) {\r
+               if (!strcmp(tpl->name, sub_cmd)) {\r
+                       he_id = tpl->id;\r
+                       he_len = wl_he_iovt2len(tpl->type);\r
+                       break;\r
+               }\r
+       }\r
+       if (he_id < 0) {\r
+               CONFIG_ERROR("No he id found for %s\n", sub_cmd);\r
+               return 0;\r
+       }\r
+\r
+       pxtlv = (bcm_xtlv_t *)mybuf;\r
+\r
+       if (strlen(he_val_str)) {\r
+               he_val = simple_strtol(he_val_str, NULL, 0);\r
+               ret = bcm_pack_xtlv_entry((uint8**)&pxtlv, &mybuf_len, he_id,\r
+                       he_len, (uint8 *)&he_val, BCM_XTLV_OPTION_ALIGN32);\r
+               if (ret != BCME_OK) {\r
+                       CONFIG_ERROR("failed to pack he enab, err: %s\n", bcmerrorstr(ret));\r
+                       return 0;\r
+               }\r
+               CONFIG_MSG("he %s 0x%x\n", sub_cmd, he_val);\r
+               dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "he", (char *)&mybuf,\r
+                       sizeof(mybuf), TRUE);\r
+       }\r
+\r
+       return 0;\r
+}\r
+\r
+typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf);\r
+\r
+typedef struct iovar_tpl_t {\r
+       int cmd;\r
+       char *name;\r
+       tpl_parse_t *parse;\r
+} iovar_tpl_t;\r
+\r
+const iovar_tpl_t iovar_tpl_list[] = {\r
+       {WLC_SET_VAR,   "rsdb_mode",    dhd_conf_rsdb_mode},\r
+       {WLC_SET_VAR,   "he",           dhd_conf_he_cmd},\r
+};\r
+\r
+static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,\r
+       dhd_pub_t *dhd, int cmd, char *name, char *buf)\r
+{\r
+       int i, ret = 0;\r
+\r
+       /* look for a matching code in the table */\r
+       for (i = 0; i < tpl_count; i++, tpl++) {\r
+               if (tpl->cmd == cmd && !strcmp(tpl->name, name))\r
+                       break;\r
+       }\r
+       if (i < tpl_count && tpl->parse) {\r
+               ret = tpl->parse(dhd, buf);\r
+       } else {\r
+               ret = -1;\r
+       }\r
+\r
+       return ret;\r
+}\r
+\r
+bool\r
+dhd_conf_set_wl_cmd(dhd_pub_t *dhd, char *data, bool down)\r
+{\r
+       int cmd, val, ret = 0, len;\r
+       char name[32], *pch, *pick_tmp, *pick_tmp2, *pdata = NULL;\r
+\r
+       /* Process wl_preinit:\r
+        * wl_preinit=[cmd]=[val], [cmd]=[val]\r
+        * Ex: wl_preinit=86=0, mpc=0\r
+        */\r
+\r
+       if (data == NULL)\r
+               return FALSE;\r
+\r
+       len = strlen(data);\r
+       pdata = kmalloc(len+1, GFP_KERNEL);\r
+       if (pdata == NULL) {\r
+               CONFIG_ERROR("Failed to allocate buffer of %d bytes\n", len+1);\r
+               goto exit;\r
+       }\r
+       memset(pdata, 0, len+1);\r
+       strcpy(pdata, data);\r
+\r
+       pick_tmp = pdata;\r
+       while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {\r
+               pch = bcmstrtok(&pick_tmp2, "=", 0);\r
+               if (!pch)\r
+                       break;\r
+               if (*pch == ' ') {\r
+                       pch++;\r
+               }\r
+               memset(name, 0 , sizeof (name));\r
+               cmd = (int)simple_strtol(pch, NULL, 0);\r
+               if (cmd == 0) {\r
+                       cmd = WLC_SET_VAR;\r
+                       strcpy(name, pch);\r
+               }\r
+               pch = bcmstrtok(&pick_tmp2, ",", 0);\r
+               if (!pch) {\r
+                       break;\r
+               }\r
+               ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),\r
+                       dhd, cmd, name, pch);\r
+               if (ret) {\r
+                       val = (int)simple_strtol(pch, NULL, 0);\r
+                       dhd_conf_set_intiovar(dhd, cmd, name, val, -1, down);\r
+               }\r
+       }\r
+\r
+exit:\r
+       if (pdata)\r
+               kfree(pdata);\r
+       return true;\r
+}\r
+\r
 int\r
 dhd_conf_get_band(dhd_pub_t *dhd)\r
 {\r
@@ -845,25 +1006,28 @@ dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)
 int\r
 dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)\r
 {\r
-       int bcmerror = -1, i;\r
+       int bcmerror = -1;\r
        struct dhd_conf *conf = dhd->conf;\r
-       conf_country_list_t *country_list = &conf->country_list;\r
-\r
-       for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
-               if (country_list->cspec[i] != NULL) {\r
-                       if (!strncmp("**", country_list->cspec[i]->country_abbrev, 2)) {\r
-                               memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ);\r
-                               cspec->rev = country_list->cspec[i]->rev;\r
-                               bcmerror = 0;\r
-                               break;\r
-                       } else if (!strncmp(cspec->country_abbrev,\r
-                                       country_list->cspec[i]->country_abbrev, 2)) {\r
-                               memcpy(cspec->ccode, country_list->cspec[i]->ccode, WLC_CNTRY_BUF_SZ);\r
-                               cspec->rev = country_list->cspec[i]->rev;\r
-                               bcmerror = 0;\r
-                               break;\r
-                       }\r
+       country_list_t *country = conf->country_head;\r
+\r
+#ifdef CCODE_LIST\r
+       bcmerror = dhd_ccode_map_country_list(dhd, cspec);\r
+#endif\r
+\r
+       while (country != NULL) {\r
+               if (!strncmp("**", country->cspec.country_abbrev, 2)) {\r
+                       memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);\r
+                       cspec->rev = country->cspec.rev;\r
+                       bcmerror = 0;\r
+                       break;\r
+               } else if (!strncmp(cspec->country_abbrev,\r
+                               country->cspec.country_abbrev, 2)) {\r
+                       memcpy(cspec->ccode, country->cspec.ccode, WLC_CNTRY_BUF_SZ);\r
+                       cspec->rev = country->cspec.rev;\r
+                       bcmerror = 0;\r
+                       break;\r
                }\r
+               country = country->next;\r
        }\r
 \r
        if (!bcmerror)\r
@@ -1073,7 +1237,7 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd)
                param.bw_cap = (uint)dhd->conf->bw_cap[0];\r
                CONFIG_MSG("set bw_cap 2g 0x%x\n", param.bw_cap);\r
                dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)&param,\r
-                       sizeof(param), FALSE);\r
+                       sizeof(param), TRUE);\r
        }\r
 \r
        if (dhd->conf->bw_cap[1] >= 0) {\r
@@ -1082,7 +1246,7 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd)
                param.bw_cap = (uint)dhd->conf->bw_cap[1];\r
                CONFIG_MSG("set bw_cap 5g 0x%x\n", param.bw_cap);\r
                dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "bw_cap", (char *)&param,\r
-                       sizeof(param), FALSE);\r
+                       sizeof(param), TRUE);\r
        }\r
 }\r
 \r
@@ -1226,18 +1390,19 @@ dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode)
 void\r
 dhd_conf_set_mchan_bw(dhd_pub_t *dhd, int p2p_mode, int miracast_mode)\r
 {\r
-       int i;\r
        struct dhd_conf *conf = dhd->conf;\r
+       mchan_params_t *mchan = conf->mchan;\r
        bool set = true;\r
 \r
-       for (i=0; i<MCHAN_MAX_NUM; i++) {\r
+       while (mchan != NULL) {\r
                set = true;\r
-               set &= (conf->mchan[i].bw >= 0);\r
-               set &= ((conf->mchan[i].p2p_mode == -1) | (conf->mchan[i].p2p_mode == p2p_mode));\r
-               set &= ((conf->mchan[i].miracast_mode == -1) | (conf->mchan[i].miracast_mode == miracast_mode));\r
+               set &= (mchan->bw >= 0);\r
+               set &= ((mchan->p2p_mode == -1) | (mchan->p2p_mode == p2p_mode));\r
+               set &= ((mchan->miracast_mode == -1) | (mchan->miracast_mode == miracast_mode));\r
                if (set) {\r
-                       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", conf->mchan[i].bw, 0, FALSE);\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mchan_bw", mchan->bw, 0, FALSE);\r
                }\r
+               mchan = mchan->next;\r
        }\r
 \r
        return;\r
@@ -1370,6 +1535,24 @@ dhd_conf_check_hostsleep(dhd_pub_t *dhd, int cmd, void *buf, int len,
                        goto exit;\r
                }\r
        }\r
+#ifdef NO_POWER_SAVE\r
+       if (cmd == WLC_SET_PM) {\r
+               if (*(const u32*)buf != 0) {\r
+                       CONFIG_TRACE("skip PM\n");\r
+                       *ret = BCME_OK;\r
+                       goto exit;\r
+               }\r
+       } else if (cmd == WLC_SET_VAR) {\r
+               int cmd_len = strlen("mpc");\r
+               if (!strncmp(buf, "mpc", cmd_len)) {\r
+                       if (*((u32 *)((u8*)buf+cmd_len+1)) != 0) {\r
+                               CONFIG_TRACE("skip mpc\n");\r
+                               *ret = BCME_OK;\r
+                               goto exit;\r
+                       }\r
+               }\r
+       }\r
+#endif\r
 \r
        return 0;\r
 exit:\r
@@ -1576,7 +1759,6 @@ dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period,
        wl_mkeep_alive_pkt_t *mkeep_alive_pktp;\r
        int ret = 0, len_bytes=0, buf_len=0;\r
        char *buf = NULL, *iovar_buf = NULL;\r
-       struct ether_addr bssid;\r
        uint8 *pdata;\r
 \r
        CONFIG_TRACE("id=%d, period=%d, packet=%s\n", id, period, packet);\r
@@ -1597,17 +1779,11 @@ dhd_conf_mkeep_alive(dhd_pub_t *dhd, int ifidx, int id, int period,
                mkeep_alive_pktp->keep_alive_id = id;\r
                buf_len += WL_MKEEP_ALIVE_FIXED_LEN;\r
                mkeep_alive_pktp->period_msec = period;\r
-               if (strlen(packet)) {\r
+               if (packet && strlen(packet)) {\r
                        len_bytes = wl_pattern_atoh(packet, (char *)mkeep_alive_pktp->data);\r
                        buf_len += len_bytes;\r
                        if (bcast) {\r
                                memcpy(mkeep_alive_pktp->data, &ether_bcast, ETHER_ADDR_LEN);\r
-                       } else {\r
-                               memset(&bssid, 0, ETHER_ADDR_LEN);\r
-                               ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN,\r
-                                       FALSE, ifidx);\r
-                               if (ret != BCME_NOTASSOCIATED && memcmp(&ether_null, &bssid, ETHER_ADDR_LEN))\r
-                                       memcpy(mkeep_alive_pktp->data, &bssid, ETHER_ADDR_LEN);\r
                        }\r
                        ret = dhd_conf_get_iovar(dhd, ifidx, WLC_GET_VAR, "cur_etheraddr",\r
                                iovar_buf, WLC_IOCTL_SMLEN);\r
@@ -1658,11 +1834,18 @@ dhd_conf_set_garp(dhd_pub_t *dhd, int ifidx, uint32 ipa, bool enable)
                for (i=0; i<ETHER_ADDR_LEN; i++)\r
                        len += snprintf(packet+len, total_len, "%02x", iovar_buf[i]);\r
                len += snprintf(packet+len, total_len, "08060001080006040001");\r
+                // Sender Hardware Addr.\r
                for (i=0; i<ETHER_ADDR_LEN; i++)\r
                        len += snprintf(packet+len, total_len, "%02x", iovar_buf[i]);\r
+                // Sender IP Addr.\r
+               len += snprintf(packet+len, total_len, "%02x%02x%02x%02x",\r
+                       ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff);\r
+                // Target Hardware Addr.\r
+               len += snprintf(packet+len, total_len, "ffffffffffff");\r
+                // Target IP Addr.\r
                len += snprintf(packet+len, total_len, "%02x%02x%02x%02x",\r
                        ipa&0xff, (ipa>>8)&0xff, (ipa>>16)&0xff, (ipa>>24)&0xff);\r
-               len += snprintf(packet+len, total_len, "ffffffffffffc0a80101000000000000000000000000000000000000");\r
+               len += snprintf(packet+len, total_len, "000000000000000000000000000000000000");\r
        }\r
 \r
        dhd_conf_mkeep_alive(dhd, ifidx, 0, dhd->conf->keep_alive_period, packet, TRUE);\r
@@ -1707,6 +1890,7 @@ dhd_conf_set_suspend_event(dhd_pub_t *dhd, int suspend)
        struct net_device *net;\r
 #endif /* defined(WL_CFG80211) */\r
 \r
+       CONFIG_TRACE("Enter\n");\r
        if (suspend) {\r
 #ifdef PROP_TXSTATUS\r
 #if defined(BCMSDIO) || defined(BCMDBUS)\r
@@ -1783,26 +1967,50 @@ dhd_conf_set_suspend_event(dhd_pub_t *dhd, int suspend)
 }\r
 #endif\r
 \r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+static void\r
+dhd_conf_wait_event_complete(struct dhd_pub *dhd, int ifidx)\r
+{\r
+       s32 timeout = -1;\r
+\r
+       timeout = wait_event_interruptible_timeout(dhd->conf->event_complete,\r
+               wl_ext_event_complete(dhd, ifidx), msecs_to_jiffies(10000));\r
+       if (timeout <= 0 || !wl_ext_event_complete(dhd, ifidx)) {\r
+               wl_ext_event_complete(dhd, ifidx);\r
+               CONFIG_ERROR("timeout\n");\r
+       }\r
+}\r
+#endif\r
+\r
 int\r
 dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)\r
 {\r
-       uint insuspend = 0;\r
        struct dhd_conf *conf = dhd->conf;\r
+       uint insuspend = 0;\r
+       int pm;\r
+#ifdef BCMSDIO\r
+       uint32 intstatus = 0;\r
+       int ret = 0;\r
+#endif\r
 #ifdef WL_EXT_WOWL\r
        int i;\r
 #endif\r
 \r
        insuspend = dhd_conf_get_insuspend(dhd, ALL_IN_SUSPEND);\r
        if (insuspend)\r
-               CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x\n",\r
-                       dhd->op_mode, suspend, conf->suspended, insuspend);\r
+               CONFIG_MSG("op_mode %d, suspend %d, suspended %d, insuspend 0x%x, suspend_mode=%d\n",\r
+                       dhd->op_mode, suspend, conf->suspended, insuspend, conf->suspend_mode);\r
 \r
-       if (conf->suspended == suspend) {\r
+       if (conf->suspended == suspend || !dhd->up) {\r
                return 0;\r
        }\r
 \r
        if (suspend) {\r
                if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off",\r
+                               dhd->conf->roam_off_suspend, 0, FALSE);\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_li_dtim",\r
+                               dhd->conf->suspend_bcn_li_dtim, 0, FALSE);\r
                        if (insuspend & ROAM_OFFLOAD_IN_SUSPEND)\r
                                dhd_conf_enable_roam_offload(dhd, 2);\r
                } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {\r
@@ -1810,14 +2018,36 @@ dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)
                                dhd_conf_set_intiovar(dhd, WLC_DOWN, "WLC_DOWN", 1, 0, FALSE);\r
                        }\r
                }\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+               if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {\r
+                       if (conf->suspend_mode == PM_NOTIFIER)\r
+                               dhd_conf_wait_event_complete(dhd, 0);\r
+               }\r
+#endif\r
+               if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
+                       dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);\r
+               }\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+               if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {\r
+                       if (conf->suspend_mode == PM_NOTIFIER)\r
+                               wl_ext_user_sync(dhd, 0, TRUE);\r
+               }\r
+#endif\r
 #ifdef SUSPEND_EVENT\r
                if (insuspend & NO_EVENT_IN_SUSPEND) {\r
                        dhd_conf_set_suspend_event(dhd, suspend);\r
                }\r
 #endif\r
-               if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
-                       dhd_txflowcontrol(dhd, ALL_INTERFACES, ON);\r
+               if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
+                       if (conf->pm_in_suspend >= 0)\r
+                               pm = conf->pm_in_suspend;\r
+                       else if (conf->pm >= 0)\r
+                               pm = conf->pm;\r
+                       else\r
+                               pm = PM_FAST;\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);\r
                }\r
+               dhd_conf_set_wl_cmd(dhd, conf->wl_suspend, FALSE);\r
 #ifdef WL_EXT_WOWL\r
                if ((insuspend & WOWL_IN_SUSPEND) && dhd_master_mode) {\r
                        dhd_conf_wowl_pattern(dhd, FALSE, "clr");\r
@@ -1828,10 +2058,18 @@ dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)
                        dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "wowl_activate", 1, 0, FALSE);\r
                        dhd_conf_wowl_wakeind(dhd, TRUE);\r
                        dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 1, 0, FALSE);\r
+#ifdef BCMSDIO\r
+                       ret = dhd_bus_sleep(dhd, TRUE, &intstatus);\r
+                       CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus);\r
+#endif\r
                } else\r
 #endif\r
                if (insuspend & NO_TXCTL_IN_SUSPEND) {\r
                        dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "hostsleep", 2, 0, FALSE);\r
+#ifdef BCMSDIO\r
+                       ret = dhd_bus_sleep(dhd, TRUE, &intstatus);\r
+                       CONFIG_TRACE("ret = %d, intstatus = 0x%x\n", ret, intstatus);\r
+#endif\r
                }\r
                conf->suspended = TRUE;\r
        } else {\r
@@ -1846,21 +2084,40 @@ dhd_conf_set_suspend_resume(dhd_pub_t *dhd, int suspend)
                        dhd_conf_wowl_pattern(dhd, FALSE, "clr");\r
                }\r
 #endif\r
+               dhd_conf_set_wl_cmd(dhd, conf->wl_resume, FALSE);\r
+               dhd_conf_get_iovar(dhd, 0, WLC_GET_PM, "WLC_GET_PM", (char *)&pm, sizeof(pm));\r
+               CONFIG_TRACE("PM in suspend = %d\n", pm);\r
 #ifdef SUSPEND_EVENT\r
                if (insuspend & NO_EVENT_IN_SUSPEND) {\r
                        dhd_conf_set_suspend_event(dhd, suspend);\r
                }\r
 #endif\r
+#if defined(WL_CFG80211) || defined(WL_ESCAN)\r
+               if (insuspend & (NO_EVENT_IN_SUSPEND|NO_TXCTL_IN_SUSPEND|WOWL_IN_SUSPEND)) {\r
+                       if (conf->suspend_mode == PM_NOTIFIER)\r
+                               wl_ext_user_sync(dhd, 0, FALSE);\r
+               }\r
+#endif\r
+               if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
+                       dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);\r
+               }\r
                if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
                        if (insuspend & ROAM_OFFLOAD_IN_SUSPEND)\r
                                dhd_conf_enable_roam_offload(dhd, 0);\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bcn_li_dtim", 0, 0, FALSE);\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off",\r
+                               dhd->conf->roam_off, 0, FALSE);\r
                } else if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) {\r
                        if (insuspend & AP_DOWN_IN_SUSPEND) {\r
                                dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE);\r
                        }\r
                }\r
-               if (insuspend & NO_TXDATA_IN_SUSPEND) {\r
-                       dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);\r
+               if (dhd->op_mode & DHD_FLAG_STA_MODE) {\r
+                       if (conf->pm >= 0)\r
+                               pm = conf->pm;\r
+                       else\r
+                               pm = PM_FAST;\r
+                       dhd_conf_set_intiovar(dhd, WLC_SET_PM, "WLC_SET_PM", pm, 0, FALSE);\r
                }\r
                conf->suspended = FALSE;\r
        }\r
@@ -1919,7 +2176,7 @@ dhd_conf_get_disable_proptx(dhd_pub_t *dhd)
 #endif\r
 \r
 uint\r
-pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf)\r
+pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf, int picklen)\r
 {\r
        bool findNewline, changenewline=FALSE, pick=FALSE;\r
        int column;\r
@@ -1972,6 +2229,8 @@ pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf)
                if (pick) {\r
                        if (varbuf[n] == 0x9)\r
                                continue;\r
+                       if (pick_column >= picklen)\r
+                               break;\r
                        pickbuf[pick_column] = varbuf[n];\r
                        pick_column++;\r
                }\r
@@ -2017,6 +2276,10 @@ dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param)
                dhd_msg_level = (int)simple_strtol(data, NULL, 0);\r
                CONFIG_MSG("dhd_msg_level = 0x%X\n", dhd_msg_level);\r
        }\r
+       else if (!strncmp("dump_msg_level=", full_param, len_param)) {\r
+               dump_msg_level = (int)simple_strtol(data, NULL, 0);\r
+               CONFIG_MSG("dump_msg_level = 0x%X\n", dump_msg_level);\r
+       }\r
 #ifdef BCMSDIO\r
        else if (!strncmp("sd_msglevel=", full_param, len_param)) {\r
                sd_msglevel = (int)simple_strtol(data, NULL, 0);\r
@@ -2162,6 +2425,7 @@ dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)
         */\r
 \r
        if (!strncmp("fw_by_mac=", full_param, len_param)) {\r
+               dhd_conf_free_mac_list(&conf->fw_by_mac);\r
                pick_tmp = data;\r
                pch = bcmstrtok(&pick_tmp, " ", 0);\r
                conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
@@ -2218,6 +2482,7 @@ dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)
         * [nv_by_mac]: The same format as fw_by_mac\r
         */\r
        if (!strncmp("nv_by_mac=", full_param, len_param)) {\r
+               dhd_conf_free_mac_list(&conf->nv_by_mac);\r
                pick_tmp = data;\r
                pch = bcmstrtok(&pick_tmp, " ", 0);\r
                conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
@@ -2277,6 +2542,7 @@ dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param)
         *  43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \\r
         */\r
        if (!strncmp("nv_by_chip=", full_param, len_param)) {\r
+               dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
                pick_tmp = data;\r
                pch = bcmstrtok(&pick_tmp, " ", 0);\r
                conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);\r
@@ -2346,14 +2612,13 @@ dhd_conf_read_roam_params(dhd_pub_t *dhd, char *full_param, uint len_param)
 }\r
 \r
 bool\r
-dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)\r
+dhd_conf_read_country(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
        struct dhd_conf *conf = dhd->conf;\r
-       conf_country_list_t *country_list = &conf->country_list;\r
+       country_list_t *country_next = NULL, *country;\r
        int i, count = 0;\r
        char *pch, *pick_tmp, *pick_tmp2;\r
        char *data = full_param+len_param;\r
-       wl_country_t *cspec;\r
        uint len_data = strlen(data);\r
 \r
        /* Process country_list:\r
@@ -2373,6 +2638,7 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)
                CONFIG_MSG("regrev = %d\n", conf->cspec.rev);\r
        }\r
        else if (!strncmp("country_list=", full_param, len_param)) {\r
+               dhd_conf_free_country_list(conf);\r
                pick_tmp = data;\r
                for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
                        pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);\r
@@ -2381,30 +2647,36 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)
                        pch = bcmstrtok(&pick_tmp2, ":", 0);\r
                        if (!pch)\r
                                break;\r
-                       cspec = NULL;\r
-                       if (!(cspec = kmalloc(sizeof(wl_country_t), GFP_KERNEL))) {\r
+                       country = NULL;\r
+                       if (!(country = kmalloc(sizeof(country_list_t), GFP_KERNEL))) {\r
                                CONFIG_ERROR("kmalloc failed\n");\r
                                break;\r
                        }\r
-                       memset(cspec, 0, sizeof(wl_country_t));\r
+                       memset(country, 0, sizeof(country_list_t));\r
 \r
-                       strcpy(cspec->country_abbrev, pch);\r
+                       memcpy(country->cspec.country_abbrev, pch, 2);\r
                        pch = bcmstrtok(&pick_tmp2, "/", 0);\r
                        if (!pch) {\r
-                               kfree(cspec);\r
+                               kfree(country);\r
                                break;\r
                        }\r
-                       memcpy(cspec->ccode, pch, 2);\r
+                       memcpy(country->cspec.ccode, pch, 2);\r
                        pch = bcmstrtok(&pick_tmp2, "/", 0);\r
                        if (!pch) {\r
-                               kfree(cspec);\r
+                               kfree(country);\r
                                break;\r
                        }\r
-                       cspec->rev = (int32)simple_strtol(pch, NULL, 10);\r
+                       country->cspec.rev = (int32)simple_strtol(pch, NULL, 10);\r
                        count++;\r
-                       country_list->cspec[i] = cspec;\r
-                       CONFIG_TRACE("country_list abbrev=%s, ccode=%s, regrev=%d\n",\r
-                               cspec->country_abbrev, cspec->ccode, cspec->rev);\r
+                       if (!conf->country_head) {\r
+                               conf->country_head = country;\r
+                               country_next = country;\r
+                       } else {\r
+                               country_next->next = country;\r
+                               country_next = country;\r
+                       }\r
+                       CONFIG_TRACE("abbrev=%s, ccode=%s, regrev=%d\n",\r
+                               country->cspec.country_abbrev, country->cspec.ccode, country->cspec.rev);\r
                }\r
                CONFIG_MSG("%d country in list\n", count);\r
        }\r
@@ -2420,6 +2692,7 @@ dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param)
        int i;\r
        char *pch, *pick_tmp, *pick_tmp2;\r
        struct dhd_conf *conf = dhd->conf;\r
+       mchan_params_t *mchan_next = NULL, *mchan;\r
        char *data = full_param+len_param;\r
 \r
        /* Process mchan_bw:\r
@@ -2427,51 +2700,65 @@ dhd_conf_read_mchan_params(dhd_pub_t *dhd, char *full_param, uint len_param)
         * Ex: mchan_bw=80/go/source, 30/gc/sink\r
         */\r
        if (!strncmp("mchan_bw=", full_param, len_param)) {\r
+               dhd_conf_free_mchan_list(conf);\r
                pick_tmp = data;\r
                for (i=0; i<MCHAN_MAX_NUM; i++) {\r
                        pick_tmp2 = bcmstrtok(&pick_tmp, ", ", 0);\r
                        if (!pick_tmp2)\r
                                break;\r
                        pch = bcmstrtok(&pick_tmp2, "/", 0);\r
-                       if (!pch) {\r
+                       if (!pch)\r
+                               break;\r
+\r
+                       mchan = NULL;\r
+                       if (!(mchan = kmalloc(sizeof(mchan_params_t), GFP_KERNEL))) {\r
+                               CONFIG_ERROR("kmalloc failed\n");\r
                                break;\r
-                       } else {\r
-                               conf->mchan[i].bw = (int)simple_strtol(pch, NULL, 0);\r
-                               if (conf->mchan[i].bw < 0 || conf->mchan[i].bw > 100) {\r
-                                       CONFIG_ERROR("wrong bw %d\n", conf->mchan[i].bw);\r
-                                       conf->mchan[i].bw = 0;\r
-                                       break;\r
-                               }\r
                        }\r
+                       memset(mchan, 0, sizeof(mchan_params_t));\r
+\r
+                       mchan->bw = (int)simple_strtol(pch, NULL, 0);\r
+                       if (mchan->bw < 0 || mchan->bw > 100) {\r
+                               CONFIG_ERROR("wrong bw %d\n", mchan->bw);\r
+                               kfree(mchan);\r
+                               break;\r
+                       }\r
+\r
                        pch = bcmstrtok(&pick_tmp2, "/", 0);\r
                        if (!pch) {\r
+                               kfree(mchan);\r
                                break;\r
                        } else {\r
                                if (bcmstrstr(pch, "any")) {\r
-                                       conf->mchan[i].p2p_mode = -1;\r
+                                       mchan->p2p_mode = -1;\r
                                } else if (bcmstrstr(pch, "go")) {\r
-                                       conf->mchan[i].p2p_mode = WL_P2P_IF_GO;\r
+                                       mchan->p2p_mode = WL_P2P_IF_GO;\r
                                } else if (bcmstrstr(pch, "gc")) {\r
-                                       conf->mchan[i].p2p_mode = WL_P2P_IF_CLIENT;\r
+                                       mchan->p2p_mode = WL_P2P_IF_CLIENT;\r
                                }\r
                        }\r
                        pch = bcmstrtok(&pick_tmp2, "/", 0);\r
                        if (!pch) {\r
+                               kfree(mchan);\r
                                break;\r
                        } else {\r
                                if (bcmstrstr(pch, "any")) {\r
-                                       conf->mchan[i].miracast_mode = -1;\r
+                                       mchan->miracast_mode = -1;\r
                                } else if (bcmstrstr(pch, "source")) {\r
-                                       conf->mchan[i].miracast_mode = MIRACAST_SOURCE;\r
+                                       mchan->miracast_mode = MIRACAST_SOURCE;\r
                                } else if (bcmstrstr(pch, "sink")) {\r
-                                       conf->mchan[i].miracast_mode = MIRACAST_SINK;\r
+                                       mchan->miracast_mode = MIRACAST_SINK;\r
                                }\r
                        }\r
-               }\r
-               for (i=0; i<MCHAN_MAX_NUM; i++) {\r
-                       if (conf->mchan[i].bw >= 0)\r
-                               CONFIG_MSG("mchan_bw=%d/%d/%d\n", conf->mchan[i].bw,\r
-                                       conf->mchan[i].p2p_mode, conf->mchan[i].miracast_mode);\r
+                       if (!conf->mchan) {\r
+                               conf->mchan = mchan;\r
+                               mchan_next = mchan;\r
+                       } else {\r
+                               mchan_next->next = mchan;\r
+                               mchan_next = mchan;\r
+                       }\r
+                       CONFIG_TRACE("mchan_bw=%d/%d/%d\n", mchan->bw,mchan->p2p_mode,\r
+                               mchan->miracast_mode);\r
                }\r
        }\r
        else\r
@@ -2531,6 +2818,10 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param)
                printf("\n");\r
        }\r
        else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) {\r
+               if (conf->magic_pkt_filter_add) {\r
+                       kfree(conf->magic_pkt_filter_add);\r
+                       conf->magic_pkt_filter_add = NULL;\r
+               }\r
                if (!(conf->magic_pkt_filter_add = kmalloc(MAGIC_PKT_FILTER_LEN, GFP_KERNEL))) {\r
                        CONFIG_ERROR("kmalloc failed\n");\r
                } else {\r
@@ -2806,6 +3097,12 @@ dhd_conf_read_pm_params(dhd_pub_t *dhd, char *full_param, uint len_param)
                conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10);\r
                CONFIG_MSG("pm_in_suspend = %d\n", conf->pm_in_suspend);\r
        }\r
+       else if (!strncmp("suspend_mode=", full_param, len_param)) {\r
+               conf->suspend_mode = (int)simple_strtol(data, NULL, 0);\r
+               CONFIG_MSG("suspend_mode = %d\n", conf->suspend_mode);\r
+               if (conf->suspend_mode == PM_NOTIFIER)\r
+                       conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);\r
+       }\r
        else if (!strncmp("suspend_bcn_li_dtim=", full_param, len_param)) {\r
                conf->suspend_bcn_li_dtim = (int)simple_strtol(data, NULL, 10);\r
                CONFIG_MSG("suspend_bcn_li_dtim = %d\n", conf->suspend_bcn_li_dtim);\r
@@ -2992,6 +3289,10 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
                CONFIG_MSG("in4way = 0x%x\n", conf->in4way);\r
        }\r
        else if (!strncmp("wl_preinit=", full_param, len_param)) {\r
+               if (conf->wl_preinit) {\r
+                       kfree(conf->wl_preinit);\r
+                       conf->wl_preinit = NULL;\r
+               }\r
                if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) {\r
                        CONFIG_ERROR("kmalloc failed\n");\r
                } else {\r
@@ -3000,6 +3301,32 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
                        CONFIG_MSG("wl_preinit = %s\n", conf->wl_preinit);\r
                }\r
        }\r
+       else if (!strncmp("wl_suspend=", full_param, len_param)) {\r
+               if (conf->wl_suspend) {\r
+                       kfree(conf->wl_suspend);\r
+                       conf->wl_suspend = NULL;\r
+               }\r
+               if (!(conf->wl_suspend = kmalloc(len_param+1, GFP_KERNEL))) {\r
+                       CONFIG_ERROR("kmalloc failed\n");\r
+               } else {\r
+                       memset(conf->wl_suspend, 0, len_param+1);\r
+                       strcpy(conf->wl_suspend, data);\r
+                       CONFIG_MSG("wl_suspend = %s\n", conf->wl_suspend);\r
+               }\r
+       }\r
+       else if (!strncmp("wl_resume=", full_param, len_param)) {\r
+               if (conf->wl_resume) {\r
+                       kfree(conf->wl_resume);\r
+                       conf->wl_resume = NULL;\r
+               }\r
+               if (!(conf->wl_resume = kmalloc(len_param+1, GFP_KERNEL))) {\r
+                       CONFIG_ERROR("kmalloc failed\n");\r
+               } else {\r
+                       memset(conf->wl_resume, 0, len_param+1);\r
+                       strcpy(conf->wl_resume, data);\r
+                       CONFIG_MSG("wl_resume = %s\n", conf->wl_resume);\r
+               }\r
+       }\r
 #ifdef GET_CUSTOM_MAC_FROM_CONFIG\r
        else if (!strncmp("mac=", full_param, len_param)) {\r
                if (!bcm_ether_atoe(data, &ea_addr)) {\r
@@ -3024,6 +3351,16 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
                        }\r
                }\r
        }\r
+#endif\r
+#ifdef PROPTX_MAXCOUNT\r
+       else if (!strncmp("proptx_maxcnt_2g=", full_param, len_param)) {\r
+               conf->proptx_maxcnt_2g = (int)simple_strtol(data, NULL, 0);\r
+               CONFIG_MSG("proptx_maxcnt_2g = 0x%x\n", conf->proptx_maxcnt_2g);\r
+       }\r
+       else if (!strncmp("proptx_maxcnt_5g=", full_param, len_param)) {\r
+               conf->proptx_maxcnt_5g = (int)simple_strtol(data, NULL, 0);\r
+               CONFIG_MSG("proptx_maxcnt_5g = 0x%x\n", conf->proptx_maxcnt_5g);\r
+       }\r
 #endif\r
        else\r
                return false;\r
@@ -3035,16 +3372,16 @@ int
 dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)\r
 {\r
        int bcmerror = -1, chip_match = -1;\r
-       uint len = 0, start_pos=0;\r
-       void * image = NULL;\r
-       char * memblock = NULL;\r
+       uint len = 0, start_pos=0, end_pos=0;\r
+       void *image = NULL;\r
+       char *memblock = NULL;\r
        char *bufp, *pick = NULL, *pch;\r
        bool conf_file_exists;\r
        uint len_param;\r
 \r
        conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));\r
        if (!conf_file_exists) {\r
-               printf("%s: config path %s\n", __FUNCTION__, conf_path);\r
+               CONFIG_MSG("config path %s\n", conf_path);\r
                return (0);\r
        }\r
 \r
@@ -3078,7 +3415,10 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
 \r
                while (start_pos < len) {\r
                        memset(pick, 0, MAXSZ_BUF);\r
-                       start_pos = pick_config_vars(bufp, len, start_pos, pick);\r
+                       end_pos = pick_config_vars(bufp, len, start_pos, pick, MAXSZ_BUF);\r
+                       if (end_pos - start_pos >= MAXSZ_BUF)\r
+                               CONFIG_ERROR("out of buf to read MAXSIZ_BUF=%d\n", MAXSZ_BUF);\r
+                       start_pos = end_pos;\r
                        pch = strchr(pick, '=');\r
                        if (pch != NULL) {\r
                                len_param = pch-pick+1;\r
@@ -3109,7 +3449,7 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
 #endif\r
                        else if (dhd_conf_read_nv_by_chip(dhd, pick, len_param))\r
                                continue;\r
-                       else if (dhd_conf_read_country_list(dhd, pick, len_param))\r
+                       else if (dhd_conf_read_country(dhd, pick, len_param))\r
                                continue;\r
                        else if (dhd_conf_read_mchan_params(dhd, pick, len_param))\r
                                continue;\r
@@ -3226,99 +3566,15 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable)
 }\r
 #endif\r
 \r
-static int\r
-dhd_conf_rsdb_mode(dhd_pub_t *dhd, char *buf)\r
-{\r
-       char *pch;\r
-       wl_config_t rsdb_mode_cfg = {1, 0};\r
-\r
-       pch = buf;\r
-       rsdb_mode_cfg.config = (int)simple_strtol(pch, NULL, 0);\r
-\r
-       if (pch) {\r
-               dhd_conf_set_bufiovar(dhd, 0, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,\r
-                       sizeof(rsdb_mode_cfg), TRUE);\r
-               CONFIG_MSG("rsdb_mode %d\n", rsdb_mode_cfg.config);\r
-       }\r
-\r
-       return 0;\r
-}\r
-\r
-typedef int (tpl_parse_t)(dhd_pub_t *dhd, char *buf);\r
-\r
-typedef struct iovar_tpl_t {\r
-       int cmd;\r
-       char *name;\r
-       tpl_parse_t *parse;\r
-} iovar_tpl_t;\r
-\r
-const iovar_tpl_t iovar_tpl_list[] = {\r
-       {WLC_SET_VAR,   "rsdb_mode",    dhd_conf_rsdb_mode},\r
-};\r
-\r
-static int iovar_tpl_parse(const iovar_tpl_t *tpl, int tpl_count,\r
-       dhd_pub_t *dhd, int cmd, char *name, char *buf)\r
-{\r
-       int i, ret = 0;\r
-\r
-       /* look for a matching code in the table */\r
-       for (i = 0; i < tpl_count; i++, tpl++) {\r
-               if (tpl->cmd == cmd && !strcmp(tpl->name, name))\r
-                       break;\r
-       }\r
-       if (i < tpl_count && tpl->parse) {\r
-               ret = tpl->parse(dhd, buf);\r
-       } else {\r
-               ret = -1;\r
-       }\r
-\r
-       return ret;\r
-}\r
-\r
-bool\r
-dhd_conf_set_wl_preinit(dhd_pub_t *dhd, char *data)\r
-{\r
-       int cmd, val, ret = 0;\r
-       char name[32], *pch, *pick_tmp, *pick_tmp2;\r
-\r
-       /* Process wl_preinit:\r
-        * wl_preinit=[cmd]=[val], [cmd]=[val]\r
-        * Ex: wl_preinit=86=0, mpc=0\r
-        */\r
-       pick_tmp = data;\r
-       while (pick_tmp && (pick_tmp2 = bcmstrtok(&pick_tmp, ",", 0)) != NULL) {\r
-               pch = bcmstrtok(&pick_tmp2, "=", 0);\r
-               if (!pch)\r
-                       break;\r
-               if (*pch == ' ') {\r
-                       pch++;\r
-               }\r
-               memset(name, 0 , sizeof (name));\r
-               cmd = (int)simple_strtol(pch, NULL, 0);\r
-               if (cmd == 0) {\r
-                       cmd = WLC_SET_VAR;\r
-                       strcpy(name, pch);\r
-               }\r
-               pch = bcmstrtok(&pick_tmp2, ",", 0);\r
-               if (!pch) {\r
-                       break;\r
-               }\r
-               ret = iovar_tpl_parse(iovar_tpl_list, ARRAY_SIZE(iovar_tpl_list),\r
-                       dhd, cmd, name, pch);\r
-               if (ret) {\r
-                       val = (int)simple_strtol(pch, NULL, 0);\r
-                       dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE);\r
-               }\r
-       }\r
-\r
-       return true;\r
-}\r
-\r
 void\r
 dhd_conf_postinit_ioctls(dhd_pub_t *dhd)\r
 {\r
        struct dhd_conf *conf = dhd->conf;\r
-       char wl_preinit[] = "assoc_retry_max=30";\r
+       char wl_preinit[] = "assoc_retry_max=20";\r
+#ifdef NO_POWER_SAVE\r
+       char wl_no_power_save[] = "mpc=0, 86=0";\r
+       dhd_conf_set_wl_cmd(dhd, wl_no_power_save, FALSE);\r
+#endif\r
 \r
        dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE);\r
        dhd_conf_map_country_list(dhd, &conf->cspec);\r
@@ -3358,25 +3614,26 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd)
        dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG",\r
                conf->frameburst, 0, FALSE);\r
 \r
-       dhd_conf_set_wl_preinit(dhd, wl_preinit);\r
+       dhd_conf_set_wl_cmd(dhd, wl_preinit, TRUE);\r
 #if defined(BCMSDIO)\r
        {\r
                char ampdu_mpdu[] = "ampdu_mpdu=16";\r
-               dhd_conf_set_wl_preinit(dhd, ampdu_mpdu);\r
+               dhd_conf_set_wl_cmd(dhd, ampdu_mpdu, TRUE);\r
        }\r
 #endif\r
        if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
                        conf->chip == BCM4371_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||\r
-                       conf->chip == BCM43569_CHIP_ID) {\r
+                       conf->chip == BCM43569_CHIP_ID ||\r
+                       conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) {\r
                dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", 1, 0, FALSE);\r
        }\r
 #if defined(WLEASYMESH)\r
        {\r
                char ezmesh[] = "mbss=1, rsdb_mode=0";\r
-               dhd_conf_set_wl_preinit(dhd, ezmesh);\r
+               dhd_conf_set_wl_cmd(dhd, ezmesh, TRUE);\r
        }\r
 #endif\r
-       dhd_conf_set_wl_preinit(dhd, conf->wl_preinit);\r
+       dhd_conf_set_wl_cmd(dhd, conf->wl_preinit, TRUE);\r
 \r
 #ifndef WL_CFG80211\r
        dhd_conf_set_intiovar(dhd, WLC_UP, "WLC_UP", 0, 0, FALSE);\r
@@ -3388,16 +3645,16 @@ int
 dhd_conf_preinit(dhd_pub_t *dhd)\r
 {\r
        struct dhd_conf *conf = dhd->conf;\r
-       int i;\r
 \r
        CONFIG_TRACE("Enter\n");\r
 \r
 #ifdef BCMSDIO\r
        dhd_conf_free_mac_list(&conf->fw_by_mac);\r
        dhd_conf_free_mac_list(&conf->nv_by_mac);\r
-       dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
 #endif\r
-       dhd_conf_free_country_list(&conf->country_list);\r
+       dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
+       dhd_conf_free_country_list(conf);\r
+       dhd_conf_free_mchan_list(conf);\r
        if (conf->magic_pkt_filter_add) {\r
                kfree(conf->magic_pkt_filter_add);\r
                conf->magic_pkt_filter_add = NULL;\r
@@ -3406,7 +3663,14 @@ dhd_conf_preinit(dhd_pub_t *dhd)
                kfree(conf->wl_preinit);\r
                conf->wl_preinit = NULL;\r
        }\r
-       memset(&conf->country_list, 0, sizeof(conf_country_list_t));\r
+       if (conf->wl_suspend) {\r
+               kfree(conf->wl_suspend);\r
+               conf->wl_suspend = NULL;\r
+       }\r
+       if (conf->wl_resume) {\r
+               kfree(conf->wl_resume);\r
+               conf->wl_resume = NULL;\r
+       }\r
        conf->band = -1;\r
        memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));\r
        if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {\r
@@ -3416,8 +3680,7 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        } else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||\r
                        conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
                        conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
-                       conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID ||\r
-                       conf->chip == BCM4362_CHIP_ID || conf->chip == BCM43751_CHIP_ID) {\r
+                       conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID) {\r
                strcpy(conf->cspec.country_abbrev, "CN");\r
                strcpy(conf->cspec.ccode, "CN");\r
                conf->cspec.rev = 38;\r
@@ -3482,14 +3745,16 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->deepsleep = FALSE;\r
        conf->pm = -1;\r
        conf->pm_in_suspend = -1;\r
+       conf->insuspend = 0;\r
+       conf->suspend_mode = EARLY_SUSPEND;\r
        conf->suspend_bcn_li_dtim = -1;\r
 #ifdef WL_EXT_WOWL\r
        dhd_master_mode = TRUE;\r
        conf->wowl = WL_WOWL_NET|WL_WOWL_DIS|WL_WOWL_BCN;\r
-       conf->insuspend = WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND;\r
-#else\r
-       conf->insuspend = 0;\r
+       conf->insuspend |= (WOWL_IN_SUSPEND | NO_TXDATA_IN_SUSPEND);\r
 #endif\r
+       if (conf->suspend_mode == PM_NOTIFIER)\r
+               conf->insuspend |= (NO_TXDATA_IN_SUSPEND | NO_TXCTL_IN_SUSPEND);\r
        conf->suspended = FALSE;\r
 #ifdef SUSPEND_EVENT\r
        memset(&conf->resume_eventmask, 0, sizeof(conf->resume_eventmask));\r
@@ -3518,15 +3783,16 @@ dhd_conf_preinit(dhd_pub_t *dhd)
 #endif\r
        conf->pktprio8021x = -1;\r
        conf->ctrl_resched = 2;\r
-       conf->in4way = NO_SCAN_IN4WAY | WAIT_DISCONNECTED;\r
+       conf->in4way = NO_SCAN_IN4WAY | DONT_DELETE_GC_AFTER_WPS | WAIT_DISCONNECTED;\r
+#ifdef PROPTX_MAXCOUNT\r
+       conf->proptx_maxcnt_2g = 46;\r
+       conf->proptx_maxcnt_5g = WL_TXSTATUS_FREERUNCTR_MASK;\r
+#endif /* DYNAMIC_PROPTX_MAXCOUNT */\r
 #ifdef ISAM_PREINIT\r
        memset(conf->isam_init, 0, sizeof(conf->isam_init));\r
        memset(conf->isam_config, 0, sizeof(conf->isam_config));\r
        memset(conf->isam_enable, 0, sizeof(conf->isam_enable));\r
 #endif\r
-       for (i=0; i<MCHAN_MAX_NUM; i++) {\r
-               memset(&conf->mchan[i], -1, sizeof(mchan_params_t));\r
-       }\r
 #ifdef CUSTOMER_HW_AMLOGIC\r
        dhd_slpauto = FALSE;\r
 #ifdef BCMSDIO\r
@@ -3539,8 +3805,8 @@ dhd_conf_preinit(dhd_pub_t *dhd)
                        conf->chip == BCM43454_CHIP_ID || conf->chip == BCM4345_CHIP_ID ||\r
                        conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
                        conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
-                       conf->chip == BCM4359_CHIP_ID || conf->chip == BCM43751_CHIP_ID || \r
-                       conf->chip == BCM43752_CHIP_ID) {\r
+                       conf->chip == BCM4359_CHIP_ID ||\r
+                       conf->chip == BCM43751_CHIP_ID || conf->chip == BCM43752_CHIP_ID) {\r
                conf->intr_extn = TRUE;\r
        }\r
 #endif\r
@@ -3595,6 +3861,7 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)\r
                conf->txglomsize = SDPCM_MAXGLOM_SIZE;\r
 #endif\r
+       init_waitqueue_head(&conf->event_complete);\r
 \r
        return 0;\r
 }\r
@@ -3602,21 +3869,32 @@ dhd_conf_preinit(dhd_pub_t *dhd)
 int\r
 dhd_conf_reset(dhd_pub_t *dhd)\r
 {\r
+       struct dhd_conf *conf = dhd->conf;\r
+\r
 #ifdef BCMSDIO\r
-       dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
-       dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
-       dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
+       dhd_conf_free_mac_list(&conf->fw_by_mac);\r
+       dhd_conf_free_mac_list(&conf->nv_by_mac);\r
 #endif\r
-       dhd_conf_free_country_list(&dhd->conf->country_list);\r
-       if (dhd->conf->magic_pkt_filter_add) {\r
-               kfree(dhd->conf->magic_pkt_filter_add);\r
-               dhd->conf->magic_pkt_filter_add = NULL;\r
+       dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
+       dhd_conf_free_country_list(conf);\r
+       dhd_conf_free_mchan_list(conf);\r
+       if (conf->magic_pkt_filter_add) {\r
+               kfree(conf->magic_pkt_filter_add);\r
+               conf->magic_pkt_filter_add = NULL;\r
        }\r
-       if (dhd->conf->wl_preinit) {\r
-               kfree(dhd->conf->wl_preinit);\r
-               dhd->conf->wl_preinit = NULL;\r
+       if (conf->wl_preinit) {\r
+               kfree(conf->wl_preinit);\r
+               conf->wl_preinit = NULL;\r
        }\r
-       memset(dhd->conf, 0, sizeof(dhd_conf_t));\r
+       if (conf->wl_suspend) {\r
+               kfree(conf->wl_suspend);\r
+               conf->wl_suspend = NULL;\r
+       }\r
+       if (conf->wl_resume) {\r
+               kfree(conf->wl_resume);\r
+               conf->wl_resume = NULL;\r
+       }\r
+       memset(conf, 0, sizeof(dhd_conf_t));\r
        return 0;\r
 }\r
 \r
@@ -3651,24 +3929,34 @@ fail:
 void\r
 dhd_conf_detach(dhd_pub_t *dhd)\r
 {\r
-       CONFIG_TRACE("Enter\n");\r
+       struct dhd_conf *conf = dhd->conf;\r
 \r
+       CONFIG_TRACE("Enter\n");\r
        if (dhd->conf) {\r
 #ifdef BCMSDIO\r
-               dhd_conf_free_mac_list(&dhd->conf->fw_by_mac);\r
-               dhd_conf_free_mac_list(&dhd->conf->nv_by_mac);\r
-               dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
+               dhd_conf_free_mac_list(&conf->fw_by_mac);\r
+               dhd_conf_free_mac_list(&conf->nv_by_mac);\r
 #endif\r
-               dhd_conf_free_country_list(&dhd->conf->country_list);\r
-               if (dhd->conf->magic_pkt_filter_add) {\r
-                       kfree(dhd->conf->magic_pkt_filter_add);\r
-                       dhd->conf->magic_pkt_filter_add = NULL;\r
+               dhd_conf_free_chip_nv_path_list(&conf->nv_by_chip);\r
+               dhd_conf_free_country_list(conf);\r
+               dhd_conf_free_mchan_list(conf);\r
+               if (conf->magic_pkt_filter_add) {\r
+                       kfree(conf->magic_pkt_filter_add);\r
+                       conf->magic_pkt_filter_add = NULL;\r
                }\r
-               if (dhd->conf->wl_preinit) {\r
-                       kfree(dhd->conf->wl_preinit);\r
-                       dhd->conf->wl_preinit = NULL;\r
+               if (conf->wl_preinit) {\r
+                       kfree(conf->wl_preinit);\r
+                       conf->wl_preinit = NULL;\r
                }\r
-               MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));\r
+               if (conf->wl_suspend) {\r
+                       kfree(conf->wl_suspend);\r
+                       conf->wl_suspend = NULL;\r
+               }\r
+               if (conf->wl_resume) {\r
+                       kfree(conf->wl_resume);\r
+                       conf->wl_resume = NULL;\r
+               }\r
+               MFREE(dhd->osh, conf, sizeof(dhd_conf_t));\r
        }\r
        dhd->conf = NULL;\r
 }\r
index 79021711de65b3f44764df97f2f97f52ccd15a03..cdd76c42ab4c0ba468edb924c9d61d3d6a2e8c56 100644 (file)
@@ -86,16 +86,18 @@ typedef struct conf_pkt_filter_del {
 } conf_pkt_filter_del_t;
 #endif
 
-#define CONFIG_COUNTRY_LIST_SIZE 100
-typedef struct conf_country_list {
-       wl_country_t *cspec[CONFIG_COUNTRY_LIST_SIZE];
-} conf_country_list_t;
+#define CONFIG_COUNTRY_LIST_SIZE 500
+typedef struct country_list {
+       struct country_list *next;
+       wl_country_t cspec;
+} country_list_t;
 
 /* mchan_params */
 #define MCHAN_MAX_NUM 4
 #define MIRACAST_SOURCE        1
 #define MIRACAST_SINK  2
 typedef struct mchan_params {
+       struct mchan_params *next;
        int bw;
        int p2p_mode;
        int miracast_mode;
@@ -119,6 +121,11 @@ enum in_suspend_flags {
        ALL_IN_SUSPEND                  = 0xFFFFFFFF,
 };
 
+enum in_suspend_mode {
+       EARLY_SUSPEND = 0,
+       PM_NOTIFIER = 1
+};
+
 enum eapol_status {
        EAPOL_STATUS_NONE = 0,
        EAPOL_STATUS_REQID = 1,
@@ -146,13 +153,17 @@ enum eapol_status {
 typedef struct dhd_conf {
        uint chip;
        uint chiprev;
+#ifdef GET_OTP_MODULE_NAME
+       char module_name[16];
+#endif
+       struct ether_addr otp_mac;
        int fw_type;
 #ifdef BCMSDIO
        wl_mac_list_ctrl_t fw_by_mac;
        wl_mac_list_ctrl_t nv_by_mac;
 #endif
        wl_chip_nv_path_list_ctrl_t nv_by_chip;
-       conf_country_list_t country_list;
+       country_list_t *country_head;
        int band;
        int bw_cap[2];
        wl_country_t cspec;
@@ -218,6 +229,7 @@ typedef struct dhd_conf {
        bool deepsleep;
        int pm;
        int pm_in_suspend;
+       int suspend_mode;
        int suspend_bcn_li_dtim;
 #ifdef DHDTCPACK_SUPPRESS
        uint8 tcpack_sup_mode;
@@ -244,8 +256,10 @@ typedef struct dhd_conf {
        char isam_enable[50];
 #endif
        int ctrl_resched;
-       struct mchan_params mchan[MCHAN_MAX_NUM];
+       mchan_params_t *mchan;
        char *wl_preinit;
+       char *wl_suspend;
+       char *wl_resume;
        int tsq;
        int orphan_move;
        uint eapol_status;
@@ -256,24 +270,30 @@ typedef struct dhd_conf {
 #ifdef GET_CUSTOM_MAC_FROM_CONFIG
        char hw_ether[62];
 #endif
+       wait_queue_head_t event_complete;
+#ifdef PROPTX_MAXCOUNT
+       int proptx_maxcnt_2g;
+       int proptx_maxcnt_5g;
+#endif /* DYNAMIC_PROPTX_MAXCOUNT */
 } dhd_conf_t;
 
 #ifdef BCMSDIO
-int dhd_conf_get_mac(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih, uint8 *mac);
+void dhd_conf_get_otp(dhd_pub_t *dhd, bcmsdh_info_t *sdh, si_t *sih);
 #if defined(HW_OOB) || defined(FORCE_WOWLAN)
 void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, struct si_pub *sih);
 #endif
 void dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable);
-int dhd_conf_set_blksize(bcmsdh_info_t *sdh);
 #endif
-void dhd_conf_set_path_params(dhd_pub_t *dhd, void *sdh, void *sih,
-       char *fw_path, char *nv_path);
+void dhd_conf_set_path_params(dhd_pub_t *dhd, char *fw_path, char *nv_path);
 int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val,
        int def, bool down);
 int dhd_conf_get_band(dhd_pub_t *dhd);
 int dhd_conf_set_country(dhd_pub_t *dhd, wl_country_t *cspec);
 int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec);
 int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec);
+#ifdef CCODE_LIST
+int dhd_ccode_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec);
+#endif
 int dhd_conf_fix_country(dhd_pub_t *dhd);
 bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel);
 void dhd_conf_set_wme(dhd_pub_t *dhd, int ifidx, int mode);
@@ -307,4 +327,7 @@ int dhd_conf_attach(dhd_pub_t *dhd);
 void dhd_conf_detach(dhd_pub_t *dhd);
 void *dhd_get_pub(struct net_device *dev);
 int wl_pattern_atoh(char *src, char *dst);
+#ifdef BCMSDIO
+extern int dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus);
+#endif
 #endif /* _dhd_config_ */
diff --git a/bcmdhd.100.10.315.x/dhd_csi.c b/bcmdhd.100.10.315.x/dhd_csi.c
new file mode 100644 (file)
index 0000000..dd1a068
--- /dev/null
@@ -0,0 +1,220 @@
+/*\r
+ * Broadcom Dongle Host Driver (DHD)\r
+ *\r
+ * Copyright (C) 1999-2018, Broadcom.\r
+ *\r
+ *      Unless you and Broadcom execute a separate written software license\r
+ * agreement governing use of this software, this software is licensed to you\r
+ * under the terms of the GNU General Public License version 2 (the "GPL"),\r
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the\r
+ * following added to such license:\r
+ *\r
+ *      As a special exception, the copyright holders of this software give you\r
+ * permission to link this software with independent modules, and to copy and\r
+ * distribute the resulting executable under terms of your choice, provided that\r
+ * you also meet, for each linked independent module, the terms and conditions of\r
+ * the license of that module.  An independent module is a module which is not\r
+ * derived from this software.  The special exception does not apply to any\r
+ * modifications of the software.\r
+ *\r
+ *      Notwithstanding the above, under no circumstances may you combine this\r
+ * software in any way with any other Broadcom software provided under a license\r
+ * other than the GPL, without Broadcom's express prior written consent.\r
+ *\r
+ * $Id: dhd_csi.c 606280 2015-12-15 05:28:25Z $\r
+ */\r
+#include <osl.h>\r
+\r
+#include <bcmutils.h>\r
+\r
+#include <bcmendian.h>\r
+#include <linuxver.h>\r
+#include <linux/list.h>\r
+#include <linux/sort.h>\r
+#include <dngl_stats.h>\r
+#include <wlioctl.h>\r
+\r
+#include <bcmevent.h>\r
+#include <dhd.h>\r
+#include <dhd_dbg.h>\r
+#include <dhd_csi.h>\r
+\r
+#define NULL_CHECK(p, s, err)  \\r
+       do { \\r
+               if (!(p)) { \\r
+                       printf("NULL POINTER (%s) : %s\n", __FUNCTION__, (s)); \\r
+                       err = BCME_ERROR; \\r
+                       return err; \\r
+               } \\r
+       } while (0)\r
+\r
+#define TIMESPEC_TO_US(ts)  (((uint64)(ts).tv_sec * USEC_PER_SEC) + \\r
+                                               (ts).tv_nsec / NSEC_PER_USEC)\r
+\r
+#define NULL_ADDR      "\x00\x00\x00\x00\x00\x00"\r
+\r
+int\r
+dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data)\r
+{\r
+       int ret = BCME_OK;\r
+       bool is_new = TRUE;\r
+       cfr_dump_data_t *p_event;\r
+       cfr_dump_list_t *ptr, *next, *new;\r
+\r
+       NULL_CHECK(dhd, "dhd is NULL", ret);\r
+\r
+       DHD_TRACE(("Enter %s\n", __FUNCTION__));\r
+\r
+       if (!event_data) {\r
+               DHD_ERROR(("%s: event_data is NULL\n", __FUNCTION__));\r
+               return -EINVAL;\r
+       }\r
+       p_event = (cfr_dump_data_t *)event_data;\r
+\r
+       /* check if this addr exist */\r
+       if (!list_empty(&dhd->csi_list)) {\r
+               list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+                       if (bcmp(&ptr->entry.header.peer_macaddr, &p_event->header.peer_macaddr,\r
+                                       ETHER_ADDR_LEN) == 0) {\r
+                               int pos = 0, dump_len = 0, remain = 0;\r
+                               is_new = FALSE;\r
+                               DHD_INFO(("CSI data exist\n"));\r
+                               if (p_event->header.status == 0) {\r
+                                       bcopy(&p_event->header, &ptr->entry.header, sizeof(cfr_dump_header_t));\r
+                                       dump_len = p_event->header.cfr_dump_length;\r
+                                       if (dump_len < MAX_EVENT_SIZE) {\r
+                                               bcopy(&p_event->data, &ptr->entry.data, dump_len);\r
+                                       } else { \r
+                                               /* for big csi data */\r
+                                               uint8 *p = (uint8 *)&ptr->entry.data;\r
+                                               remain = p_event->header.remain_length;\r
+                                               if (remain) {\r
+                                                       pos = dump_len - remain - MAX_EVENT_SIZE;\r
+                                                       p += pos;\r
+                                                       bcopy(&p_event->data, p, MAX_EVENT_SIZE);\r
+                                               }\r
+                                               /* copy rest of csi data */\r
+                                               else {\r
+                                                       pos = dump_len - (dump_len % MAX_EVENT_SIZE);\r
+                                                       p += pos;\r
+                                                       bcopy(&p_event->data, p, (dump_len % MAX_EVENT_SIZE));\r
+                                               }\r
+                                       }\r
+                                       return BCME_OK;\r
+                               }\r
+                       }\r
+               }\r
+       }\r
+       if (is_new) {\r
+               if (dhd->csi_count < MAX_CSI_NUM) {\r
+                       new = (cfr_dump_list_t *)MALLOCZ(dhd->osh, sizeof(cfr_dump_list_t));\r
+                       if (!new){\r
+                               DHD_ERROR(("Malloc cfr dump list error\n"));\r
+                               return BCME_NOMEM;\r
+                       }\r
+                       bcopy(&p_event->header, &new->entry.header, sizeof(cfr_dump_header_t));\r
+                       DHD_INFO(("New entry data size %d\n", p_event->header.cfr_dump_length));\r
+                       /* for big csi data */\r
+                       if (p_event->header.remain_length) {\r
+                               DHD_TRACE(("remain %d\n", p_event->header.remain_length));\r
+                               bcopy(&p_event->data, &new->entry.data, MAX_EVENT_SIZE);\r
+                       }\r
+                       else\r
+                               bcopy(&p_event->data, &new->entry.data, p_event->header.cfr_dump_length);\r
+                       INIT_LIST_HEAD(&(new->list));\r
+                       list_add_tail(&(new->list), &dhd->csi_list);\r
+                       dhd->csi_count++;\r
+               }\r
+               else {\r
+                       DHD_TRACE(("Over maximum CSI Number 8. SKIP it.\n"));\r
+               }\r
+       }\r
+       return ret;\r
+}\r
+\r
+int\r
+dhd_csi_init(dhd_pub_t *dhd)\r
+{\r
+       int err = BCME_OK;\r
+\r
+       NULL_CHECK(dhd, "dhd is NULL", err);\r
+       INIT_LIST_HEAD(&dhd->csi_list);\r
+       dhd->csi_count = 0;\r
+\r
+       return err;\r
+}\r
+\r
+int\r
+dhd_csi_deinit(dhd_pub_t *dhd)\r
+{\r
+       int err = BCME_OK;\r
+       cfr_dump_list_t *ptr, *next;\r
+\r
+       NULL_CHECK(dhd, "dhd is NULL", err);\r
+\r
+       if (!list_empty(&dhd->csi_list)) {\r
+               list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+                       list_del(&ptr->list);\r
+                       MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t));\r
+               }\r
+       }\r
+       return err;\r
+}\r
+\r
+void\r
+dhd_csi_clean_list(dhd_pub_t *dhd)\r
+{\r
+       cfr_dump_list_t *ptr, *next;\r
+       int num = 0;\r
+\r
+       if (!dhd) {\r
+               DHD_ERROR(("NULL POINTER: %s\n", __FUNCTION__));\r
+               return;\r
+       }\r
+\r
+       if (!list_empty(&dhd->csi_list)) {\r
+               list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+                       if (0 == ptr->entry.header.remain_length) {\r
+                               list_del(&ptr->list);\r
+                               num++;\r
+                               MFREE(dhd->osh, ptr, sizeof(cfr_dump_list_t));\r
+                       }\r
+               }\r
+       }\r
+       dhd->csi_count = 0;\r
+       DHD_TRACE(("Clean up %d record\n", num));\r
+}\r
+\r
+int\r
+dhd_csi_dump_list(dhd_pub_t *dhd, char *buf)\r
+{\r
+       int ret = BCME_OK;\r
+       cfr_dump_list_t *ptr, *next;\r
+       uint8 * pbuf = buf;\r
+       int num = 0;\r
+       int length = 0;\r
+\r
+       NULL_CHECK(dhd, "dhd is NULL", ret);\r
+\r
+       /* check if this addr exist */\r
+       if (!list_empty(&dhd->csi_list)) {\r
+               list_for_each_entry_safe(ptr, next, &dhd->csi_list, list) {\r
+                       if (ptr->entry.header.remain_length) {\r
+                               DHD_ERROR(("data not ready %d\n", ptr->entry.header.remain_length));\r
+                               continue;\r
+                       }\r
+                       bcopy(&ptr->entry.header, pbuf, sizeof(cfr_dump_header_t));\r
+                       length += sizeof(cfr_dump_header_t);\r
+                       pbuf += sizeof(cfr_dump_header_t);\r
+                       DHD_TRACE(("Copy data size %d\n", ptr->entry.header.cfr_dump_length));\r
+                       bcopy(&ptr->entry.data, pbuf, ptr->entry.header.cfr_dump_length);\r
+                       length += ptr->entry.header.cfr_dump_length;\r
+                       pbuf += ptr->entry.header.cfr_dump_length;\r
+                       num++;\r
+               }\r
+       }\r
+       DHD_TRACE(("dump %d record %d bytes\n", num, length));\r
+\r
+       return length;\r
+}\r
+\r
diff --git a/bcmdhd.100.10.315.x/dhd_csi.h b/bcmdhd.100.10.315.x/dhd_csi.h
new file mode 100644 (file)
index 0000000..bcc712c
--- /dev/null
@@ -0,0 +1,77 @@
+/*\r
+ * Broadcom Dongle Host Driver (DHD), CSI\r
+ *\r
+ * Copyright (C) 1999-2018, Broadcom.\r
+ *\r
+ *      Unless you and Broadcom execute a separate written software license\r
+ * agreement governing use of this software, this software is licensed to you\r
+ * under the terms of the GNU General Public License version 2 (the "GPL"),\r
+ * available at http://www.broadcom.com/licenses/GPLv2.php, with the\r
+ * following added to such license:\r
+ *\r
+ *      As a special exception, the copyright holders of this software give you\r
+ * permission to link this software with independent modules, and to copy and\r
+ * distribute the resulting executable under terms of your choice, provided that\r
+ * you also meet, for each linked independent module, the terms and conditions of\r
+ * the license of that module.  An independent module is a module which is not\r
+ * derived from this software.  The special exception does not apply to any\r
+ * modifications of the software.\r
+ *\r
+ *      Notwithstanding the above, under no circumstances may you combine this\r
+ * software in any way with any other Broadcom software provided under a license\r
+ * other than the GPL, without Broadcom's express prior written consent.\r
+ *\r
+ * $Id: dhd_csi.h 558438 2015-05-22 06:05:11Z $\r
+ */\r
+#ifndef __DHD_CSI_H__\r
+#define __DHD_CSI_H__\r
+\r
+/* Maxinum csi file dump size */\r
+#define MAX_CSI_FILESZ         (32 * 1024)\r
+/* Maxinum subcarrier number */\r
+#define MAXINUM_CFR_DATA       256 * 4\r
+#define CSI_DUMP_PATH          "/sys/bcm-dhd/csi"\r
+#define MAX_EVENT_SIZE         1400\r
+/* maximun csi number stored at dhd */\r
+#define MAX_CSI_NUM            8\r
+\r
+typedef struct cfr_dump_header {\r
+       /* 0 - successful; 1 - Failed */\r
+       uint8 status;\r
+       /* Peer MAC address */\r
+       uint8 peer_macaddr[6];\r
+       /* Number of Space Time Streams */\r
+       uint8 sts;\r
+       /* Number of RX chain */\r
+       uint8 num_rx;\r
+       /* Number of subcarrier */\r
+       uint16 num_carrier;\r
+       /* Length of the CSI dump */\r
+       uint32 cfr_dump_length;\r
+       /* remain unsend CSI data length */\r
+       uint32 remain_length;\r
+       /* RSSI */\r
+       int8 rssi;\r
+} __attribute__((packed)) cfr_dump_header_t;\r
+\r
+typedef struct cfr_dump_data {\r
+       cfr_dump_header_t header;\r
+       uint32 data[MAXINUM_CFR_DATA];\r
+} cfr_dump_data_t;\r
+\r
+typedef struct {\r
+       struct list_head list;\r
+       cfr_dump_data_t entry;\r
+} cfr_dump_list_t;\r
+\r
+int dhd_csi_event_handler(dhd_pub_t *dhd, wl_event_msg_t *event, void *event_data);\r
+\r
+int dhd_csi_init(dhd_pub_t *dhd);\r
+\r
+int dhd_csi_deinit(dhd_pub_t *dhd);\r
+\r
+void dhd_csi_clean_list(dhd_pub_t *dhd);\r
+\r
+int dhd_csi_dump_list(dhd_pub_t *dhd, char *buf);\r
+#endif /* __DHD_CSI_H__ */\r
+\r
index 136d2a22d895115aac51a0bcd675ead7422a42d2..f3facfd7f999c6d7e845ec8aa78474460608e1db 100644 (file)
@@ -85,7 +85,7 @@ dhd_customer_gpio_wlan_ctrl(void *adapter, int onoff)
        return err;
 }
 
-#ifdef GET_CUSTOM_MAC_ENABLE
+#if 0
 /* Function to get custom MAC address */
 int
 dhd_custom_get_mac_address(void *adapter, unsigned char *buf)
index 7b0e65d85b30cfb95a75477e24b784d6f52a4b7d..fc8fd44971179a6b5f4359983403337111ca95f1 100644 (file)
@@ -24,6 +24,7 @@ static int gpio_wl_host_wake = -1; // WL_HOST_WAKE is output pin of WLAN module
 #include <linux/amlogic/aml_gpio_consumer.h>
 extern int wifi_irq_trigger_level(void);
 extern u8 *wifi_get_mac(void);
+extern u8 *wifi_get_ap_mac(void);
 #endif
 extern  void sdio_reinit(void);
 extern void set_usb_bt_power(int is_power);
@@ -177,18 +178,45 @@ static int dhd_wlan_set_carddetect(int present)
        return err;
 }
 
-static int dhd_wlan_get_mac_addr(unsigned char *buf)
+static int dhd_wlan_get_mac_addr(unsigned char *buf
+#ifdef CUSTOM_MULTI_MAC
+       , char *name
+#endif
+)
 {
        int err = 0;
 
-       printf("======== %s ========\n", __FUNCTION__);
-#ifdef EXAMPLE_GET_MAC
-       /* EXAMPLE code */
+#ifdef CUSTOM_MULTI_MAC
+       if (!strcmp("wlan1", name)) {
+#ifdef CUSTOMER_HW_AMLOGIC
+#ifdef CUSTOM_AP_MAC
+               bcopy((char *)wifi_get_ap_mac(), buf, sizeof(struct ether_addr));
+               if (buf[0] == 0xff) {
+                       printf("custom wifi ap mac is not set\n");
+                       err = -1;
+               } else
+                       printf("custom wifi ap mac-addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                               buf[0], buf[1], buf[2],
+                               buf[3], buf[4], buf[5]);
+#else
+               err = -1;
+#endif
+#endif
+       } else
+#endif /* CUSTOM_MULTI_MAC */
        {
-               struct ether_addr ea_example = {{0x00, 0x11, 0x22, 0x33, 0x44, 0xFF}};
-               bcopy((char *)&ea_example, buf, sizeof(struct ether_addr));
+#ifdef CUSTOMER_HW_AMLOGIC
+               bcopy((char *)wifi_get_mac(), buf, sizeof(struct ether_addr));
+               if (buf[0] == 0xff) {
+                       printf("custom wifi mac is not set\n");
+                       err = -1;
+               } else
+                       printf("custom wifi mac-addr: %02x:%02x:%02x:%02x:%02x:%02x\n",
+                               buf[0], buf[1], buf[2],
+                               buf[3], buf[4], buf[5]);
+#endif
        }
-#endif /* EXAMPLE_GET_MAC */
+
 #ifdef EXAMPLE_GET_MAC_VER2
        /* EXAMPLE code */
        {
@@ -204,6 +232,8 @@ static int dhd_wlan_get_mac_addr(unsigned char *buf)
        }
 #endif /* EXAMPLE_GET_MAC_VER2 */
 
+       printf("======== %s err=%d ========\n", __FUNCTION__, err);
+
        return err;
 }
 
@@ -295,7 +325,7 @@ int dhd_wlan_init_gpio(void)
 #ifdef CUSTOMER_HW_AMLOGIC
 #if defined(BCMPCIE)
        printf("======== Card detection to detect PCIE card! ========\n");
-       pci_remove_reinit(0x14e4, 0x43ec, 1);
+       //pci_remove_reinit(0x14e4, 0x449d, 1);
 #endif
 #endif
 
index 9495648148370a3c6517dee80e5911047729174b..54fa3ca05c527b77e69595baabb80b9b459ae333 100644 (file)
 #include <dhd_rtt.h>
 #endif // endif
 
+#ifdef CSI_SUPPORT
+#include <dhd_csi.h>
+#endif /* CSI_SUPPORT */
+
 #ifdef CONFIG_COMPAT
 #include <linux/compat.h>
 #endif // endif
@@ -247,6 +251,7 @@ MODULE_LICENSE("GPL and additional rights");
 DEFINE_MUTEX(_dhd_mutex_lock_);
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
 #endif
+static int dhd_suspend_resume_helper(struct dhd_info *dhd, int val, int force);
 
 #ifdef CONFIG_BCM_DETECT_CONSECUTIVE_HANG
 #define MAX_CONSECUTIVE_HANG_COUNTS 5
@@ -874,18 +879,33 @@ static int dhd_pm_callback(struct notifier_block *nfb, unsigned long action, voi
                break;
        }
 
-#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
+       printf("%s: action=%ld, suspend=%d, suspend_mode=%d\n",
+               __FUNCTION__, action, suspend, dhdinfo->pub.conf->suspend_mode);
        if (suspend) {
                DHD_OS_WAKE_LOCK_WAIVE(&dhdinfo->pub);
+               if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+                       dhd_suspend_resume_helper(dhdinfo, suspend, 0);
+#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
                dhd_wlfc_suspend(&dhdinfo->pub);
+#endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */
+               if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+                       dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend);
                DHD_OS_WAKE_LOCK_RESTORE(&dhdinfo->pub);
        } else {
+               if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+                       dhd_conf_set_suspend_resume(&dhdinfo->pub, suspend);
+#if defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS)
                dhd_wlfc_resume(&dhdinfo->pub);
-       }
 #endif /* defined(SUPPORT_P2P_GO_PS) && defined(PROP_TXSTATUS) */
+               if (dhdinfo->pub.conf->suspend_mode == PM_NOTIFIER)
+                       dhd_suspend_resume_helper(dhdinfo, suspend, 0);
+       }
 
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (LINUX_VERSION_CODE <= \
+        KERNEL_VERSION(2, 6, 39))
        dhd_mmc_suspend = suspend;
        smp_mb();
+#endif
 
        return ret;
 }
@@ -1810,7 +1830,9 @@ dhd_packet_filter_add_remove(dhd_pub_t *dhdp, int add_remove, int num)
 
 static int dhd_set_suspend(int value, dhd_pub_t *dhd)
 {
+#ifndef SUPPORT_PM2_ONLY
        int power_mode = PM_MAX;
+#endif /* SUPPORT_PM2_ONLY */
        /* wl_pkt_filter_enable_t       enable_parm; */
        int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */
        int ret = 0;
@@ -1822,7 +1844,7 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
        int roam_time_thresh = 0;   /* (ms) */
 #endif /* CUSTOM_ROAM_TIME_THRESH_IN_SUSPEND */
 #ifndef ENABLE_FW_ROAM_SUSPEND
-       uint roamvar = dhd->conf->roam_off_suspend;
+       uint roamvar = 1;
 #endif /* ENABLE_FW_ROAM_SUSPEND */
 #ifdef ENABLE_BCN_LI_BCN_WAKEUP
        int bcn_li_bcn = 1;
@@ -1876,12 +1898,6 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
        /* set specific cpucore */
        dhd_set_cpucore(dhd, TRUE);
 #endif /* CUSTOM_SET_CPUCORE */
-
-       if (dhd->conf->pm >= 0)
-               power_mode = dhd->conf->pm;
-       else
-               power_mode = PM_FAST;
-
        if (dhd->up) {
                if (value && dhd->in_suspend) {
 #ifdef PKT_FILTER_SUPPORT
@@ -1890,10 +1906,10 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
                        /* Kernel suspended */
                        DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__));
 
-                       if (dhd->conf->pm_in_suspend >= 0)
-                               power_mode = dhd->conf->pm_in_suspend;
+#ifndef SUPPORT_PM2_ONLY
                        dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
                                sizeof(power_mode), TRUE, 0);
+#endif /* SUPPORT_PM2_ONLY */
 
 #ifdef PKT_FILTER_SUPPORT
                        /* Enable packet filter,
@@ -2110,8 +2126,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
                                DHD_ERROR(("failed to set intr_width (%d)\n", ret));
                        }
 #endif /* DYNAMIC_SWOOB_DURATION */
+#ifndef SUPPORT_PM2_ONLY
+                       power_mode = PM_FAST;
                        dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
                                sizeof(power_mode), TRUE, 0);
+#endif /* SUPPORT_PM2_ONLY */
 #if defined(WL_CFG80211) && defined(WL_BCNRECV)
                        ret = wl_android_bcnrecv_resume(dhd_linux_get_primary_netdev(dhd));
                        if (ret != BCME_OK) {
@@ -2300,8 +2319,10 @@ static void dhd_early_suspend(struct early_suspend *h)
        struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
        DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
 
-       if (dhd)
+       if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) {
                dhd_suspend_resume_helper(dhd, 1, 0);
+               dhd_conf_set_suspend_resume(&dhd->pub, 1);
+       }
 }
 
 static void dhd_late_resume(struct early_suspend *h)
@@ -2309,8 +2330,10 @@ static void dhd_late_resume(struct early_suspend *h)
        struct dhd_info *dhd = container_of(h, struct dhd_info, early_suspend);
        DHD_TRACE_HW4(("%s: enter\n", __FUNCTION__));
 
-       if (dhd)
+       if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) {
+               dhd_conf_set_suspend_resume(&dhd->pub, 0);
                dhd_suspend_resume_helper(dhd, 0, 0);
+       }
 }
 #endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */
 
@@ -3565,6 +3588,8 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
 
        bcm_object_trace_opr(skb, BCM_OBJDBG_ADD_PKT, __FUNCTION__, __LINE__);
 
+       skb_orphan(skb);
+
        /* re-align socket buffer if "skb->data" is odd address */
        if (((unsigned long)(skb->data)) & 0x1) {
                unsigned char *data = skb->data;
@@ -3824,13 +3849,13 @@ __dhd_txflowcontrol(dhd_pub_t *dhdp, struct net_device *net, bool state)
                netif_stop_queue(net);
                dhd_prot_update_pktid_txq_stop_cnt(dhdp);
        } else if (state == ON) {
-               DHD_ERROR(("%s: Netif Queue has already stopped\n", __FUNCTION__));
+               DHD_INFO(("%s: Netif Queue has already stopped\n", __FUNCTION__));
        }
        if ((state == OFF) && (dhdp->txoff == TRUE)) {
                netif_wake_queue(net);
                dhd_prot_update_pktid_txq_start_cnt(dhdp);
        } else if (state == OFF) {
-               DHD_ERROR(("%s: Netif Queue has already started\n", __FUNCTION__));
+               DHD_INFO(("%s: Netif Queue has already started\n", __FUNCTION__));
        }
 }
 
@@ -4666,7 +4691,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
                         * logtrace_pkt_sendup is true
                         */
                        if (event_type == WLC_E_TRACE) {
-                               DHD_TRACE(("%s: WLC_E_TRACE\n", __FUNCTION__));
+                               DHD_EVENT(("%s: WLC_E_TRACE\n", __FUNCTION__));
                                dhd_event_logtrace_enqueue(dhdp, ifidx, pktbuf);
                                continue;
                        }
@@ -4739,7 +4764,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan)
                                continue;
                        }
 
-                       if (dhdp->wl_event_enabled) {
+#ifdef SENDPROB
+                       if (dhdp->wl_event_enabled ||
+                               (dhdp->recv_probereq && (event.event_type == WLC_E_PROBREQ_MSG)))
+#else
+                       if (dhdp->wl_event_enabled)
+#endif
+                       {
 #ifdef DHD_USE_STATIC_CTRLBUF
                                /* If event bufs are allocated via static buf pool
                                 * and wl events are enabled, make a copy, free the
@@ -5503,8 +5534,8 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr)
                /* Copy out any request driver name */
                if (copy_from_user(&info, uaddr, sizeof(info)))
                        return -EFAULT;
-               strncpy(drvname, info.driver, sizeof(info.driver));
-               drvname[sizeof(info.driver)-1] = '\0';
+               strncpy(drvname, info.driver, sizeof(drvname) - 1);
+               drvname[sizeof(drvname) - 1] = '\0';
 
                /* clear struct for return */
                memset(&info, 0, sizeof(info));
@@ -6411,10 +6442,12 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd)
                }
        }
 
+#ifndef CONFIG_VTS_SUPPORT
        if (!capable(CAP_NET_ADMIN)) {
                bcmerror = BCME_EPERM;
                goto done;
        }
+#endif
 
        /* Take backup of ioc.buf and restore later */
        ioc_buf_user = ioc.buf;
@@ -7213,6 +7246,17 @@ dhd_pri_open(struct net_device *net)
        /* Allow transmit calls */
        netif_start_queue(net);
        DHD_ERROR(("[%s] tx queue started\n", net->name));
+
+#if defined(SET_RPS_CPUS)
+       dhd_rps_cpus_enable(net, TRUE);
+       DHD_ERROR(("[%s] RPS started\n", net->name));
+#endif
+
+#if defined(SET_XPS_CPUS)
+       dhd_xps_cpus_enable(net, TRUE);
+       DHD_ERROR(("[%s] XPS started\n", net->name));
+#endif
+
        return ret;
 }
 
@@ -8433,7 +8477,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
 #endif /* DHD_DEBUG */
 
 #ifdef GET_CUSTOM_MAC_ENABLE
-       wifi_platform_get_mac_addr(dhd->adapter, hw_ether);
+       wifi_platform_get_mac_addr(dhd->adapter, hw_ether, iface_name);
        bcopy(hw_ether, dhd->pub.mac.octet, sizeof(struct ether_addr));
 #endif /* GET_CUSTOM_MAC_ENABLE */
 #ifdef CUSTOM_FORCE_NODFS_FLAG
@@ -8492,7 +8536,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
                len = strlen(if_name);
                ch = if_name[len - 1];
                if ((ch > '9' || ch < '0') && (len < IFNAMSIZ - 2))
-                       strncat(if_name, "%d", 2);
+                       strncat(if_name, "%d", IFNAMSIZ - len - 1);
        }
 
        /* Passing NULL to dngl_name to ensure host gets if_name in dngl_name member */
@@ -8911,6 +8955,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
        dhd->dhd_state = dhd_state;
 
        dhd_found++;
+       
+#ifdef CSI_SUPPORT
+       dhd_csi_init(&dhd->pub);
+#endif /* CSI_SUPPORT */
 
 #ifdef DHD_DUMP_MNGR
        dhd->pub.dump_file_manage =
@@ -10072,7 +10120,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 
 #ifdef GET_CUSTOM_MAC_ENABLE
        memset(hw_ether, 0, sizeof(hw_ether));
-       ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether);
+       ret = wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, iface_name);
 #ifdef GET_CUSTOM_MAC_FROM_CONFIG
        if (!memcmp(&ether_null, &dhd->conf->hw_ether, ETHER_ADDR_LEN)) {
                ret = 0;
@@ -10752,6 +10800,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #ifdef WL_ESCAN
        setbit(eventmask, WLC_E_ESCAN_RESULT);
 #endif /* WL_ESCAN */
+#ifdef CSI_SUPPORT
+       setbit(eventmask, WLC_E_CSI);
+#endif /* CSI_SUPPORT */
 #ifdef RTT_SUPPORT
        setbit(eventmask, WLC_E_PROXD);
 #endif /* RTT_SUPPORT */
@@ -10774,6 +10825,8 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        setbit(eventmask, WLC_E_TRACE);
 #else
        clrbit(eventmask, WLC_E_TRACE);
+       if (dhd->conf->chip == BCM43752_CHIP_ID)
+               setbit(eventmask, WLC_E_TRACE);
 #endif /* defined(SHOW_LOGTRACE) && defined(LOGTRACE_FROM_FILE) */
 
        setbit(eventmask, WLC_E_CSA_COMPLETE_IND);
@@ -10846,6 +10899,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #ifdef WL_MBO
                setbit(eventmask_msg->mask, WLC_E_MBO);
 #endif /* WL_MBO */
+#ifdef WL_CLIENT_SAE
+               setbit(eventmask_msg->mask, WLC_E_JOIN_START);
+#endif /* WL_CLIENT_SAE */
 #ifdef WL_BCNRECV
                setbit(eventmask_msg->mask, WLC_E_BCNRECV_ABORTED);
 #endif /* WL_BCNRECV */
@@ -11005,7 +11061,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        memset(buf, 0, sizeof(buf));
        ret = dhd_iovar(dhd, 0, "clmver", NULL, 0, buf, sizeof(buf), FALSE);
        if (ret < 0)
-               DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
+               DHD_ERROR(("%s clmver failed %d\n", __FUNCTION__, ret));
        else {
                char *ver_temp_buf = NULL, *ver_date_buf = NULL;
                int len;
@@ -11045,11 +11101,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 
        /* query for 'wlc_ver' to get version info from firmware */
        memset(&wlc_ver, 0, sizeof(wl_wlc_version_t));
-       ret = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver,
+       ret2 = dhd_iovar(dhd, 0, "wlc_ver", NULL, 0, (char *)&wlc_ver,
                sizeof(wl_wlc_version_t), FALSE);
-       if (ret < 0)
-               DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
-       else {
+       if (ret2 < 0) {
+               DHD_ERROR(("%s wlc_ver failed %d\n", __FUNCTION__, ret2));
+               if (ret2 != BCME_UNSUPPORTED)
+                       ret = ret2;
+       } else {
                dhd->wlc_ver_major = wlc_ver.wlc_ver_major;
                dhd->wlc_ver_minor = wlc_ver.wlc_ver_minor;
        }
@@ -11835,17 +11893,9 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
        if (ifidx == 0)
                printf("%s\n", dhd_version);
        else {
-#if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN)
-               wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
-#ifdef WL_ESCAN
-               wl_escan_event_attach(net, dhdp);
-#endif /* WL_ESCAN */
 #ifdef WL_EXT_IAPSTA
-               wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
+               wl_ext_iapsta_update_net_device(net, ifidx);
 #endif /* WL_EXT_IAPSTA */
-#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */
-       }
-       if (ifidx != 0) {
                if (_dhd_set_mac_address(dhd, ifidx, net->dev_addr) == 0)
                        DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__));
                else
@@ -11861,20 +11911,16 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
                DHD_ERROR(("couldn't register the net device [%s], err %d\n", net->name, err));
                goto fail;
        }
-       if (ifidx == 0) {
 #if defined(WL_EXT_IAPSTA) || defined(USE_IW) || defined(WL_ESCAN)
-               wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
+       wl_ext_event_attach_netdev(net, ifidx, ifp->bssidx);
 #ifdef WL_ESCAN
-               wl_escan_event_attach(net, dhdp);
+       wl_escan_event_attach(net, dhdp);
 #endif /* WL_ESCAN */
 #ifdef WL_EXT_IAPSTA
-               wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
-#endif /* WL_EXT_IAPSTA */
-#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */
-       }
-#ifdef WL_EXT_IAPSTA
+       wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
        wl_ext_iapsta_attach_name(net, ifidx);
 #endif /* WL_EXT_IAPSTA */
+#endif /* WL_EXT_IAPSTA || USE_IW || WL_ESCAN */
 
        printf("Register interface [%s]  MAC: "MACDBG"\n\n", net->name,
                MAC2STRDBG(net->dev_addr));
@@ -11988,6 +12034,14 @@ void dhd_detach(dhd_pub_t *dhdp)
 
        if (dev) {
                rtnl_lock();
+#if defined(WL_CFG80211) && defined(WL_STATIC_IF)
+               if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) {
+                       cfg = wl_get_cfg(dev);
+                       if (cfg && cfg->static_ndev && (cfg->static_ndev->flags & IFF_UP)) {
+                               dev_close(cfg->static_ndev);
+                       }
+               }
+#endif /* WL_CFG80211 && WL_STATIC_IF */
                if (dev->flags & IFF_UP) {
                        /* If IFF_UP is still up, it indicates that
                         * "ifconfig wlan0 down" hasn't been called.
@@ -12143,6 +12197,10 @@ void dhd_detach(dhd_pub_t *dhdp)
 
                        MFREE(dhd->pub.osh, ifp, sizeof(*ifp));
                        dhd->iflist[0] = NULL;
+#ifdef WL_CFG80211
+                       if (cfg && cfg->wdev)
+                               cfg->wdev->netdev = NULL;
+#endif
                }
        }
 
@@ -12213,6 +12271,10 @@ void dhd_detach(dhd_pub_t *dhdp)
        }
 #endif /* DHD_LB */
 
+#ifdef CSI_SUPPORT
+       dhd_csi_deinit(dhdp);
+#endif /* CSI_SUPPORT */
+
 #if defined(DNGL_AXI_ERROR_LOGGING) && defined(DHD_USE_WQ_FOR_DNGL_AXI_ERROR)
        cancel_work_sync(&dhd->axi_error_dispatcher_work);
 #endif /* DNGL_AXI_ERROR_LOGGING && DHD_USE_WQ_FOR_DNGL_AXI_ERROR */
@@ -13214,6 +13276,10 @@ dhd_get_wireless_stats(struct net_device *dev)
                return NULL;
        }
 
+       if (!(dev->flags & IFF_UP)) {
+               return NULL;
+       }
+
        res = wl_iw_get_wireless_stats(dev, &dhd->iw.wstats);
 
        if (res == 0)
@@ -13475,7 +13541,9 @@ int net_os_set_suspend(struct net_device *dev, int val, int force)
        int ret = 0;
        dhd_info_t *dhd = DHD_DEV_INFO(dev);
 
-       if (dhd) {
+       if (dhd && dhd->pub.conf->suspend_mode == EARLY_SUSPEND) {
+               if (!val)
+                       dhd_conf_set_suspend_resume(&dhd->pub, val);
 #ifdef CONFIG_MACH_UNIVERSAL7420
 #endif /* CONFIG_MACH_UNIVERSAL7420 */
 #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND)
@@ -13486,6 +13554,8 @@ int net_os_set_suspend(struct net_device *dev, int val, int force)
 #ifdef WL_CFG80211
                wl_cfg80211_update_power_mode(dev);
 #endif // endif
+               if (val)
+                       dhd_conf_set_suspend_resume(&dhd->pub, val);
        }
        return ret;
 }
@@ -15480,7 +15550,7 @@ dhd_wait_pend8021x(struct net_device *dev)
        if (ntimes == 0)
        {
                atomic_set(&dhd->pend_8021x_cnt, 0);
-               DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__));
+               WL_MSG(dev->name, "TIMEOUT\n");
        }
        return pend;
 }
@@ -18906,6 +18976,98 @@ int dhd_set_block_tdls_status(dhd_pub_t *dhdp, uint32 idx, int val)
 }
 #endif /* DHD_L2_FILTER */
 
+#if defined(SET_XPS_CPUS)
+int dhd_xps_cpus_enable(struct net_device *net, int enable)
+{
+       dhd_info_t *dhd = DHD_DEV_INFO(net);
+       dhd_if_t *ifp;
+       int ifidx;
+       char * XPS_CPU_SETBUF;
+
+       ifidx = dhd_net2idx(dhd, net);
+       if (ifidx == DHD_BAD_IF) {
+               DHD_ERROR(("%s bad ifidx\n", __FUNCTION__));
+               return -ENODEV;
+       }
+
+       if (ifidx == PRIMARY_INF) {
+               if (dhd->pub.op_mode == DHD_FLAG_IBSS_MODE) {
+                       DHD_INFO(("%s : set for IBSS.\n", __FUNCTION__));
+                       XPS_CPU_SETBUF = RPS_CPUS_MASK_IBSS;
+               } else {
+                       DHD_INFO(("%s : set for BSS.\n", __FUNCTION__));
+                       XPS_CPU_SETBUF = RPS_CPUS_MASK;
+               }
+       } else if (ifidx == VIRTUAL_INF) {
+               DHD_INFO(("%s : set for P2P.\n", __FUNCTION__));
+               XPS_CPU_SETBUF = RPS_CPUS_MASK_P2P;
+       } else {
+               DHD_ERROR(("%s : Invalid index : %d.\n", __FUNCTION__, ifidx));
+               return -EINVAL;
+       }
+
+       ifp = dhd->iflist[ifidx];
+       if (ifp) {
+               if (enable) {
+                       DHD_INFO(("%s : set xps_cpus as [%s]\n", __FUNCTION__, XPS_CPU_SETBUF));
+                       custom_xps_map_set(ifp->net, XPS_CPU_SETBUF, strlen(XPS_CPU_SETBUF));
+               } else {
+                       custom_xps_map_clear(ifp->net);
+               }
+       } else {
+               DHD_ERROR(("%s : ifp is NULL!!\n", __FUNCTION__));
+               return -ENODEV;
+       }
+       return BCME_OK;
+}
+
+int custom_xps_map_set(struct net_device *net, char *buf, size_t len)
+{
+       cpumask_var_t mask;
+       int err;
+
+       DHD_INFO(("%s : Entered.\n", __FUNCTION__));
+
+       if (!alloc_cpumask_var(&mask, GFP_KERNEL)) {
+               DHD_ERROR(("%s : alloc_cpumask_var fail.\n", __FUNCTION__));
+               return -ENOMEM;
+       }
+
+       err = bitmap_parse(buf, len, cpumask_bits(mask), nr_cpumask_bits);
+       if (err) {
+               free_cpumask_var(mask);
+               DHD_ERROR(("%s : bitmap_parse fail.\n", __FUNCTION__));
+               return err;
+       }
+
+       err = netif_set_xps_queue(net, mask, 0);
+
+       free_cpumask_var(mask);
+
+       if (0 == err)
+               DHD_ERROR(("%s : Done. mapping cpu\n", __FUNCTION__));
+
+       return err;
+}
+
+void custom_xps_map_clear(struct net_device *net)
+{
+    struct xps_dev_maps *dev_maps;
+
+       DHD_INFO(("%s : Entered.\n", __FUNCTION__));
+
+    rcu_read_lock();
+    dev_maps = rcu_dereference(net->xps_maps);
+    rcu_read_unlock();
+
+       if (dev_maps) {
+               RCU_INIT_POINTER(net->xps_maps, NULL);
+               kfree_rcu(dev_maps, rcu);
+               DHD_INFO(("%s : xps_cpus map clear.\n", __FUNCTION__));
+       }
+}
+#endif // endif
+
 #if defined(SET_RPS_CPUS)
 int dhd_rps_cpus_enable(struct net_device *net, int enable)
 {
@@ -19011,7 +19173,7 @@ int custom_rps_map_set(struct netdev_rx_queue *queue, char *buf, size_t len)
        }
        free_cpumask_var(mask);
 
-       DHD_INFO(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len));
+       DHD_ERROR(("%s : Done. mapping cpu nummber : %d\n", __FUNCTION__, map->len));
        return map->len;
 }
 
index ae2b4e2b5373c9d91371904e6bcd76355ad4cda3..2f2097de5ac6e2a2c9521b17bfda477a5f578a09 100644 (file)
@@ -274,6 +274,7 @@ typedef struct wifi_adapter_info {
 
 #define WLAN_PLAT_NODFS_FLAG   0x01
 #define WLAN_PLAT_AP_FLAG      0x02
+#if !defined(CONFIG_WIFI_CONTROL_FUNC)
 struct wifi_platform_data {
 #ifdef BUS_POWER_RESTORE
        int (*set_power)(int val, wifi_adapter_info_t *adapter);
@@ -283,7 +284,11 @@ struct wifi_platform_data {
        int (*set_reset)(int val);
        int (*set_carddetect)(int val);
        void *(*mem_prealloc)(int section, unsigned long size);
+#ifdef CUSTOM_MULTI_MAC
+       int (*get_mac_addr)(unsigned char *buf, char *name);
+#else
        int (*get_mac_addr)(unsigned char *buf);
+#endif
 #ifdef BCMSDIO
        int (*get_wake_irq)(void);
 #endif // endif
@@ -293,6 +298,7 @@ struct wifi_platform_data {
        void *(*get_country_code)(char *ccode);
 #endif
 };
+#endif
 
 typedef struct bcmdhd_wifi_platdata {
        uint                            num_adapters;
@@ -409,7 +415,7 @@ wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_n
 int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec);
 int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_present);
 int wifi_platform_get_irq_number(wifi_adapter_info_t *adapter, unsigned long *irq_flags_ptr);
-int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf);
+int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf, char *name);
 #ifdef CUSTOM_COUNTRY_CODE
 void *wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode,
        u32 flags);
index 5e85bb3f9925cb5c6ac12bd386997d8e0850f3c9..fc9326dd57e0a19f469b86096a98c57cce7edaba 100644 (file)
@@ -36,6 +36,9 @@
 #ifdef DHD_ADPS_BAM_EXPORT
 #include <wl_bam.h>
 #endif // endif
+#ifdef CSI_SUPPORT
+#include <dhd_csi.h>
+#endif /* CSI_SUPPORT */
 
 #ifdef SHOW_LOGTRACE
 extern dhd_pub_t* g_dhd_pub;
@@ -558,7 +561,7 @@ static struct dhd_attr dhd_attr_cntl_macaddr =
 
 #ifdef DHD_FW_COREDUMP
 
-#define MEMDUMPINFO "/data/vendor/misc/wifi/.memdump.info"
+#define MEMDUMPINFO "/data/misc/wifi/.memdump.info"
 
 uint32
 get_mem_val_from_file(void)
@@ -674,7 +677,7 @@ static struct dhd_attr dhd_attr_cntl_memdump =
 #endif /* DHD_FW_COREDUMP */
 
 #ifdef BCMASSERT_LOG
-#define ASSERTINFO "/data/vendor/misc/wifi/.assert.info"
+#define ASSERTINFO "/data/misc/wifi/.assert.info"
 int
 get_assert_val_from_file(void)
 {
@@ -1334,6 +1337,29 @@ static struct kobj_type dhd_cntl_file_ktype = {
        .default_attrs = control_file_attrs,
 };
 
+#ifdef CSI_SUPPORT
+/* Function to show current ccode */
+static ssize_t read_csi_data(struct file *filp, struct kobject *kobj,
+       struct bin_attribute *bin_attr, char *buf, loff_t off, size_t count)
+{
+       dhd_info_t *dhd = to_dhd(kobj);
+       int n = 0;
+
+       n = dhd_csi_dump_list(&dhd->pub, buf);
+       DHD_INFO(("Dump data to file, size %d\n", n));
+       dhd_csi_clean_list(&dhd->pub);
+
+       return n;
+}
+
+static struct bin_attribute dhd_attr_csi = {
+       .attr = { .name = "csi",
+                 .mode = 0660, },
+       .size = MAX_CSI_FILESZ,
+       .read = read_csi_data,
+};
+#endif /* CSI_SUPPORT */
+
 /* Create a kobject and attach to sysfs interface */
 int dhd_sysfs_init(dhd_info_t *dhd)
 {
@@ -1358,6 +1384,15 @@ int dhd_sysfs_init(dhd_info_t *dhd)
                return ret;
        }
 
+#ifdef CSI_SUPPORT
+       ret = sysfs_create_bin_file(&dhd->dhd_kobj, &dhd_attr_csi);
+       if (ret) {
+               DHD_ERROR(("%s: can't create %s\n", __FUNCTION__, dhd_attr_csi.attr.name));
+               kobject_put(&dhd->dhd_kobj);
+               return ret;
+       }
+#endif /* CSI_SUPPORT */
+
        /*
         * We are always responsible for sending the uevent that the kobject
         * was added to the system.
index 254d6969f7104a985ccdcb991828cbaa8ce01521..aa6857014fe6db4352984f13be7433293bf14ce5 100644 (file)
@@ -44,8 +44,8 @@
 #include <dhd_linux_pktdump.h>
 #include <dhd_config.h>
 
-#define DHD_PKTDUMP(arg)       DHD_ERROR(arg)
-#define DHD_PKTDUMP_MEM(arg)   DHD_ERROR(arg)
+#define DHD_PKTDUMP(arg)       printk arg
+#define DHD_PKTDUMP_MEM(arg)   printk arg
 #define PACKED_STRUCT __attribute__ ((packed))
 
 #define EAPOL_HDR_LEN          4
@@ -161,6 +161,7 @@ typedef struct pkt_cnt_log {
 #define PKT_CNT_RSN_VALID(rsn) \
        (((rsn) > (PKT_CNT_RSN_INVALID)) && ((rsn) < (PKT_CNT_RSN_MAX)))
 
+#ifdef DHD_PKTDUMP_ROAM
 static const char pkt_cnt_msg[][20] = {
        "INVALID",
        "ROAM_SUCCESS",
@@ -168,6 +169,7 @@ static const char pkt_cnt_msg[][20] = {
        "CONNECT_SUCCESS",
        "INVALID"
 };
+#endif
 
 static const char tx_pktfate[][30] = {
        "TX_PKT_FATE_ACKED",            /* 0: WLFC_CTL_PKTFLAG_DISCARD */
@@ -197,60 +199,78 @@ static const char tx_pktfate[][30] = {
 #define TX_FATE(fate)          ((fate) ? (TX_FATE_STR(fate)) : "N/A")
 #define TX_FATE_ACKED(fate)    ((fate) ? ((*fate) == (WLFC_CTL_PKTFLAG_DISCARD)) : (0))
 
-#define EAP_PRINT(str) \
+#define EAP_PRINT(x, args...) \
        do { \
-               if (tx) { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \
-                               str TXFATE_FMT "\n", ifname, \
-                               TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
-               } else { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \
-                               str "\n", ifname)); \
+               if (dump_msg_level & DUMP_EAPOL_VAL) { \
+                       if (tx) { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"TXFATE_FMT"\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+                       } else { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf)); \
+                       } \
                } \
        } while (0)
 
-#define EAP_PRINT_REPLAY(str) \
+#define EAP_PRINT_REPLAY(x, args...) \
        do { \
-               if (tx) { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \
-                               str DBGREPLAY TXFATE_FMT "\n", ifname, \
-                               REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), \
-                               TX_FATE(pktfate))); \
-               } else { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \
-                               str DBGREPLAY "\n", ifname, \
-                               REPLAY_FMT(eap_key))); \
+               if (dump_msg_level & DUMP_EAPOL_VAL) { \
+                       if (tx) { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s)"DBGREPLAY TXFATE_FMT"\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       REPLAY_FMT(eap_key), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+                       } else { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s)"DBGREPLAY"\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       REPLAY_FMT(eap_key))); \
+                       } \
                } \
        } while (0)
 
-#define EAP_PRINT_OTHER(str) \
+#define EAP_PRINT_OTHER(x, args...) \
        do { \
-               if (tx) { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " \
-                               str "ver %d, type %d" TXFATE_FMT "\n", ifname, \
-                               eapol_hdr->version, eapol_hdr->type, \
-                               TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
-               } else { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " \
-                               str "ver %d, type %d\n", ifname, \
-                               eapol_hdr->version, eapol_hdr->type)); \
+               if (dump_msg_level & DUMP_EAPOL_VAL) { \
+                       if (tx) { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \
+                                       "ver %d, type %d"TXFATE_FMT"\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       eapol_hdr->version, eapol_hdr->type, \
+                                       TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+                       } else { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \
+                                       "ver %d, type %d\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       eapol_hdr->version, eapol_hdr->type)); \
+                       } \
                } \
        } while (0)
 
-#define EAP_PRINT_OTHER_4WAY(str) \
+#define EAP_PRINT_OTHER_4WAY(x, args...) \
        do { \
-               if (tx) { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [TX]: " str \
-                               "ver %d type %d keytype %d keyinfo 0x%02X" \
-                               TXFATE_FMT "\n", ifname, eapol_hdr->version, \
-                               eapol_hdr->type, eap_key->type, \
-                               (uint32)hton16(eap_key->key_info), \
-                               TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
-               } else { \
-                       DHD_PKTDUMP(("[dhd-%s] ETHER_TYPE_802_1X [RX]: " str \
-                               "ver %d type %d keytype %d keyinfo 0x%02X\n", \
-                               ifname, eapol_hdr->version, eapol_hdr->type, \
-                               eap_key->type, (uint32)hton16(eap_key->key_info))); \
+               if (dump_msg_level & DUMP_EAPOL_VAL) { \
+                       if (tx) { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [TX] : (%s) %s (%s) " \
+                                       "ver %d type %d keytype %d keyinfo 0x%02X"TXFATE_FMT"\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       eapol_hdr->version, eapol_hdr->type, eap_key->type, \
+                                       (uint32)hton16(eap_key->key_info), \
+                                       TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+                       } else { \
+                               DHD_PKTDUMP(("[dhd-%s] 802_1X " x " [RX] : (%s) %s (%s) " \
+                                       "ver %d type %d keytype %d keyinfo 0x%02X\n", \
+                                       ifname, ## args, \
+                                       tx?seabuf:deabuf, tx?"->":"<-", tx?deabuf:seabuf, \
+                                       eapol_hdr->version, eapol_hdr->type, eap_key->type, \
+                                       (uint32)hton16(eap_key->key_info))); \
+                       } \
                } \
        } while (0)
 
@@ -551,6 +571,8 @@ dhd_dump_wsc_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
        char *ifname;
        uint16 eap_len;
        bool cond;
+       char seabuf[ETHER_ADDR_STR_LEN]="";
+       char deabuf[ETHER_ADDR_STR_LEN]="";
 
        if (!pktdata) {
                DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
@@ -562,6 +584,9 @@ dhd_dump_wsc_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
                return;
        }
 
+       bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+       bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
        eapol_hdr = (eapol_header_t *)pktdata;
        eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body);
        if (eap_hdr->type != EAP_TYPE_EXP) {
@@ -660,12 +685,17 @@ dhd_dump_eap_packet(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
        eap_header_fmt_t *eap_hdr;
        char *ifname;
        bool cond;
+       char seabuf[ETHER_ADDR_STR_LEN]="";
+       char deabuf[ETHER_ADDR_STR_LEN]="";
 
        if (!pktdata) {
                DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
                return;
        }
 
+       bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+       bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
        eapol_hdr = (eapol_header_t *)pktdata;
        eap_hdr = (eap_header_fmt_t *)(eapol_hdr->body);
        ifname = dhd_ifname(dhd, ifidx);
@@ -783,12 +813,17 @@ dhd_dump_eapol_4way_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata, bool tx,
        msg_eapol_t type;
        char *ifname;
        bool cond;
+       char seabuf[ETHER_ADDR_STR_LEN]="";
+       char deabuf[ETHER_ADDR_STR_LEN]="";
 
        if (!pktdata) {
                DHD_PKTDUMP(("%s: pktdata is NULL\n", __FUNCTION__));
                return;
        }
 
+       bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+       bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
        type = dhd_is_4way_msg(pktdata);
        ifname = dhd_ifname(dhd, ifidx);
        eapol_hdr = (eapol_header_t *)pktdata;
@@ -846,12 +881,17 @@ dhd_dump_eapol_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
        char *ifname;
        eapol_header_t *eapol_hdr = (eapol_header_t *)pktdata;
        bool cond;
+       char seabuf[ETHER_ADDR_STR_LEN]="";
+       char deabuf[ETHER_ADDR_STR_LEN]="";
 
        if (!pktdata) {
                DHD_ERROR(("%s: pktdata is NULL\n", __FUNCTION__));
                return;
        }
 
+       bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+       bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
+
        eapol_hdr = (eapol_header_t *)pktdata;
        ifname = dhd_ifname(dhd, ifidx);
        cond = (tx && pktfate) ? FALSE : TRUE;
@@ -891,12 +931,14 @@ dhd_dump_eapol_message(dhd_pub_t *dhd, int ifidx, uint8 *pktdata,
 #define DHCP_PRINT(str) \
        do { \
                if (tx) { \
-                       DHD_PKTDUMP(("[dhd-%s] "str " %s[%s] [TX] -" TXFATE_FMT "\n", \
-                               ifname, typestr, opstr, \
+                       DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
+                               ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                               tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
                                TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                } else { \
-                       DHD_PKTDUMP(("[dhd-%s] "str" %s[%s] [RX]\n", \
-                               ifname, typestr, opstr)); \
+                       DHD_PKTDUMP(("[dhd-%s] " str " %8s[%8s] [RX] : %s(%s) %s %s(%s)\n", \
+                               ifname, typestr, opstr, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                               tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf)); \
                } \
        } while (0)
 
@@ -944,6 +986,12 @@ dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        int dhcp_type = 0, len, opt_len;
        char *ifname = NULL, *typestr = NULL, *opstr = NULL;
        bool cond;
+       char sabuf[20]="", dabuf[20]="";
+       char seabuf[ETHER_ADDR_STR_LEN]="";
+       char deabuf[ETHER_ADDR_STR_LEN]="";
+
+       if (!(dump_msg_level & DUMP_DHCP_VAL))
+               return;
 
        /* check IP header */
        if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
@@ -964,6 +1012,10 @@ dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        if (ntohs(iph->tot_len) < ntohs(b->udph.len) + sizeof(struct bcmudp_hdr)) {
                return;
        }
+       bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
+       bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
+       bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+       bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
 
        ifname = dhd_ifname(dhdp, ifidx);
        cond = (tx && pktfate) ? FALSE : TRUE;
@@ -1008,7 +1060,7 @@ dhd_dhcp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        do { \
                if (tx) { \
                        DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) SEQNUM=%d" \
-                               TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                               TXFATE_FMT"\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
                                tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, seqnum, \
                                TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                } else { \
@@ -1046,6 +1098,9 @@ dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        char seabuf[ETHER_ADDR_STR_LEN]="";
        char deabuf[ETHER_ADDR_STR_LEN]="";
 
+       if (!(dump_msg_level & DUMP_ICMP_VAL))
+               return;
+
        /* check IP header */
        if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
                IP_VER(iph) != IP_VER_4 ||
@@ -1091,12 +1146,12 @@ dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        do { \
                if (tx) { \
                        if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
-                               DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)" TXFATE_FMT "\n", \
+                               DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
                                        ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
                                        tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
                                        TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } else { \
-                               DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)" TXFATE_FMT "\n", \
+                               DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s)"TXFATE_FMT"\n", \
                                        ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
                                        tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
                                        TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
@@ -1112,18 +1167,20 @@ dhd_icmp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        do { \
                if (tx) { \
                        if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
-                               DHD_PKTDUMP(("[dhd-%s] "str " [TX] op_code=%d" \
-                                       TXFATE_FMT "\n", ifname, opcode, \
-                                       TX_PKTHASH(pkthash), \
-                                       TX_FATE(pktfate))); \
+                               DHD_PKTDUMP(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
+                                       TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
+                                       TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } else { \
-                               DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] op_code=%d" \
-                               TXFATE_FMT "\n", ifname, opcode, \
+                               DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] : %s(%s) %s %s(%s) op_code=%d" \
+                               TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode, \
                                TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } \
                } else { \
-                       DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] op_code=%d\n", \
-                               ifname, opcode)); \
+                       DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] : %s(%s) %s %s(%s) op_code=%d\n", \
+                               ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, opcode)); \
                } \
        } while (0)
 
@@ -1140,6 +1197,9 @@ dhd_arp_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        char seabuf[ETHER_ADDR_STR_LEN]="";
        char deabuf[ETHER_ADDR_STR_LEN]="";
 
+       if (!(dump_msg_level & DUMP_ARP_VAL))
+               return;
+
        /* validation check */
        if (arph->htype != hton16(HTYPE_ETHERNET) ||
                arph->hlen != ETHER_ADDR_LEN ||
@@ -1206,17 +1266,20 @@ static const char dns_opcode_types[][11] = {
        do { \
                if (tx) { \
                        if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
-                               DHD_PKTDUMP(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s" \
-                                       TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
-                                       TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+                               DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
+                                       TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
+                                       id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } else { \
-                               DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s" \
-                                       TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
-                                       TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
+                               DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s" \
+                                       TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
+                                       id, DNSOPCODE(opcode), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } \
                } else { \
-                       DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] ID:0x%04X OPCODE:%s\n", \
-                               ifname, id, DNSOPCODE(opcode))); \
+                       DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s\n", \
+                               ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, tx?"->":"<-", \
+                               tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode))); \
                } \
        } while (0)
 
@@ -1224,19 +1287,21 @@ static const char dns_opcode_types[][11] = {
        do { \
                if (tx) { \
                        if (dump_enabled && pktfate && !TX_FATE_ACKED(pktfate)) { \
-                               DHD_PKTDUMP(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s RCODE:%d" \
-                                       TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
-                                       GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), \
-                                       TX_FATE(pktfate))); \
+                               DHD_PKTDUMP(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
+                                       TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
+                                       GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } else { \
-                               DHD_PKTDUMP_MEM(("[dhd-%s] "str " [TX] ID:0x%04X OPCODE:%s RCODE:%d" \
-                                       TXFATE_FMT "\n", ifname, id, DNSOPCODE(opcode), \
-                                       GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), \
-                                       TX_FATE(pktfate))); \
+                               DHD_PKTDUMP_MEM(("[dhd-%s] " str " [TX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d" \
+                                       TXFATE_FMT "\n", ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                                       tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, id, DNSOPCODE(opcode), \
+                                       GET_DNS_RCODE(flags), TX_PKTHASH(pkthash), TX_FATE(pktfate))); \
                        } \
                } else { \
-                       DHD_PKTDUMP_MEM(("[dhd-%s] "str " [RX] ID:0x%04X OPCODE:%s RCODE:%d\n", \
-                               ifname, id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \
+                       DHD_PKTDUMP_MEM(("[dhd-%s] " str " [RX] : %s(%s) %s %s(%s) ID:0x%04X OPCODE:%s RCODE:%d\n", \
+                               ifname, tx?sabuf:dabuf, tx?seabuf:deabuf, \
+                               tx?"->":"<-", tx?dabuf:sabuf, tx?deabuf:seabuf, \
+                               id, DNSOPCODE(opcode), GET_DNS_RCODE(flags))); \
                } \
        } while (0)
 
@@ -1249,6 +1314,12 @@ dhd_dns_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        uint16 flags, opcode, id;
        char *ifname;
        bool cond, dump_enabled;
+       char sabuf[20]="", dabuf[20]="";
+       char seabuf[ETHER_ADDR_STR_LEN]="";
+       char deabuf[ETHER_ADDR_STR_LEN]="";
+
+       if (!(dump_msg_level & DUMP_DNS_VAL))
+               return;
 
        /* check IP header */
        if ((IPV4_HLEN(iph) < IPV4_HLEN_MIN) ||
@@ -1275,6 +1346,10 @@ dhd_dns_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, bool tx,
        flags = hton16(dnsh->flags);
        opcode = GET_DNS_OPCODE(flags);
        id = hton16(dnsh->id);
+       bcm_ip_ntoa((struct ipv4_addr *)iph->src_ip, sabuf);
+       bcm_ip_ntoa((struct ipv4_addr *)iph->dst_ip, dabuf);
+       bcm_ether_ntoa((struct ether_addr *)pktdata, deabuf);
+       bcm_ether_ntoa((struct ether_addr *)(pktdata+6), seabuf);
        if (GET_DNS_QR(flags)) {
                /* Response */
                DHD_STATLOG_DATA(dhdp, ST(DNS_RESP), ifidx, tx, cond);
@@ -1299,6 +1374,9 @@ dhd_trx_pkt_dump(dhd_pub_t *dhdp, int ifidx, uint8 *pktdata, uint32 pktlen, bool
        uint16 protocol;
        char *pkttype = "UNKNOWN";
 
+       if (!(dump_msg_level & DUMP_TRX_VAL))
+               return;
+
        if (!dhdp) {
                DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
                return;
index b4839119057c87d5beee61441b4dcf45140717ee..7ceaa40cc899e843bfc81ac753878a1c830f28ef 100644 (file)
@@ -282,7 +282,8 @@ int wifi_platform_bus_enumerate(wifi_adapter_info_t *adapter, bool device_presen
 
 }
 
-int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf)
+int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf,
+       char *name)
 {
        struct wifi_platform_data *plat_data;
 
@@ -291,7 +292,11 @@ int wifi_platform_get_mac_addr(wifi_adapter_info_t *adapter, unsigned char *buf)
                return -EINVAL;
        plat_data = adapter->wifi_plat_data;
        if (plat_data->get_mac_addr) {
+#ifdef CUSTOM_MULTI_MAC
+               return plat_data->get_mac_addr(buf, name);
+#else
                return plat_data->get_mac_addr(buf);
+#endif
        }
        return -EOPNOTSUPP;
 }
@@ -339,8 +344,11 @@ static int wifi_plat_dev_drv_probe(struct platform_device *pdev)
        ASSERT(dhd_wifi_platdata != NULL);
        ASSERT(dhd_wifi_platdata->num_adapters == 1);
        adapter = &dhd_wifi_platdata->adapters[0];
+#if defined(CONFIG_WIFI_CONTROL_FUNC)
+       adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
+#else
        adapter->wifi_plat_data = (void *)&dhd_wlan_control;
-//     adapter->wifi_plat_data = (struct wifi_platform_data *)(pdev->dev.platform_data);
+#endif
 
        resource = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcmdhd_wlan_irq");
        if (resource == NULL)
index 33ceb5a2f22abb877bb265f15d47fa03381fd784..41e883066e84fc0d1db50754fd4dbcd789b6c167 100644 (file)
@@ -7575,7 +7575,6 @@ dhd_msgbuf_iovar_timeout_dump(dhd_pub_t *dhd)
        if (prot->curr_ioctl_cmd == WLC_SET_VAR ||
                        prot->curr_ioctl_cmd == WLC_GET_VAR) {
                char iovbuf[32];
-               int i;
                int dump_size = 128;
                uint8 *ioctl_buf = (uint8 *)prot->ioctbuf.va;
                memset(iovbuf, 0, sizeof(iovbuf));
@@ -7585,12 +7584,7 @@ dhd_msgbuf_iovar_timeout_dump(dhd_pub_t *dhd)
                        prot->curr_ioctl_cmd == WLC_SET_VAR ?
                        "WLC_SET_VAR" : "WLC_GET_VAR", iovbuf));
                DHD_ERROR(("========== START IOCTL REQBUF DUMP ==========\n"));
-               for (i = 0; i < dump_size; i++) {
-                       DHD_ERROR(("%02X ", ioctl_buf[i]));
-                       if ((i % 32) == 31) {
-                               DHD_ERROR(("\n"));
-                       }
-               }
+               prhex("ioctl_buf", (const u8 *) ioctl_buf, dump_size);
                DHD_ERROR(("\n========== END IOCTL REQBUF DUMP ==========\n"));
        }
 
index de29e2d3d8072bf2db5612e9c96a9d6072d6826b..ff69b1387aa03b508c61ed9f6df9ed57c9d7055c 100644 (file)
@@ -605,13 +605,12 @@ dhd_bus_pcie_pwr_req_nolock(struct dhd_bus *bus)
 bool
 dhdpcie_chip_support_msi(dhd_bus_t *bus)
 {
-       DHD_ERROR(("%s: buscorerev=%d chipid=0x%x\n",
+       DHD_INFO(("%s: buscorerev=%d chipid=0x%x\n",
                __FUNCTION__, bus->sih->buscorerev, si_chipid(bus->sih)));
        if (bus->sih->buscorerev <= 14 ||
                si_chipid(bus->sih) == BCM4375_CHIP_ID ||
                si_chipid(bus->sih) == BCM4362_CHIP_ID ||
                si_chipid(bus->sih) == BCM43751_CHIP_ID ||
-               si_chipid(bus->sih) == BCM43752_CHIP_ID ||
                si_chipid(bus->sih) == BCM4361_CHIP_ID ||
                si_chipid(bus->sih) == BCM4359_CHIP_ID) {
                return FALSE;
@@ -2807,7 +2806,7 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
 
        DHD_OS_WAKE_LOCK(bus->dhd);
 
-       dhd_conf_set_path_params(bus->dhd, NULL, NULL, bus->fw_path, bus->nv_path);
+       dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
        dhd_set_bus_params(bus);
 
        ret = _dhdpcie_download_firmware(bus);
index 08d3776c2535c601dd0def6d4bb9605d919f7b4f..701f975b7fcda09c5cb44fbdfb1ee45f5b0c5fb4 100644 (file)
@@ -1498,6 +1498,11 @@ dhdpcie_request_irq(dhdpcie_info_t *dhdpcie_info)
                        }
                }
 
+               if (bus->d2h_intr_method == PCIE_MSI)
+                       printf("%s: MSI enabled\n", __FUNCTION__);
+               else
+                       printf("%s: INTx enabled\n", __FUNCTION__);
+
                if (request_irq(pdev->irq, dhdpcie_isr, IRQF_SHARED,
                        dhdpcie_info->pciname, bus) < 0) {
                        DHD_ERROR(("%s: request_irq() failed\n", __FUNCTION__));
@@ -1824,8 +1829,11 @@ int dhdpcie_init(struct pci_dev *pdev)
                if (bus->dev->bus) {
                        /* self member of structure pci_bus is bridge device as seen by parent */
                        bus->rc_dev = bus->dev->bus->self;
-                       DHD_ERROR(("%s: rc_dev from dev->bus->self (%x:%x) is %pK\n", __FUNCTION__,
-                               bus->rc_dev->vendor, bus->rc_dev->device, bus->rc_dev));
+                       if (bus->rc_dev)
+                               DHD_ERROR(("%s: rc_dev from dev->bus->self (%x:%x) is %pK\n", __FUNCTION__,
+                                       bus->rc_dev->vendor, bus->rc_dev->device, bus->rc_dev));
+                       else
+                               DHD_ERROR(("%s: bus->dev->bus->self is NULL\n", __FUNCTION__));
                } else {
                        DHD_ERROR(("%s: unable to get rc_dev as dev->bus is NULL\n", __FUNCTION__));
                }
@@ -2541,7 +2549,7 @@ int dhdpcie_oob_intr_register(dhd_bus_t *bus)
 
        dhdpcie_osinfo->oob_irq_registered = TRUE;
 
-       return err;
+       return 0;
 }
 
 void dhdpcie_oob_intr_unregister(dhd_bus_t *bus)
index 390fb8144a713bd877abbd88d7f6f8b37ffc3835..6bb2fa4034c3e6b939a08892b72dc0fa9387a164 100644 (file)
@@ -3090,7 +3090,7 @@ _dhd_pno_get_for_batch(dhd_pub_t *dhd, char *buf, int bufsize, int reason)
        STATIC_ASSERT(sizeof(wl_pfn_net_info_v1_t) == sizeof(wl_pfn_net_info_v2_t));
        STATIC_ASSERT(sizeof(wl_pfn_lnet_info_v1_t) == sizeof(wl_pfn_lnet_info_v2_t));
        STATIC_ASSERT(sizeof(wl_pfn_subnet_info_v1_t) == sizeof(wl_pfn_subnet_info_v2_t));
-       STATIC_ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
+       ASSERT(OFFSETOF(wl_pfn_subnet_info_v1_t, SSID) ==
                      OFFSETOF(wl_pfn_subnet_info_v2_t, u.SSID));
 
        DHD_PNO(("%s enter\n", __FUNCTION__));
index 46c55fe685eb4a0410ffa621884de23aaa337586..b1281e0608a5b278260fe08d2b999e0e8fecba64 100644 (file)
@@ -449,6 +449,9 @@ typedef struct dhd_bus {
        uint            txglomframes;   /* Number of tx glom frames (superframes) */
        uint            txglompkts;             /* Number of packets from tx glom frames */
        uint8           *membuf;                /* Buffer for dhdsdio_membytes */
+#ifdef CONSOLE_DPC
+       char            cons_cmd[16];
+#endif
 } dhd_bus_t;
 
 /*
@@ -7085,6 +7088,12 @@ clkwait:
 
        if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
                dhdsdio_sendpendctl(bus);
+#ifdef CONSOLE_DPC
+       else if (DATAOK(bus) && strlen(bus->cons_cmd) && (bus->clkstate == CLK_AVAIL) &&
+                       !bus->fcstate) {
+               dhd_bus_console_in(bus->dhd, bus->cons_cmd, strlen(bus->cons_cmd));
+       }
+#endif
 
        /* Send queued frames (limit 1 if rx may still be pending) */
        else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
@@ -7846,23 +7855,36 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
        int rv;
        void *pkt;
 
-       /* Address could be zero if CONSOLE := 0 in dongle Makefile */
-       if (bus->console_addr == 0)
-               return BCME_UNSUPPORTED;
-
+#ifndef CONSOLE_DPC
        /* Exclusive bus access */
        dhd_os_sdlock(bus->dhd);
+#endif
+
+       /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+       if (bus->console_addr == 0) {
+               rv = BCME_UNSUPPORTED;
+               goto exit;
+       }
 
        /* Don't allow input if dongle is in reset */
        if (bus->dhd->dongle_reset) {
-               dhd_os_sdunlock(bus->dhd);
-               return BCME_NOTREADY;
+               rv = BCME_NOTREADY;
+               goto exit;
+       }
+
+#ifndef CONSOLE_DPC
+       if (!DATAOK(bus)) {
+               DHD_CTL(("%s: No bus credit bus->tx_max %d, bus->tx_seq %d, pktq_len %d\n",
+                       __FUNCTION__, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
+               rv = BCME_NOTREADY;
+               goto exit;
        }
 
        /* Request clock to allow SDIO accesses */
        BUS_WAKE(bus);
        /* No pend allowed since txpkt is called later, ht clk has to be on */
        dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+#endif
 
        /* Zero cbuf_index */
        addr = bus->console_addr + OFFSETOF(hnd_cons_t, cbuf_idx);
@@ -7881,11 +7903,6 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
        if ((rv = dhdsdio_membytes(bus, TRUE, addr, (uint8 *)&val, sizeof(val))) < 0)
                goto done;
 
-       if (!DATAOK(bus)) {
-               rv = BCME_NOTREADY;
-               goto done;
-       }
-
        /* Bump dongle by sending an empty packet on the event channel.
         * sdpcm_sendup (RX) checks for virtual console input.
         */
@@ -7893,18 +7910,72 @@ dhd_bus_console_in(dhd_pub_t *dhdp, uchar *msg, uint msglen)
                rv = dhdsdio_txpkt(bus, SDPCM_EVENT_CHANNEL, &pkt, 1, TRUE);
 
 done:
+#ifndef CONSOLE_DPC
        if ((bus->idletime == DHD_IDLE_IMMEDIATE) && !bus->dpc_sched &&
                NO_OTHER_ACTIVE_BUS_USER(bus)) {
                bus->activity = FALSE;
                dhdsdio_bussleep(bus, TRUE);
                dhdsdio_clkctl(bus, CLK_NONE, FALSE);
        }
+#endif
 
+exit:
+#ifdef CONSOLE_DPC
+       memset(bus->cons_cmd, 0, sizeof(bus->cons_cmd));
+#else
        dhd_os_sdunlock(bus->dhd);
-
+#endif
        return rv;
 }
 
+#ifdef CONSOLE_DPC
+extern int
+dhd_bus_txcons(dhd_pub_t *dhdp, uchar *msg, uint msglen)
+{
+       dhd_bus_t *bus = dhdp->bus;
+       int ret = BCME_OK;
+
+       dhd_os_sdlock(bus->dhd);
+
+       /* Address could be zero if CONSOLE := 0 in dongle Makefile */
+       if (bus->console_addr == 0) {
+               ret = BCME_UNSUPPORTED;
+               goto exit;
+       }
+
+       /* Don't allow input if dongle is in reset */
+       if (bus->dhd->dongle_reset) {
+               ret = BCME_NOTREADY;
+               goto exit;
+       }
+
+       if (msglen >= sizeof(bus->cons_cmd)) {
+               DHD_ERROR(("%s: \"%s\"(%d) too long\n", __FUNCTION__, msg, msglen));
+               ret = BCME_BADARG;
+               goto exit;
+       }
+
+       if (!strlen(bus->cons_cmd)) {
+               strncpy(bus->cons_cmd, msg, sizeof(bus->cons_cmd));
+               DHD_CTL(("%s: \"%s\" delay send, tx_max %d, tx_seq %d, pktq_len %d\n",
+                       __FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
+               if (!bus->dpc_sched) {
+                       bus->dpc_sched = TRUE;
+                       dhd_sched_dpc(bus->dhd);
+               }
+       } else {
+               DHD_CTL(("%s: \"%s\" is pending, tx_max %d, tx_seq %d, pktq_len %d\n",
+                       __FUNCTION__, bus->cons_cmd, bus->tx_max, bus->tx_seq, pktq_n_pkts_tot(&bus->txq)));
+               ret = BCME_NOTREADY;
+       }
+
+exit:
+       dhd_os_sdunlock(bus->dhd);
+
+       return ret;
+}
+#endif
+
 #if defined(DHD_DEBUG) && !defined(BCMSDIOLITE)
 static void
 dhd_dump_cis(uint fn, uint8 *cis)
@@ -7999,9 +8070,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
 {
        int ret;
        dhd_bus_t *bus;
-#ifdef GET_OTP_MAC_ENABLE
-       struct ether_addr ea_addr;
-#endif
 
        DHD_MUTEX_LOCK();
 
@@ -8107,6 +8175,10 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
                goto fail;
        }
 
+#if defined(GET_OTP_MAC_ENABLE) || defined(GET_OTP_MODULE_NAME)
+       dhd_conf_get_otp(bus->dhd, sdh, bus->sih);
+#endif
+
        /* Allocate buffers */
        if (!(dhdsdio_probe_malloc(bus, osh, sdh))) {
                DHD_ERROR(("%s: dhdsdio_probe_malloc failed\n", __FUNCTION__));
@@ -8165,10 +8237,8 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
 #endif /* BT_OVER_SDIO */
 
 #ifdef GET_OTP_MAC_ENABLE
-       if (dhd_conf_get_mac(bus->dhd, sdh, bus->sih, ea_addr.octet)) {
-               DHD_TRACE(("%s: Can not read MAC address\n", __FUNCTION__));
-       } else
-               memcpy(bus->dhd->mac.octet, (void *)&ea_addr, ETHER_ADDR_LEN);
+       if (memcmp(&ether_null, &bus->dhd->conf->otp_mac, ETHER_ADDR_LEN))
+               memcpy(bus->dhd->mac.octet, (void *)&bus->dhd->conf->otp_mac, ETHER_ADDR_LEN);
 #endif /* GET_CUSTOM_MAC_ENABLE */
 
        /* Ok, have the per-port tell the stack we're open for business */
@@ -8697,12 +8767,12 @@ dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
                __FUNCTION__, bus->fw_path, bus->nv_path));
        DHD_OS_WAKE_LOCK(bus->dhd);
 
+       dhd_conf_set_path_params(bus->dhd, bus->fw_path, bus->nv_path);
+       dhd_set_bus_params(bus);
+
        /* Download the firmware */
        dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
 
-       dhd_conf_set_path_params(bus->dhd, bus->sdh, bus->sih, bus->fw_path, bus->nv_path);
-       dhd_set_bus_params(bus);
-
        ret = _dhdsdio_download_firmware(bus);
 
        dhdsdio_clkctl(bus, CLK_SDONLY, FALSE);
@@ -10479,3 +10549,31 @@ dhd_bus_get_bus_wake(dhd_pub_t *dhd)
        return bcmsdh_set_get_wake(dhd->bus->sdh, 0);
 }
 #endif /* DHD_WAKE_STATUS */
+
+int
+dhd_bus_sleep(dhd_pub_t *dhdp, bool sleep, uint32 *intstatus)
+{
+       dhd_bus_t *bus = dhdp->bus;
+       uint32 retry = 0;
+       int ret = 0;
+
+       if (bus) {
+               dhd_os_sdlock(dhdp);
+               BUS_WAKE(bus);
+               R_SDREG(*intstatus, &bus->regs->intstatus, retry);
+               if (sleep) {
+                       if (SLPAUTO_ENAB(bus)) {
+                               ret = dhdsdio_bussleep(bus, sleep);
+                               if (ret != BCME_BUSY)
+                                       dhd_os_wd_timer(bus->dhd, 0);
+                       } else
+                               dhdsdio_clkctl(bus, CLK_NONE, FALSE);
+               }
+               dhd_os_sdunlock(dhdp);
+       } else {
+               DHD_ERROR(("bus is NULL\n"));
+               ret = -1;
+       }
+
+       return ret;
+}
\ No newline at end of file
index 77ad69bc13a2dac4eebe5d7fc5dadce305c43ff3..fb68b01fb61c12a71485b5dd1635c302160b16c8 100644 (file)
-/*
- * drivers/amlogic/wifi/dhd_static_buf.c
- *
- * Copyright (C) 2017 Amlogic, Inc. All rights reserved.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
- * more details.
- *
- */
-
-#define pr_fmt(fmt)    "Wifi: %s: " fmt, __func__
-
-#include <linux/module.h>
-#include <linux/kernel.h>
-#include <linux/init.h>
-#include <linux/platform_device.h>
-#include <linux/delay.h>
-#include <linux/err.h>
-#include <linux/skbuff.h>
-#include <linux/wlan_plat.h>
-#include <linux/amlogic/dhd_buf.h>
-
-#define        DHD_STATIC_VERSION_STR          "100.10.545.3"
-
-#define BCMDHD_SDIO
-#define BCMDHD_PCIE
-
-enum dhd_prealloc_index {
-       DHD_PREALLOC_PROT = 0,
-#if defined(BCMDHD_SDIO)
-       DHD_PREALLOC_RXBUF = 1,
-       DHD_PREALLOC_DATABUF = 2,
-#endif
-       DHD_PREALLOC_OSL_BUF = 3,
-       DHD_PREALLOC_SKB_BUF = 4,
-       DHD_PREALLOC_WIPHY_ESCAN0 = 5,
-       DHD_PREALLOC_WIPHY_ESCAN1 = 6,
-       DHD_PREALLOC_DHD_INFO = 7,
-       DHD_PREALLOC_DHD_WLFC_INFO = 8,
-#ifdef BCMDHD_PCIE
-       DHD_PREALLOC_IF_FLOW_LKUP = 9,
-#endif
-       DHD_PREALLOC_MEMDUMP_BUF = 10,
-       DHD_PREALLOC_MEMDUMP_RAM = 11,
-       DHD_PREALLOC_DHD_WLFC_HANGER = 12,
-       DHD_PREALLOC_PKTID_MAP = 13,
-       DHD_PREALLOC_PKTID_MAP_IOCTL = 14,
-       DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15,
-       DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16,
-       DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17,
-       DHD_PREALLOC_STAT_REPORT_BUF = 18,
-       DHD_PREALLOC_WL_WEXT_INFO = 19,
-       DHD_PREALLOC_FW_VERBOSE_RING = 20,
-       DHD_PREALLOC_FW_EVENT_RING = 21,
-       DHD_PREALLOC_DHD_EVENT_RING = 22,
-       DHD_PREALLOC_NAN_EVENT_RING = 23,
-       DHD_PREALLOC_MAX
-};
-
-#define STATIC_BUF_MAX_NUM     20
-#define STATIC_BUF_SIZE        (PAGE_SIZE*2)
-
-#define DHD_PREALLOC_PROT_SIZE (16 * 1024)
-#define DHD_PREALLOC_RXBUF_SIZE        (24 * 1024)
-#define DHD_PREALLOC_DATABUF_SIZE      (64 * 1024)
-#define DHD_PREALLOC_OSL_BUF_SIZE      (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)
-#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)
-#define DHD_PREALLOC_DHD_INFO_SIZE     (32 * 1024)
-#define DHD_PREALLOC_MEMDUMP_RAM_SIZE  (1290 * 1024)
-#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE      (73 * 1024)
-#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB)
-#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024)
-#define DHD_PREALLOC_WL_WEXT_INFO_SIZE (70 * 1024)
-#ifdef CONFIG_64BIT
-#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)
-#else
-#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024)
-#endif
-#define FW_VERBOSE_RING_SIZE           (256 * 1024)
-#define FW_EVENT_RING_SIZE             (64 * 1024)
-#define DHD_EVENT_RING_SIZE            (64 * 1024)
-#define NAN_EVENT_RING_SIZE            (64 * 1024)
-
-#if defined(CONFIG_64BIT)
-#define WLAN_DHD_INFO_BUF_SIZE (24 * 1024)
-#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)
-#define WLAN_DHD_IF_FLOW_LKUP_SIZE     (64 * 1024)
-#else
-#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024)
-#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)
-#define WLAN_DHD_IF_FLOW_LKUP_SIZE     (20 * 1024)
-#endif /* CONFIG_64BIT */
-#define WLAN_DHD_MEMDUMP_SIZE  (800 * 1024)
-
-#define DHD_SKB_1PAGE_BUFSIZE  (PAGE_SIZE*1)
-#define DHD_SKB_2PAGE_BUFSIZE  (PAGE_SIZE*2)
-#define DHD_SKB_4PAGE_BUFSIZE  (PAGE_SIZE*4)
-
-#define DHD_SKB_1PAGE_BUF_NUM  8
-#define DHD_SKB_2PAGE_BUF_NUM  64
-#define DHD_SKB_4PAGE_BUF_NUM  1
-
-/* The number is defined in linux_osl.c
- * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM
- * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM
- */
-#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \
-               (DHD_SKB_2PAGE_BUF_NUM))
-#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))
-
-void *wlan_static_prot;
-void *wlan_static_rxbuf;
-void *wlan_static_databuf;
-void *wlan_static_osl_buf;
-void *wlan_static_scan_buf0;
-void *wlan_static_scan_buf1;
-void *wlan_static_dhd_info_buf;
-void *wlan_static_dhd_wlfc_info_buf;
-void *wlan_static_if_flow_lkup;
-void *wlan_static_dhd_memdump_ram_buf;
-void *wlan_static_dhd_wlfc_hanger_buf;
-void *wlan_static_dhd_log_dump_buf;
-void *wlan_static_dhd_log_dump_buf_ex;
-void *wlan_static_wl_escan_info_buf;
-void *wlan_static_fw_verbose_ring_buf;
-void *wlan_static_fw_event_ring_buf;
-void *wlan_static_dhd_event_ring_buf;
-void *wlan_static_nan_event_ring_buf;
-
-static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];
-
-void *bcmdhd_mem_prealloc(int section, unsigned long size)
-{
-       pr_info("sectoin %d, size %ld\n", section, size);
-       if (section == DHD_PREALLOC_PROT)
-               return wlan_static_prot;
-
-#if defined(BCMDHD_SDIO)
-       if (section == DHD_PREALLOC_RXBUF)
-               return wlan_static_rxbuf;
-
-       if (section == DHD_PREALLOC_DATABUF)
-               return wlan_static_databuf;
-#endif /* BCMDHD_SDIO */
-
-       if (section == DHD_PREALLOC_SKB_BUF)
-               return wlan_static_skb;
-
-       if (section == DHD_PREALLOC_WIPHY_ESCAN0)
-               return wlan_static_scan_buf0;
-
-       if (section == DHD_PREALLOC_WIPHY_ESCAN1)
-               return wlan_static_scan_buf1;
-
-       if (section == DHD_PREALLOC_OSL_BUF) {
-               if (size > DHD_PREALLOC_OSL_BUF_SIZE) {
-                       pr_err("request OSL_BUF(%lu) > %ld\n",
-                               size, DHD_PREALLOC_OSL_BUF_SIZE);
-                       return NULL;
-               }
-               return wlan_static_osl_buf;
-       }
-
-       if (section == DHD_PREALLOC_DHD_INFO) {
-               if (size > DHD_PREALLOC_DHD_INFO_SIZE) {
-                       pr_err("request DHD_INFO size(%lu) > %d\n",
-                               size, DHD_PREALLOC_DHD_INFO_SIZE);
-                       return NULL;
-               }
-               return wlan_static_dhd_info_buf;
-       }
-       if (section == DHD_PREALLOC_DHD_WLFC_INFO) {
-               if (size > WLAN_DHD_WLFC_BUF_SIZE) {
-                       pr_err("request DHD_WLFC_INFO size(%lu) > %d\n",
-                               size, WLAN_DHD_WLFC_BUF_SIZE);
-                       return NULL;
-               }
-               return wlan_static_dhd_wlfc_info_buf;
-       }
-#ifdef BCMDHD_PCIE
-       if (section == DHD_PREALLOC_IF_FLOW_LKUP)  {
-               if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {
-                       pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n",
-                               size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_if_flow_lkup;
-       }
-#endif /* BCMDHD_PCIE */
-       if (section == DHD_PREALLOC_MEMDUMP_RAM) {
-               if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) {
-                       pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n",
-                               size, DHD_PREALLOC_MEMDUMP_RAM_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_dhd_memdump_ram_buf;
-       }
-       if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {
-               if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {
-                       pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n",
-                               size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);
-                       return NULL;
-               }
-               return wlan_static_dhd_wlfc_hanger_buf;
-       }
-       if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) {
-               if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) {
-                       pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n",
-                               size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_dhd_log_dump_buf;
-       }
-       if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) {
-               if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) {
-                       pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n",
-                               size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_dhd_log_dump_buf_ex;
-       }
-       if (section == DHD_PREALLOC_WL_WEXT_INFO) {
-               if (size > DHD_PREALLOC_WL_WEXT_INFO_SIZE) {
-                       pr_err("request DHD_PREALLOC_WL_WEXT_INFO_SIZE(%lu) > %d\n",
-                               size, DHD_PREALLOC_WL_WEXT_INFO_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_wl_escan_info_buf;
-       }
-       if (section == DHD_PREALLOC_FW_VERBOSE_RING) {
-               if (size > FW_VERBOSE_RING_SIZE) {
-                       pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n",
-                               size, FW_VERBOSE_RING_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_fw_verbose_ring_buf;
-       }
-       if (section == DHD_PREALLOC_FW_EVENT_RING) {
-               if (size > FW_EVENT_RING_SIZE) {
-                       pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n",
-                               size, FW_EVENT_RING_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_fw_event_ring_buf;
-       }
-       if (section == DHD_PREALLOC_DHD_EVENT_RING) {
-               if (size > DHD_EVENT_RING_SIZE) {
-                       pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n",
-                               size, DHD_EVENT_RING_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_dhd_event_ring_buf;
-       }
-       if (section == DHD_PREALLOC_NAN_EVENT_RING) {
-               if (size > NAN_EVENT_RING_SIZE) {
-                       pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n",
-                               size, NAN_EVENT_RING_SIZE);
-                       return NULL;
-               }
-
-               return wlan_static_nan_event_ring_buf;
-       }
-       if ((section < 0) || (section > DHD_PREALLOC_MAX))
-               pr_err("request section id(%d) is out of max index %d\n",
-                               section, DHD_PREALLOC_MAX);
-
-       pr_err("%s: failed to alloc section %d, size=%ld\n",
-               __func__, section, size);
-
-       return NULL;
-}
-EXPORT_SYMBOL(bcmdhd_mem_prealloc);
-
-int bcmdhd_init_wlan_mem(void)
-{
-       int i;
-       int j;
-       pr_info("%s(): %s\n", __func__, DHD_STATIC_VERSION_STR);
-
-       for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {
-               wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);
-               if (!wlan_static_skb[i])
-                       goto err_skb_alloc;
-       }
-
-       for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {
-               wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);
-               if (!wlan_static_skb[i])
-                       goto err_skb_alloc;
-       }
-
-#if defined(BCMDHD_SDIO)
-       wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);
-       if (!wlan_static_skb[i])
-               goto err_skb_alloc;
-#endif /* BCMDHD_SDIO */
-
-       wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);
-       if (!wlan_static_prot)
-               goto err_mem_alloc;
-
-#if defined(BCMDHD_SDIO)
-       wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);
-       if (!wlan_static_rxbuf)
-               goto err_mem_alloc;
-
-       wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);
-       if (!wlan_static_databuf)
-               goto err_mem_alloc;
-#endif /* BCMDHD_SDIO */
-
-       wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);
-       if (!wlan_static_osl_buf)
-               goto err_mem_alloc;
-
-       wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);
-       if (!wlan_static_scan_buf0)
-               goto err_mem_alloc;
-
-       wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_info_buf)
-               goto err_mem_alloc;
-
-       wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_wlfc_info_buf)
-               goto err_mem_alloc;
-
-#ifdef BCMDHD_PCIE
-       wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);
-       if (!wlan_static_if_flow_lkup)
-               goto err_mem_alloc;
-#endif /* BCMDHD_PCIE */
-
-       wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_memdump_ram_buf)
-               goto err_mem_alloc;
-
-       wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_wlfc_hanger_buf)
-               goto err_mem_alloc;
-
-       wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_log_dump_buf)
-               goto err_mem_alloc;
-
-       wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_log_dump_buf_ex)
-               goto err_mem_alloc;
-
-       wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_WEXT_INFO_SIZE, GFP_KERNEL);
-       if (!wlan_static_wl_escan_info_buf)
-               goto err_mem_alloc;
-
-       wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL);
-       if (!wlan_static_fw_verbose_ring_buf)
-               goto err_mem_alloc;
-
-       wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL);
-       if (!wlan_static_fw_event_ring_buf)
-               goto err_mem_alloc;
-
-       wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL);
-       if (!wlan_static_dhd_event_ring_buf)
-               goto err_mem_alloc;
-
-       wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL);
-       if (!wlan_static_nan_event_ring_buf)
-               goto err_mem_alloc;
-
-       pr_info("bcmdhd_init_wlan_mem prealloc ok\n");
-       return 0;
-
-err_mem_alloc:
-
-       if (wlan_static_prot)
-               kfree(wlan_static_prot);
-
-#if defined(BCMDHD_SDIO)
-       if (wlan_static_rxbuf)
-               kfree(wlan_static_rxbuf);
-
-       if (wlan_static_databuf)
-               kfree(wlan_static_databuf);
-#endif /* BCMDHD_SDIO */
-
-       if (wlan_static_osl_buf)
-               kfree(wlan_static_osl_buf);
-
-       if (wlan_static_scan_buf0)
-               kfree(wlan_static_scan_buf0);
-
-       if (wlan_static_scan_buf1)
-               kfree(wlan_static_scan_buf1);
-
-       if (wlan_static_dhd_info_buf)
-               kfree(wlan_static_dhd_info_buf);
-
-       if (wlan_static_dhd_wlfc_info_buf)
-               kfree(wlan_static_dhd_wlfc_info_buf);
-
-#ifdef BCMDHD_PCIE
-       if (wlan_static_if_flow_lkup)
-               kfree(wlan_static_if_flow_lkup);
-#endif /* BCMDHD_PCIE */
-
-       if (wlan_static_dhd_memdump_ram_buf)
-               kfree(wlan_static_dhd_memdump_ram_buf);
-
-       if (wlan_static_dhd_wlfc_hanger_buf)
-               kfree(wlan_static_dhd_wlfc_hanger_buf);
-
-       if (wlan_static_dhd_log_dump_buf)
-               kfree(wlan_static_dhd_log_dump_buf);
-
-       if (wlan_static_dhd_log_dump_buf_ex)
-               kfree(wlan_static_dhd_log_dump_buf_ex);
-
-       if (wlan_static_wl_escan_info_buf)
-               kfree(wlan_static_wl_escan_info_buf);
-
-#ifdef BCMDHD_PCIE
-       if (wlan_static_fw_verbose_ring_buf)
-               kfree(wlan_static_fw_verbose_ring_buf);
-
-       if (wlan_static_fw_event_ring_buf)
-               kfree(wlan_static_fw_event_ring_buf);
-
-       if (wlan_static_dhd_event_ring_buf)
-               kfree(wlan_static_dhd_event_ring_buf);
-
-       if (wlan_static_nan_event_ring_buf)
-               kfree(wlan_static_nan_event_ring_buf);
-#endif /* BCMDHD_PCIE */
-
-       pr_err("%s: Failed to mem_alloc for WLAN\n", __func__);
-
-       i = WLAN_SKB_BUF_NUM;
-
-err_skb_alloc:
-       pr_err("%s: Failed to skb_alloc for WLAN\n", __func__);
-       for (j = 0; j < i; j++)
-               dev_kfree_skb(wlan_static_skb[j]);
-
-       return -ENOMEM;
-}
-EXPORT_SYMBOL(bcmdhd_init_wlan_mem);
-MODULE_LICENSE("GPL");
-MODULE_AUTHOR("AMLOGIC");
-MODULE_DESCRIPTION("wifi device tree driver");
+#include <linux/module.h>\r
+#include <linux/kernel.h>\r
+#include <linux/init.h>\r
+#include <linux/platform_device.h>\r
+#include <linux/delay.h>\r
+#include <linux/err.h>\r
+#include <linux/skbuff.h>\r
+\r
+#define        DHD_STATIC_VERSION_STR          "100.10.545.7 (r826445-20200110-2)"\r
+\r
+#define BCMDHD_SDIO\r
+#define BCMDHD_PCIE\r
+\r
+enum dhd_prealloc_index {\r
+       DHD_PREALLOC_PROT = 0,\r
+#if defined(BCMDHD_SDIO)\r
+       DHD_PREALLOC_RXBUF = 1,\r
+       DHD_PREALLOC_DATABUF = 2,\r
+#endif\r
+       DHD_PREALLOC_OSL_BUF = 3,\r
+       DHD_PREALLOC_SKB_BUF = 4,\r
+       DHD_PREALLOC_WIPHY_ESCAN0 = 5,\r
+       DHD_PREALLOC_WIPHY_ESCAN1 = 6,\r
+       DHD_PREALLOC_DHD_INFO = 7,\r
+       DHD_PREALLOC_DHD_WLFC_INFO = 8,\r
+#ifdef BCMDHD_PCIE\r
+       DHD_PREALLOC_IF_FLOW_LKUP = 9,\r
+#endif\r
+       DHD_PREALLOC_MEMDUMP_BUF = 10,\r
+       DHD_PREALLOC_MEMDUMP_RAM = 11,\r
+       DHD_PREALLOC_DHD_WLFC_HANGER = 12,\r
+       DHD_PREALLOC_PKTID_MAP = 13,\r
+       DHD_PREALLOC_PKTID_MAP_IOCTL = 14,\r
+       DHD_PREALLOC_DHD_LOG_DUMP_BUF = 15,\r
+       DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX = 16,\r
+       DHD_PREALLOC_DHD_PKTLOG_DUMP_BUF = 17,\r
+       DHD_PREALLOC_STAT_REPORT_BUF = 18,\r
+       DHD_PREALLOC_WL_ESCAN = 19,\r
+       DHD_PREALLOC_FW_VERBOSE_RING = 20,\r
+       DHD_PREALLOC_FW_EVENT_RING = 21,\r
+       DHD_PREALLOC_DHD_EVENT_RING = 22,\r
+       DHD_PREALLOC_NAN_EVENT_RING = 23,\r
+       DHD_PREALLOC_MAX\r
+};\r
+\r
+#define STATIC_BUF_MAX_NUM     20\r
+#define STATIC_BUF_SIZE        (PAGE_SIZE*2)\r
+\r
+#ifndef CUSTOM_LOG_DUMP_BUFSIZE_MB\r
+#define CUSTOM_LOG_DUMP_BUFSIZE_MB     4 /* DHD_LOG_DUMP_BUF_SIZE 4 MB static memory in kernel */\r
+#endif /* CUSTOM_LOG_DUMP_BUFSIZE_MB */\r
+\r
+#define DHD_PREALLOC_PROT_SIZE (16 * 1024)\r
+#define DHD_PREALLOC_RXBUF_SIZE        (24 * 1024)\r
+#define DHD_PREALLOC_DATABUF_SIZE      (64 * 1024)\r
+#define DHD_PREALLOC_OSL_BUF_SIZE      (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)\r
+#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)\r
+#define DHD_PREALLOC_DHD_INFO_SIZE     (32 * 1024)\r
+#define DHD_PREALLOC_MEMDUMP_RAM_SIZE  (1290 * 1024)\r
+#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE      (73 * 1024)\r
+#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE (1024 * 1024 * CUSTOM_LOG_DUMP_BUFSIZE_MB)\r
+#define DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE (8 * 1024)\r
+#define DHD_PREALLOC_WL_ESCAN_SIZE     (70 * 1024)\r
+#ifdef CONFIG_64BIT\r
+#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)\r
+#else\r
+#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024)\r
+#endif\r
+#define FW_VERBOSE_RING_SIZE           (256 * 1024)\r
+#define FW_EVENT_RING_SIZE             (64 * 1024)\r
+#define DHD_EVENT_RING_SIZE            (64 * 1024)\r
+#define NAN_EVENT_RING_SIZE            (64 * 1024)\r
+\r
+#if defined(CONFIG_64BIT)\r
+#define WLAN_DHD_INFO_BUF_SIZE (24 * 1024)\r
+#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)\r
+#define WLAN_DHD_IF_FLOW_LKUP_SIZE     (64 * 1024)\r
+#else\r
+#define WLAN_DHD_INFO_BUF_SIZE (16 * 1024)\r
+#define WLAN_DHD_WLFC_BUF_SIZE (64 * 1024)\r
+#define WLAN_DHD_IF_FLOW_LKUP_SIZE     (20 * 1024)\r
+#endif /* CONFIG_64BIT */\r
+#define WLAN_DHD_MEMDUMP_SIZE  (800 * 1024)\r
+\r
+#define DHD_SKB_1PAGE_BUFSIZE  (PAGE_SIZE*1)\r
+#define DHD_SKB_2PAGE_BUFSIZE  (PAGE_SIZE*2)\r
+#define DHD_SKB_4PAGE_BUFSIZE  (PAGE_SIZE*4)\r
+\r
+#define DHD_SKB_1PAGE_BUF_NUM  8\r
+#ifdef BCMDHD_PCIE\r
+#define DHD_SKB_2PAGE_BUF_NUM  64\r
+#elif defined(BCMDHD_SDIO)\r
+#define DHD_SKB_2PAGE_BUF_NUM  8\r
+#endif\r
+#define DHD_SKB_4PAGE_BUF_NUM  1\r
+\r
+/* The number is defined in linux_osl.c\r
+ * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM\r
+ * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM\r
+ */\r
+#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \\r
+               (DHD_SKB_2PAGE_BUF_NUM))\r
+#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))\r
+\r
+void *wlan_static_prot = NULL;\r
+void *wlan_static_rxbuf = NULL;\r
+void *wlan_static_databuf = NULL;\r
+void *wlan_static_osl_buf = NULL;\r
+void *wlan_static_scan_buf0 = NULL;\r
+void *wlan_static_scan_buf1 = NULL;\r
+void *wlan_static_dhd_info_buf = NULL;\r
+void *wlan_static_dhd_wlfc_info_buf = NULL;\r
+void *wlan_static_if_flow_lkup = NULL;\r
+void *wlan_static_dhd_memdump_ram_buf = NULL;\r
+void *wlan_static_dhd_wlfc_hanger_buf = NULL;\r
+void *wlan_static_dhd_log_dump_buf = NULL;\r
+void *wlan_static_dhd_log_dump_buf_ex = NULL;\r
+void *wlan_static_wl_escan_info_buf = NULL;\r
+void *wlan_static_fw_verbose_ring_buf = NULL;\r
+void *wlan_static_fw_event_ring_buf = NULL;\r
+void *wlan_static_dhd_event_ring_buf = NULL;\r
+void *wlan_static_nan_event_ring_buf = NULL;\r
+\r
+static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];\r
+\r
+void *dhd_wlan_mem_prealloc(int section, unsigned long size)\r
+{\r
+       pr_err("%s: sectoin %d, %ld\n", __func__, section, size);\r
+       if (section == DHD_PREALLOC_PROT)\r
+               return wlan_static_prot;\r
+\r
+#if defined(BCMDHD_SDIO)\r
+       if (section == DHD_PREALLOC_RXBUF)\r
+               return wlan_static_rxbuf;\r
+\r
+       if (section == DHD_PREALLOC_DATABUF)\r
+               return wlan_static_databuf;\r
+#endif /* BCMDHD_SDIO */\r
+\r
+       if (section == DHD_PREALLOC_SKB_BUF)\r
+               return wlan_static_skb;\r
+\r
+       if (section == DHD_PREALLOC_WIPHY_ESCAN0)\r
+               return wlan_static_scan_buf0;\r
+\r
+       if (section == DHD_PREALLOC_WIPHY_ESCAN1)\r
+               return wlan_static_scan_buf1;\r
+\r
+       if (section == DHD_PREALLOC_OSL_BUF) {\r
+               if (size > DHD_PREALLOC_OSL_BUF_SIZE) {\r
+                       pr_err("request OSL_BUF(%lu) > %ld\n",\r
+                               size, DHD_PREALLOC_OSL_BUF_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_osl_buf;\r
+       }\r
+\r
+       if (section == DHD_PREALLOC_DHD_INFO) {\r
+               if (size > DHD_PREALLOC_DHD_INFO_SIZE) {\r
+                       pr_err("request DHD_INFO size(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_DHD_INFO_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_dhd_info_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_DHD_WLFC_INFO) {\r
+               if (size > WLAN_DHD_WLFC_BUF_SIZE) {\r
+                       pr_err("request DHD_WLFC_INFO size(%lu) > %d\n",\r
+                               size, WLAN_DHD_WLFC_BUF_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_dhd_wlfc_info_buf;\r
+       }\r
+#ifdef BCMDHD_PCIE\r
+       if (section == DHD_PREALLOC_IF_FLOW_LKUP)  {\r
+               if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {\r
+                       pr_err("request DHD_IF_FLOW_LKUP size(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_if_flow_lkup;\r
+       }\r
+#endif /* BCMDHD_PCIE */\r
+       if (section == DHD_PREALLOC_MEMDUMP_RAM) {\r
+               if (size > DHD_PREALLOC_MEMDUMP_RAM_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_MEMDUMP_RAM_SIZE(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_MEMDUMP_RAM_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_dhd_memdump_ram_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {\r
+               if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {\r
+                       pr_err("request DHD_WLFC_HANGER size(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_dhd_wlfc_hanger_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF) {\r
+               if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_dhd_log_dump_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX) {\r
+               if (size > DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_dhd_log_dump_buf_ex;\r
+       }\r
+       if (section == DHD_PREALLOC_WL_ESCAN) {\r
+               if (size > DHD_PREALLOC_WL_ESCAN_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_WL_ESCAN_SIZE(%lu) > %d\n",\r
+                               size, DHD_PREALLOC_WL_ESCAN_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_wl_escan_info_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_FW_VERBOSE_RING) {\r
+               if (size > FW_VERBOSE_RING_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_FW_VERBOSE_RING(%lu) > %d\n",\r
+                               size, FW_VERBOSE_RING_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_fw_verbose_ring_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_FW_EVENT_RING) {\r
+               if (size > FW_EVENT_RING_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_FW_EVENT_RING(%lu) > %d\n",\r
+                               size, FW_EVENT_RING_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_fw_event_ring_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_DHD_EVENT_RING) {\r
+               if (size > DHD_EVENT_RING_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_DHD_EVENT_RING(%lu) > %d\n",\r
+                               size, DHD_EVENT_RING_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_dhd_event_ring_buf;\r
+       }\r
+       if (section == DHD_PREALLOC_NAN_EVENT_RING) {\r
+               if (size > NAN_EVENT_RING_SIZE) {\r
+                       pr_err("request DHD_PREALLOC_NAN_EVENT_RING(%lu) > %d\n",\r
+                               size, NAN_EVENT_RING_SIZE);\r
+                       return NULL;\r
+               }\r
+\r
+               return wlan_static_nan_event_ring_buf;\r
+       }\r
+       if ((section < 0) || (section > DHD_PREALLOC_MAX))\r
+               pr_err("request section id(%d) is out of max index %d\n",\r
+                               section, DHD_PREALLOC_MAX);\r
+\r
+       pr_err("%s: failed to alloc section %d, size=%ld\n",\r
+               __func__, section, size);\r
+\r
+       return NULL;\r
+}\r
+EXPORT_SYMBOL(dhd_wlan_mem_prealloc);\r
+\r
+static int dhd_init_wlan_mem(void)\r
+{\r
+       int i;\r
+       int j;\r
+       printk(KERN_ERR "%s(): %s\n", __func__, DHD_STATIC_VERSION_STR);\r
+\r
+       for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
+               wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);\r
+               if (!wlan_static_skb[i]) {\r
+                       goto err_skb_alloc;\r
+               }\r
+               pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__,\r
+                       DHD_PREALLOC_SKB_BUF, i, DHD_SKB_1PAGE_BUFSIZE);\r
+       }\r
+\r
+       for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {\r
+               wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);\r
+               if (!wlan_static_skb[i]) {\r
+                       goto err_skb_alloc;\r
+               }\r
+               pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__,\r
+                       DHD_PREALLOC_SKB_BUF, i, DHD_SKB_2PAGE_BUFSIZE);\r
+       }\r
+\r
+#if defined(BCMDHD_SDIO)\r
+       wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);\r
+       if (!wlan_static_skb[i])\r
+               goto err_skb_alloc;\r
+       pr_err("%s: sectoin %d skb[%d], size=%ld\n", __func__,\r
+               DHD_PREALLOC_SKB_BUF, i, DHD_SKB_4PAGE_BUFSIZE);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+       wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_prot)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_PROT, DHD_PREALLOC_PROT_SIZE);\r
+\r
+#if defined(BCMDHD_SDIO)\r
+       wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_rxbuf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_RXBUF, DHD_PREALLOC_RXBUF_SIZE);\r
+\r
+       wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_databuf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DATABUF, DHD_PREALLOC_DATABUF_SIZE);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+       wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_osl_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%ld\n", __func__,\r
+               DHD_PREALLOC_OSL_BUF, DHD_PREALLOC_OSL_BUF_SIZE);\r
+\r
+       wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_scan_buf0)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_WIPHY_ESCAN0, DHD_PREALLOC_WIPHY_ESCAN0_SIZE);\r
+\r
+       wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_info_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DHD_INFO, DHD_PREALLOC_DHD_INFO_SIZE);\r
+\r
+       wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_wlfc_info_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DHD_WLFC_INFO, WLAN_DHD_WLFC_BUF_SIZE);\r
+\r
+#ifdef BCMDHD_PCIE\r
+       wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_if_flow_lkup)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_IF_FLOW_LKUP, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+       wlan_static_dhd_memdump_ram_buf = kmalloc(DHD_PREALLOC_MEMDUMP_RAM_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_memdump_ram_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_MEMDUMP_RAM, DHD_PREALLOC_MEMDUMP_RAM_SIZE);\r
+\r
+       wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_wlfc_hanger_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);\r
+\r
+       wlan_static_dhd_log_dump_buf = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_log_dump_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DHD_LOG_DUMP_BUF, DHD_PREALLOC_DHD_LOG_DUMP_BUF_SIZE);\r
+\r
+       wlan_static_dhd_log_dump_buf_ex = kmalloc(DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_log_dump_buf_ex)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX, DHD_PREALLOC_DHD_LOG_DUMP_BUF_EX_SIZE);\r
+\r
+       wlan_static_wl_escan_info_buf = kmalloc(DHD_PREALLOC_WL_ESCAN_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_wl_escan_info_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_WL_ESCAN, DHD_PREALLOC_WL_ESCAN_SIZE);\r
+\r
+       wlan_static_fw_verbose_ring_buf = kmalloc(FW_VERBOSE_RING_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_fw_verbose_ring_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_FW_VERBOSE_RING, FW_VERBOSE_RING_SIZE);\r
+\r
+       wlan_static_fw_event_ring_buf = kmalloc(FW_EVENT_RING_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_fw_event_ring_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_FW_EVENT_RING, FW_EVENT_RING_SIZE);\r
+\r
+       wlan_static_dhd_event_ring_buf = kmalloc(DHD_EVENT_RING_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_event_ring_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_DHD_EVENT_RING, DHD_EVENT_RING_SIZE);\r
+\r
+       wlan_static_nan_event_ring_buf = kmalloc(NAN_EVENT_RING_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_nan_event_ring_buf)\r
+               goto err_mem_alloc;\r
+       pr_err("%s: sectoin %d, size=%d\n", __func__,\r
+               DHD_PREALLOC_NAN_EVENT_RING, NAN_EVENT_RING_SIZE);\r
+\r
+       return 0;\r
+\r
+err_mem_alloc:\r
+\r
+       if (wlan_static_prot)\r
+               kfree(wlan_static_prot);\r
+\r
+#if defined(BCMDHD_SDIO)\r
+       if (wlan_static_rxbuf)\r
+               kfree(wlan_static_rxbuf);\r
+\r
+       if (wlan_static_databuf)\r
+               kfree(wlan_static_databuf);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+       if (wlan_static_osl_buf)\r
+               kfree(wlan_static_osl_buf);\r
+\r
+       if (wlan_static_scan_buf0)\r
+               kfree(wlan_static_scan_buf0);\r
+\r
+       if (wlan_static_scan_buf1)\r
+               kfree(wlan_static_scan_buf1);\r
+\r
+       if (wlan_static_dhd_info_buf)\r
+               kfree(wlan_static_dhd_info_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_info_buf)\r
+               kfree(wlan_static_dhd_wlfc_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+       if (wlan_static_if_flow_lkup)\r
+               kfree(wlan_static_if_flow_lkup);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+       if (wlan_static_dhd_memdump_ram_buf)\r
+               kfree(wlan_static_dhd_memdump_ram_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_hanger_buf)\r
+               kfree(wlan_static_dhd_wlfc_hanger_buf);\r
+\r
+       if (wlan_static_dhd_log_dump_buf)\r
+               kfree(wlan_static_dhd_log_dump_buf);\r
+\r
+       if (wlan_static_dhd_log_dump_buf_ex)\r
+               kfree(wlan_static_dhd_log_dump_buf_ex);\r
+\r
+       if (wlan_static_wl_escan_info_buf)\r
+               kfree(wlan_static_wl_escan_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+       if (wlan_static_fw_verbose_ring_buf)\r
+               kfree(wlan_static_fw_verbose_ring_buf);\r
+\r
+       if (wlan_static_fw_event_ring_buf)\r
+               kfree(wlan_static_fw_event_ring_buf);\r
+\r
+       if (wlan_static_dhd_event_ring_buf)\r
+               kfree(wlan_static_dhd_event_ring_buf);\r
+\r
+       if (wlan_static_nan_event_ring_buf)\r
+               kfree(wlan_static_nan_event_ring_buf);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+       pr_err("%s: Failed to mem_alloc for WLAN\n", __func__);\r
+\r
+       i = WLAN_SKB_BUF_NUM;\r
+\r
+err_skb_alloc:\r
+       pr_err("%s: Failed to skb_alloc for WLAN\n", __func__);\r
+       for (j = 0; j < i; j++)\r
+               dev_kfree_skb(wlan_static_skb[j]);\r
+\r
+       return -ENOMEM;\r
+}\r
+\r
+static int __init\r
+dhd_static_buf_init(void)\r
+{\r
+       dhd_init_wlan_mem();\r
+\r
+       return 0;\r
+}\r
+\r
+static void __exit\r
+dhd_static_buf_exit(void)\r
+{\r
+       int i;\r
+\r
+       pr_err("%s()\n", __FUNCTION__);\r
+\r
+       for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
+               if (wlan_static_skb[i])\r
+                       dev_kfree_skb(wlan_static_skb[i]);\r
+       }\r
+\r
+       for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {\r
+               if (wlan_static_skb[i])\r
+                       dev_kfree_skb(wlan_static_skb[i]);\r
+       }\r
+\r
+#if defined(BCMDHD_SDIO)\r
+       if (wlan_static_skb[i])\r
+               dev_kfree_skb(wlan_static_skb[i]);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+       if (wlan_static_prot)\r
+               kfree(wlan_static_prot);\r
+\r
+#if defined(BCMDHD_SDIO)\r
+       if (wlan_static_rxbuf)\r
+               kfree(wlan_static_rxbuf);\r
+\r
+       if (wlan_static_databuf)\r
+               kfree(wlan_static_databuf);\r
+#endif /* BCMDHD_SDIO */\r
+\r
+       if (wlan_static_osl_buf)\r
+               kfree(wlan_static_osl_buf);\r
+\r
+       if (wlan_static_scan_buf0)\r
+               kfree(wlan_static_scan_buf0);\r
+\r
+       if (wlan_static_scan_buf1)\r
+               kfree(wlan_static_scan_buf1);\r
+\r
+       if (wlan_static_dhd_info_buf)\r
+               kfree(wlan_static_dhd_info_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_info_buf)\r
+               kfree(wlan_static_dhd_wlfc_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+       if (wlan_static_if_flow_lkup)\r
+               kfree(wlan_static_if_flow_lkup);\r
+#endif /* BCMDHD_PCIE */\r
+\r
+       if (wlan_static_dhd_memdump_ram_buf)\r
+               kfree(wlan_static_dhd_memdump_ram_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_hanger_buf)\r
+               kfree(wlan_static_dhd_wlfc_hanger_buf);\r
+\r
+       if (wlan_static_dhd_log_dump_buf)\r
+               kfree(wlan_static_dhd_log_dump_buf);\r
+\r
+       if (wlan_static_dhd_log_dump_buf_ex)\r
+               kfree(wlan_static_dhd_log_dump_buf_ex);\r
+\r
+       if (wlan_static_wl_escan_info_buf)\r
+               kfree(wlan_static_wl_escan_info_buf);\r
+\r
+#ifdef BCMDHD_PCIE\r
+       if (wlan_static_fw_verbose_ring_buf)\r
+               kfree(wlan_static_fw_verbose_ring_buf);\r
+\r
+       if (wlan_static_fw_event_ring_buf)\r
+               kfree(wlan_static_fw_event_ring_buf);\r
+\r
+       if (wlan_static_dhd_event_ring_buf)\r
+               kfree(wlan_static_dhd_event_ring_buf);\r
+\r
+       if (wlan_static_nan_event_ring_buf)\r
+               kfree(wlan_static_nan_event_ring_buf);\r
+#endif\r
+\r
+       return;\r
+}\r
+\r
+module_init(dhd_static_buf_init);\r
+\r
+module_exit(dhd_static_buf_exit);\r
index a7f034ee233f713ea91639befd4c819cafc4aa4a..a54ed81243c73854ce3fe57364f20971f0d79aa0 100644 (file)
@@ -41,6 +41,7 @@
 
 #include <dhd_dbg.h>
 #include <dhd_config.h>
+#include <wl_android.h>
 
 #ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */
 #include <wlfc_proto.h>
@@ -1322,6 +1323,9 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, int prec,
                ASSERT(entry);
 
                if (entry->occupied && _dhd_wlfc_is_destination_open(ctx, entry, prec) &&
+#ifdef PROPTX_MAXCOUNT
+                       (entry->transit_count < entry->transit_maxcount) &&
+#endif /* PROPTX_MAXCOUNT */
                        (entry->transit_count < WL_TXSTATUS_FREERUNCTR_MASK) &&
                        (!entry->suppressed)) {
                        *ac_credit_spent = credit_spent;
@@ -1828,6 +1832,9 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t*
                if (action == eWLFC_MAC_ENTRY_ACTION_ADD) {
                        entry->suppressed = FALSE;
                        entry->transit_count = 0;
+#ifdef PROPTX_MAXCOUNT
+                       entry->transit_maxcount = wl_ext_get_wlfc_maxcount(ctx->dhdp, ifid);
+#endif /* PROPTX_MAXCOUNT */
                        entry->suppr_transit_count = 0;
                        entry->onbus_pkts_count = 0;
                }
@@ -4573,4 +4580,36 @@ int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val)
        return BCME_OK;
 }
 
+#ifdef PROPTX_MAXCOUNT
+int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount)
+{
+       athost_wl_status_info_t* ctx;
+       int rc = 0;
+
+       if (dhdp == NULL) {
+               DHD_ERROR(("%s: dhdp is NULL\n", __FUNCTION__));
+               return BCME_BADARG;
+       }
+
+       dhd_os_wlfc_block(dhdp);
+
+       if (!dhdp->wlfc_state || (dhdp->proptxstatus_mode == WLFC_FCMODE_NONE)) {
+               rc = WLFC_UNSUPPORTED;
+               goto exit;
+       }
+
+       if (ifid >= WLFC_MAX_IFNUM) {
+               DHD_ERROR(("%s: bad ifid\n", __FUNCTION__));
+               rc = BCME_BADARG;
+               goto exit;
+       }
+
+       ctx = (athost_wl_status_info_t*)dhdp->wlfc_state;
+       ctx->destination_entries.interfaces[ifid].transit_maxcount = maxcount;
+exit:
+       dhd_os_wlfc_unblock(dhdp);
+       return rc;
+}
+#endif /* PROPTX_MAXCOUNT */
+
 #endif /* PROP_TXSTATUS */
index 88b0650ab91ec5e0f4c895546e0542362c6d70f7..7ca1968a4e9715bbc04336b401836dc23b3d64e2 100644 (file)
@@ -166,6 +166,10 @@ typedef struct wlfc_mac_descriptor {
        uint32 opened_ct;
        uint32 closed_ct;
 #endif // endif
+#ifdef PROPTX_MAXCOUNT
+       /** Max Number of packets at dongle for this entry. */
+       int transit_maxcount;
+#endif /* PROPTX_MAXCOUNT */
        struct wlfc_mac_descriptor* prev;
        struct wlfc_mac_descriptor* next;
 } wlfc_mac_descriptor_t;
@@ -558,5 +562,8 @@ int dhd_wlfc_set_txstatus_ignore(dhd_pub_t *dhd, int val);
 
 int dhd_wlfc_get_rxpkt_chk(dhd_pub_t *dhd, int *val);
 int dhd_wlfc_set_rxpkt_chk(dhd_pub_t *dhd, int val);
+#ifdef PROPTX_MAXCOUNT
+int dhd_wlfc_update_maxcount(dhd_pub_t *dhdp, uint8 ifid, int maxcount);
+#endif /* PROPTX_MAXCOUNT */
 
 #endif /* __wlfc_host_driver_definitions_h__ */
index 247400d9f28033600f9ef660e38032df5dcd0ea7..edb9c40c6869f06b3f46f4575b828e9c12a2f631 100644 (file)
 #define BCM4362_D11AX_ID       0x4490          /* 4362 802.11ax dualband device */
 #define BCM4362_D11AX2G_ID     0x4491          /* 4362 802.11ax 2.4G device */
 #define BCM4362_D11AX5G_ID     0x4492          /* 4362 802.11ax 5G device */
-#define BCM43751_D11AX_ID      0x4490          /* 43751 802.11ax dualband device */
-#define BCM43751_D11AX2G_ID    0x4491          /* 43751 802.11ax 2.4G device */
-#define BCM43751_D11AX5G_ID    0x4492          /* 43751 802.11ax 5G device */
-#define BCM43752_D11AX_ID      0x4490          /* 43752 802.11ax dualband device */
-#define BCM43752_D11AX2G_ID    0x4491          /* 43752 802.11ax 2.4G device */
-#define BCM43752_D11AX5G_ID    0x4492          /* 43752 802.11ax 5G device */
+#define BCM43751_D11AX_ID      0x449a          /* 43751 802.11ax dualband device */
+#define BCM43751_D11AX2G_ID    0x449b          /* 43751 802.11ax 2.4G device */
+#define BCM43751_D11AX5G_ID    0x449c          /* 43751 802.11ax 5G device */
+#define BCM43752_D11AX_ID      0x449d          /* 43752 802.11ax dualband device */
+#define BCM43752_D11AX2G_ID    0x449e          /* 43752 802.11ax 2.4G device */
+#define BCM43752_D11AX5G_ID    0x449f          /* 43752 802.11ax 5G device */
 
 #define BCM4364_D11AC_ID       0x4464          /* 4364 802.11ac dualband device */
 #define BCM4364_D11AC2G_ID     0x446a          /* 4364 802.11ac 2.4G device */
 #define BCM4369_CHIP_GRPID             BCM4369_CHIP_ID: \
                                        case BCM4377_CHIP_ID
 
-#define BCM4362_CHIP(chipid)   (CHIPID(chipid) == BCM4362_CHIP_ID)
-#define BCM4362_CHIP_GRPID     BCM4362_CHIP_ID
+#define BCM4362_CHIP(chipid)   ((CHIPID(chipid) == BCM4362_CHIP_ID) || \
+                               (CHIPID(chipid) == BCM43751_CHIP_ID) || \
+                               (CHIPID(chipid) == BCM43752_CHIP_ID))
+#define BCM4362_CHIP_GRPID     BCM4362_CHIP_ID: \
+                               case BCM43751_CHIP_ID: \
+                               case BCM43752_CHIP_ID
 
 #define BCM4365_CHIP_ID                0x4365          /* 4365 chipcommon chipid */
 #define BCM4366_CHIP_ID                0x4366          /* 4366 chipcommon chipid */
index 1dbb7b5397ebadc48f471699ea109f0d2be14206..97adab151ca6c7fb3b397f25a3614d887f1de888 100644 (file)
@@ -175,7 +175,11 @@ typedef union bcm_event_msg_u {
 #define WLC_E_ACTION_FRAME_COMPLETE    60      /* Action frame Tx complete */
 #define WLC_E_PRE_ASSOC_IND    61      /* assoc request received */
 #define WLC_E_PRE_REASSOC_IND  62      /* re-assoc request received */
+#ifdef CSI_SUPPORT
+#define WLC_E_CSI              63
+#else
 #define WLC_E_CHANNEL_ADOPTED  63
+#endif /* CSI_SUPPORT */
 #define WLC_E_AP_STARTED       64      /* AP started */
 #define WLC_E_DFS_AP_STOP      65      /* AP stopped due to DFS */
 #define WLC_E_DFS_AP_RESUME    66      /* AP resumed due to DFS */
@@ -591,6 +595,9 @@ typedef struct wl_event_data_natoe {
 #define WLC_E_IF_ROLE_WDS              2       /* WDS link */
 #define WLC_E_IF_ROLE_P2P_GO           3       /* P2P Group Owner */
 #define WLC_E_IF_ROLE_P2P_CLIENT       4       /* P2P Client */
+#ifdef WLMESH_CFG80211
+#define WLC_E_IF_ROLE_MESH             5       /* MESH */
+#endif /* WLMESH_CFG80211 */
 #define WLC_E_IF_ROLE_IBSS             8       /* IBSS */
 #define WLC_E_IF_ROLE_NAN              9       /* NAN */
 
index 8e745138c41669a23ac6231559d9c7be1444ffbb..fa2675d3d3c7ada0fc35b9cfce7bb85c9faab4d0 100644 (file)
@@ -179,6 +179,12 @@ typedef enum {
 #define DHD_IW_VAL     0x20000
 #define DHD_CFG_VAL    0x40000
 #define DHD_CONFIG_VAL 0x80000
+#define DUMP_EAPOL_VAL 0x0001
+#define DUMP_ARP_VAL   0x0002
+#define DUMP_DHCP_VAL  0x0004
+#define DUMP_ICMP_VAL  0x0008
+#define DUMP_DNS_VAL   0x0010
+#define DUMP_TRX_VAL   0x0080
 
 #ifdef SDTEST
 /* For pktgen iovar */
index 88c63db2302c6d5298897c7b6a419e87d05914df..db6ea090de3a987cc50536ae3b935b016ba6e94f 100644 (file)
@@ -46,6 +46,6 @@
 #define EPI_VERSION_DEV                100.10.545
 
 /* Driver Version String, ASCII, 32 chars max */
-#define        EPI_VERSION_STR         "100.10.545.4 (r826445-20190826-1) (amlogic-20190916-1)"
+#define        EPI_VERSION_STR         "100.10.545.11 (r826445-20200610-1)"
 
 #endif /* _epivers_h_ */
index fd4384d791c894e424936cb3b3b31fbb24544a8c..8d6fc34f208533a418d76090bee658e1c12247c4 100644 (file)
@@ -340,7 +340,7 @@ extern uint64 osl_systztime_us(void);
 #define OSL_LOCALTIME_NS()     osl_localtime_ns()
 #define OSL_GET_LOCALTIME(sec, usec)   osl_get_localtime((sec), (usec))
 #define OSL_SYSTZTIME_US()     osl_systztime_us()
-#define        printf(fmt, args...)    printk(fmt , ## args)
+#define        printf(fmt, args...)    printk("[dhd] " fmt , ## args)
 #include <linux/kernel.h>      /* for vsn/printf's */
 #include <linux/string.h>      /* for mem*, str* */
 /* bcopy's: Linux kernel doesn't provide these (anymore) */
@@ -445,7 +445,11 @@ extern uint64 osl_systztime_us(void);
 
 /* map/unmap physical to virtual I/O */
 #if !defined(CONFIG_MMC_MSM7X00A)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+#define        REG_MAP(pa, size)       ioremap((unsigned long)(pa), (unsigned long)(size))
+#else
 #define        REG_MAP(pa, size)       ioremap_nocache((unsigned long)(pa), (unsigned long)(size))
+#endif
 #else
 #define REG_MAP(pa, size)       (void *)(0)
 #endif /* !defined(CONFIG_MMC_MSM7X00A */
@@ -617,7 +621,11 @@ extern unsigned long osl_spin_lock(void *lock);
 extern void osl_spin_unlock(void *lock, unsigned long flags);
 
 typedef struct osl_timespec {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0))
+       __kernel_old_time_t     tv_sec;                 /* seconds */
+#else
        __kernel_time_t tv_sec;                 /* seconds */
+#endif
        __kernel_suseconds_t    tv_usec;        /* microseconds */
        long            tv_nsec;                /* nanoseconds */
 } osl_timespec_t;
index 6dc718d1aa9c0da128758199cb5a42299e617771..16aefaf61cf7fd75809d741360a99f919aafc160 100644 (file)
@@ -19890,6 +19890,13 @@ enum wl_sc_cmd {
        WL_SC_CMD_LAST
 };
 
+typedef struct wl_ext_auth_evt {
+       wlc_ssid_t ssid;
+       struct ether_addr bssid;
+       unsigned int key_mgmt_suite;
+       int status;
+} wl_ext_auth_evt_t;
+
 /* WBUS sub-command IDs for unit test */
 #define WL_WBUS_INA_SLOT_START                0x01u /**< Inactive slot start sub command ID. */
 #define WL_WBUS_INA_SLOT_STOP                 0x02u /**< Inactive slot stop sub command ID. */
index aa73924f20aa752cf8bd5fedf3f2c96d6cfa5573..4f0ee1dfe16b00ff9876f015d0201de6437a1cc9 100644 (file)
 #define WLC_GET_RSSI_QDB                       321 /* qdB portion of the RSSI */
 #define WLC_DUMP_RATESET                       322
 #define WLC_ECHO                               323
-#define WLC_LAST                               324     /* The last ioctl. Also push this
+#define WLC_SCB_AUTHENTICATE   325
+#define WLC_LAST                               326     /* The last ioctl. Also push this
                                                         * number when adding new ioctls
                                                         */
 /*
 #define WL_AUTH_OPEN_SYSTEM            0       /* d11 open authentication */
 #define WL_AUTH_SHARED_KEY             1       /* d11 shared authentication */
 #define WL_AUTH_OPEN_SHARED            2       /* try open, then shared if open failed w/rc 13 */
+#define WL_AUTH_SAE_KEY                        3       /* d11 sae authentication */
 #define WL_AUTH_FILS_SHARED            4       /* d11 fils shared key authentication */
 #define WL_AUTH_FILS_SHARED_PFS                5       /* d11 fils shared key w/ pfs authentication */
 #define WL_AUTH_FILS_PUBLIC            6       /* d11 fils public key authentication */
index 1e853ccb4e46f5ab9de046cba8c29efc4b3b13db..e48c0c8985065f1623707840ce3fea979a7447ba 100644 (file)
@@ -1208,10 +1208,10 @@ osl_get_localtime(uint64 *sec, uint64 *usec)
 uint64
 osl_systztime_us(void)
 {
-       struct timeval tv;
+       struct osl_timespec tv;
        uint64 tzusec;
 
-       do_gettimeofday(&tv);
+       osl_do_gettimeofday(&tv);
        /* apply timezone */
        tzusec = (uint64)((tv.tv_sec - (sys_tz.tz_minuteswest * 60)) *
                USEC_PER_SEC);
@@ -2064,13 +2064,19 @@ osl_dma_lock_init(osl_t *osh)
 void
 osl_do_gettimeofday(struct osl_timespec *ts)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+       struct timespec64 curtime;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
        struct timespec curtime;
 #else
        struct timeval curtime;
 #endif
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+       ktime_get_real_ts64(&curtime);
+       ts->tv_nsec = curtime.tv_nsec;
+       ts->tv_usec     = curtime.tv_nsec / 1000;
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
        getnstimeofday(&curtime);
        ts->tv_nsec = curtime.tv_nsec;
        ts->tv_usec = curtime.tv_nsec / 1000;
@@ -2085,9 +2091,15 @@ osl_do_gettimeofday(struct osl_timespec *ts)
 void
 osl_get_monotonic_boottime(struct osl_timespec *ts)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+       struct timespec64 curtime;
+#else
        struct timespec curtime;
+#endif
 
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 6, 0)
+       curtime = ktime_to_timespec64(ktime_get_boottime());
+#elif LINUX_VERSION_CODE >= KERNEL_VERSION(4, 20, 0)
        curtime = ktime_to_timespec(ktime_get_boottime());
 #else
        get_monotonic_boottime(&curtime);
index bfc245fc1b54f542fb0f385b5dafd9b29e4742bd..994430f15c2358326afeb4103b55412f6685d132 100644 (file)
@@ -348,7 +348,7 @@ si_get_pmu_reg_addr(si_t *sih, uint32 offset)
                pmuaddr = SI_ENUM_BASE(sih) + offset;
 
 done:
-       printf("%s: addrRET: %x\n", __FUNCTION__, pmuaddr);
+       SI_MSG(("%s: addrRET: %x\n", __FUNCTION__, pmuaddr));
        return pmuaddr;
 }
 
index f9144988ff64d8e21b2dd8cc3fd93ff0d38f56a0..84a46675b2333477cff5f4b97883be90c1741c63 100644 (file)
@@ -2994,73 +2994,6 @@ extern int g_mhs_chan_for_cpcoex;
 #define APCS_DEFAULT_2G_CH     1
 #define APCS_DEFAULT_5G_CH     149
 
-#ifdef WL_ESCAN
-static int
-wl_android_escan_autochannel(struct net_device *dev, uint32 band)
-{
-       struct dhd_pub *dhd = dhd_get_pub(dev);
-       wlc_ssid_t ssid;
-       struct wl_escan_info *escan = NULL;
-       int ret = 0, retry = 0, retry_max, retry_interval = 250, channel = 0, up = 1;
-#ifdef WL_CFG80211
-       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
-#endif
-
-       escan = dhd->escan;
-       if (dhd) {
-               retry_max = WL_ESCAN_TIMER_INTERVAL_MS/retry_interval;
-               memset(&ssid, 0, sizeof(ssid));
-               ret = wldev_ioctl_get(dev, WLC_GET_UP, &up, sizeof(s32));
-               if (ret < 0 || up == 0) {
-                       ret = wldev_ioctl_set(dev, WLC_UP, &up, sizeof(s32));
-               }
-               retry = retry_max;
-               while (retry--) {
-#ifdef WL_CFG80211
-                       if (wl_get_drv_status_all(cfg, SCANNING) ||
-                                       escan->escan_state == ESCAN_STATE_SCANING)
-#else
-                       if (escan->escan_state == ESCAN_STATE_SCANING)
-#endif
-                       {
-                               ANDROID_INFO(("Scanning %d tried, ret = %d\n",
-                                       (retry_max - retry), ret));
-                       } else {
-                               escan->autochannel = 1;
-                               ret = wl_escan_set_scan(dev, dhd, &ssid, TRUE);
-                               if (!ret)
-                                       break;
-                       }
-                       OSL_SLEEP(retry_interval);
-               }
-               if ((retry == 0) || (ret < 0))
-                       goto done;
-               retry = retry_max;
-               while (retry--) {
-                       if (escan->escan_state == ESCAN_STATE_IDLE) {
-                               if (band == WLC_BAND_5G)
-                                       channel = escan->best_5g_ch;
-                               else
-                                       channel = escan->best_2g_ch;
-                               WL_MSG(dev->name, "selected channel = %d\n", channel);
-                               goto done;
-                       }
-                       ANDROID_INFO(("escan_state=%d, %d tried, ret = %d\n",
-                               escan->escan_state, (retry_max - retry), ret));
-                       OSL_SLEEP(retry_interval);
-               }
-               if ((retry == 0) || (ret < 0))
-                       goto done;
-       }
-
-done:
-       if (escan)
-               escan->autochannel = 0;
-
-       return channel;
-}
-#endif /* WL_ESCAN */
-
 static int
 wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
        char* command, int total_len)
@@ -3145,13 +3078,11 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
                goto done2;
        }
 
-#ifdef WL_ESCAN
-       channel = wl_android_escan_autochannel(dev, band);
+       channel = wl_ext_autochannel(dev, ACS_FW_BIT|ACS_DRV_BIT, band);
        if (channel)
                goto done2;
        else
                goto done;
-#endif /* WL_ESCAN */
 
        ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
        if (ret) {
@@ -3944,7 +3875,7 @@ wl_android_set_rps_cpus(struct net_device *dev, char *command)
        enable = command[strlen(CMD_RPSMODE) + 1] - '0';
        error = dhd_rps_cpus_enable(dev, enable);
 
-#if defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
+#if 0 //defined(DHDTCPACK_SUPPRESS) && defined(BCMPCIE) && defined(WL_CFG80211)
        if (!error) {
                void *dhdp = wl_cfg80211_get_dhdp(net);
                if (enable) {
@@ -6512,6 +6443,7 @@ wl_android_set_wifi_on_flag(bool enable)
 #endif /* BT_OVER_SDIO */
 
 #ifdef WL_STATIC_IF
+#include <dhd_linux_priv.h>
 struct net_device *
 wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifname)
 {
@@ -6523,6 +6455,10 @@ wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifnam
 #ifdef DHD_USE_RANDMAC
        struct ether_addr ea_addr;
 #endif /* DHD_USE_RANDMAC */
+#ifdef CUSTOM_MULTI_MAC
+       char hw_ether[62];
+       dhd_pub_t *dhd = cfg->pub;
+#endif
 
        WL_INFORM_MEM(("[STATIC_IF] Enter (%s) iftype:%d\n", ifname, iftype));
 
@@ -6536,9 +6472,17 @@ wl_cfg80211_register_static_if(struct bcm_cfg80211 *cfg, u16 iftype, char *ifnam
        dhd_generate_mac_addr(&ea_addr);
        (void)memcpy_s(mac_addr, ETH_ALEN, ea_addr.octet, ETH_ALEN);
 #else
+#if defined(CUSTOM_MULTI_MAC)
+       if (wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, "wlan1")) {
+#endif
        /* Use primary mac with locally admin bit set */
        (void)memcpy_s(mac_addr, ETH_ALEN, primary_ndev->dev_addr, ETH_ALEN);
        mac_addr[0] |= 0x02;
+#if defined(CUSTOM_MULTI_MAC)
+       } else {
+               (void)memcpy_s(mac_addr, ETH_ALEN, hw_ether, ETH_ALEN);
+       }
+#endif
 #endif /* DHD_USE_RANDMAC */
 
        ndev = wl_cfg80211_allocate_if(cfg, ifidx, ifname, mac_addr,
@@ -6601,6 +6545,10 @@ wl_cfg80211_static_if_open(struct net_device *net)
        struct net_device *primary_ndev = bcmcfg_to_prmry_ndev(cfg);
        u16 iftype = net->ieee80211_ptr ? net->ieee80211_ptr->iftype : 0;
        u16 wl_iftype, wl_mode;
+#ifdef CUSTOM_MULTI_MAC
+       char hw_ether[62];
+       dhd_pub_t *dhd = dhd_get_pub(net);
+#endif
 
        WL_INFORM_MEM(("[STATIC_IF] dev_open ndev %p and wdev %p\n", net, net->ieee80211_ptr));
        ASSERT(cfg->static_ndev == net);
@@ -6612,7 +6560,15 @@ wl_cfg80211_static_if_open(struct net_device *net)
 #ifdef DHD_USE_RANDMAC
                wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, net->dev_addr);
 #else
+#if defined(CUSTOM_MULTI_MAC)
+               if (wifi_platform_get_mac_addr(dhd->info->adapter, hw_ether, net->name)) {
+#endif
                wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, NULL);
+#if defined(CUSTOM_MULTI_MAC)
+               } else {
+                       wdev = wl_cfg80211_add_if(cfg, primary_ndev, wl_iftype, net->name, hw_ether);
+               }
+#endif
 #endif // endif
                if (!wdev) {
                        ANDROID_ERROR(("[STATIC_IF] wdev is NULL, can't proceed"));
index 3e989d2d0b680734261e48c68e88bda7b2c11002..f05470dffd1f8dddf223d38230dc5003efe635d2 100644 (file)
@@ -82,6 +82,29 @@ typedef struct _compat_android_wifi_priv_cmd {
                } \
        } while (0)
 
+#define WL_MSG_PRINT_RATE_LIMIT_PERIOD 1000000000u /* 1s in units of ns */
+#define WL_MSG_RLMT(name, cmp, size, arg1, args...) \
+do {   \
+       if (android_msg_level & ANDROID_MSG_LEVEL) {    \
+               static uint64 __err_ts = 0; \
+               static uint32 __err_cnt = 0; \
+               uint64 __cur_ts = 0; \
+               static uint8 static_tmp[size]; \
+               __cur_ts = local_clock(); \
+               if (__err_ts == 0 || (__cur_ts > __err_ts && \
+               (__cur_ts - __err_ts > WL_MSG_PRINT_RATE_LIMIT_PERIOD)) || \
+               memcmp(&static_tmp, cmp, size)) { \
+                       __err_ts = __cur_ts; \
+                       memcpy(static_tmp, cmp, size); \
+                       printk(KERN_ERR "[dhd-%s] %s : [%u times] " arg1, \
+                               name, __func__, __err_cnt, ## args); \
+                       __err_cnt = 0; \
+               } else { \
+                       ++__err_cnt; \
+               } \
+       }       \
+} while (0)
+
 /**
  * wl_android_init will be called from module init function (dhd_module_init now), similarly
  * wl_android_exit will be called from module exit function (dhd_module_cleanup now)
@@ -97,17 +120,22 @@ int wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len);
 int wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx);
 int wl_ext_iapsta_attach_name(struct net_device *net, int ifidx);
 int wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx);
-u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel);
+int wl_ext_iapsta_update_net_device(struct net_device *net, int ifidx);
+void wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add);
+#ifdef PROPTX_MAXCOUNT
+void wl_ext_update_wlfc_maxcount(struct dhd_pub *dhd);
+int wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx);
+#endif /* PROPTX_MAXCOUNT */
 int wl_ext_iapsta_alive_preinit(struct net_device *dev);
 int wl_ext_iapsta_alive_postinit(struct net_device *dev);
 int wl_ext_iapsta_attach(dhd_pub_t *pub);
 void wl_ext_iapsta_dettach(dhd_pub_t *pub);
-bool wl_ext_check_mesh_creating(struct net_device *net);
 #ifdef WL_CFG80211
+u32 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev, u32 channel);
 void wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype);
-#endif
-#ifdef WL_STATIC_IF
+bool wl_ext_iapsta_iftype_enabled(struct net_device *net, int wl_iftype);
 void wl_ext_iapsta_ifadding(struct net_device *net, int ifidx);
+bool wl_ext_iapsta_mesh_creating(struct net_device *net);
 #endif
 extern int op_mode;
 #endif
@@ -117,6 +145,8 @@ typedef struct bcol_gtk_para {
        char ptk[64];
        char replay[8];
 } bcol_gtk_para_t;
+#define ACS_FW_BIT             (1<<0)
+#define ACS_DRV_BIT            (1<<1)
 #if defined(WL_EXT_IAPSTA) || defined(USE_IW)
 typedef enum WL_EVENT_PRIO {
        PRIO_EVENT_IAPSTA,
@@ -133,9 +163,18 @@ void wl_ext_event_deregister(struct net_device *dev, dhd_pub_t *dhd,
        uint32 event, void *cb_func);
 void wl_ext_event_send(void *params, const wl_event_msg_t * e, void *data);
 #endif
+int wl_ext_autochannel(struct net_device *dev, uint acs, uint32 band);
 int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
        int *bytes_written);
 void wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len);
+bool wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp);
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+void wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock);
+bool wl_ext_event_complete(struct dhd_pub *dhd, int ifidx);
+#endif
+#if defined(WL_CFG80211)
+void wl_ext_bss_iovar_war(struct net_device *dev, s32 *val);
+#endif
 enum wl_ext_status {
        WL_EXT_STATUS_DISCONNECTING = 0,
        WL_EXT_STATUS_DISCONNECTED,
@@ -323,7 +362,7 @@ int wl_update_rssi_offset(struct net_device *net, int rssi);
 typedef struct wl_bss_cache {
        struct wl_bss_cache *next;
        int dirty;
-       struct timeval tv;
+       struct osl_timespec tv;
        wl_scan_results_t results;
 } wl_bss_cache_t;
 
index a1498ae08107ef72b0c7bd7174b553366582856c..dde787ccb1cc00b160790d34acae93d3cac95a1d 100644 (file)
@@ -16,7 +16,7 @@
 #include <linux/wireless.h>
 #if defined(WL_WIRELESS_EXT)
 #include <wl_iw.h>
-#endif
+#endif /* WL_WIRELESS_EXT */
 #include <wldev_common.h>
 #include <wlioctl.h>
 #include <bcmutils.h>
 #include <dhd_config.h>
 #ifdef WL_CFG80211
 #include <wl_cfg80211.h>
-#endif
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif /* WL_ESCAN */
 
 #define AEXT_ERROR(name, arg1, args...) \
        do { \
 #define AEXT_TRACE(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_TRACE_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] AEXT-TRACE) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] AEXT-TRACE) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 #define AEXT_INFO(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_INFO_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] AEXT-INFO) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] AEXT-INFO) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 #define AEXT_DBG(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_DBG_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] AEXT-DBG) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] AEXT-DBG) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 
@@ -66,7 +69,7 @@
 #define WL_SCAN_JOIN_PROBE_INTERVAL_MS                 20
 #define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS      320
 #define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS     400
-#endif
+#endif /* WL_CFG80211 */
 #define strtoul(nptr, endptr, base) bcm_strtoul((nptr), (endptr), (base))
 
 #ifndef IW_CUSTOM_MAX
 #define CMD_ISAM_ENABLE                        "ISAM_ENABLE"
 #define CMD_ISAM_DISABLE               "ISAM_DISABLE"
 #define CMD_ISAM_STATUS                        "ISAM_STATUS"
+#define CMD_ISAM_PEER_PATH             "ISAM_PEER_PATH"
+#define CMD_ISAM_PARAM                 "ISAM_PARAM"
 #ifdef PROP_TXSTATUS
 #ifdef PROP_TXSTATUS_VSDB
 #include <dhd_wlfc.h>
 extern int disable_proptx;
 #endif /* PROP_TXSTATUS_VSDB */
-#endif
-#endif
+#endif /* PROP_TXSTATUS */
+#endif /* WL_EXT_IAPSTA */
 #define CMD_AUTOCHANNEL                "AUTOCHANNEL"
 #define CMD_WL         "WL"
 
 #ifdef WL_EXT_IAPSTA
 typedef enum APSTAMODE {
+       IUNKNOWN_MODE = 0,
        ISTAONLY_MODE = 1,
        IAPONLY_MODE = 2,
        ISTAAP_MODE = 3,
@@ -120,6 +126,8 @@ typedef enum APSTAMODE {
 typedef enum IFMODE {
        ISTA_MODE = 1,
        IAP_MODE,
+       IGO_MODE,
+       IGC_MODE,
        IMESH_MODE
 } ifmode_t;
 
@@ -179,6 +187,15 @@ typedef struct wl_if_info {
        authmode_t amode;
        encmode_t emode;
        char key[100];
+#if defined(WLMESH) && defined(WL_ESCAN)
+       struct wl_escan_info *escan;
+       timer_list_compat_t delay_scan;
+#endif /* WLMESH && WL_ESCAN */
+       struct delayed_work pm_enable_work;
+       struct mutex pm_sync;
+#ifdef PROPTX_MAXCOUNT
+       int transit_maxcount;
+#endif /* PROP_TXSTATUS_VSDB */
 } wl_if_info_t;
 
 #define CSA_FW_BIT             (1<<0)
@@ -189,12 +206,18 @@ typedef struct wl_apsta_params {
        struct dhd_pub *dhd;
        int ioctl_ver;
        bool init;
-       bool rsdb;
+       int rsdb;
        bool vsdb;
        uint csa;
+       uint acs;
+       bool radar;
        apstamode_t apstamode;
        wait_queue_head_t netif_change_event;
        struct mutex usr_sync;
+#if defined(WLMESH) && defined(WL_ESCAN)
+       int macs;
+       struct wl_mesh_params mesh_info;
+#endif /* WLMESH && WL_ESCAN */
 } wl_apsta_params_t;
 
 #define MAX_AP_LINK_WAIT_TIME   3000
@@ -217,8 +240,12 @@ enum wifi_isam_status {
 #define wl_chg_isam_status(cur_if, stat) \
        (change_bit(ISAM_STATUS_ ## stat, &(cur_if)->status))
 
-static int wl_ext_enable_iface(struct net_device *dev, char *ifname);
-#endif
+static int wl_ext_enable_iface(struct net_device *dev, char *ifname, int wait_up);
+static int wl_ext_disable_iface(struct net_device *dev, char *ifname);
+#if defined(WLMESH) && defined(WL_ESCAN)
+static int wl_mesh_escan_attach(dhd_pub_t *dhd, struct wl_if_info *cur_if);
+#endif /* WLMESH && WL_ESCAN */
+#endif /* WL_EXT_IAPSTA */
 
 #ifdef IDHCP
 typedef struct dhcpc_parameter {
@@ -226,7 +253,7 @@ typedef struct dhcpc_parameter {
        uint32 ip_serv;
        uint32 lease_time;
 } dhcpc_para_t;
-#endif
+#endif /* IDHCP */
 
 #ifdef WL_EXT_WOWL
 #define WL_WOWL_TCPFIN (1 << 26)
@@ -234,7 +261,7 @@ typedef struct wl_wowl_pattern2 {
        char cmd[4];
        wl_wowl_pattern_t wowl_pattern;
 } wl_wowl_pattern2_t;
-#endif
+#endif /* WL_EXT_WOWL */
 
 #ifdef WL_EXT_TCPKA
 typedef struct tcpka_conn {
@@ -266,7 +293,7 @@ typedef struct tcpka_conn_info {
        uint32 seq;
        uint32 ack;
 } tcpka_conn_sess_info_t;
-#endif
+#endif /* WL_EXT_TCPKA */
 
 static int wl_ext_wl_iovar(struct net_device *dev, char *command, int total_len);
 
@@ -432,9 +459,6 @@ wl_ext_ch_to_chanspec(int ioctl_ver, int ch,
 
                join_params->params.chanspec_num =
                        htod32(join_params->params.chanspec_num);
-               AEXT_ERROR("wlan", "join_params->params.chanspec_list[0]= %X, %d channels\n",
-                       join_params->params.chanspec_list[0],
-                       join_params->params.chanspec_num);
        }
 }
 
@@ -484,7 +508,107 @@ wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
 
        return chanspec;
 }
+#endif /* WL_EXT_IAPSTA || WL_CFG80211 || WL_ESCAN */
+
+bool
+wl_ext_check_scan(struct net_device *dev, dhd_pub_t *dhdp)
+{
+#ifdef WL_CFG80211
+       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+       struct wl_escan_info *escan = dhdp->escan;
+#endif /* WL_ESCAN */
+
+#ifdef WL_CFG80211
+       if (wl_get_drv_status_all(cfg, SCANNING)) {
+               AEXT_ERROR(dev->name, "cfg80211 scanning...\n");
+               return TRUE;
+       }
+#endif /* WL_CFG80211 */
+
+#ifdef WL_ESCAN
+       if (escan->escan_state == ESCAN_STATE_SCANING) {
+               AEXT_ERROR(dev->name, "escan scanning...\n");
+               return TRUE;
+       }
+#endif /* WL_ESCAN */
+
+       return FALSE;
+}
+
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+void
+wl_ext_user_sync(struct dhd_pub *dhd, int ifidx, bool lock)
+{
+       struct net_device *dev = dhd_idx2net(dhd, ifidx);
+#ifdef WL_CFG80211
+       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+       struct wl_escan_info *escan = dhd->escan;
+#endif /* WL_ESCAN */
+
+       AEXT_INFO(dev->name, "lock=%d\n", lock);
+
+       if (lock) {
+#if defined(WL_CFG80211)
+               mutex_lock(&cfg->usr_sync);
+#endif
+#if defined(WL_ESCAN)
+               mutex_lock(&escan->usr_sync);
 #endif
+       } else {
+#if defined(WL_CFG80211)
+               mutex_unlock(&cfg->usr_sync);
+#endif
+#if defined(WL_ESCAN)
+               mutex_unlock(&escan->usr_sync);
+#endif
+       }
+}
+
+bool
+wl_ext_event_complete(struct dhd_pub *dhd, int ifidx)
+{
+       struct net_device *dev = dhd_idx2net(dhd, ifidx);
+#ifdef WL_CFG80211
+       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+       struct wl_escan_info *escan = dhd->escan;
+#endif /* WL_ESCAN */
+       bool complete = TRUE;
+
+#ifdef WL_CFG80211
+       if (wl_get_drv_status_all(cfg, SCANNING)) {
+               AEXT_INFO(dev->name, "SCANNING\n");
+               complete = FALSE;
+       }
+       if (wl_get_drv_status_all(cfg, CONNECTING)) {
+               AEXT_INFO(dev->name, "CONNECTING\n");
+               complete = FALSE;
+       }
+       if (wl_get_drv_status_all(cfg, DISCONNECTING)) {
+               AEXT_INFO(dev->name, "DISCONNECTING\n");
+               complete = FALSE;
+       }
+#endif /* WL_CFG80211 */
+#ifdef WL_ESCAN
+       if (escan->escan_state == ESCAN_STATE_SCANING) {
+               AEXT_INFO(dev->name, "ESCAN_STATE_SCANING\n");
+               complete = FALSE;
+       }
+#endif /* WL_ESCAN */
+       if (dhd->conf->eapol_status >= EAPOL_STATUS_4WAY_START &&
+                       dhd->conf->eapol_status < EAPOL_STATUS_4WAY_DONE) {
+               AEXT_INFO(dev->name, "4-WAY handshaking\n");
+               complete = FALSE;
+       }
+
+       return complete;
+}
+#endif /* WL_CFG80211 && WL_ESCAN */
 
 static int
 wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
@@ -508,6 +632,38 @@ wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
        return ret;
 }
 
+void
+wl_ext_bss_iovar_war(struct net_device *ndev, s32 *val)
+{
+       dhd_pub_t *dhd = dhd_get_pub(ndev);
+       uint chip;
+       bool need_war = false;
+
+       chip = dhd_conf_get_chip(dhd);
+
+       if (chip == BCM43362_CHIP_ID || chip == BCM4330_CHIP_ID ||
+               chip == BCM43430_CHIP_ID || chip == BCM43012_CHIP_ID ||
+               chip == BCM4345_CHIP_ID || chip == BCM4356_CHIP_ID ||
+               chip == BCM4359_CHIP_ID) {
+               need_war = true;
+       }
+
+       if (need_war) {
+               /* Few firmware branches have issues in bss iovar handling and
+                * that can't be changed since they are in production.
+                */
+               if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
+                       *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
+               } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
+                       *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
+               } else {
+                       /* Ignore for other bss enums */
+                       return;
+               }
+               AEXT_TRACE(ndev->name, "wl bss %d\n", *val);
+       }
+}
+
 static int
 wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
        uint16 channel, chanspec_t *ret_chspec)
@@ -564,7 +720,7 @@ set_channel:
                        if ((err = wl_ext_iovar_setint(dev, "chanspec", fw_chspec)) == BCME_BADCHAN) {
                                if (bw == WL_CHANSPEC_BW_80)
                                        goto change_bw;
-                               wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
+                               err = wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
                                WL_MSG(dev->name, "channel %d\n", _chan);
                        } else if (err) {
                                AEXT_ERROR(dev->name, "failed to set chanspec error %d\n", err);
@@ -762,6 +918,8 @@ wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info)
        int ioctl_ver = 0;
        char sec[32];
 
+       wl_ext_get_ioctl_ver(dev, &ioctl_ver);
+
        if (dhd->conf->chip == BCM43362_CHIP_ID)
                goto set_ssid;
 
@@ -786,7 +944,6 @@ wl_ext_connect(struct net_device *dev, struct wl_conn_info *conn_info)
                err = -ENOMEM;
                goto exit;
        }
-       wl_ext_get_ioctl_ver(dev, &ioctl_ver);
        ext_join_params->ssid.SSID_len = min((uint32)sizeof(ext_join_params->ssid.SSID),
                conn_info->ssid.SSID_len);
        memcpy(&ext_join_params->ssid.SSID, conn_info->ssid.SSID, ext_join_params->ssid.SSID_len);
@@ -846,7 +1003,8 @@ set_ssid:
        memset(&join_params, 0, sizeof(join_params));
        join_params_size = sizeof(join_params.ssid);
 
-       join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID), conn_info->ssid.SSID_len);
+       join_params.ssid.SSID_len = min((uint32)sizeof(join_params.ssid.SSID),
+               conn_info->ssid.SSID_len);
        memcpy(&join_params.ssid.SSID, conn_info->ssid.SSID, join_params.ssid.SSID_len);
        join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
        if (memcmp(&ether_null, &conn_info->bssid, ETHER_ADDR_LEN))
@@ -866,9 +1024,13 @@ set_ssid:
                "Connecting with %pM channel (%d) ssid \"%s\", len (%d), sec=%s\n\n",
                &join_params.params.bssid, conn_info->channel,
                join_params.ssid.SSID, join_params.ssid.SSID_len, sec);
-       err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params,join_params_size, 1);
+       err = wl_ext_ioctl(dev, WLC_SET_SSID, &join_params, join_params_size, 1);
 
 exit:
+#ifdef WL_EXT_IAPSTA
+       if (!err)
+               wl_ext_add_remove_pm_enable_work(dev, TRUE);
+#endif /* WL_EXT_IAPSTA */
        if (iovar_buf)
                kfree(iovar_buf);
        if (ext_join_params)
@@ -880,65 +1042,296 @@ exit:
 void
 wl_ext_get_sec(struct net_device *dev, int ifmode, char *sec, int total_len)
 {
-       int auth=-1, wpa_auth=-1, wsec=0;
+       int auth=0, wpa_auth=0, wsec=0, mfp=0;
        int bytes_written=0;
 
        memset(sec, 0, total_len);
        wl_ext_iovar_getint(dev, "auth", &auth);
        wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
        wl_ext_iovar_getint(dev, "wsec", &wsec);
+       wldev_iovar_getint(dev, "mfp", &mfp);
 
-#if defined(WL_EXT_IAPSTA) && defined(WLMESH)
+#ifdef WL_EXT_IAPSTA
        if (ifmode == IMESH_MODE) {
-               if (auth == 0 && wpa_auth == 0) {
+               if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) {
                        bytes_written += snprintf(sec+bytes_written, total_len, "open");
-               } else if (auth == 0 && wpa_auth == 128) {
+               } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA2_AUTH_PSK) {
                        bytes_written += snprintf(sec+bytes_written, total_len, "sae");
                } else {
-                       bytes_written += snprintf(sec+bytes_written, total_len, "unknown");
+                       bytes_written += snprintf(sec+bytes_written, total_len, "%d/0x%x",
+                               auth, wpa_auth);
                }
        } else
-#endif
-       if (auth == 0 && wpa_auth == 0) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "open");
-       } else if (auth == 1 && wpa_auth == 0) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "shared");
-       } else if (auth == 0 && wpa_auth == 4) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "wpapsk");
-       } else if (auth == 0 && wpa_auth == 128) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "wpa2psk");
-       } else if (auth == 0 && wpa_auth == 132) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "wpawpa2psk");
+#endif /* WL_EXT_IAPSTA */
+       {
+               if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_DISABLED) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "open");
+               } else if (auth == WL_AUTH_SHARED_KEY && wpa_auth == WPA_AUTH_DISABLED) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "shared");
+               } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA_AUTH_PSK) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "wpapsk");
+               } else if (auth == WL_AUTH_OPEN_SYSTEM && wpa_auth == WPA2_AUTH_PSK) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "wpa2psk");
+               } else if (auth == WL_AUTH_OPEN_SHARED && wpa_auth == WPA3_AUTH_SAE_PSK) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "wpa3");
+               } else if ((auth == WL_AUTH_OPEN_SYSTEM || auth == WL_AUTH_SAE_KEY) &&
+                               wpa_auth == 0x20) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "wpa3");
+               } else {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "%d/0x%x",
+                               auth, wpa_auth);
+               }
+       }
+
+       if (mfp == WL_MFP_NONE) {
+               bytes_written += snprintf(sec+bytes_written, total_len, "/mfpn");
+       } else if (mfp == WL_MFP_CAPABLE) {
+               bytes_written += snprintf(sec+bytes_written, total_len, "/mfpc");
+       } else if (mfp == WL_MFP_REQUIRED) {
+               bytes_written += snprintf(sec+bytes_written, total_len, "/mfpr");
        } else {
-               bytes_written += snprintf(sec+bytes_written, total_len, "(%d/%d)",
-                       auth, wpa_auth);
+               bytes_written += snprintf(sec+bytes_written, total_len, "/%d", mfp);
        }
 
-#if defined(WL_EXT_IAPSTA) && defined(WLMESH)
+#ifdef WL_EXT_IAPSTA
        if (ifmode == IMESH_MODE) {
-               if (wsec == 0) {
+               if (wsec == WSEC_NONE) {
                        bytes_written += snprintf(sec+bytes_written, total_len, "/none");
                } else {
-                       bytes_written += snprintf(sec+bytes_written, total_len, "/sae");
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/aes");
                }
        } else
-#endif
-       if (wsec == 0) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "/none");
-       } else if (wsec == 1) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "/wep");
-       } else if (wsec == 2 || wsec == 10) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "/tkip");
-       } else if (wsec == 4 || wsec == 12) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "/aes");
-       } else if (wsec == 6 || wsec == 14) {
-               bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes");
-       } else {
-               bytes_written += snprintf(sec+bytes_written, total_len, "/%d", wsec);
+#endif /* WL_EXT_IAPSTA */
+       {
+               if (wsec == WSEC_NONE) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/none");
+               } else if (wsec == WEP_ENABLED) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/wep");
+               } else if (wsec == (TKIP_ENABLED|AES_ENABLED) ||
+                               wsec == (WSEC_SWFLAG|TKIP_ENABLED|AES_ENABLED)) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/tkipaes");
+               } else if (wsec == TKIP_ENABLED || wsec == (WSEC_SWFLAG|TKIP_ENABLED)) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/tkip");
+               } else if (wsec == AES_ENABLED || wsec == (WSEC_SWFLAG|AES_ENABLED)) {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/aes");
+               } else {
+                       bytes_written += snprintf(sec+bytes_written, total_len, "/0x%x", wsec);
+               }
+       }
+
+}
+
+static bool
+wl_ext_dfs_chan(uint16 chan)
+{
+       if (chan >= 52 && chan <= 144)
+               return TRUE;
+       return FALSE;
+}
+
+static uint16
+wl_ext_get_default_chan(struct net_device *dev,
+       uint16 *chan_2g, uint16 *chan_5g, bool nodfs)
+{
+       struct dhd_pub *dhd = dhd_get_pub(dev);
+       uint16 chan_tmp = 0, chan = 0;
+       wl_uint32_list_t *list;
+       u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
+       s32 ret = BCME_OK;
+       int i;
+
+       *chan_2g = 0;
+       *chan_5g = 0;
+       memset(valid_chan_list, 0, sizeof(valid_chan_list));
+       list = (wl_uint32_list_t *)(void *) valid_chan_list;
+       list->count = htod32(WL_NUMCHANNELS);
+       ret = wl_ext_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+               sizeof(valid_chan_list), 0);
+       if (ret == 0) {
+               for (i=0; i<dtoh32(list->count); i++) {
+                       chan_tmp = dtoh32(list->element[i]);
+                       if (!dhd_conf_match_channel(dhd, chan_tmp))
+                               continue;
+                       if (chan_tmp <= 13) {
+                               *chan_2g = chan_tmp;
+                       } else {
+                               if (wl_ext_dfs_chan(chan_tmp) && nodfs)
+                                       continue;
+                               else if (chan_tmp >= 36 && chan_tmp <= 161)
+                                       *chan_5g = chan_tmp;
+                       }
+               }
+       }
+
+       return chan;
+}
+
+#if defined(SENDPROB) || (defined(WLMESH) && defined(WL_ESCAN))
+static int
+wl_ext_add_del_ie(struct net_device *dev, uint pktflag, char *ie_data, const char* add_del_cmd)
+{
+       vndr_ie_setbuf_t *vndr_ie = NULL;
+       char iovar_buf[WLC_IOCTL_SMLEN]="\0";
+       int ie_data_len = 0, tot_len = 0, iecount;
+       int err = -1;
+
+       if (!strlen(ie_data)) {
+               AEXT_ERROR(dev->name, "wrong ie %s\n", ie_data);
+               goto exit;
+       }
+
+       tot_len = (int)(sizeof(vndr_ie_setbuf_t) + ((strlen(ie_data)-2)/2));
+       vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, GFP_KERNEL);
+       if (!vndr_ie) {
+               AEXT_ERROR(dev->name, "IE memory alloc failed\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
+       strncpy(vndr_ie->cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
+       vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+
+       /* Set the IE count - the buffer contains only 1 IE */
+       iecount = htod32(1);
+       memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
+
+       /* Set packet flag to indicate that BEACON's will contain this IE */
+       pktflag = htod32(pktflag);
+       memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
+               sizeof(u32));
+
+       /* Set the IE ID */
+       vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar)DOT11_MNG_VS_ID;
+
+       /* Set the IE LEN */
+       vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (strlen(ie_data)-2)/2;
+
+       /* Set the IE OUI and DATA */
+       ie_data_len = wl_pattern_atoh(ie_data,
+               (char *)vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui);
+       if (ie_data_len <= 0) {
+               AEXT_ERROR(dev->name, "wrong ie_data_len %d\n", (int)strlen(ie_data)-2);
+               goto exit;
+       }
+
+       err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, tot_len, iovar_buf,
+               sizeof(iovar_buf), NULL);
+
+exit:
+       if (vndr_ie) {
+               kfree(vndr_ie);
        }
+       return err;
 }
+#endif /* SENDPROB || (WLMESH && WL_ESCAN) */
 
 #ifdef WL_EXT_IAPSTA
+#define WL_PM_ENABLE_TIMEOUT 10000
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+       4 && __GNUC_MINOR__ >= 6))
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
+_Pragma("GCC diagnostic push") \
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
+entry = container_of((ptr), type, member); \
+_Pragma("GCC diagnostic pop")
+#else
+#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
+entry = container_of((ptr), type, member);
+#endif /* STRICT_GCC_WARNINGS */
+
+static void
+wl_ext_pm_work_handler(struct work_struct *work)
+{
+       struct wl_if_info *cur_if;
+       s32 pm = PM_FAST;
+       dhd_pub_t *dhd;
+
+       BCM_SET_CONTAINER_OF(cur_if, work, struct wl_if_info, pm_enable_work.work);
+
+       WL_TRACE(("%s: Enter\n", __FUNCTION__));
+
+       if (cur_if->dev == NULL)
+               return;
+
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+       4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic push")
+_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
+#endif
+
+       dhd = dhd_get_pub(cur_if->dev);
+
+       if (!dhd || !dhd->up) {
+               AEXT_TRACE(cur_if->ifname, "dhd is null or not up\n");
+               return;
+       }
+       if (dhd_conf_get_pm(dhd) >= 0)
+               pm = dhd_conf_get_pm(dhd);
+       wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
+       4 && __GNUC_MINOR__ >= 6))
+_Pragma("GCC diagnostic pop")
+#endif
+       DHD_PM_WAKE_UNLOCK(dhd);
+
+}
+
+void
+wl_ext_add_remove_pm_enable_work(struct net_device *dev, bool add)
+{
+       dhd_pub_t *dhd = dhd_get_pub(dev);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
+       u16 wq_duration = 0;
+       s32 pm = PM_OFF;
+       int i;
+
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev && tmp_if->dev == dev) {
+                       cur_if = tmp_if;
+                       break;
+               }
+       }
+
+       if (!cur_if)
+               return;
+
+       mutex_lock(&cur_if->pm_sync);
+       /*
+        * Make cancel and schedule work part mutually exclusive
+        * so that while cancelling, we are sure that there is no
+        * work getting scheduled.
+        */
+
+       if (delayed_work_pending(&cur_if->pm_enable_work)) {
+               cancel_delayed_work_sync(&cur_if->pm_enable_work);
+               DHD_PM_WAKE_UNLOCK(dhd);
+       }
+
+       if (add) {
+               wq_duration = (WL_PM_ENABLE_TIMEOUT);
+       }
+
+       /* It should schedule work item only if driver is up */
+       if (dhd->up) {
+               if (dhd_conf_get_pm(dhd) >= 0)
+                       pm = dhd_conf_get_pm(dhd);
+               wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+               if (wq_duration) {
+                       if (schedule_delayed_work(&cur_if->pm_enable_work,
+                                       msecs_to_jiffies((const unsigned int)wq_duration))) {
+                               DHD_PM_WAKE_LOCK_TIMEOUT(dhd, wq_duration);
+                       } else {
+                               AEXT_ERROR(cur_if->ifname, "Can't schedule pm work handler\n");
+                       }
+               }
+       }
+       mutex_unlock(&cur_if->pm_sync);
+
+}
+
 static int
 wl_ext_parse_wep(char *key, struct wl_wsec_key *wsec_key)
 {
@@ -1058,35 +1451,35 @@ wl_ext_set_amode(struct wl_if_info *cur_if)
 #ifdef WLMESH
        if (cur_if->ifmode == IMESH_MODE) {
                if (amode == AUTH_SAE) {
-                       auth = 0;
-                       wpa_auth = 128;
+                       auth = WL_AUTH_OPEN_SYSTEM;
+                       wpa_auth = WPA2_AUTH_PSK;
                        AEXT_INFO(dev->name, "SAE\n");
                } else {
-                       auth = 0;
-                       wpa_auth = 0;
+                       auth = WL_AUTH_OPEN_SYSTEM;
+                       wpa_auth = WPA_AUTH_DISABLED;
                        AEXT_INFO(dev->name, "Open System\n");
                }
        } else
-#endif
+#endif /* WLMESH */
        if (amode == AUTH_OPEN) {
-               auth = 0;
-               wpa_auth = 0;
+               auth = WL_AUTH_OPEN_SYSTEM;
+               wpa_auth = WPA_AUTH_DISABLED;
                AEXT_INFO(dev->name, "Open System\n");
        } else if (amode == AUTH_SHARED) {
-               auth = 1;
-               wpa_auth = 0;
+               auth = WL_AUTH_SHARED_KEY;
+               wpa_auth = WPA_AUTH_DISABLED;
                AEXT_INFO(dev->name, "Shared Key\n");
        } else if (amode == AUTH_WPAPSK) {
-               auth = 0;
-               wpa_auth = 4;
+               auth = WL_AUTH_OPEN_SYSTEM;
+               wpa_auth = WPA_AUTH_PSK;
                AEXT_INFO(dev->name, "WPA-PSK\n");
        } else if (amode == AUTH_WPA2PSK) {
-               auth = 0;
-               wpa_auth = 128;
+               auth = WL_AUTH_OPEN_SYSTEM;
+               wpa_auth = WPA2_AUTH_PSK;
                AEXT_INFO(dev->name, "WPA2-PSK\n");
        } else if (amode == AUTH_WPAWPA2PSK) {
-               auth = 0;
-               wpa_auth = 132;
+               auth = WL_AUTH_OPEN_SYSTEM;
+               wpa_auth = WPA2_AUTH_PSK | WPA_AUTH_PSK;
                AEXT_INFO(dev->name, "WPA/WPA2-PSK\n");
        }
 #ifdef WLMESH
@@ -1094,7 +1487,7 @@ wl_ext_set_amode(struct wl_if_info *cur_if)
                s32 val = WL_BSSTYPE_MESH;
                wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1);
        } else
-#endif
+#endif /* WLMESH */
        if (cur_if->ifmode == ISTA_MODE) {
                s32 val = WL_BSSTYPE_INFRA;
                wl_ext_ioctl(dev, WLC_SET_INFRA, &val, sizeof(val), 1);
@@ -1125,33 +1518,33 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params,
 #ifdef WLMESH
        if (cur_if->ifmode == IMESH_MODE) {
                if (amode == AUTH_SAE) {
-                       wsec = 4;
+                       wsec = AES_ENABLED;
                } else {
-                       wsec = 0;
+                       wsec = WSEC_NONE;
                }
        } else
-#endif
+#endif /* WLMESH */
        if (emode == ENC_NONE) {
-               wsec = 0;
+               wsec = WSEC_NONE;
                AEXT_INFO(dev->name, "No securiy\n");
        } else if (emode == ENC_WEP) {
-               wsec = 1;
+               wsec = WEP_ENABLED;
                wl_ext_parse_wep(key, &wsec_key);
                AEXT_INFO(dev->name, "WEP key \"%s\"\n", wsec_key.data);
        } else if (emode == ENC_TKIP) {
-               wsec = 2;
+               wsec = TKIP_ENABLED;
                psk.key_len = strlen(key);
                psk.flags = WSEC_PASSPHRASE;
                memcpy(psk.key, key, strlen(key));
                AEXT_INFO(dev->name, "TKIP key \"%s\"\n", psk.key);
        } else if (emode == ENC_AES || amode == AUTH_SAE) {
-               wsec = 4;
+               wsec = AES_ENABLED;
                psk.key_len = strlen(key);
                psk.flags = WSEC_PASSPHRASE;
                memcpy(psk.key, key, strlen(key));
                AEXT_INFO(dev->name, "AES key \"%s\"\n", psk.key);
        } else if (emode == ENC_TKIPAES) {
-               wsec = 6;
+               wsec = TKIP_ENABLED | AES_ENABLED;
                psk.key_len = strlen(key);
                psk.flags = WSEC_PASSPHRASE;
                memcpy(psk.key, key, strlen(key));
@@ -1159,7 +1552,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params,
        }
        if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 &&
                        apsta_params->apstamode == ISTAAP_MODE) {
-               wsec |= 0x8; // terence 20180628: fix me, this is a workaround
+               wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround
        }
 
        wl_ext_iovar_setint(dev, "wsec", wsec);
@@ -1168,7 +1561,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params,
        if (cur_if->ifmode == IMESH_MODE) {
                if (amode == AUTH_SAE) {
                        s8 iovar_buf[WLC_IOCTL_SMLEN];
-                       AEXT_INFO(dev->name, "SAE key \"%s\"\n", key);
+                       AEXT_INFO(dev->name, "AES key \"%s\"\n", key);
                        wl_ext_iovar_setint(dev, "mesh_auth_proto", 1);
                        wl_ext_iovar_setint(dev, "mfp", WL_MFP_REQUIRED);
                        wl_ext_iovar_setbuf(dev, "sae_password", key, strlen(key),
@@ -1179,7 +1572,7 @@ wl_ext_set_emode(struct wl_apsta_params *apsta_params,
                        wl_ext_iovar_setint(dev, "mfp", WL_MFP_NONE);
                }
        } else
-#endif
+#endif /* WLMESH */
        if (emode == ENC_WEP) {
                wl_ext_ioctl(dev, WLC_SET_KEY, &wsec_key, sizeof(wsec_key), 1);
        } else if (emode == ENC_TKIP || emode == ENC_AES || emode == ENC_TKIPAES) {
@@ -1303,103 +1696,270 @@ set_channel:
 }
 
 static bool
-wl_ext_dfs_chan(struct wl_apsta_params *apsta_params, struct net_device *dev,
-       uint16 chan)
+wl_ext_radar_detect(struct net_device *dev)
 {
-       u32 channel = chan;
-       s32 err = BCME_OK;
-       bool dfs = FALSE;
-
-       if (chan <= CH_MAX_2G_CHANNEL)
-               return FALSE;
+       int ret = BCME_OK;
+       bool radar = FALSE;
+       s32 val = 0;
 
-       channel |= WL_CHANSPEC_BAND_5G;
-       channel |= WL_CHANSPEC_BW_20;
-       channel = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, channel);
-       err = wl_ext_iovar_getint(dev, "per_chan_info", &channel);
-       if (!err) {
-               if (channel & WL_CHAN_PASSIVE) {
-                       dfs = TRUE;
-               }
+       if ((ret = wldev_ioctl(dev, WLC_GET_RADAR, &val, sizeof(int), false) == 0)) {
+               radar = TRUE;
        }
 
-       return dfs;
-}
-
-static void
-wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
-       struct wl_if_info *cur_if)
-{
-       rtnl_unlock();
-       wait_event_interruptible_timeout(apsta_params->netif_change_event,
-               wl_get_isam_status(cur_if, IF_READY),
-               msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
-       rtnl_lock();
+       return radar;
 }
 
-bool
-wl_ext_check_mesh_creating(struct net_device *net)
+static struct wl_if_info *
+wl_ext_if_enabled(struct wl_apsta_params *apsta_params, ifmode_t ifmode)
 {
-       struct dhd_pub *dhd = dhd_get_pub(net);
-       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
-       struct wl_if_info *cur_if;
+       struct wl_if_info *tmp_if, *target_if = NULL;
        int i;
 
-       if (apsta_params) {
-               for (i=0; i<MAX_IF_NUM; i++) {
-                       cur_if = &apsta_params->if_info[i];
-                       if (cur_if->ifmode==IMESH_MODE && wl_get_isam_status(cur_if, IF_ADDING))
-                               return TRUE;
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if && tmp_if->ifmode == ifmode &&
+                               wl_get_isam_status(tmp_if, IF_READY)) {
+                       if (wl_ext_get_chan(apsta_params, tmp_if->dev)) {
+                               target_if = tmp_if;
+                               break;
+                       }
                }
        }
-       return FALSE;
+
+       return target_if;
 }
 
-bool
-wl_ext_check_other_enabling(struct wl_apsta_params *apsta_params,
-       struct wl_if_info *cur_if)
+#ifndef WL_STATIC_IF
+s32
+wl_ext_add_del_bss(struct net_device *ndev, s32 bsscfg_idx,
+       int iftype, s32 del, u8 *addr)
 {
-       struct wl_if_info *tmp_if;
-       bool enabling = FALSE;
-       u32 timeout = 1;
-       int i;
+       s32 ret = BCME_OK;
+       s32 val = 0;
+       u8 ioctl_buf[WLC_IOCTL_SMLEN];
+       struct {
+               s32 cfg;
+               s32 val;
+               struct ether_addr ea;
+       } bss_setbuf;
 
-       for (i=0; i<MAX_IF_NUM; i++) {
-               tmp_if = &apsta_params->if_info[i];
-               if (tmp_if->dev && tmp_if->dev != cur_if->dev) {
-                       if (tmp_if->ifmode == ISTA_MODE)
-                               enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
-                       else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
-                               enabling = wl_get_isam_status(tmp_if, AP_CREATING);
-                       if (enabling)
-                               WL_MSG(cur_if->ifname, "waiting for %s[%c] enabling...\n",
-                                       tmp_if->ifname, tmp_if->prefix);
-                       if (enabling && tmp_if->ifmode == ISTA_MODE) {
-                               timeout = wait_event_interruptible_timeout(
-                                       apsta_params->netif_change_event,
-                                       !wl_get_isam_status(tmp_if, STA_CONNECTING),
-                                       msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
-                       } else if (enabling &&
-                                       (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)) {
-                               timeout = wait_event_interruptible_timeout(
-                                       apsta_params->netif_change_event,
-                                       !wl_get_isam_status(tmp_if, AP_CREATING),
-                                       msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
+       AEXT_TRACE(ndev->name, "wl_iftype:%d del:%d \n", iftype, del);
+
+       bzero(&bss_setbuf, sizeof(bss_setbuf));
+
+       /* AP=2, STA=3, up=1, down=0, val=-1 */
+       if (del) {
+               val = WLC_AP_IOV_OP_DELETE;
+       } else if (iftype == WL_INTERFACE_CREATE_AP) {
+               /* Add/role change to AP Interface */
+               AEXT_TRACE(ndev->name, "Adding AP Interface\n");
+               val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
+       } else if (iftype == WL_INTERFACE_CREATE_STA) {
+               /* Add/role change to STA Interface */
+               AEXT_TRACE(ndev->name, "Adding STA Interface\n");
+               val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
+       } else {
+               AEXT_ERROR(ndev->name, "add_del_bss NOT supported for IFACE type:0x%x", iftype);
+               return -EINVAL;
+       }
+
+       if (!del) {
+               wl_ext_bss_iovar_war(ndev, &val);
+       }
+
+       bss_setbuf.cfg = htod32(bsscfg_idx);
+       bss_setbuf.val = htod32(val);
+
+       if (addr) {
+               memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
+       }
+
+       AEXT_INFO(ndev->name, "wl bss %d bssidx:%d\n", val, bsscfg_idx);
+       ret = wl_ext_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
+               ioctl_buf, WLC_IOCTL_SMLEN, NULL);
+       if (ret != 0)
+               WL_ERR(("'bss %d' failed with %d\n", val, ret));
+
+       return ret;
+}
+
+static int
+wl_ext_interface_ops(struct net_device *dev,
+       struct wl_apsta_params *apsta_params, int iftype, u8 *addr)
+{
+       s32 ret;
+       struct wl_interface_create_v2 iface;
+       wl_interface_create_v3_t iface_v3;
+       struct wl_interface_info_v1 *info;
+       wl_interface_info_v2_t *info_v2;
+       uint32 ifflags = 0;
+       bool use_iface_info_v2 = false;
+       u8 ioctl_buf[WLC_IOCTL_SMLEN];
+       wl_wlc_version_t wlc_ver;
+
+       /* Interface create */
+       bzero(&iface, sizeof(iface));
+
+       if (addr) {
+               ifflags |= WL_INTERFACE_MAC_USE;
+       }
+
+       ret = wldev_iovar_getbuf(dev, "wlc_ver", NULL, 0,
+               &wlc_ver, sizeof(wl_wlc_version_t), NULL);
+       if ((ret == BCME_OK) && (wlc_ver.wlc_ver_major >= 5)) {
+               ret = wldev_iovar_getbuf(dev, "interface_create",
+                       &iface, sizeof(struct wl_interface_create_v2),
+                       ioctl_buf, sizeof(ioctl_buf), NULL);
+               if ((ret == BCME_OK) && (*((uint32 *)ioctl_buf) == WL_INTERFACE_CREATE_VER_3)) {
+                       use_iface_info_v2 = true;
+                       bzero(&iface_v3, sizeof(wl_interface_create_v3_t));
+                       iface_v3.ver = WL_INTERFACE_CREATE_VER_3;
+                       iface_v3.iftype = iftype;
+                       iface_v3.flags = ifflags;
+                       if (addr) {
+                               memcpy(&iface_v3.mac_addr.octet, addr, ETH_ALEN);
                        }
-                       if (tmp_if->ifmode == ISTA_MODE)
-                               enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
-                       else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
-                               enabling = wl_get_isam_status(tmp_if, AP_CREATING);
-                       if (timeout <= 0 || enabling) {
-                               WL_MSG(cur_if->ifname, "%s[%c] is still enabling...\n",
-                                       tmp_if->ifname, tmp_if->prefix);
+                       ret = wl_ext_iovar_getbuf(dev, "interface_create",
+                               &iface_v3, sizeof(wl_interface_create_v3_t),
+                               ioctl_buf, sizeof(ioctl_buf), NULL);
+                       if (unlikely(ret)) {
+                               WL_ERR(("Interface v3 create failed!! ret %d\n", ret));
+                               return ret;
                        }
                }
        }
 
-       return enabling;
+       /* success case */
+       if (use_iface_info_v2 == true) {
+               info_v2 = (wl_interface_info_v2_t *)ioctl_buf;
+               ret = info_v2->bsscfgidx;
+       } else {
+               /* Use v1 struct */
+               iface.ver = WL_INTERFACE_CREATE_VER_2;
+               iface.iftype = iftype;
+               iface.flags = ifflags;
+               if (addr) {
+                       memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
+               }
+               ret = wldev_iovar_getbuf(dev, "interface_create",
+                       &iface, sizeof(struct wl_interface_create_v2),
+                       ioctl_buf, sizeof(ioctl_buf), NULL);
+               if (ret == BCME_OK) {
+                       info = (struct wl_interface_info_v1 *)ioctl_buf;
+                       ret = info->bsscfgidx;
+               }
+       }
+
+       AEXT_INFO(dev->name, "wl interface create success!! bssidx:%d \n", ret);
+       return ret;
+}
+
+static void
+wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *cur_if)
+{
+       rtnl_unlock();
+       wait_event_interruptible_timeout(apsta_params->netif_change_event,
+               wl_get_isam_status(cur_if, IF_READY),
+               msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
+       rtnl_lock();
+}
+
+static void
+wl_ext_interface_create(struct net_device *dev, struct wl_apsta_params *apsta_params,
+       struct wl_if_info *cur_if, int iftype, u8 *addr)
+{
+       s32 ret;
+
+       wl_set_isam_status(cur_if, IF_ADDING);
+       ret = wl_ext_interface_ops(dev, apsta_params, iftype, addr);
+       if (ret == BCME_UNSUPPORTED) {
+               wl_ext_add_del_bss(dev, 1, iftype, 0, addr);
+       }
+       wl_ext_wait_netif_change(apsta_params, cur_if);
 }
 
+static void
+wl_ext_iapsta_intf_add(struct net_device *dev, struct wl_apsta_params *apsta_params)
+{
+       struct dhd_pub *dhd;
+       apstamode_t apstamode = apsta_params->apstamode;
+       struct wl_if_info *cur_if;
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+       wl_p2p_if_t ifreq;
+       struct ether_addr mac_addr;
+
+       dhd = dhd_get_pub(dev);
+       bzero(&mac_addr, sizeof(mac_addr));
+
+       if (apstamode == ISTAAP_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+       }
+       else if (apstamode == ISTAGO_MODE) {
+               bzero(&ifreq, sizeof(wl_p2p_if_t));
+               ifreq.type = htod32(WL_P2P_IF_GO);
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_set_isam_status(cur_if, IF_ADDING);
+               wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, cur_if);
+       }
+       else if (apstamode == ISTASTA_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+               mac_addr.octet[0] |= 0x02;
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA,
+                       (u8*)&mac_addr);
+       }
+       else if (apstamode == IDUALAP_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+       }
+       else if (apstamode == ISTAAPAP_MODE) {
+               u8 rand_bytes[2] = {0, };
+               get_random_bytes(&rand_bytes, sizeof(rand_bytes));
+               cur_if = &apsta_params->if_info[IF_VIF];
+               memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+               mac_addr.octet[0] |= 0x02;
+               mac_addr.octet[5] += 0x01;
+               memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
+                       (u8*)&mac_addr);
+               cur_if = &apsta_params->if_info[IF_VIF2];
+               memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+               mac_addr.octet[0] |= 0x02;
+               mac_addr.octet[5] += 0x02;
+               memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
+                       (u8*)&mac_addr);
+       }
+#ifdef WLMESH
+       else if (apstamode == ISTAMESH_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
+       }
+       else if (apstamode == IMESHAP_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+       }
+       else if (apstamode == ISTAAPMESH_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+               cur_if = &apsta_params->if_info[IF_VIF2];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
+       }
+       else if (apstamode == IMESHAPAP_MODE) {
+               cur_if = &apsta_params->if_info[IF_VIF];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+               cur_if = &apsta_params->if_info[IF_VIF2];
+               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+       }
+#endif /* WLMESH */
+
+}
+#endif /* WL_STATIC_IF */
+
 static void
 wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params)
 {
@@ -1408,7 +1968,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
        struct wl_if_info *cur_if;
        s8 iovar_buf[WLC_IOCTL_SMLEN];
        s32 val = 0;
-       int i, dfs = 1, disable_5g_band = 0;
+       int i;
 
        dhd = dhd_get_pub(dev);
 
@@ -1428,7 +1988,6 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                        cur_if->prio = PRIO_AP;
                        cur_if->prefix = 'A';
                        snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
-                       dfs = 0;
 #ifdef WLMESH
                } else if (cur_if->ifmode == IMESH_MODE) {
                        cur_if->channel = 1;
@@ -1436,37 +1995,25 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                        cur_if->prio = PRIO_MESH;
                        cur_if->prefix = 'M';
                        snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
-                       dfs = 0;
-#endif
-               }
-       }
-
-       if (!dfs && !apsta_params->vsdb) {
-               wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
-               wl_ext_iovar_getint(dev, "disable_5g_band", &disable_5g_band);
-               disable_5g_band |= 0x6;
-               wl_ext_iovar_setint(dev, "disable_5g_band", disable_5g_band);
-               wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
-#ifdef WL_CFG80211
-               if (dhd->up) {
-                       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
-                       wl_update_wiphybands(cfg, true);
+#ifdef WL_ESCAN
+                       if (i == 0 && apsta_params->macs)
+                               wl_mesh_escan_attach(dhd, cur_if);
+#endif /* WL_ESCAN */
+#endif /* WLMESH */
                }
-#endif
        }
 
        if (FW_SUPPORTED(dhd, rsdb)) {
                if (apstamode == IDUALAP_MODE)
-                       apsta_params->rsdb = TRUE;
+                       apsta_params->rsdb = -1;
                else if (apstamode == ISTAAPAP_MODE)
-                       apsta_params->rsdb = FALSE;
-               if (apstamode == ISTAAP_MODE || apstamode == ISTAAPAP_MODE ||
+                       apsta_params->rsdb = 0;
+               if (apstamode == ISTAAPAP_MODE || apstamode == IDUALAP_MODE ||
                                apstamode == IMESHONLY_MODE || apstamode == ISTAMESH_MODE ||
                                apstamode == IMESHAP_MODE || apstamode == ISTAAPMESH_MODE ||
                                apstamode == IMESHAPAP_MODE) {
                        wl_config_t rsdb_mode_cfg = {0, 0};
-                       if (apsta_params->rsdb)
-                               rsdb_mode_cfg.config = 1;
+                       rsdb_mode_cfg.config = apsta_params->rsdb;
                        AEXT_INFO(dev->name, "set rsdb_mode %d\n", rsdb_mode_cfg.config);
                        wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                        wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
@@ -1474,7 +2021,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                        wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                }
        } else {
-               apsta_params->rsdb = FALSE;
+               apsta_params->rsdb = 0;
        }
 
        if (apstamode == ISTAONLY_MODE) {
@@ -1503,7 +2050,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                                wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                        }
                }
-#endif
+#endif /* BCMSDIO */
 #endif /* PROP_TXSTATUS_VSDB */
        }
        else if (apstamode == ISTAAP_MODE) {
@@ -1557,122 +2104,45 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
        }
-#endif
+#endif /* WLMESH */
 
        wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
        apsta_params->init = TRUE;
 
-       WL_MSG(dev->name, "apstamode=%d\n", apstamode);
-}
-
-static void
-wl_ext_interface_create(struct net_device *dev, struct wl_apsta_params *apsta_params,
-       struct wl_if_info *cur_if, int iftype, u8 *addr)
-{
-       wl_interface_create_t iface;
-       u8 iovar_buf[WLC_IOCTL_SMLEN];
-
-       bzero(&iface, sizeof(iface));
-       if (addr) {
-               iftype |= WL_INTERFACE_MAC_USE;
-       }
-       iface.ver = WL_INTERFACE_CREATE_VER;
-       iface.flags = iftype;
-       if (addr) {
-               memcpy(&iface.mac_addr.octet, addr, ETH_ALEN);
-       }
-       wl_set_isam_status(cur_if, IF_ADDING);
-       wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
-               iovar_buf, WLC_IOCTL_SMLEN, NULL);
-       wl_ext_wait_netif_change(apsta_params, cur_if);
-}
-
-static void
-wl_ext_iapsta_intf_add(struct net_device *dev, struct wl_apsta_params *apsta_params)
-{
-       struct dhd_pub *dhd;
-       apstamode_t apstamode = apsta_params->apstamode;
-       struct wl_if_info *cur_if;
-       wlc_ssid_t ssid = { 0, {0} };
-       s8 iovar_buf[WLC_IOCTL_SMLEN];
-       wl_p2p_if_t ifreq;
-       struct ether_addr mac_addr;
-
-       dhd = dhd_get_pub(dev);
-       bzero(&mac_addr, sizeof(mac_addr));
-
-       if (apstamode == ISTAAP_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               if (FW_SUPPORTED(dhd, rsdb)) {
-                       wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
-               } else {
-                       wl_set_isam_status(cur_if, IF_ADDING);
-                       wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid),
-                               iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
-                       wl_ext_wait_netif_change(apsta_params, cur_if);
-               }
-       }
-       else if (apstamode == ISTAGO_MODE) {
-               bzero(&ifreq, sizeof(wl_p2p_if_t));
-               ifreq.type = htod32(WL_P2P_IF_GO);
-               cur_if = &apsta_params->if_info[IF_VIF];
-               wl_set_isam_status(cur_if, IF_ADDING);
-               wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
-                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
-               wl_ext_wait_netif_change(apsta_params, cur_if);
-       }
-       else if (apstamode == ISTASTA_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
-               mac_addr.octet[0] |= 0x02;
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA,
-                       (u8*)&mac_addr);
-       }
-       else if (apstamode == IDUALAP_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
-       }
-       else if (apstamode == ISTAAPAP_MODE) {
-               u8 rand_bytes[2] = {0, };
-               get_random_bytes(&rand_bytes, sizeof(rand_bytes));
-               cur_if = &apsta_params->if_info[IF_VIF];
-               memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
-               mac_addr.octet[0] |= 0x02;
-               mac_addr.octet[5] += 0x01;
-               memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
-                       (u8*)&mac_addr);
-               cur_if = &apsta_params->if_info[IF_VIF2];
-               memcpy(&mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
-               mac_addr.octet[0] |= 0x02;
-               mac_addr.octet[5] += 0x02;
-               memcpy(&mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP,
-                       (u8*)&mac_addr);
-       }
-#ifdef WLMESH
-       else if (apstamode == ISTAMESH_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
-       }
-       else if (apstamode == IMESHAP_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
-       }
-       else if (apstamode == ISTAAPMESH_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
-               cur_if = &apsta_params->if_info[IF_VIF2];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_STA, NULL);
-       }
-       else if (apstamode == IMESHAPAP_MODE) {
-               cur_if = &apsta_params->if_info[IF_VIF];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
-               cur_if = &apsta_params->if_info[IF_VIF2];
-               wl_ext_interface_create(dev, apsta_params, cur_if, WL_INTERFACE_CREATE_AP, NULL);
+       WL_MSG(dev->name, "apstamode=%d\n", apstamode);
+}
+
+static int
+wl_ext_isam_param(struct net_device *dev, char *command, int total_len)
+{
+       struct dhd_pub *dhd = dhd_get_pub(dev);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       int ret = -1;
+       char *pick_tmp, *data, *param;
+       int bytes_written=-1;
+
+       AEXT_TRACE(dev->name, "command=%s, len=%d\n", command, total_len);
+
+       pick_tmp = command;
+       param = bcmstrtok(&pick_tmp, " ", 0); // pick isam_param
+       param = bcmstrtok(&pick_tmp, " ", 0); // pick cmd
+       while (param != NULL) {
+               data = bcmstrtok(&pick_tmp, " ", 0); // pick data
+               if (!strcmp(param, "acs")) {
+                       if (data) {
+                               apsta_params->acs = simple_strtol(data, NULL, 0);
+                               ret = 0;
+                       } else {
+                               bytes_written = snprintf(command, total_len, "%d", apsta_params->acs);
+                               ret = bytes_written;
+                               goto exit;
+                       }
+               }
+               param = bcmstrtok(&pick_tmp, " ", 0); // pick cmd
        }
-#endif
 
+exit:
+       return ret;
 }
 
 static int
@@ -1682,11 +2152,6 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len)
        char *pch, *pick_tmp, *pick_tmp2, *param;
        struct wl_apsta_params *apsta_params = dhd->iapsta_params;
        int i;
-       
-#ifdef WL_STATIC_IF
-       AEXT_ERROR(dev->name, "please remove WL_STATIC_IF from Makefile\n");
-       return -1;
-#endif
 
        if (apsta_params->init) {
                AEXT_ERROR(dev->name, "don't init twice\n");
@@ -1698,120 +2163,104 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len)
        param = bcmstrtok(&pick_tmp, " ", 0); // skip iapsta_init
        param = bcmstrtok(&pick_tmp, " ", 0);
        while (param != NULL) {
+               pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
+               if (!pick_tmp2) {
+                       AEXT_ERROR(dev->name, "wrong param %s\n", param);
+                       return -1;
+               }
                if (!strcmp(param, "mode")) {
                        pch = NULL;
-                       pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
-                       if (pick_tmp2) {
-                               if (!strcmp(pick_tmp2, "sta")) {
-                                       apsta_params->apstamode = ISTAONLY_MODE;
-                               } else if (!strcmp(pick_tmp2, "ap")) {
-                                       apsta_params->apstamode = IAPONLY_MODE;
-                               } else if (!strcmp(pick_tmp2, "sta-ap")) {
-                                       apsta_params->apstamode = ISTAAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "sta-sta")) {
-                                       apsta_params->apstamode = ISTASTA_MODE;
-                                       apsta_params->vsdb = TRUE;
-                               } else if (!strcmp(pick_tmp2, "ap-ap")) {
-                                       apsta_params->apstamode = IDUALAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "sta-ap-ap")) {
-                                       apsta_params->apstamode = ISTAAPAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "apsta")) {
-                                       apsta_params->apstamode = ISTAAP_MODE;
-                                       apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
-                                       apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "dualap")) {
-                                       apsta_params->apstamode = IDUALAP_MODE;
-                                       apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
-                                       apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "sta-go") ||
-                                               !strcmp(pick_tmp2, "gosta")) {
-                                       if (!FW_SUPPORTED(dhd, p2p)) {
-                                               return -1;
-                                       }
-                                       apsta_params->apstamode = ISTAGO_MODE;
-                                       apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
-                                       apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
-#ifdef WLMESH
-                               } else if (!strcmp(pick_tmp2, "mesh")) {
-                                       apsta_params->apstamode = IMESHONLY_MODE;
-                               } else if (!strcmp(pick_tmp2, "sta-mesh")) {
-                                       apsta_params->apstamode = ISTAMESH_MODE;
-                               } else if (!strcmp(pick_tmp2, "sta-ap-mesh")) {
-                                       apsta_params->apstamode = ISTAAPMESH_MODE;
-                               } else if (!strcmp(pick_tmp2, "mesh-ap")) {
-                                       apsta_params->apstamode = IMESHAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
-                                       apsta_params->apstamode = IMESHAPAP_MODE;
-#endif
-                               } else {
-                                       AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n");
+                       if (!strcmp(pick_tmp2, "sta")) {
+                               apsta_params->apstamode = ISTAONLY_MODE;
+                       } else if (!strcmp(pick_tmp2, "ap")) {
+                               apsta_params->apstamode = IAPONLY_MODE;
+                       } else if (!strcmp(pick_tmp2, "sta-ap")) {
+                               apsta_params->apstamode = ISTAAP_MODE;
+                       } else if (!strcmp(pick_tmp2, "sta-sta")) {
+                               apsta_params->apstamode = ISTASTA_MODE;
+                               apsta_params->vsdb = TRUE;
+                       } else if (!strcmp(pick_tmp2, "ap-ap")) {
+                               apsta_params->apstamode = IDUALAP_MODE;
+                       } else if (!strcmp(pick_tmp2, "sta-ap-ap")) {
+                               apsta_params->apstamode = ISTAAPAP_MODE;
+                       } else if (!strcmp(pick_tmp2, "apsta")) {
+                               apsta_params->apstamode = ISTAAP_MODE;
+                               apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
+                               apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
+                       } else if (!strcmp(pick_tmp2, "dualap")) {
+                               apsta_params->apstamode = IDUALAP_MODE;
+                               apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
+                               apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
+                       } else if (!strcmp(pick_tmp2, "sta-go") ||
+                                       !strcmp(pick_tmp2, "gosta")) {
+                               if (!FW_SUPPORTED(dhd, p2p)) {
                                        return -1;
                                }
-                               pch = bcmstrtok(&pick_tmp2, " -", 0);
-                               for (i=0; i<MAX_IF_NUM && pch; i++) {
-                                       if (!strcmp(pch, "sta"))
-                                               apsta_params->if_info[i].ifmode = ISTA_MODE;
-                                       else if (!strcmp(pch, "ap"))
-                                               apsta_params->if_info[i].ifmode = IAP_MODE;
+                               apsta_params->apstamode = ISTAGO_MODE;
+                               apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
+                               apsta_params->if_info[IF_VIF].ifmode = IAP_MODE;
 #ifdef WLMESH
-                                       else if (!strcmp(pch, "mesh")) {
-                                               if (dhd->conf->fw_type != FW_TYPE_MESH) {
-                                                       AEXT_ERROR(dev->name, "wrong fw type\n");
-                                                       return -1;
-                                               }
-                                               apsta_params->if_info[i].ifmode = IMESH_MODE;
+                       } else if (!strcmp(pick_tmp2, "mesh")) {
+                               apsta_params->apstamode = IMESHONLY_MODE;
+                       } else if (!strcmp(pick_tmp2, "sta-mesh")) {
+                               apsta_params->apstamode = ISTAMESH_MODE;
+                       } else if (!strcmp(pick_tmp2, "sta-ap-mesh")) {
+                               apsta_params->apstamode = ISTAAPMESH_MODE;
+                       } else if (!strcmp(pick_tmp2, "mesh-ap")) {
+                               apsta_params->apstamode = IMESHAP_MODE;
+                       } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
+                               apsta_params->apstamode = IMESHAPAP_MODE;
+#endif /* WLMESH */
+                       } else {
+                               AEXT_ERROR(dev->name, "mode [sta|ap|sta-ap|ap-ap]\n");
+                               return -1;
+                       }
+                       pch = bcmstrtok(&pick_tmp2, " -", 0);
+                       for (i=0; i<MAX_IF_NUM && pch; i++) {
+                               if (!strcmp(pch, "sta"))
+                                       apsta_params->if_info[i].ifmode = ISTA_MODE;
+                               else if (!strcmp(pch, "ap"))
+                                       apsta_params->if_info[i].ifmode = IAP_MODE;
+#ifdef WLMESH
+                               else if (!strcmp(pch, "mesh")) {
+                                       if (dhd->conf->fw_type != FW_TYPE_MESH) {
+                                               AEXT_ERROR(dev->name, "wrong fw type\n");
+                                               return -1;
                                        }
-#endif
-                                       pch = bcmstrtok(&pick_tmp2, " -", 0);
+                                       apsta_params->if_info[i].ifmode = IMESH_MODE;
                                }
+#endif /* WLMESH */
+                               pch = bcmstrtok(&pick_tmp2, " -", 0);
                        }
                }
                else if (!strcmp(param, "rsdb")) {
-                       pch = bcmstrtok(&pick_tmp, " ", 0);
-                       if (pch) {
-                               if (!strcmp(pch, "y")) {
-                                       apsta_params->rsdb = TRUE;
-                               } else if (!strcmp(pch, "n")) {
-                                       apsta_params->rsdb = FALSE;
-                               } else {
-                                       AEXT_ERROR(dev->name, "rsdb [y|n]\n");
-                                       return -1;
-                               }
-                       }
+                       apsta_params->rsdb = (int)simple_strtol(pick_tmp2, NULL, 0);
                } else if (!strcmp(param, "vsdb")) {
-                       pch = bcmstrtok(&pick_tmp, " ", 0);
-                       if (pch) {
-                               if (!strcmp(pch, "y")) {
-                                       apsta_params->vsdb = TRUE;
-                               } else if (!strcmp(pch, "n")) {
-                                       apsta_params->vsdb = FALSE;
-                               } else {
-                                       AEXT_ERROR(dev->name, "vsdb [y|n]\n");
-                                       return -1;
-                               }
+                       if (!strcmp(pick_tmp2, "y")) {
+                               apsta_params->vsdb = TRUE;
+                       } else if (!strcmp(pick_tmp2, "n")) {
+                               apsta_params->vsdb = FALSE;
+                       } else {
+                               AEXT_ERROR(dev->name, "vsdb [y|n]\n");
+                               return -1;
                        }
                } else if (!strcmp(param, "csa")) {
-                       pch = bcmstrtok(&pick_tmp, " ", 0);
-                       if (pch) {
-                               apsta_params->csa = (int)simple_strtol(pch, NULL, 0);
-                       }
+                       apsta_params->csa = (int)simple_strtol(pick_tmp2, NULL, 0);
+               } else if (!strcmp(param, "acs")) {
+                       apsta_params->acs = (int)simple_strtol(pick_tmp2, NULL, 0);
+#if defined(WLMESH) && defined(WL_ESCAN)
+               } else if (!strcmp(param, "macs")) {
+                       apsta_params->macs = (int)simple_strtol(pick_tmp2, NULL, 0);
+#endif /* WLMESH && WL_ESCAN */
                } else if (!strcmp(param, "ifname")) {
                        pch = NULL;
-                       pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
-                       if (pick_tmp2)
-                               pch = bcmstrtok(&pick_tmp2, " -", 0);
+                       pch = bcmstrtok(&pick_tmp2, " -", 0);
                        for (i=0; i<MAX_IF_NUM && pch; i++) {
                                strcpy(apsta_params->if_info[i].ifname, pch);
                                pch = bcmstrtok(&pick_tmp2, " -", 0);
                        }
                } else if (!strcmp(param, "vifname")) {
-                       pch = bcmstrtok(&pick_tmp, " ", 0);
-                       if (pch)
-                               strcpy(apsta_params->if_info[IF_VIF].ifname, pch);
-                       else {
-                               AEXT_ERROR(dev->name, "vifname [wlan1]\n");
-                               return -1;
-                       }
+                       strcpy(apsta_params->if_info[IF_VIF].ifname, pick_tmp2);
                }
                param = bcmstrtok(&pick_tmp, " ", 0);
        }
@@ -1822,7 +2271,9 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len)
        }
 
        wl_ext_iapsta_preinit(dev, apsta_params);
+#ifndef WL_STATIC_IF
        wl_ext_iapsta_intf_add(dev, apsta_params);
+#endif /* WL_STATIC_IF */
 
        return 0;
 }
@@ -2159,54 +2610,540 @@ wl_mesh_get_peer_results(struct net_device *dev, char *buf, int len)
                ret = peer_results->count;
        }
 
-       return ret;
+       return ret;
+}
+
+static int
+wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command,
+       int total_len)
+{
+       struct dhd_pub *dhd = dhd_get_pub(dev);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       int i;
+       struct wl_if_info *cur_if;
+       mesh_peer_info_dump_t *peer_results;
+       mesh_peer_info_ext_t *mpi_ext;
+       char *peer_buf = NULL;
+       int peer_len = WLC_IOCTL_MAXLEN;
+       int dump_written = 0, ret;
+
+       if (!data) {
+               peer_buf = kmalloc(peer_len, GFP_KERNEL);
+               if (peer_buf == NULL) {
+                       AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
+                               peer_len); 
+                       return -1;
+               }
+               for (i=0; i<MAX_IF_NUM; i++) {
+                       cur_if = &apsta_params->if_info[i];
+                       if (cur_if && dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) {
+                               memset(peer_buf, 0, peer_len);
+                               ret = wl_mesh_get_peer_results(dev, peer_buf, peer_len);
+                               if (ret >= 0) {
+                                       peer_results = (mesh_peer_info_dump_t *)peer_buf;
+                                       mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
+                                       dump_written += wl_mesh_print_peer_info(mpi_ext,
+                                               peer_results->count, command+dump_written,
+                                               total_len-dump_written);
+                               }
+                       } else if (cur_if && dev == cur_if->dev) {
+                               AEXT_ERROR(dev->name, "[%s][%c] is not mesh interface\n",
+                                       cur_if->ifname, cur_if->prefix);
+                       }
+               }
+       }
+
+       if (peer_buf)
+               kfree(peer_buf);
+       return dump_written;
+}
+
+#ifdef WL_ESCAN
+#define WL_MESH_DELAY_SCAN_MS  3000
+static void
+wl_mesh_timer(unsigned long data)
+{
+       wl_event_msg_t msg;
+       struct wl_if_info *mesh_if = (struct wl_if_info *)data;
+       struct dhd_pub *dhd;
+
+       if (!mesh_if) {
+               AEXT_ERROR("wlan", "mesh_if is not ready\n");
+               return;
+       }
+
+       if (!mesh_if->dev) {
+               AEXT_ERROR("wlan", "ifidx %d is not ready\n", mesh_if->ifidx);
+               return;
+       }
+       dhd = dhd_get_pub(mesh_if->dev);
+
+       bzero(&msg, sizeof(wl_event_msg_t));
+       AEXT_TRACE(mesh_if->dev->name, "timer expired\n");
+
+       msg.ifidx = mesh_if->ifidx;
+       msg.event_type = hton32(WLC_E_RESERVED);
+       msg.reason = 0xFFFFFFFF;
+       wl_ext_event_send(dhd->event_params, &msg, NULL);
+}
+
+static void
+wl_mesh_set_timer(struct wl_if_info *mesh_if, uint timeout)
+{
+       AEXT_TRACE(mesh_if->dev->name, "timeout=%d\n", timeout);
+
+       if (timer_pending(&mesh_if->delay_scan))
+               del_timer_sync(&mesh_if->delay_scan);
+
+       if (timeout) {
+               if (timer_pending(&mesh_if->delay_scan))
+                       del_timer_sync(&mesh_if->delay_scan);
+               mod_timer(&mesh_if->delay_scan, jiffies + msecs_to_jiffies(timeout));
+       }
+}
+
+static int
+wl_mesh_clear_vndr_ie(struct net_device *dev, uchar *oui)
+{
+       char *vndr_ie_buf = NULL;
+       vndr_ie_setbuf_t *vndr_ie = NULL;
+       ie_getbuf_t vndr_ie_tmp;
+       char *iovar_buf = NULL;
+       int err = -1, i;
+       vndr_ie_buf_t *vndr_ie_dump = NULL;
+       uchar *iebuf;
+       vndr_ie_info_t *ie_info;
+       vndr_ie_t *ie;
+
+       vndr_ie_buf = kzalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
+       if (!vndr_ie_buf) {
+               AEXT_ERROR(dev->name, "IE memory alloc failed\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       iovar_buf = kzalloc(WLC_IOCTL_MEDLEN, GFP_KERNEL);
+       if (!iovar_buf) {
+               AEXT_ERROR(dev->name, "iovar_buf alloc failed\n");
+               err = -ENOMEM;
+               goto exit;
+       }
+
+       memset(iovar_buf, 0, WLC_IOCTL_MEDLEN);
+       vndr_ie_tmp.pktflag = (uint32) -1;
+       vndr_ie_tmp.id = (uint8) DOT11_MNG_PROPR_ID;
+       err = wl_ext_iovar_getbuf(dev, "vndr_ie", &vndr_ie_tmp, sizeof(vndr_ie_tmp),
+               iovar_buf, WLC_IOCTL_MEDLEN, NULL);
+       if (err)
+               goto exit;
+
+       vndr_ie_dump = (vndr_ie_buf_t *)iovar_buf;
+       if (!vndr_ie_dump->iecount)
+               goto exit;
+
+       iebuf = (uchar *)&vndr_ie_dump->vndr_ie_list[0];
+       for (i=0; i<vndr_ie_dump->iecount; i++) {
+               ie_info = (vndr_ie_info_t *) iebuf;
+               ie = &ie_info->vndr_ie_data;
+               if (memcmp(ie->oui, oui, 3))
+                       memset(ie->oui, 0, 3);
+               iebuf += sizeof(uint32) + ie->len + VNDR_IE_HDR_LEN;
+       }
+
+       vndr_ie = (vndr_ie_setbuf_t *) vndr_ie_buf;
+       strncpy(vndr_ie->cmd, "del", VNDR_IE_CMD_LEN - 1);
+       vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
+       memcpy(&vndr_ie->vndr_ie_buffer, vndr_ie_dump, WLC_IOCTL_SMLEN-VNDR_IE_CMD_LEN-1);
+
+       memset(iovar_buf, 0, WLC_IOCTL_MEDLEN);
+       err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, WLC_IOCTL_SMLEN, iovar_buf,
+               WLC_IOCTL_MEDLEN, NULL);
+
+exit:
+       if (vndr_ie) {
+               kfree(vndr_ie);
+       }
+       if (iovar_buf) {
+               kfree(iovar_buf);
+       }
+       return err;
+}
+
+static int
+wl_mesh_clear_mesh_info(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *mesh_if, bool scan)
+{
+       struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+       uchar mesh_oui[]={0x00, 0x22, 0xf4};
+       int ret;
+
+       AEXT_TRACE(mesh_if->dev->name, "Enter\n");
+
+       ret = wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui);
+       memset(mesh_info, 0, sizeof(struct wl_mesh_params));
+       if (scan) {
+               mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
+               wl_mesh_set_timer(mesh_if, 100);
+       }
+
+       return ret;
+}
+
+static int
+wl_mesh_update_vndr_ie(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *mesh_if)
+{
+       struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+       char *vndr_ie;
+       uchar mesh_oui[]={0x00, 0x22, 0xf4};
+       int bytes_written = 0;
+       int ret = 0, i, vndr_ie_len;
+       uint8 *peer_bssid;
+
+       wl_mesh_clear_vndr_ie(mesh_if->dev, mesh_oui);
+
+       vndr_ie_len = WLC_IOCTL_MEDLEN;
+       vndr_ie = kmalloc(vndr_ie_len, GFP_KERNEL);
+       if (vndr_ie == NULL) {
+               AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n",
+                       WLC_IOCTL_MEDLEN); 
+               ret = -1;
+               goto exit;
+       }
+
+       bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+               "0x%02x%02x%02x", mesh_oui[0], mesh_oui[1], mesh_oui[2]);
+
+       bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+               "%02x%02x%02x%02x%02x%02x%02x%02x", MESH_INFO_MASTER_BSSID, ETHER_ADDR_LEN,
+               ((u8 *)(&mesh_info->master_bssid))[0], ((u8 *)(&mesh_info->master_bssid))[1],
+               ((u8 *)(&mesh_info->master_bssid))[2], ((u8 *)(&mesh_info->master_bssid))[3],
+               ((u8 *)(&mesh_info->master_bssid))[4], ((u8 *)(&mesh_info->master_bssid))[5]);
+
+       bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+               "%02x%02x%02x", MESH_INFO_MASTER_CHANNEL, 1, mesh_info->master_channel);
+
+       bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+               "%02x%02x%02x", MESH_INFO_HOP_CNT, 1, mesh_info->hop_cnt);
+
+       bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+               "%02x%02x", MESH_INFO_PEER_BSSID, mesh_info->hop_cnt*ETHER_ADDR_LEN);
+       for (i=0; i<mesh_info->hop_cnt && i<MAX_HOP_LIST; i++) {
+               peer_bssid = (uint8 *)&mesh_info->peer_bssid[i];
+               bytes_written += snprintf(vndr_ie+bytes_written, vndr_ie_len,
+                       "%02x%02x%02x%02x%02x%02x",
+                       peer_bssid[0], peer_bssid[1], peer_bssid[2],
+                       peer_bssid[3], peer_bssid[4], peer_bssid[5]);
+       }
+
+       ret = wl_ext_add_del_ie(mesh_if->dev, VNDR_IE_BEACON_FLAG|VNDR_IE_PRBRSP_FLAG,
+               vndr_ie, "add");
+       if (!ret) {
+               AEXT_INFO(mesh_if->dev->name, "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM\n",
+                       &mesh_info->master_bssid, mesh_info->master_channel, mesh_info->hop_cnt,
+                       mesh_info->peer_bssid); 
+       }
+
+exit:
+       if (vndr_ie)
+               kfree(vndr_ie);
+       return ret;
+}
+
+static bool
+wl_mesh_update_master_info(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *mesh_if)
+{
+       struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+       struct wl_if_info *sta_if = NULL;
+       bool updated = FALSE;
+
+       sta_if = wl_ext_if_enabled(apsta_params, ISTA_MODE);
+       if (sta_if) {
+               wldev_ioctl(mesh_if->dev, WLC_GET_BSSID, &mesh_info->master_bssid,
+                       ETHER_ADDR_LEN, 0);
+               mesh_info->master_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
+               mesh_info->hop_cnt = 0;
+               memset(mesh_info->peer_bssid, 0, MAX_HOP_LIST*ETHER_ADDR_LEN);
+               if (!wl_mesh_update_vndr_ie(apsta_params, mesh_if))
+                       updated = TRUE;
+       }
+
+       return updated;
+}
+
+static bool
+wl_mesh_update_mesh_info(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *mesh_if)
+{
+       struct wl_mesh_params *mesh_info = &apsta_params->mesh_info, peer_mesh_info;
+       uint32 count = 0;
+       char *dump_buf = NULL;
+       mesh_peer_info_dump_t *peer_results;
+       mesh_peer_info_ext_t *mpi_ext;
+       struct ether_addr bssid;
+       bool updated = FALSE, bss_found = FALSE;
+       uint16 cur_chan;
+
+       dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+       if (dump_buf == NULL) {
+               AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n",
+                       WLC_IOCTL_MAXLEN); 
+               return FALSE;
+       }
+       count = wl_mesh_get_peer_results(mesh_if->dev, dump_buf, WLC_IOCTL_MAXLEN);
+       if (count > 0) {
+               memset(&bssid, 0, ETHER_ADDR_LEN);
+               wldev_ioctl(mesh_if->dev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, 0);
+               peer_results = (mesh_peer_info_dump_t *)dump_buf;
+               mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
+               for (count = 0; count < peer_results->count; count++) {
+                       if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT &&
+                                       mpi_ext->peer_info.state == MESH_PEERING_ESTAB) {
+                               memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params));
+                               bss_found = wl_escan_mesh_info(mesh_if->dev, mesh_if->escan,
+                                       &mpi_ext->ea, &peer_mesh_info);
+                               if (bss_found && (mesh_info->master_channel == 0 ||
+                                               peer_mesh_info.hop_cnt <= mesh_info->hop_cnt) &&
+                                               memcmp(&peer_mesh_info.peer_bssid, &bssid, ETHER_ADDR_LEN)) {
+                                       memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+                                               ETHER_ADDR_LEN);
+                                       mesh_info->master_channel = peer_mesh_info.master_channel;
+                                       mesh_info->hop_cnt = peer_mesh_info.hop_cnt+1;
+                                       memset(mesh_info->peer_bssid, 0, MAX_HOP_LIST*ETHER_ADDR_LEN);
+                                       memcpy(&mesh_info->peer_bssid, &mpi_ext->ea, ETHER_ADDR_LEN);
+                                       memcpy(&mesh_info->peer_bssid[1], peer_mesh_info.peer_bssid,
+                                               (MAX_HOP_LIST-1)*ETHER_ADDR_LEN);
+                                       updated = TRUE;
+                               }
+                       }
+                       mpi_ext++;
+               }
+               if (updated) {
+                       if (wl_mesh_update_vndr_ie(apsta_params, mesh_if)) {
+                               AEXT_ERROR(mesh_if->dev->name, "update failed\n");
+                               mesh_info->master_channel = 0;
+                               updated = FALSE;
+                               goto exit;
+                       }
+               }
+       }
+
+       if (!mesh_info->master_channel) {
+               wlc_ssid_t cur_ssid;
+               char sec[32];
+               bool sae = FALSE;
+               memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params));
+               wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &cur_ssid, sizeof(cur_ssid), 0);
+               wl_ext_get_sec(mesh_if->dev, mesh_if->ifmode, sec, sizeof(sec));
+               if (strnicmp(sec, "sae/sae", strlen("sae/sae")) == 0)
+                       sae = TRUE;
+               cur_chan = wl_ext_get_chan(apsta_params, mesh_if->dev);
+               bss_found = wl_escan_mesh_peer(mesh_if->dev, mesh_if->escan, &cur_ssid, cur_chan,
+                       sae, &peer_mesh_info);
+
+               if (bss_found && peer_mesh_info.master_channel&&
+                               (cur_chan != peer_mesh_info.master_channel)) {
+                       WL_MSG(mesh_if->ifname, "moving channel %d -> %d\n",
+                               cur_chan, peer_mesh_info.master_channel);
+                       wl_ext_disable_iface(mesh_if->dev, mesh_if->ifname);
+                       mesh_if->channel = peer_mesh_info.master_channel;
+                       wl_ext_enable_iface(mesh_if->dev, mesh_if->ifname, 500);
+               }
+       }
+
+exit:
+       if (dump_buf)
+               kfree(dump_buf);
+       return updated;
+}
+
+static void
+wl_mesh_event_handler( struct wl_apsta_params *apsta_params,
+       struct wl_if_info *mesh_if, const wl_event_msg_t *e, void *data)
+{
+       struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+       uint32 event_type = ntoh32(e->event_type);
+       uint32 status = ntoh32(e->status);
+       uint32 reason = ntoh32(e->reason);
+       wlc_ssid_t ssid;
+       int ret;
+
+       if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+                       ((event_type == WLC_E_SET_SSID && status == WLC_E_STATUS_SUCCESS) ||
+                       (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+                       reason == WLC_E_REASON_INITIAL_ASSOC))) {
+               if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+                       mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
+                       wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS);
+               }
+       }
+       else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
+                       (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
+                       reason == WLC_E_REASON_DEAUTH)) {
+               wl_mesh_clear_mesh_info(apsta_params, mesh_if, FALSE);
+       }
+       else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+                       (event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
+                       reason == DOT11_SC_SUCCESS) {
+               mesh_info->scan_channel = wl_ext_get_chan(apsta_params, mesh_if->dev);
+               wl_mesh_set_timer(mesh_if, 100);
+       }
+       else if (event_type == WLC_E_DISASSOC_IND || event_type == WLC_E_DEAUTH_IND ||
+                       (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
+               if (!memcmp(&mesh_info->peer_bssid, &e->addr, ETHER_ADDR_LEN))
+                       wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
+       }
+       else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+                       event_type == WLC_E_RESERVED && reason == 0xFFFFFFFF) {
+               if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+                       wl_ext_ioctl(mesh_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
+                       ret = wl_escan_set_scan(mesh_if->dev, apsta_params->dhd, &ssid,
+                               mesh_info->scan_channel, FALSE);
+                       if (ret)
+                               wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS);
+               }
+       }
+       else if (wl_get_isam_status(mesh_if, AP_CREATED) &&
+                       ((event_type == WLC_E_ESCAN_RESULT && status == WLC_E_STATUS_SUCCESS) ||
+                       (event_type == WLC_E_ESCAN_RESULT &&
+                       (status == WLC_E_STATUS_ABORT || status == WLC_E_STATUS_NEWSCAN ||
+                       status == WLC_E_STATUS_11HQUIET || status == WLC_E_STATUS_CS_ABORT ||
+                       status == WLC_E_STATUS_NEWASSOC || status == WLC_E_STATUS_TIMEOUT)))) {
+               if (!wl_mesh_update_master_info(apsta_params, mesh_if)) {
+                       if (!wl_mesh_update_mesh_info(apsta_params, mesh_if)) {
+                               mesh_info->scan_channel = 0;
+                               wl_mesh_set_timer(mesh_if, WL_MESH_DELAY_SCAN_MS);
+                       }
+               }
+       }
+}
+
+static void
+wl_mesh_escan_detach(dhd_pub_t *dhd, struct wl_if_info *mesh_if)
+{
+       AEXT_TRACE(mesh_if->dev->name, "Enter\n");
+
+       del_timer_sync(&mesh_if->delay_scan);
+
+       if (mesh_if->escan) {
+               mesh_if->escan = NULL;
+       }
+}
+
+static int
+wl_mesh_escan_attach(dhd_pub_t *dhd, struct wl_if_info *mesh_if)
+{
+       AEXT_TRACE(mesh_if->dev->name, "Enter\n");
+
+       mesh_if->escan = dhd->escan;
+       init_timer_compat(&mesh_if->delay_scan, wl_mesh_timer, mesh_if);
+
+       return 0;
+}
+
+static uint
+wl_mesh_update_peer_path(struct wl_if_info *mesh_if, char *command,
+       int total_len)
+{
+       struct wl_mesh_params peer_mesh_info;
+       uint32 count = 0;
+       char *dump_buf = NULL;
+       mesh_peer_info_dump_t *peer_results;
+       mesh_peer_info_ext_t *mpi_ext;
+       int bytes_written = 0, j, k;
+       bool bss_found = FALSE;
+
+       dump_buf = kmalloc(WLC_IOCTL_MAXLEN, GFP_KERNEL);
+       if (dump_buf == NULL) {
+               AEXT_ERROR(mesh_if->dev->name, "Failed to allocate buffer of %d bytes\n",
+                       WLC_IOCTL_MAXLEN); 
+               return FALSE;
+       }
+       count = wl_mesh_get_peer_results(mesh_if->dev, dump_buf, WLC_IOCTL_MAXLEN);
+       if (count > 0) {
+               peer_results = (mesh_peer_info_dump_t *)dump_buf;
+               mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
+               for (count = 0; count < peer_results->count; count++) {
+                       if (mpi_ext->entry_state != MESH_SELF_PEER_ENTRY_STATE_TIMEDOUT &&
+                                       mpi_ext->peer_info.state == MESH_PEERING_ESTAB) {
+                               memset(&peer_mesh_info, 0, sizeof(struct wl_mesh_params));
+                               bss_found = wl_escan_mesh_info(mesh_if->dev, mesh_if->escan,
+                                       &mpi_ext->ea, &peer_mesh_info);
+                               if (bss_found) {
+                                       bytes_written += snprintf(command+bytes_written, total_len,
+                                               "\npeer=%pM, hop=%d",
+                                               &mpi_ext->ea, peer_mesh_info.hop_cnt);
+                                       for (j=1; j<peer_mesh_info.hop_cnt; j++) {
+                                               bytes_written += snprintf(command+bytes_written,
+                                                       total_len, "\n");
+                                               for (k=0; k<j; k++) {
+                                                       bytes_written += snprintf(command+bytes_written,
+                                                               total_len, " ");
+                                               }
+                                               bytes_written += snprintf(command+bytes_written, total_len,
+                                                       "%pM", &peer_mesh_info.peer_bssid[j]);
+                                       }
+                               }
+                       }
+                       mpi_ext++;
+               }
+       }
+
+       if (dump_buf)
+               kfree(dump_buf);
+       return bytes_written;
 }
 
 static int
-wl_ext_mesh_peer_status(struct net_device *dev, char *data, char *command,
-       int total_len)
+wl_ext_isam_peer_path(struct net_device *dev, char *command, int total_len)
 {
        struct dhd_pub *dhd = dhd_get_pub(dev);
        struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_mesh_params *mesh_info = &apsta_params->mesh_info;
+       struct wl_if_info *tmp_if;
+       uint16 chan = 0;
+       char *dump_buf = NULL;
+       int dump_len = WLC_IOCTL_MEDLEN;
+       int dump_written = 0;
        int i;
-       struct wl_if_info *cur_if;
-       mesh_peer_info_dump_t *peer_results;
-       mesh_peer_info_ext_t *mpi_ext;
-       char *peer_buf = NULL;
-       int peer_len = WLC_IOCTL_MAXLEN;
-       int dump_written = 0, ret;
 
-       if (!data) {
-               peer_buf = kmalloc(peer_len, GFP_KERNEL);
-               if (peer_buf == NULL) {
-                       AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
-                               peer_len); 
-                       return -1;
+       if (command || android_msg_level & ANDROID_INFO_LEVEL) {
+               if (command) {
+                       dump_buf = command;
+                       dump_len = total_len;
+               } else {
+                       dump_buf = kmalloc(dump_len, GFP_KERNEL);
+                       if (dump_buf == NULL) {
+                               AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
+                                       dump_len); 
+                               return -1;
+                       }
                }
                for (i=0; i<MAX_IF_NUM; i++) {
-                       cur_if = &apsta_params->if_info[i];
-                       if (cur_if && dev == cur_if->dev && cur_if->ifmode == IMESH_MODE) {
-                               memset(peer_buf, 0, peer_len);
-                               ret = wl_mesh_get_peer_results(dev, peer_buf, peer_len);
-                               if (ret >= 0) {
-                                       peer_results = (mesh_peer_info_dump_t *)peer_buf;
-                                       mpi_ext = (mesh_peer_info_ext_t *)peer_results->mpi_ext;
-                                       dump_written += wl_mesh_print_peer_info(mpi_ext,
-                                               peer_results->count, command+dump_written,
-                                               total_len-dump_written);
+                       tmp_if = &apsta_params->if_info[i];
+                       if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE && apsta_params->macs) {
+                               chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
+                               if (chan) {
+                                       dump_written += snprintf(dump_buf+dump_written, dump_len,
+                                               "[dhd-%s-%c] mbssid=%pM, mchan=%d, hop=%d, pbssid=%pM",
+                                               tmp_if->ifname, tmp_if->prefix, &mesh_info->master_bssid,
+                                               mesh_info->master_channel, mesh_info->hop_cnt,
+                                               &mesh_info->peer_bssid);
+                                       dump_written += wl_mesh_update_peer_path(tmp_if,
+                                               dump_buf+dump_written, dump_len-dump_written);
                                }
-                       } else if (cur_if && dev == cur_if->dev) {
-                               AEXT_ERROR(dev->name, "[%s][%c] is not mesh interface\n",
-                                       cur_if->ifname, cur_if->prefix);
                        }
                }
+               AEXT_INFO(dev->name, "%s\n", dump_buf);
        }
 
-       if (peer_buf)
-               kfree(peer_buf);
+       if (!command && dump_buf)
+               kfree(dump_buf);
        return dump_written;
 }
-#endif
+#endif /* WL_ESCAN */
+#endif /* WLMESH */
 
 static int
 wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
@@ -2214,7 +3151,6 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
        struct dhd_pub *dhd = dhd_get_pub(dev);
        struct wl_apsta_params *apsta_params = dhd->iapsta_params;
        int i;
-       bool now_if;
        struct wl_if_info *tmp_if;
        uint16 chan = 0;
        wlc_ssid_t ssid = { 0, {0} };
@@ -2241,13 +3177,10 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
                dump_written += snprintf(dump_buf+dump_written, dump_len,
                        "apstamode=%d", apsta_params->apstamode);
                for (i=0; i<MAX_IF_NUM; i++) {
-                       now_if = FALSE;
                        memset(&ssid, 0, sizeof(ssid));
                        memset(&bssid, 0, sizeof(bssid));
                        memset(&scb_val, 0, sizeof(scb_val));
                        tmp_if = &apsta_params->if_info[i];
-                       if (dev == tmp_if->dev)
-                               now_if = TRUE;
                        if (tmp_if->dev) {
                                chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
                                if (chan) {
@@ -2258,10 +3191,12 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
                                        chanspec = wl_ext_get_chanspec(apsta_params, tmp_if->dev);
                                        wl_ext_get_sec(tmp_if->dev, tmp_if->ifmode, sec, sizeof(sec));
                                        dump_written += snprintf(dump_buf+dump_written, dump_len,
-                                               "\n[dhd-%s][%c-%c%s]: bssid=%pM, chan=%3d(0x%x), "
+                                               "\n[dhd-%s-%c]: bssid=%pM, chan=%3d(0x%x %sMHz), "
                                                "rssi=%3d, sec=%-15s, SSID=\"%s\"",
-                                               tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
-                                               now_if?"*":" ", &bssid, chan, chanspec,
+                                               tmp_if->ifname, tmp_if->prefix, &bssid, chan, chanspec,
+                                               CHSPEC_IS20(chanspec)?"20":
+                                               CHSPEC_IS40(chanspec)?"40":
+                                               CHSPEC_IS80(chanspec)?"80":"160",
                                                dtoh32(scb_val.val), sec, ssid.SSID);
                                        if (tmp_if->ifmode == IAP_MODE) {
                                                dump_written += snprintf(dump_buf+dump_written, dump_len, "\n");
@@ -2274,12 +3209,10 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
                                                dump_written += wl_ext_mesh_peer_status(tmp_if->dev, NULL,
                                                        dump_buf+dump_written, dump_len-dump_written);
                                        }
-#endif
+#endif /* WLMESH */
                                } else {
                                        dump_written += snprintf(dump_buf+dump_written, dump_len,
-                                               "\n[dhd-%s][%c-%c%s]:",
-                                               tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
-                                               now_if?"*":" ");
+                                               "\n[dhd-%s-%c]:", tmp_if->ifname, tmp_if->prefix);
                                }
                        }
                }
@@ -2291,6 +3224,15 @@ wl_ext_isam_status(struct net_device *dev, char *command, int total_len)
        return dump_written;
 }
 
+static bool
+wl_ext_master_if(struct wl_if_info *cur_if)
+{
+       if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)
+               return TRUE;
+       else
+               return FALSE;
+}
+
 static int
 wl_ext_if_down(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
 {
@@ -2344,10 +3286,13 @@ wl_ext_if_up(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_if)
                return 0;
        }
 
-       if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) {
+       if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar) {
                WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
                        cur_if->prefix, cur_if->channel);
                return 0;
+       } else if (!cur_if->channel) {
+               WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
+               return 0;
        }
 
        WL_MSG(cur_if->ifname, "[%c] Turning on...\n", cur_if->prefix);
@@ -2419,6 +3364,7 @@ wl_ext_disable_iface(struct net_device *dev, char *ifname)
 
        if (cur_if->ifmode == ISTA_MODE) {
                wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
+               wl_ext_add_remove_pm_enable_work(dev, FALSE);
        } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
                // deauthenticate all STA first
                memcpy(scbval.ea.octet, &ether_bcast, ETHER_ADDR_LEN);
@@ -2450,38 +3396,33 @@ wl_ext_disable_iface(struct net_device *dev, char *ifname)
                                dhd_wlfc_deinit(dhd);
                        }
                }
-#endif 
+#endif /* BCMSDIO */
 #endif /* PROP_TXSTATUS_VSDB */
        }
-       else if (apstamode == IDUALAP_MODE) {
+       else if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE) {
                bss_setbuf.cfg = 0xffffffff;
                bss_setbuf.val = htod32(0);
                wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
                        iovar_buf, WLC_IOCTL_SMLEN, NULL);
 #ifdef WLMESH
        } else if (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE ||
-                       apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE ||
-                       apstamode == ISTAAPAP_MODE) {
+                       apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE) {
                bss_setbuf.cfg = 0xffffffff;
                bss_setbuf.val = htod32(0);
                wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
                        iovar_buf, WLC_IOCTL_SMLEN, NULL);
-#endif
-       }
-#ifdef WLMESH
-       if ((cur_if->ifmode == IMESH_MODE) &&
-                       (apstamode == ISTAMESH_MODE || apstamode == IMESHAP_MODE ||
-                       apstamode == ISTAAPMESH_MODE || apstamode == IMESHAPAP_MODE)) {
-               int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
-               for (i=0; i<MAX_IF_NUM; i++) {
-                       tmp_if = &apsta_params->if_info[i];
-                       if (tmp_if->dev && tmp_if->ifmode == ISTA_MODE) {
-                               wl_ext_ioctl(tmp_if->dev, WLC_SET_SCAN_CHANNEL_TIME,
-                                       &scan_assoc_time, sizeof(scan_assoc_time), 1);
+               if (cur_if->ifmode == IMESH_MODE) {
+                       int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME;
+                       for (i=0; i<MAX_IF_NUM; i++) {
+                               tmp_if = &apsta_params->if_info[i];
+                               if (tmp_if->dev && tmp_if->ifmode == ISTA_MODE) {
+                                       wl_ext_ioctl(tmp_if->dev, WLC_SET_SCAN_CHANNEL_TIME,
+                                               &scan_assoc_time, sizeof(scan_assoc_time), 1);
+                               }
                        }
                }
+#endif /* WLMESH */
        }
-#endif
 
        wl_clr_isam_status(cur_if, AP_CREATED);
 
@@ -2532,6 +3473,34 @@ wl_ext_diff_band(uint16 chan1, uint16 chan2)
        return FALSE;
 }
 
+static uint16
+wl_ext_same_band(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *cur_if, bool nodfs)
+{
+       struct wl_if_info *tmp_if;
+       uint16 tmp_chan, target_chan = 0;
+       wl_prio_t max_prio;
+       int i;
+
+       // find the max prio
+       max_prio = cur_if->prio;
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (cur_if != tmp_if && wl_get_isam_status(tmp_if, IF_READY) &&
+                               tmp_if->prio > max_prio) {
+                       tmp_chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
+                       if (wl_ext_dfs_chan(tmp_chan) && nodfs)
+                               continue;
+                       if (tmp_chan && !wl_ext_diff_band(cur_if->channel, tmp_chan)) {
+                               target_chan = tmp_chan;
+                               max_prio = tmp_if->prio;
+                       }
+               }
+       }
+
+       return target_chan;
+}
+
 static uint16
 wl_ext_get_vsdb_chan(struct wl_apsta_params *apsta_params,
        struct wl_if_info *cur_if, struct wl_if_info *target_if)
@@ -2589,12 +3558,10 @@ wl_ext_trigger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_
        s8 iovar_buf[WLC_IOCTL_SMLEN];
        bool core_conflict = FALSE;
 
-       if (apsta_params->csa & CSA_DRV_BIT &&
-                       (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) {
+       if (wl_ext_master_if(cur_if) && (apsta_params->csa & CSA_DRV_BIT)) {
                if (!cur_if->channel) {
-                       WL_MSG(cur_if->ifname, "[%c] skip channel %d\n",
-                               cur_if->prefix, cur_if->channel);
-               } else if (wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) {
+                       WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
+               } else if (wl_ext_dfs_chan(cur_if->channel) && !apsta_params->radar) {
                        WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
                                cur_if->prefix, cur_if->channel);
                        wl_ext_if_down(apsta_params, cur_if);
@@ -2627,9 +3594,139 @@ wl_ext_trigger_csa(struct wl_apsta_params *apsta_params, struct wl_if_info *cur_
        return 0;
 }
 
+static void
+wl_ext_move_cur_dfs_channel(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *cur_if)
+{
+       uint16 other_chan = 0, cur_chan = cur_if->channel;
+       uint16 chan_2g = 0, chan_5g = 0;
+       uint32 auto_band = WLC_BAND_2G;
+
+       if (wl_ext_master_if(cur_if) && wl_ext_dfs_chan(cur_if->channel) &&
+                       !apsta_params->radar) {
+
+               wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE);
+               if (!chan_2g && !chan_5g) {
+                       cur_if->channel = 0;
+                       WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
+                       return;
+               }
+
+               if (apsta_params->vsdb) {
+                       if (chan_5g) {
+                               cur_if->channel = chan_5g;
+                               auto_band = WLC_BAND_5G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                       } else {
+                               cur_if->channel = chan_2g;
+                               auto_band = WLC_BAND_2G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                       }
+                       if (!other_chan) {
+                               other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+                                       auto_band);
+                       }
+                       if (other_chan)
+                               cur_if->channel = other_chan;
+               } else if (apsta_params->rsdb) {
+                       if (chan_5g) {
+                               cur_if->channel = chan_5g;
+                               auto_band = WLC_BAND_5G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, FALSE);
+                               if (wl_ext_dfs_chan(other_chan) && chan_2g) {
+                                       cur_if->channel = chan_2g;
+                                       auto_band = WLC_BAND_2G;
+                                       other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                               }
+                       } else {
+                               cur_if->channel = chan_2g;
+                               auto_band = WLC_BAND_2G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                       }
+                       if (!other_chan) {
+                               other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+                                       auto_band);
+                       }
+                       if (other_chan)
+                               cur_if->channel = other_chan;
+               } else {
+                       cur_if->channel = chan_5g;
+                       auto_band = WLC_BAND_5G;
+                       other_chan = wl_ext_same_band(apsta_params, cur_if, FALSE);
+                       if (wl_ext_dfs_chan(other_chan)) {
+                               cur_if->channel = 0;
+                       }
+                       else if (!other_chan) {
+                               other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+                                       auto_band);
+                       }
+                       if (other_chan)
+                               cur_if->channel = other_chan;
+               }
+               WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n",
+                       cur_if->prefix, cur_chan, cur_if->channel);
+       }
+}
+
+static void
+wl_ext_move_other_dfs_channel(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *cur_if)
+{
+       uint16 other_chan = 0, cur_chan = cur_if->channel;
+       uint16 chan_2g = 0, chan_5g = 0;
+       uint32 auto_band = WLC_BAND_2G;
+
+       if (wl_ext_master_if(cur_if) && wl_ext_dfs_chan(cur_if->channel) &&
+                       !apsta_params->radar) {
+
+               wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE);
+               if (!chan_2g && !chan_5g) {
+                       cur_if->channel = 0;
+                       WL_MSG(cur_if->ifname, "[%c] no valid channel\n", cur_if->prefix);
+                       return;
+               }
+
+               if (apsta_params->vsdb) {
+                       if (chan_5g) {
+                               cur_if->channel = chan_5g;
+                               auto_band = WLC_BAND_5G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                       } else {
+                               cur_if->channel = chan_2g;
+                               auto_band = WLC_BAND_2G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                       }
+                       if (!other_chan) {
+                               other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+                                       auto_band);
+                       }
+                       if (other_chan)
+                               cur_if->channel = other_chan;
+               } else if (apsta_params->rsdb) {
+                       if (chan_2g) {
+                               cur_if->channel = chan_2g;
+                               auto_band = WLC_BAND_2G;
+                               other_chan = wl_ext_same_band(apsta_params, cur_if, TRUE);
+                               if (!other_chan) {
+                                       other_chan = wl_ext_autochannel(cur_if->dev, ACS_FW_BIT|ACS_DRV_BIT,
+                                               auto_band);
+                               }
+                       } else {
+                               cur_if->channel = 0;
+                       }
+                       if (other_chan)
+                               cur_if->channel = other_chan;
+               } else {
+                       cur_if->channel = 0;
+               }
+               WL_MSG(cur_if->ifname, "[%c] move channel %d => %d\n",
+                       cur_if->prefix, cur_chan, cur_if->channel);
+       }
+}
+
 static uint16
 wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params,
-       struct net_device *dev, struct wl_if_info *cur_if)
+       struct wl_if_info *cur_if)
 {
        struct wl_if_info *tmp_if, *target_if = NULL;
        uint16 tmp_chan, target_chan = 0;
@@ -2655,6 +3752,7 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params,
                        }
                }
        }
+
        if (target_chan) {
                tmp_chan = wl_ext_get_chan(apsta_params, cur_if->dev);
                if (apsta_params->rsdb && tmp_chan &&
@@ -2669,20 +3767,16 @@ wl_ext_move_cur_channel(struct wl_apsta_params *apsta_params,
                        cur_if->channel = target_chan;
                }
        }
+
 exit:
-       if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) &&
-                       wl_ext_dfs_chan(apsta_params, cur_if->dev, cur_if->channel)) {
-               WL_MSG(cur_if->ifname, "[%c] skip DFS channel %d\n",
-                       cur_if->prefix, cur_if->channel);
-               cur_if->channel = 0;
-       }
+       wl_ext_move_cur_dfs_channel(apsta_params, cur_if);
 
        return cur_if->channel;
 }
 
 static void
 wl_ext_move_other_channel(struct wl_apsta_params *apsta_params,
-       struct net_device *dev, struct wl_if_info *cur_if)
+       struct wl_if_info *cur_if)
 {
        struct wl_if_info *tmp_if, *target_if=NULL;
        uint16 tmp_chan, target_chan = 0;
@@ -2712,11 +3806,12 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params,
                WL_MSG(target_if->ifname, "channel=%d => %s channel=%d\n",
                        target_chan, cur_if->ifname, cur_if->channel);
                target_if->channel = cur_if->channel;
+               wl_ext_move_other_dfs_channel(apsta_params, target_if);
                if (apsta_params->csa == 0) {
                        wl_ext_if_down(apsta_params, target_if);
-                       wl_ext_move_other_channel(apsta_params, dev, target_if);
+                       wl_ext_move_other_channel(apsta_params, cur_if);
                        if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) {
-                               wl_ext_enable_iface(target_if->dev, target_if->ifname);
+                               wl_ext_enable_iface(target_if->dev, target_if->ifname, 0);
                        } else if (target_if->ifmode == IAP_MODE) {
                                wl_ext_if_up(apsta_params, target_if);
                        }
@@ -2727,8 +3822,53 @@ wl_ext_move_other_channel(struct wl_apsta_params *apsta_params,
 
 }
 
+static bool
+wl_ext_wait_other_enabling(struct wl_apsta_params *apsta_params,
+       struct wl_if_info *cur_if)
+{
+       struct wl_if_info *tmp_if;
+       bool enabling = FALSE;
+       u32 timeout = 1;
+       int i;
+
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev && tmp_if->dev != cur_if->dev) {
+                       if (tmp_if->ifmode == ISTA_MODE)
+                               enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
+                       else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
+                               enabling = wl_get_isam_status(tmp_if, AP_CREATING);
+                       if (enabling)
+                               WL_MSG(cur_if->ifname, "waiting for %s[%c] enabling...\n",
+                                       tmp_if->ifname, tmp_if->prefix);
+                       if (enabling && tmp_if->ifmode == ISTA_MODE) {
+                               timeout = wait_event_interruptible_timeout(
+                                       apsta_params->netif_change_event,
+                                       !wl_get_isam_status(tmp_if, STA_CONNECTING),
+                                       msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
+                       } else if (enabling &&
+                                       (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)) {
+                               timeout = wait_event_interruptible_timeout(
+                                       apsta_params->netif_change_event,
+                                       !wl_get_isam_status(tmp_if, AP_CREATING),
+                                       msecs_to_jiffies(MAX_STA_LINK_WAIT_TIME));
+                       }
+                       if (tmp_if->ifmode == ISTA_MODE)
+                               enabling = wl_get_isam_status(tmp_if, STA_CONNECTING);
+                       else if (tmp_if->ifmode == IAP_MODE || tmp_if->ifmode == IMESH_MODE)
+                               enabling = wl_get_isam_status(tmp_if, AP_CREATING);
+                       if (timeout <= 0 || enabling) {
+                               WL_MSG(cur_if->ifname, "%s[%c] is still enabling...\n",
+                                       tmp_if->ifname, tmp_if->prefix);
+                       }
+               }
+       }
+
+       return enabling;
+}
+
 static int
-wl_ext_enable_iface(struct net_device *dev, char *ifname)
+wl_ext_enable_iface(struct net_device *dev, char *ifname, int wait_up)
 {
        struct dhd_pub *dhd = dhd_get_pub(dev);
        int i, ret = 0;
@@ -2769,10 +3909,29 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname)
        wl_ext_isam_status(cur_if->dev, NULL, 0);
        WL_MSG(ifname, "[%c] Enabling...\n", cur_if->prefix);
 
-       wl_ext_check_other_enabling(apsta_params, cur_if);
+       wl_ext_wait_other_enabling(apsta_params, cur_if);
+
+       if (wl_ext_master_if(cur_if) && apsta_params->acs) {
+               uint16 chan_2g, chan_5g;
+               uint auto_band;
+               auto_band = WL_GET_BAND(cur_if->channel);
+               wl_ext_get_default_chan(cur_if->dev, &chan_2g, &chan_5g, TRUE);
+               if ((chan_2g && auto_band == WLC_BAND_2G) ||
+                               (chan_5g && auto_band == WLC_BAND_5G)) {
+                       cur_if->channel = wl_ext_autochannel(cur_if->dev, apsta_params->acs,
+                               auto_band);
+               } else {
+                       AEXT_ERROR(ifname, "invalid channel\n");
+                       ret = -1;
+                       goto exit;
+               }
+       }
+
+       wl_ext_move_cur_channel(apsta_params, cur_if);
 
-       wl_ext_move_cur_channel(apsta_params, dev, cur_if);
-       if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) {
+       if (wl_ext_master_if(cur_if) && !cur_if->channel) {
+               AEXT_ERROR(ifname, "skip channel 0\n");
+               ret = -1;
                goto exit;
        }
 
@@ -2790,7 +3949,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname)
                wl_clr_isam_status(cur_if, AP_CREATED);
        }
 
-       wl_ext_move_other_channel(apsta_params, dev, cur_if);
+       wl_ext_move_other_channel(apsta_params, cur_if);
 
        if (cur_if->ifidx > 0) {
                wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr,
@@ -2810,33 +3969,15 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname)
                }
        }
 
-       if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+       if (wl_ext_master_if(cur_if)) {
                wl_ext_set_bgnmode(cur_if);
                if (!cur_if->channel) {
-#ifdef WL_CFG80211
-                       char *pick_tmp, *param;
-                       char cmd[128];
-                       uint16 cur_chan;
-                       cur_chan = 1;
-                       snprintf(cmd, 128, "get_best_channels");
-                       wl_cfg80211_get_best_channels(dev, cmd, strlen(cmd));
-                       pick_tmp = cmd;
-                       param = bcmstrtok(&pick_tmp, " ", 0);
-                       while (param != NULL) {
-                               if (!strnicmp(param, "2g=", strlen("2g="))) {
-                                       cur_chan = (int)simple_strtol(param+strlen("2g="), NULL, 10);
-                               } else if (!strnicmp(param, "5g=", strlen("5g="))) {
-                                       cur_chan = (int)simple_strtol(param+strlen("5g="), NULL, 10);
-                               }
-                               param = bcmstrtok(&pick_tmp, " ", 0);
-                       }
-                       cur_if->channel = cur_chan;
-#else
                        cur_if->channel = 1;
-#endif
                }
-               wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
-                       &fw_chspec);
+               ret = wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver,
+                       cur_if->channel, &fw_chspec);
+               if (ret)
+                       goto exit;
        }
 
        wl_ext_set_amode(cur_if);
@@ -2870,7 +4011,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname)
                if (cur_if->ifmode == ISTA_MODE) {
                        wl_ext_connect(cur_if->dev, &conn_info);
                } else {
-                       if (apsta_params->rsdb) {
+                       if (FW_SUPPORTED(dhd, rsdb)) {
                                wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
                        } else {
                                bss_setbuf.cfg = htod32(cur_if->bssidx);
@@ -2893,7 +4034,7 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname)
                                        wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                                }
                        }
-#endif
+#endif /* BCMSDIO */
 #endif /* PROP_TXSTATUS_VSDB */
                }
        }
@@ -2927,14 +4068,17 @@ wl_ext_enable_iface(struct net_device *dev, char *ifname)
                } else {
                        AEXT_ERROR(cur_if->ifname, "wrong ifmode %d\n", cur_if->ifmode);
                }
-#endif
+#endif /* WLMESH */
        }
 
-       if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+       if (wait_up) {
+               OSL_SLEEP(wait_up);
+       } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
                timeout = wait_event_interruptible_timeout(apsta_params->netif_change_event,
                        wl_get_isam_status(cur_if, AP_CREATED),
                        msecs_to_jiffies(MAX_AP_LINK_WAIT_TIME));
                if (timeout <= 0 || !wl_get_isam_status(cur_if, AP_CREATED)) {
+                       mutex_unlock(&apsta_params->usr_sync);
                        wl_ext_disable_iface(dev, cur_if->ifname);
                        WL_MSG(ifname, "[%c] failed to enable with SSID: \"%s\"\n",
                                cur_if->prefix, cur_if->ssid);
@@ -2963,7 +4107,7 @@ exit:
        if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
                wl_clr_isam_status(cur_if, AP_CREATING);
        }
-       WL_MSG(ifname, "[%c] Exit\n", cur_if->prefix);
+       WL_MSG(ifname, "[%c] Exit ret=%d\n", cur_if->prefix, ret);
        mutex_unlock(&apsta_params->usr_sync);
        return ret;
 }
@@ -2985,7 +4129,7 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
                        pch = bcmstrtok(&pick_tmp, " ", 0);
                        if (pch) {
                                strcpy(ifname, pch);
-                               ret = wl_ext_enable_iface(dev, ifname);
+                               ret = wl_ext_enable_iface(dev, ifname, 0);
                                if (ret)
                                        return ret;
                        } else {
@@ -2999,88 +4143,91 @@ wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len)
        return ret;
 }
 
+#ifdef PROPTX_MAXCOUNT
 int
-wl_ext_iapsta_alive_preinit(struct net_device *dev)
+wl_ext_get_wlfc_maxcount(struct dhd_pub *dhd, int ifidx)
 {
-       struct dhd_pub *dhd = dhd_get_pub(dev);
        struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_if_info *tmp_if, *cur_if = NULL;
+       int i, maxcount = WL_TXSTATUS_FREERUNCTR_MASK;
 
-       if (apsta_params->init == TRUE) {
-               AEXT_ERROR(dev->name, "don't init twice\n");
-               return -1;
-       }
-
-       AEXT_TRACE(dev->name, "Enter\n");
-
-       apsta_params->init = TRUE;
-
-       return 0;
-}
-
-int
-wl_ext_iapsta_alive_postinit(struct net_device *dev)
-{
-       struct dhd_pub *dhd = dhd_get_pub(dev);
-       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
-       s32 apsta = 0;
-       struct wl_if_info *cur_if;
-       int i;
+       if (!apsta_params->rsdb)
+               return maxcount;
 
-       wl_ext_iovar_getint(dev, "apsta", &apsta);
-       if (apsta == 1) {
-               apsta_params->apstamode = ISTAONLY_MODE;
-               apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
-               op_mode = DHD_FLAG_STA_MODE;
-       } else {
-               apsta_params->apstamode = IAPONLY_MODE;
-               apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
-               op_mode = DHD_FLAG_HOSTAP_MODE;
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev && tmp_if->ifidx == ifidx) {
+                       cur_if = tmp_if;
+                       maxcount = cur_if->transit_maxcount;
+               }
        }
-       // fix me: how to check it's ISTAAP_MODE or IDUALAP_MODE?
 
-       wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
-       WL_MSG(dev->name, "apstamode=%d\n", apsta_params->apstamode);
+       if (cur_if)
+               AEXT_INFO(cur_if->ifname, "update maxcount %d\n", maxcount);
+       else
+               AEXT_INFO("wlan", "update maxcount %d for ifidx %d\n", maxcount, ifidx);
+       return maxcount;
+}
+
+void
+wl_ext_update_wlfc_maxcount(struct dhd_pub *dhd)
+{
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_if_info *tmp_if;
+       bool band_5g = FALSE;
+       uint16 chan = 0;
+       int i, ret;
+
+       if (!apsta_params->rsdb)
+               return;
 
        for (i=0; i<MAX_IF_NUM; i++) {
-               cur_if = &apsta_params->if_info[i];
-               if (i == 1 && !strlen(cur_if->ifname))
-                       strcpy(cur_if->ifname, "wlan1");
-               if (i == 2 && !strlen(cur_if->ifname))
-                       strcpy(cur_if->ifname, "wlan2");
-               if (cur_if->ifmode == ISTA_MODE) {
-                       cur_if->channel = 0;
-                       cur_if->maxassoc = -1;
-                       wl_set_isam_status(cur_if, IF_READY);
-                       cur_if->prio = PRIO_STA;
-                       cur_if->prefix = 'S';
-                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
-               } else if (cur_if->ifmode == IAP_MODE) {
-                       cur_if->channel = 1;
-                       cur_if->maxassoc = -1;
-                       wl_set_isam_status(cur_if, IF_READY);
-                       cur_if->prio = PRIO_AP;
-                       cur_if->prefix = 'A';
-                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
-#ifdef WLMESH
-               } else if (cur_if->ifmode == IMESH_MODE) {
-                       cur_if->channel = 1;
-                       cur_if->maxassoc = -1;
-                       wl_set_isam_status(cur_if, IF_READY);
-                       cur_if->prio = PRIO_MESH;
-                       cur_if->prefix = 'M';
-                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
-#endif
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev) {
+                       chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
+                       if (chan > CH_MAX_2G_CHANNEL) {
+                               tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g;
+                               ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx,
+                                       tmp_if->transit_maxcount);
+                               if (ret == 0)
+                                       AEXT_INFO(tmp_if->ifname, "updated maxcount %d\n",
+                                               tmp_if->transit_maxcount);
+                               band_5g = TRUE;
+                       }
                }
        }
 
-       return op_mode;
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev) {
+                       chan = wl_ext_get_chan(apsta_params, tmp_if->dev);
+                       if ((chan == 0) || (chan <= CH_MAX_2G_CHANNEL && chan >= CH_MIN_2G_CHANNEL)) {
+                               if (chan == 0) {
+                                       tmp_if->transit_maxcount = WL_TXSTATUS_FREERUNCTR_MASK;
+                               } else if (band_5g) {
+                                       tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_2g;
+                               } else {
+                                       tmp_if->transit_maxcount = dhd->conf->proptx_maxcnt_5g;
+                               }
+                               ret = dhd_wlfc_update_maxcount(dhd, tmp_if->ifidx,
+                                       tmp_if->transit_maxcount);
+                               if (ret == 0)
+                                       AEXT_INFO(tmp_if->ifname, "updated maxcount %d\n",
+                                               tmp_if->transit_maxcount);
+                       }
+               }
+       }
 }
+#endif /* PROPTX_MAXCOUNT */
 
-int
+static int
 wl_ext_iapsta_event(struct net_device *dev,
        struct wl_apsta_params *apsta_params, wl_event_msg_t *e, void* data)
 {
        struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
+#if defined(WLMESH) && defined(WL_ESCAN)
+       struct wl_if_info *mesh_if = NULL;
+#endif /* WLMESH && WL_ESCAN */
        int i;
        uint32 event_type = ntoh32(e->event_type);
        uint32 status =  ntoh32(e->status);
@@ -3094,12 +4241,21 @@ wl_ext_iapsta_event(struct net_device *dev,
                        break;
                }
        }
+#if defined(WLMESH) && defined(WL_ESCAN)
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev && tmp_if->ifmode == IMESH_MODE) {
+                       mesh_if = tmp_if;
+                       break;
+               }
+       }
+#endif /* WLMESH && WL_ESCAN */
        if (!cur_if || !cur_if->dev) {
                AEXT_DBG(dev->name, "ifidx %d is not ready\n", e->ifidx);
                return -1;
        }
 
-       if (cur_if->ifmode == ISTA_MODE) {
+       if (cur_if->ifmode == ISTA_MODE || cur_if->ifmode == IGC_MODE) {
                if (event_type == WLC_E_LINK) {
                        if (!(flags & WLC_EVENT_MSG_LINK)) {
                                WL_MSG(cur_if->ifname,
@@ -3107,24 +4263,46 @@ wl_ext_iapsta_event(struct net_device *dev,
                                        cur_if->prefix, &e->addr, bcmevent_get_name(event_type),
                                        event_type, reason);
                                wl_clr_isam_status(cur_if, STA_CONNECTED);
+#if defined(WLMESH) && defined(WL_ESCAN)
+                               if (mesh_if && apsta_params->macs)
+                                       wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
+#endif /* WLMESH && WL_ESCAN */
                        } else {
                                WL_MSG(cur_if->ifname, "[%c] Link UP with %pM\n",
                                        cur_if->prefix, &e->addr);
                                wl_set_isam_status(cur_if, STA_CONNECTED);
+#if defined(WLMESH) && defined(WL_ESCAN)
+                               if (mesh_if && apsta_params->macs)
+                                       wl_mesh_update_master_info(apsta_params, mesh_if);
+#endif /* WLMESH && WL_ESCAN */
                        }
                        wl_clr_isam_status(cur_if, STA_CONNECTING);
                        wake_up_interruptible(&apsta_params->netif_change_event);
+#ifdef PROPTX_MAXCOUNT
+                       wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+#endif /* PROPTX_MAXCOUNT */
                } else if (event_type == WLC_E_SET_SSID && status != WLC_E_STATUS_SUCCESS) {
                        WL_MSG(cur_if->ifname,
                                "connect failed event=%d, reason=%d, status=%d\n",
                                event_type, reason, status);
                        wl_clr_isam_status(cur_if, STA_CONNECTING);
                        wake_up_interruptible(&apsta_params->netif_change_event);
+#if defined(WLMESH) && defined(WL_ESCAN)
+                       if (mesh_if && apsta_params->macs)
+                               wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
+#endif /* WLMESH && WL_ESCAN */
+#ifdef PROPTX_MAXCOUNT
+                       wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+#endif /* PROPTX_MAXCOUNT */
                } else if (event_type == WLC_E_DEAUTH || event_type == WLC_E_DEAUTH_IND ||
                                event_type == WLC_E_DISASSOC || event_type == WLC_E_DISASSOC_IND) {
                        WL_MSG(cur_if->ifname, "[%c] Link down with %pM, %s(%d), reason %d\n",
                                cur_if->prefix, &e->addr, bcmevent_get_name(event_type),
                                event_type, reason);
+#if defined(WLMESH) && defined(WL_ESCAN)
+                       if (mesh_if && apsta_params->macs)
+                               wl_mesh_clear_mesh_info(apsta_params, mesh_if, TRUE);
+#endif /* WLMESH && WL_ESCAN */
                }
        }
        else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
@@ -3137,35 +4315,49 @@ wl_ext_iapsta_event(struct net_device *dev,
                                wl_set_isam_status(cur_if, AP_CREATED);
                                wake_up_interruptible(&apsta_params->netif_change_event);
                        } else {
+                               wl_set_isam_status(cur_if, AP_CREATED);
                                WL_MSG(cur_if->ifname, "[%c] Link up w/o creating? (etype=%d)\n",
                                        cur_if->prefix, event_type);
                        }
-               } else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
+#ifdef PROPTX_MAXCOUNT
+                       wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+#endif /* PROPTX_MAXCOUNT */
+               }
+               else if ((event_type == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS) ||
                                (event_type == WLC_E_LINK && status == WLC_E_STATUS_SUCCESS &&
                                reason == WLC_E_REASON_DEAUTH)) {
                        wl_clr_isam_status(cur_if, AP_CREATED);
                        WL_MSG(cur_if->ifname, "[%c] Link down, reason=%d\n",
                                cur_if->prefix, reason);
+#ifdef PROPTX_MAXCOUNT
+                       wl_ext_update_wlfc_maxcount(apsta_params->dhd);
+#endif /* PROPTX_MAXCOUNT */
                }
                else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
                                reason == DOT11_SC_SUCCESS) {
                        WL_MSG(cur_if->ifname, "[%c] connected device %pM\n",
                                cur_if->prefix, &e->addr);
                        wl_ext_isam_status(cur_if->dev, NULL, 0);
-               } else if (event_type == WLC_E_DISASSOC_IND ||
+               }
+               else if (event_type == WLC_E_DISASSOC_IND ||
                                event_type == WLC_E_DEAUTH_IND ||
                                (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
-                       WL_MSG(cur_if->ifname,
+                       WL_MSG_RLMT(cur_if->ifname, &e->addr, ETHER_ADDR_LEN,
                                "[%c] disconnected device %pM, %s(%d), reason=%d\n",
                                cur_if->prefix, &e->addr, bcmevent_get_name(event_type),
                                event_type, reason);
                        wl_ext_isam_status(cur_if->dev, NULL, 0);
                }
+#if defined(WLMESH) && defined(WL_ESCAN)
+               if (cur_if->ifmode == IMESH_MODE && apsta_params->macs)
+                       wl_mesh_event_handler(apsta_params, cur_if, e, data);
+#endif /* WLMESH && WL_ESCAN */
        }
 
        return 0;
 }
 
+#ifdef WL_CFG80211
 u32
 wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev,
        u32 channel)
@@ -3183,21 +4375,46 @@ wl_ext_iapsta_update_channel(dhd_pub_t *dhd, struct net_device *dev,
        }
 
        if (cur_if) {
-               if (cur_if->ifmode == ISTA_MODE)
-                       wl_set_isam_status(cur_if, STA_CONNECTING);
                wl_ext_isam_status(cur_if->dev, NULL, 0);
                cur_if->channel = channel;
-               channel = wl_ext_move_cur_channel(apsta_params,
-                       apsta_params->if_info[IF_PIF].dev, cur_if);
+               if (wl_ext_master_if(cur_if) && apsta_params->acs) {
+                       uint auto_band = WL_GET_BAND(channel);
+                       cur_if->channel = wl_ext_autochannel(cur_if->dev, apsta_params->acs,
+                               auto_band);
+               }
+               channel = wl_ext_move_cur_channel(apsta_params, cur_if);
                if (channel)
-                       wl_ext_move_other_channel(apsta_params,
-                               apsta_params->if_info[IF_PIF].dev, cur_if);
+                       wl_ext_move_other_channel(apsta_params, cur_if);
+               if (cur_if->ifmode == ISTA_MODE)
+                       wl_set_isam_status(cur_if, STA_CONNECTING);
        }
 
        return channel;
 }
 
-#ifdef WL_CFG80211
+static int
+wl_ext_iftype_to_ifmode(struct net_device *net, int wl_iftype, ifmode_t *ifmode)
+{      
+       switch (wl_iftype) {
+               case WL_IF_TYPE_STA:
+                       *ifmode = ISTA_MODE;
+                       break;
+               case WL_IF_TYPE_AP:
+                       *ifmode = IAP_MODE;
+                       break;
+               case WL_IF_TYPE_P2P_GO:
+                       *ifmode = IGO_MODE;
+                       break;
+               case WL_IF_TYPE_P2P_GC:
+                       *ifmode = IGC_MODE;
+                       break;
+               default:
+                       AEXT_ERROR(net->name, "Unknown interface wl_iftype:0x%x\n", wl_iftype);
+                       return BCME_ERROR;
+       }
+       return BCME_OK;
+}
+
 void
 wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype)
 {
@@ -3216,16 +4433,25 @@ wl_ext_iapsta_update_iftype(struct net_device *net, int ifidx, int wl_iftype)
                        cur_if->ifmode = ISTA_MODE;
                        cur_if->prio = PRIO_STA;
                        cur_if->prefix = 'S';
-               } else if (wl_iftype == WL_IF_TYPE_AP) {
+               } else if (wl_iftype == WL_IF_TYPE_AP && cur_if->ifmode != IMESH_MODE) {
                        cur_if->ifmode = IAP_MODE;
                        cur_if->prio = PRIO_AP;
                        cur_if->prefix = 'A';
+               } else if (wl_iftype == WL_IF_TYPE_P2P_GO) {
+                       cur_if->ifmode = IGO_MODE;
+                       cur_if->prio = PRIO_AP;
+                       cur_if->prefix = 'P';
+                       apsta_params->vsdb = TRUE;
+               } else if (wl_iftype == WL_IF_TYPE_P2P_GC) {
+                       cur_if->ifmode = IGC_MODE;
+                       cur_if->prio = PRIO_STA;
+                       cur_if->prefix = 'P';
+                       apsta_params->vsdb = TRUE;
+                       wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 3);
                }
        }
 }
-#endif
 
-#ifdef WL_STATIC_IF
 void
 wl_ext_iapsta_ifadding(struct net_device *net, int ifidx)
 {
@@ -3239,7 +4465,144 @@ wl_ext_iapsta_ifadding(struct net_device *net, int ifidx)
                wl_set_isam_status(cur_if, IF_ADDING);
        }
 }
-#endif
+
+bool
+wl_ext_iapsta_iftype_enabled(struct net_device *net, int wl_iftype)
+{
+       struct dhd_pub *dhd = dhd_get_pub(net);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_if_info *cur_if = NULL;
+       ifmode_t ifmode = 0;
+
+       wl_ext_iftype_to_ifmode(net, wl_iftype, &ifmode);
+       cur_if = wl_ext_if_enabled(apsta_params, ifmode);
+       if (cur_if)
+               return TRUE;
+
+       return FALSE;
+}
+
+bool
+wl_ext_iapsta_mesh_creating(struct net_device *net)
+{
+       struct dhd_pub *dhd = dhd_get_pub(net);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_if_info *cur_if;
+       int i;
+
+       if (apsta_params) {
+               for (i=0; i<MAX_IF_NUM; i++) {
+                       cur_if = &apsta_params->if_info[i];
+                       if (cur_if->ifmode==IMESH_MODE && wl_get_isam_status(cur_if, IF_ADDING))
+                               return TRUE;
+               }
+       }
+       return FALSE;
+}
+#endif /* WL_CFG80211 */
+
+int
+wl_ext_iapsta_alive_preinit(struct net_device *dev)
+{
+       struct dhd_pub *dhd = dhd_get_pub(dev);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+
+       if (apsta_params->init == TRUE) {
+               AEXT_ERROR(dev->name, "don't init twice\n");
+               return -1;
+       }
+
+       AEXT_TRACE(dev->name, "Enter\n");
+
+       apsta_params->init = TRUE;
+
+       return 0;
+}
+
+int
+wl_ext_iapsta_alive_postinit(struct net_device *dev)
+{
+       struct dhd_pub *dhd = dhd_get_pub(dev);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       s32 apsta = 0, ap = 0;
+       struct wl_if_info *cur_if;
+       int i;
+
+       wl_ext_iovar_getint(dev, "apsta", &apsta);
+       wl_ext_ioctl(dev, WLC_GET_AP, &ap, sizeof(ap), 0);
+       if (apsta == 1 || ap == 0) {
+               apsta_params->apstamode = ISTAONLY_MODE;
+               apsta_params->if_info[IF_PIF].ifmode = ISTA_MODE;
+               op_mode = DHD_FLAG_STA_MODE;
+       } else {
+               apsta_params->apstamode = IAPONLY_MODE;
+               apsta_params->if_info[IF_PIF].ifmode = IAP_MODE;
+               op_mode = DHD_FLAG_HOSTAP_MODE;
+       }
+       // fix me: how to check it's ISTAAP_MODE or IDUALAP_MODE?
+
+       wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
+       WL_MSG(dev->name, "apstamode=%d\n", apsta_params->apstamode);
+
+       for (i=0; i<MAX_IF_NUM; i++) {
+               cur_if = &apsta_params->if_info[i];
+               if (i == 1 && !strlen(cur_if->ifname))
+                       strcpy(cur_if->ifname, "wlan1");
+               if (i == 2 && !strlen(cur_if->ifname))
+                       strcpy(cur_if->ifname, "wlan2");
+               if (cur_if->ifmode == ISTA_MODE) {
+                       cur_if->channel = 0;
+                       cur_if->maxassoc = -1;
+                       wl_set_isam_status(cur_if, IF_READY);
+                       cur_if->prio = PRIO_STA;
+                       cur_if->prefix = 'S';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_sta");
+               } else if (cur_if->ifmode == IAP_MODE) {
+                       cur_if->channel = 1;
+                       cur_if->maxassoc = -1;
+                       wl_set_isam_status(cur_if, IF_READY);
+                       cur_if->prio = PRIO_AP;
+                       cur_if->prefix = 'A';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
+#ifdef WLMESH
+               } else if (cur_if->ifmode == IMESH_MODE) {
+                       cur_if->channel = 1;
+                       cur_if->maxassoc = -1;
+                       wl_set_isam_status(cur_if, IF_READY);
+                       cur_if->prio = PRIO_MESH;
+                       cur_if->prefix = 'M';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
+#endif /* WLMESH */
+               }
+       }
+
+       return op_mode;
+}
+
+static int
+wl_ext_iapsta_get_rsdb(struct net_device *net, struct dhd_pub *dhd)
+{
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+       wl_config_t *rsdb_p;
+       int ret = 0, rsdb = 0;
+
+       if (dhd->conf->chip == BCM4359_CHIP_ID) {
+               ret = wldev_iovar_getbuf(net, "rsdb_mode", NULL, 0,
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               if (!ret) {
+                       if (dhd->conf->fw_type == FW_TYPE_MESH) {
+                               rsdb = 1;
+                       } else {
+                               rsdb_p = (wl_config_t *) iovar_buf;
+                               rsdb = rsdb_p->config;
+                       }
+               }
+       }
+
+       AEXT_INFO(net->name, "rsdb_mode=%d\n", rsdb);
+
+       return rsdb;
+}
 
 static void
 wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if)
@@ -3250,10 +4613,11 @@ wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if)
 
        AEXT_TRACE(cur_if->ifname, "ifidx=%d\n", cur_if->ifidx);
        if (cur_if->ifidx == 0) {
-               apsta_params->csa |= CSA_FW_BIT;
-               if (dhd->conf->chip == BCM4359_CHIP_ID) {
-                       apsta_params->rsdb = TRUE;
-               }
+               apsta_params->rsdb = wl_ext_iapsta_get_rsdb(net, dhd);
+               apsta_params->vsdb = FALSE;
+               apsta_params->csa = 0;
+               apsta_params->acs = 0;
+               apsta_params->radar = wl_ext_radar_detect(net);
                if (dhd->conf->fw_type == FW_TYPE_MESH) {
                        apsta_params->csa |= (CSA_FW_BIT | CSA_DRV_BIT);
                }
@@ -3266,15 +4630,18 @@ wl_ext_iapsta_postinit(struct net_device *net, struct wl_if_info *cur_if)
                        else
                                pm = PM_FAST;
                        wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
-                       wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 30);
+                       wl_ext_iovar_setint(cur_if->dev, "assoc_retry_max", 20);
                }
 #ifdef WLMESH
                else if (cur_if->ifmode == IMESH_MODE) {
                        pm = 0;
                        wl_ext_ioctl(cur_if->dev, WLC_SET_PM, &pm, sizeof(pm), 1);
                }
-#endif
+#endif /* WLMESH */
        }
+#ifdef PROPTX_MAXCOUNT
+       wl_ext_update_wlfc_maxcount(dhd);
+#endif /* PROPTX_MAXCOUNT */
 
 }
 
@@ -3300,7 +4667,43 @@ wl_ext_iapsta_attach_name(struct net_device *net, int ifidx)
                wl_set_isam_status(cur_if, IF_READY);
 #ifndef WL_STATIC_IF
                wake_up_interruptible(&apsta_params->netif_change_event);
-#endif
+#endif /* WL_STATIC_IF */
+       }
+
+       return 0;
+}
+
+int
+wl_ext_iapsta_update_net_device(struct net_device *net, int ifidx)
+{
+       struct dhd_pub *dhd = dhd_get_pub(net);
+       struct wl_apsta_params *apsta_params = dhd->iapsta_params;
+       struct wl_if_info *cur_if = NULL, *primary_if;
+
+       AEXT_TRACE(net->name, "ifidx=%d\n", ifidx);
+       if (ifidx < MAX_IF_NUM) {
+               cur_if = &apsta_params->if_info[ifidx];
+       }
+       if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) {
+               primary_if = &apsta_params->if_info[IF_PIF];
+               if (strlen(cur_if->ifname)) {
+                       memset(net->name, 0, sizeof(IFNAMSIZ));
+                       strcpy(net->name, cur_if->ifname);
+                       net->name[IFNAMSIZ-1] = '\0';
+               }
+#ifndef WL_STATIC_IF
+               if (apsta_params->apstamode != IUNKNOWN_MODE &&
+                               apsta_params->apstamode != ISTAAPAP_MODE &&
+                               apsta_params->apstamode != ISTASTA_MODE) {
+                       memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN);
+                       net->dev_addr[0] |= 0x02;
+                       if (ifidx >= 2) {
+                               net->dev_addr[4] ^= 0x80;
+                               net->dev_addr[4] += ifidx;
+                               net->dev_addr[5] += (ifidx-1);
+                       }
+               }
+#endif /* WL_STATIC_IF */
        }
 
        return 0;
@@ -3320,7 +4723,6 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx)
        if (ifidx == 0) {
                memset(apsta_params, 0, sizeof(struct wl_apsta_params));
                apsta_params->dhd = dhd;
-               apsta_params->vsdb = FALSE;
                cur_if->dev = net;
                cur_if->ifidx = ifidx;
                cur_if->bssidx = bssidx;
@@ -3332,30 +4734,22 @@ wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx)
                strcpy(cur_if->ifname, net->name);
                init_waitqueue_head(&apsta_params->netif_change_event);
                mutex_init(&apsta_params->usr_sync);
+               mutex_init(&cur_if->pm_sync);
+               INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
        } else if (cur_if && wl_get_isam_status(cur_if, IF_ADDING)) {
                primary_if = &apsta_params->if_info[IF_PIF];
                cur_if->dev = net;
-               cur_if->ifidx = ifidx;
-               cur_if->bssidx = bssidx;
-               wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event,
-                       apsta_params, PRIO_EVENT_IAPSTA);
-               if (strlen(cur_if->ifname)) {
-                       memset(net->name, 0, sizeof(IFNAMSIZ));
-                       strcpy(net->name, cur_if->ifname);
-                       net->name[IFNAMSIZ-1] = '\0';
-               }
-#ifndef WL_STATIC_IF
-               if (apsta_params->apstamode != ISTAAPAP_MODE &&
-                               apsta_params->apstamode != ISTASTA_MODE) {
-                       memcpy(net->dev_addr, primary_if->dev->dev_addr, ETHER_ADDR_LEN);
-                       net->dev_addr[0] |= 0x02;
-                       if (ifidx >= 2) {
-                               net->dev_addr[4] ^= 0x80;
-                               net->dev_addr[4] += ifidx;
-                               net->dev_addr[5] += (ifidx-1);
-                       }
+               cur_if->ifidx = ifidx;
+               cur_if->bssidx = bssidx;
+               wl_ext_event_register(net, dhd, WLC_E_LAST, wl_ext_iapsta_event,
+                       apsta_params, PRIO_EVENT_IAPSTA);
+#if defined(WLMESH) && defined(WL_ESCAN)
+               if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
+                       wl_mesh_escan_attach(dhd, cur_if);
                }
-#endif
+#endif /* WLMESH && WL_ESCAN */
+               mutex_init(&cur_if->pm_sync);
+               INIT_DELAYED_WORK(&cur_if->pm_enable_work, wl_ext_pm_work_handler);
        }
 
        return 0;
@@ -3377,10 +4771,23 @@ wl_ext_iapsta_dettach_netdev(struct net_device *net, int ifidx)
        }
 
        if (ifidx == 0) {
+               wl_ext_add_remove_pm_enable_work(net, FALSE);
                wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event);
+#if defined(WLMESH) && defined(WL_ESCAN)
+               if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
+                       wl_mesh_escan_detach(dhd, cur_if);
+               }
+#endif /* WLMESH && WL_ESCAN */
                memset(apsta_params, 0, sizeof(struct wl_apsta_params));
-       } else if (cur_if && wl_get_isam_status(cur_if, IF_READY)) {
+       } else if (cur_if && (wl_get_isam_status(cur_if, IF_READY) ||
+                       wl_get_isam_status(cur_if, IF_ADDING))) {
+               wl_ext_add_remove_pm_enable_work(net, FALSE);
                wl_ext_event_deregister(net, dhd, WLC_E_LAST, wl_ext_iapsta_event);
+#if defined(WLMESH) && defined(WL_ESCAN)
+               if (cur_if->ifmode == IMESH_MODE && apsta_params->macs) {
+                       wl_mesh_escan_detach(dhd, cur_if);
+               }
+#endif /* WLMESH && WL_ESCAN */
                memset(cur_if, 0, sizeof(struct wl_if_info));
        }
 
@@ -3410,7 +4817,7 @@ wl_ext_iapsta_dettach(dhd_pub_t *pub)
                pub->iapsta_params = NULL;
        }
 }
-#endif
+#endif /* WL_EXT_IAPSTA */
 
 #ifdef IDHCP
 /*
@@ -3518,7 +4925,7 @@ wl_ext_dhcpc_param(struct net_device *dev, char *data, char *command,
        exit:
                return ret;
 }
-#endif
+#endif /* IDHCP */
 
 int
 wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command,
@@ -3536,7 +4943,7 @@ wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command,
                        AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
                        goto exit;
                }
-               packet = kmalloc(total_len, GFP_KERNEL);
+               packet = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
                if (packet == NULL) {
                        AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
                        goto exit;
@@ -3551,7 +4958,7 @@ wl_ext_mkeep_alive(struct net_device *dev, char *data, char *command,
                        if (id < 0)
                                id = 0;
                        ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf,
-                               sizeof(buf), NULL);
+                               total_len, NULL);
                        if (!ret) {
                                mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) buf;
                                bytes_written += snprintf(command+bytes_written, total_len,
@@ -3598,10 +5005,11 @@ wl_ext_tcpka_conn_add(struct net_device *dev, char *data, char *command,
                memset(src_ip, 0, sizeof(src_ip));
                memset(dst_ip, 0, sizeof(dst_ip));
                memset(ka_payload, 0, sizeof(ka_payload));
-               sscanf(data, "%d %s %s %s %d %d %d %u %u %d %u %u %u %u %32s",
+               sscanf(data, "%d %s %s %s %d %d %d %u %u %d %u %u %u %32s",
                        &sess_id, dst_mac, src_ip, dst_ip, &ipid, &srcport, &dstport, &seq,
-                       &ack, &tcpwin, &tsval, &tsecr, &len, &ka_payload_len, ka_payload);
+                       &ack, &tcpwin, &tsval, &tsecr, &len, ka_payload);
 
+               ka_payload_len = strlen(ka_payload) / 2;
                tcpka = kmalloc(sizeof(struct tcpka_conn) + ka_payload_len, GFP_KERNEL);
                if (tcpka == NULL) {
                        AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n",
@@ -3632,8 +5040,12 @@ wl_ext_tcpka_conn_add(struct net_device *dev, char *data, char *command,
                tcpka->tsval = tsval;
                tcpka->tsecr = tsecr;
                tcpka->len = len;
+               ka_payload_len = wl_pattern_atoh(ka_payload, (char *)tcpka->ka_payload);
+               if (ka_payload_len == -1) {
+                       AEXT_ERROR(dev->name,"rejecting ka_payload=%s\n", ka_payload);
+                       goto exit;
+               }
                tcpka->ka_payload_len = ka_payload_len;
-               strncpy(tcpka->ka_payload, ka_payload, ka_payload_len);
 
                AEXT_INFO(dev->name,
                        "tcpka_conn_add %d %pM %pM %pM %d %d %d %u %u %d %u %u %u %u \"%s\"\n",
@@ -3659,7 +5071,7 @@ wl_ext_tcpka_conn_enable(struct net_device *dev, char *data, char *command,
 {
        s8 iovar_buf[WLC_IOCTL_SMLEN];
        tcpka_conn_sess_t tcpka_conn;
-       int ret;
+       int ret = 0;
        uint32 sess_id = 0, flag, interval = 0, retry_interval = 0, retry_count = 0;
 
        if (data) {
@@ -3697,7 +5109,7 @@ wl_ext_tcpka_conn_info(struct net_device *dev, char *data, char *command,
        s8 iovar_buf[WLC_IOCTL_SMLEN];
        tcpka_conn_sess_info_t *info = NULL;
        uint32 sess_id = 0;
-       int ret = 0;
+       int ret = 0, bytes_written = 0;
 
        if (data) {
                sscanf(data, "%d", &sess_id);
@@ -3706,15 +5118,20 @@ wl_ext_tcpka_conn_info(struct net_device *dev, char *data, char *command,
                        sizeof(uint32), iovar_buf, sizeof(iovar_buf), NULL);
                if (!ret) {
                        info = (tcpka_conn_sess_info_t *) iovar_buf;
-                       ret = snprintf(command, total_len, "id=%d, ipid=%d, seq=%u, ack=%u",
+                       bytes_written += snprintf(command+bytes_written, total_len,
+                               "id   :%d\n"
+                               "ipid :%d\n"
+                               "seq  :%u\n"
+                               "ack  :%u",
                                sess_id, info->ipid, info->seq, info->ack);
                        AEXT_INFO(dev->name, "%s\n", command);
+                       ret = bytes_written;
                }
        }
 
        return ret;
 }
-#endif
+#endif /* WL_EXT_TCPKA */
 
 static int
 wl_ext_rsdb_mode(struct net_device *dev, char *data, char *command,
@@ -4047,67 +5464,9 @@ wl_ext_pkt_filter_enable(struct net_device *dev, char *data, char *command,
 
        return err;
 }
-#endif
+#endif /* PKT_FILTER_SUPPORT */
 
 #ifdef SENDPROB
-static int
-wl_ext_add_del_ie(struct net_device *dev, uint pktflag, char *ie_data, const char* add_del_cmd)
-{
-       vndr_ie_setbuf_t *vndr_ie = NULL;
-       char iovar_buf[WLC_IOCTL_SMLEN]="\0";
-       int ie_data_len = 0, tot_len = 0, iecount;
-       int err = -1;
-
-       if (!strlen(ie_data)) {
-               AEXT_ERROR(dev->name, "wrong ie %s\n", ie_data);
-               goto exit;
-       }
-
-       tot_len = (int)(sizeof(vndr_ie_setbuf_t) + ((strlen(ie_data)-2)/2));
-       vndr_ie = (vndr_ie_setbuf_t *) kzalloc(tot_len, GFP_KERNEL);
-       if (!vndr_ie) {
-               AEXT_ERROR(dev->name, "IE memory alloc failed\n");
-               err = -ENOMEM;
-               goto exit;
-       }
-
-       /* Copy the vndr_ie SET command ("add"/"del") to the buffer */
-       strncpy(vndr_ie->cmd, add_del_cmd, VNDR_IE_CMD_LEN - 1);
-       vndr_ie->cmd[VNDR_IE_CMD_LEN - 1] = '\0';
-
-       /* Set the IE count - the buffer contains only 1 IE */
-       iecount = htod32(1);
-       memcpy((void *)&vndr_ie->vndr_ie_buffer.iecount, &iecount, sizeof(s32));
-
-       /* Set packet flag to indicate that BEACON's will contain this IE */
-       pktflag = htod32(pktflag);
-       memcpy((void *)&vndr_ie->vndr_ie_buffer.vndr_ie_list[0].pktflag, &pktflag,
-               sizeof(u32));
-
-       /* Set the IE ID */
-       vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.id = (uchar)DOT11_MNG_VS_ID;
-
-       /* Set the IE LEN */
-       vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.len = (strlen(ie_data)-2)/2;
-
-       /* Set the IE OUI and DATA */
-       ie_data_len = wl_pattern_atoh(ie_data,
-               (char *)vndr_ie->vndr_ie_buffer.vndr_ie_list[0].vndr_ie_data.oui);
-       if (ie_data_len <= 0) {
-               AEXT_ERROR(dev->name, "wrong ie_data_len %d\n", strlen(ie_data)-2);
-               goto exit;
-       }
-
-       err = wl_ext_iovar_setbuf(dev, "vndr_ie", vndr_ie, tot_len, iovar_buf,
-               sizeof(iovar_buf), NULL);
-
-exit:
-       if (vndr_ie) {
-               kfree(vndr_ie);
-       }
-       return err;
-}
-
 static int
 wl_ext_send_probreq(struct net_device *dev, char *data, char *command,
        int total_len)
@@ -4276,7 +5635,7 @@ wl_ext_recv_probresp(struct net_device *dev, char *data, char *command,
 exit:
     return err;
 }
-#endif
+#endif /* SENDPROB */
 
 static int
 wl_ext_gtk_key_info(struct net_device *dev, char *data, char *command, int total_len)
@@ -4532,7 +5891,182 @@ wl_ext_wowl_wakeind(struct net_device *dev, char *data, char *command,
 
        return ret;
 }
-#endif
+#endif /* WL_EXT_WOWL */
+
+#ifdef WL_GPIO_NOTIFY
+typedef struct notify_payload {
+       int index;
+       int len;
+       char payload[128];
+} notify_payload_t;
+
+static int
+wl_ext_gpio_notify(struct net_device *dev, char *data, char *command,
+       int total_len)
+{
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+       notify_payload_t notify, *pnotify = NULL;
+       int i, ret = 0, bytes_written = 0;
+       char frame_str[WLC_IOCTL_SMLEN+3];
+
+       if (data) {
+               memset(&notify, 0, sizeof(notify));
+               memset(frame_str, 0, sizeof(frame_str));
+               sscanf(data, "%d %s", &notify.index, frame_str);
+
+               if (notify.index < 0)
+                       notify.index = 0;
+
+               if (strlen(frame_str)) {
+                       notify.len = wl_pattern_atoh(frame_str, notify.payload);
+                       if (notify.len == -1) {
+                               AEXT_ERROR(dev->name, "rejecting pattern=%s\n", frame_str);
+                               goto exit;
+                       }
+                       AEXT_INFO(dev->name, "index=%d, len=%d\n", notify.index, notify.len);
+                       if (android_msg_level & ANDROID_INFO_LEVEL)
+                               prhex("payload", (uchar *)notify.payload, notify.len);
+                       ret = wl_ext_iovar_setbuf(dev, "bcol_gpio_noti", (char *)&notify,
+                               sizeof(notify), iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               } else {
+                       AEXT_INFO(dev->name, "index=%d\n", notify.index);
+                       ret = wl_ext_iovar_getbuf(dev, "bcol_gpio_noti", &notify.index,
+                               sizeof(notify.index), iovar_buf, sizeof(iovar_buf), NULL);
+                       if (!ret) {
+                               pnotify = (notify_payload_t *)iovar_buf;
+                               bytes_written += snprintf(command+bytes_written, total_len,
+                                       "Id            :%d\n"
+                                       "Packet        :0x",
+                                       pnotify->index);
+                               for (i=0; i<pnotify->len; i++) {
+                                       bytes_written += snprintf(command+bytes_written, total_len,
+                                               "%02x", pnotify->payload[i]);
+                               }
+                               AEXT_TRACE(dev->name, "command result is\n%s\n", command);
+                               ret = bytes_written;
+                       }
+               }
+       }
+
+exit:
+       return ret;
+}
+#endif /* WL_GPIO_NOTIFY */
+
+#ifdef CSI_SUPPORT
+typedef struct csi_config {
+       /* Peer device mac address. */
+       struct ether_addr addr;
+       /* BW to be used in the measurements. This needs to be supported both by the */
+       /* device itself and the peer. */
+       uint32 bw;
+       /* Time interval between measurements (units: 1 ms). */
+       uint32 period;
+       /* CSI method */
+       uint32 method;
+} csi_config_t;
+
+typedef struct csi_list {
+       uint32 cnt;
+       csi_config_t configs[1];
+} csi_list_t;
+
+static int
+wl_ether_atoe(const char *a, struct ether_addr *n)
+{
+       char *c = NULL;
+       int i = 0;
+
+       memset(n, 0, ETHER_ADDR_LEN);
+       for (;;) {
+               n->octet[i++] = (uint8)strtoul(a, &c, 16);
+               if (!*c++ || i == ETHER_ADDR_LEN)
+                       break;
+               a = c;
+       }
+       return (i == ETHER_ADDR_LEN);
+}
+
+static int
+wl_ext_csi(struct net_device *dev, char *data, char *command, int total_len)
+{
+       csi_config_t csi, *csip;
+       csi_list_t *csi_list;
+       int ret = -1, period=-1, i;
+       char mac[32], *buf = NULL;
+       struct ether_addr ea;
+       int bytes_written = 0;
+
+       buf = kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
+       if (buf == NULL) {
+               AEXT_ERROR(dev->name, "Failed to allocate buffer of %d bytes\n", WLC_IOCTL_SMLEN);
+               goto exit;
+       }
+       memset(buf, 0, WLC_IOCTL_SMLEN);
+
+       if (data) {
+               sscanf(data, "%s %d", mac, &period);
+               ret = wl_ether_atoe(mac, &ea);
+               if (!ret) {
+                       AEXT_ERROR(dev->name, "rejecting mac=%s, ret=%d\n", mac, ret);
+                       goto exit;
+               }
+               AEXT_TRACE(dev->name, "mac=%pM, period=%d", &ea, period);
+               if (period > 0) {
+                       memset(&csi, 0, sizeof(csi_config_t));
+                       bcopy(&ea, &csi.addr, ETHER_ADDR_LEN);
+                       csi.period = period;
+                       ret = wl_ext_iovar_setbuf(dev, "csi", (char *)&csi, sizeof(csi),
+                               buf, WLC_IOCTL_SMLEN, NULL);
+               } else if (period == 0) {
+                       memset(&csi, 0, sizeof(csi_config_t));
+                       bcopy(&ea, &csi.addr, ETHER_ADDR_LEN);
+                       ret = wl_ext_iovar_setbuf(dev, "csi_del", (char *)&csi, sizeof(csi),
+                               buf, WLC_IOCTL_SMLEN, NULL);
+               } else {
+                       ret = wl_ext_iovar_getbuf(dev, "csi", &ea, ETHER_ADDR_LEN, buf,
+                               WLC_IOCTL_SMLEN, NULL);
+                       if (!ret) {
+                               csip = (csi_config_t *) buf;
+                                       /* Dump all lists */
+                               bytes_written += snprintf(command+bytes_written, total_len,
+                                       "Mac    :%pM\n"
+                                       "Period :%d\n"
+                                       "BW     :%d\n"
+                                       "Method :%d\n",
+                                       &csip->addr, csip->period, csip->bw, csip->method);
+                               AEXT_TRACE(dev->name, "command result is %s\n", command);
+                               ret = bytes_written;
+                       }
+               }
+       }
+       else {
+               ret = wl_ext_iovar_getbuf(dev, "csi_list", NULL, 0, buf, WLC_IOCTL_SMLEN, NULL);
+               if (!ret) {
+                       csi_list = (csi_list_t *)buf;
+                       bytes_written += snprintf(command+bytes_written, total_len,
+                               "Total number :%d\n", csi_list->cnt);
+                       for (i=0; i<csi_list->cnt; i++) {
+                               csip = &csi_list->configs[i];
+                               bytes_written += snprintf(command+bytes_written, total_len,
+                                       "Idx    :%d\n"
+                                       "Mac    :%pM\n"
+                                       "Period :%d\n"
+                                       "BW     :%d\n"
+                                       "Method :%d\n\n",
+                                       i+1, &csip->addr, csip->period, csip->bw, csip->method);
+                       }
+                       AEXT_TRACE(dev->name, "command result is %s\n", command);
+                       ret = bytes_written;
+               }
+       }
+
+exit:
+       if (buf)
+               kfree(buf);
+       return ret;
+}
+#endif /* CSI_SUPPORT */
 
 typedef int (wl_ext_tpl_parse_t)(struct net_device *dev, char *data, char *command,
        int total_len);
@@ -4554,29 +6088,35 @@ const wl_ext_iovar_tpl_t wl_ext_iovar_tpl_list[] = {
        {WLC_GET_VAR,   WLC_SET_VAR,    "pkt_filter_add",               wl_ext_pkt_filter_add},
        {WLC_GET_VAR,   WLC_SET_VAR,    "pkt_filter_delete",    wl_ext_pkt_filter_delete},
        {WLC_GET_VAR,   WLC_SET_VAR,    "pkt_filter_enable",    wl_ext_pkt_filter_enable},
-#endif
+#endif /* PKT_FILTER_SUPPORT */
 #if defined(WL_EXT_IAPSTA) && defined(WLMESH)
        {WLC_GET_VAR,   WLC_SET_VAR,    "mesh_peer_status",     wl_ext_mesh_peer_status},
-#endif
+#endif /* WL_EXT_IAPSTA && WLMESH */
 #ifdef SENDPROB
        {WLC_GET_VAR,   WLC_SET_VAR,    "send_probreq",         wl_ext_send_probreq},
        {WLC_GET_VAR,   WLC_SET_VAR,    "send_probresp",        wl_ext_send_probresp},
        {WLC_GET_VAR,   WLC_SET_VAR,    "recv_probreq",         wl_ext_recv_probreq},
        {WLC_GET_VAR,   WLC_SET_VAR,    "recv_probresp",        wl_ext_recv_probresp},
-#endif
+#endif /* SENDPROB */
 #ifdef WL_EXT_TCPKA
        {WLC_GET_VAR,   WLC_SET_VAR,    "tcpka_conn_add",               wl_ext_tcpka_conn_add},
        {WLC_GET_VAR,   WLC_SET_VAR,    "tcpka_conn_enable",    wl_ext_tcpka_conn_enable},
        {WLC_GET_VAR,   WLC_SET_VAR,    "tcpka_conn_sess_info", wl_ext_tcpka_conn_info},
-#endif
+#endif /* WL_EXT_TCPKA */
 #ifdef WL_EXT_WOWL
        {WLC_GET_VAR,   WLC_SET_VAR,    "wowl_pattern",         wl_ext_wowl_pattern},
        {WLC_GET_VAR,   WLC_SET_VAR,    "wowl_wakeind",         wl_ext_wowl_wakeind},
-#endif
+#endif /* WL_EXT_WOWL */
 #ifdef IDHCP
        {WLC_GET_VAR,   WLC_SET_VAR,    "dhcpc_dump",           wl_ext_dhcpc_dump},
        {WLC_GET_VAR,   WLC_SET_VAR,    "dhcpc_param",          wl_ext_dhcpc_param},
-#endif
+#endif /* IDHCP */
+#ifdef WL_GPIO_NOTIFY
+       {WLC_GET_VAR,   WLC_SET_VAR,    "bcol_gpio_noti",       wl_ext_gpio_notify},
+#endif /* WL_GPIO_NOTIFY */
+#ifdef CSI_SUPPORT
+       {WLC_GET_VAR,   WLC_SET_VAR,    "csi",                          wl_ext_csi},
+#endif /* CSI_SUPPORT */
 };
 
 /*
@@ -4703,17 +6243,25 @@ wl_android_ext_priv_cmd(struct net_device *net, char *command,
        else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) {
                *bytes_written = wl_ext_isam_status(net, command, total_len);
        }
-#endif
+       else if (strnicmp(command, CMD_ISAM_PARAM, strlen(CMD_ISAM_PARAM)) == 0) {
+               *bytes_written = wl_ext_isam_param(net, command, total_len);
+       }
+#if defined(WLMESH) && defined(WL_ESCAN)
+       else if (strnicmp(command, CMD_ISAM_PEER_PATH, strlen(CMD_ISAM_PEER_PATH)) == 0) {
+               *bytes_written = wl_ext_isam_peer_path(net, command, total_len);
+       }
+#endif /* WLMESH && WL_ESCAN */
+#endif /* WL_EXT_IAPSTA */
 #ifdef WL_CFG80211
        else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
                *bytes_written = wl_cfg80211_autochannel(net, command, total_len);
        }
-#endif
+#endif /* WL_CFG80211 */
 #if defined(WL_WIRELESS_EXT) && defined(WL_ESCAN)
        else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
                *bytes_written = wl_iw_autochannel(net, command, total_len);
        }
-#endif
+#endif /* WL_WIRELESS_EXT && WL_ESCAN */
        else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) {
                *bytes_written = wl_ext_wl_iovar(net, command, total_len);
        }
@@ -4776,7 +6324,7 @@ wl_ext_get_best_channel(struct net_device *net,
        wl_bss_cache_ctrl_t *bss_cache_ctrl,
 #else
        struct wl_scan_results *bss_list,
-#endif
+#endif /* BSSCACHE */
        int ioctl_ver, int *best_2g_ch, int *best_5g_ch
 )
 {
@@ -4784,13 +6332,14 @@ wl_ext_get_best_channel(struct net_device *net,
        s32 i, j;
 #if defined(BSSCACHE)
        wl_bss_cache_t *node;
-#endif
+#endif /* BSSCACHE */
        int b_band[CH_MAX_2G_CHANNEL]={0}, a_band1[4]={0}, a_band4[5]={0};
        s32 cen_ch, distance, distance_2g, distance_5g, ch, min_ap=999;
        u8 valid_chan_list[sizeof(u32)*(WL_NUMCHANNELS + 1)];
        wl_uint32_list_t *list;
        int ret;
        chanspec_t chanspec;
+       struct dhd_pub *dhd = dhd_get_pub(net);
 
        memset(b_band, -1, sizeof(b_band));
        memset(a_band1, -1, sizeof(a_band1));
@@ -4807,6 +6356,8 @@ wl_ext_get_best_channel(struct net_device *net,
        } else {
                for (i = 0; i < dtoh32(list->count); i++) {
                        ch = dtoh32(list->element[i]);
+                       if (!dhd_conf_match_channel(dhd, ch))
+                               continue;
                        if (ch < CH_MAX_2G_CHANNEL)
                                b_band[ch-1] = 0;
                        else if (ch <= 48)
@@ -4824,13 +6375,13 @@ wl_ext_get_best_channel(struct net_device *net,
        for (i=0; node && i<256; i++)
 #else
        for (i=0; i < bss_list->count; i++)
-#endif
+#endif /* BSSCACHE */
        {
 #if defined(BSSCACHE)
                bi = node->results.bss_info;
 #else
                bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : bss_list->bss_info;
-#endif
+#endif /* BSSCACHE */
                chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec);
                cen_ch = CHSPEC_CHANNEL(bi->chanspec);
                distance = 0;
@@ -4847,7 +6398,7 @@ wl_ext_get_best_channel(struct net_device *net,
                        distance += distance_2g;
                        for (j=0; j<ARRAYSIZE(b_band); j++) {
                                if (b_band[j] >= 0 && abs(cen_ch-(1+j)) <= distance)
-                               b_band[j] += 1;
+                                       b_band[j] += 1;
                        }
                } else {
                        distance += distance_5g;
@@ -4865,7 +6416,7 @@ wl_ext_get_best_channel(struct net_device *net,
                }
 #if defined(BSSCACHE)
                node = node->next;
-#endif
+#endif /* BSSCACHE */
        }
 
        *best_2g_ch = 0;
@@ -4920,8 +6471,234 @@ wl_ext_get_best_channel(struct net_device *net,
 exit:
        return 0;
 }
+#endif /* WL_CFG80211 || WL_ESCAN */
+
+#ifdef WL_CFG80211
+#define APCS_MAX_RETRY         10
+static int
+wl_ext_fw_apcs(struct net_device *dev, uint32 band)
+{
+       int channel = 0, chosen = 0, retry = 0, ret = 0, spect = 0;
+       u8 *reqbuf = NULL;
+       uint32 buf_size;
+
+       ret = wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect));
+       if (ret) {
+               AEXT_ERROR(dev->name, "ACS: error getting the spect, ret=%d\n", ret);
+               goto done;
+       }
+
+       if (spect > 0) {
+               ret = wl_cfg80211_set_spect(dev, 0);
+               if (ret < 0) {
+                       AEXT_ERROR(dev->name, "ACS: error while setting spect, ret=%d\n", ret);
+                       goto done;
+               }
+       }
+
+       reqbuf = kmalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
+       if (reqbuf == NULL) {
+               AEXT_ERROR(dev->name, "failed to allocate chanspec buffer\n");
+               goto done;
+       }
+       memset(reqbuf, 0, CHANSPEC_BUF_SIZE);
+
+       if (band == WLC_BAND_AUTO) {
+               AEXT_INFO(dev->name, "ACS full channel scan \n");
+               reqbuf[0] = htod32(0);
+       } else if (band == WLC_BAND_5G) {
+               AEXT_INFO(dev->name, "ACS 5G band scan \n");
+               if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
+                       AEXT_ERROR(dev->name, "ACS 5g chanspec retreival failed! \n");
+                       goto done;
+               }
+       } else if (band == WLC_BAND_2G) {
+               /*
+                * If channel argument is not provided/ argument 20 is provided,
+                * Restrict channel to 2GHz, 20MHz BW, No SB
+                */
+               AEXT_INFO(dev->name, "ACS 2G band scan \n");
+               if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
+                       AEXT_ERROR(dev->name, "ACS 2g chanspec retreival failed! \n");
+                       goto done;
+               }
+       } else {
+               AEXT_ERROR(dev->name, "ACS: No band chosen\n");
+               goto done;
+       }
+
+       buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
+       ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
+               buf_size);
+       if (ret < 0) {
+               AEXT_ERROR(dev->name, "can't start auto channel scan, err = %d\n", ret);
+               channel = 0;
+               goto done;
+       }
+
+       /* Wait for auto channel selection, max 3000 ms */
+       if ((band == WLC_BAND_2G) || (band == WLC_BAND_5G)) {
+               OSL_SLEEP(500);
+       } else {
+               /*
+                * Full channel scan at the minimum takes 1.2secs
+                * even with parallel scan. max wait time: 3500ms
+                */
+               OSL_SLEEP(1000);
+       }
+
+       retry = APCS_MAX_RETRY;
+       while (retry--) {
+               ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &chosen,
+                       sizeof(chosen));
+               if (ret < 0) {
+                       chosen = 0;
+               } else {
+                       chosen = dtoh32(chosen);
+               }
+
+               if (chosen) {
+                       int chosen_band;
+                       int apcs_band;
+#ifdef D11AC_IOTYPES
+                       if (wl_cfg80211_get_ioctl_version() == 1) {
+                               channel = LCHSPEC_CHANNEL((chanspec_t)chosen);
+                       } else {
+                               channel = CHSPEC_CHANNEL((chanspec_t)chosen);
+                       }
+#else
+                       channel = CHSPEC_CHANNEL((chanspec_t)chosen);
+#endif /* D11AC_IOTYPES */
+                       apcs_band = (band == WLC_BAND_AUTO) ? WLC_BAND_2G : band;
+                       chosen_band = (channel <= CH_MAX_2G_CHANNEL) ? WLC_BAND_2G : WLC_BAND_5G;
+                       if (apcs_band == chosen_band) {
+                               WL_MSG(dev->name, "selected channel = %d\n", channel);
+                               break;
+                       }
+               }
+               AEXT_INFO(dev->name, "%d tried, ret = %d, chosen = 0x%x\n",
+                       (APCS_MAX_RETRY - retry), ret, chosen);
+               OSL_SLEEP(250);
+       }
+
+done:
+       if (spect > 0) {
+               if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
+                       AEXT_ERROR(dev->name, "ACS: error while setting spect\n");
+               }
+       }
+
+       if (reqbuf) {
+               kfree(reqbuf);
+       }
+
+       return channel;
+}
+#endif /* WL_CFG80211 */
+
+#ifdef WL_ESCAN
+int
+wl_ext_drv_apcs(struct net_device *dev, uint32 band)
+{
+       int ret = 0, channel = 0;
+       struct dhd_pub *dhd = dhd_get_pub(dev);
+       struct wl_escan_info *escan = NULL;
+       int retry = 0, retry_max, retry_interval = 250, up = 1;
+#ifdef WL_CFG80211
+       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+#endif /* WL_CFG80211 */
+
+       escan = dhd->escan;
+       if (dhd) {
+               retry_max = WL_ESCAN_TIMER_INTERVAL_MS/retry_interval;
+               ret = wldev_ioctl_get(dev, WLC_GET_UP, &up, sizeof(s32));
+               if (ret < 0 || up == 0) {
+                       ret = wldev_ioctl_set(dev, WLC_UP, &up, sizeof(s32));
+               }
+               retry = retry_max;
+               while (retry--) {
+                       if (escan->escan_state == ESCAN_STATE_SCANING
+#ifdef WL_CFG80211
+                               || wl_get_drv_status_all(cfg, SCANNING)
+#endif
+                       )
+                       {
+                               AEXT_INFO(dev->name, "Scanning %d tried, ret = %d\n",
+                                       (retry_max - retry), ret);
+                       } else {
+                               escan->autochannel = 1;
+                               ret = wl_escan_set_scan(dev, dhd, NULL, 0, TRUE);
+                               if (!ret)
+                                       break;
+                       }
+                       OSL_SLEEP(retry_interval);
+               }
+               if ((retry == 0) || (ret < 0))
+                       goto done;
+               retry = retry_max;
+               while (retry--) {
+                       if (escan->escan_state == ESCAN_STATE_IDLE) {
+                               if (band == WLC_BAND_5G)
+                                       channel = escan->best_5g_ch;
+                               else
+                                       channel = escan->best_2g_ch;
+                               WL_MSG(dev->name, "selected channel = %d\n", channel);
+                               goto done;
+                       }
+                       AEXT_INFO(dev->name, "escan_state=%d, %d tried, ret = %d\n",
+                               escan->escan_state, (retry_max - retry), ret);
+                       OSL_SLEEP(retry_interval);
+               }
+               if ((retry == 0) || (ret < 0))
+                       goto done;
+       }
+
+done:
+       if (escan)
+               escan->autochannel = 0;
+
+       return channel;
+}
+#endif /* WL_ESCAN */
+
+int
+wl_ext_autochannel(struct net_device *dev, uint acs, uint32 band)
+{
+       int channel = 0;
+       uint16 chan_2g, chan_5g;
+
+       AEXT_INFO(dev->name, "acs=0x%x, band=%d \n", acs, band);
+
+#ifdef WL_CFG80211
+       if (acs & ACS_FW_BIT) {
+               int ret = 0;
+               ret = wldev_ioctl_get(dev, WLC_GET_CHANNEL_SEL, &channel, sizeof(channel));
+               channel = 0;
+               if (ret != BCME_UNSUPPORTED)
+                       channel = wl_ext_fw_apcs(dev, band);
+               if (channel)
+                       return channel;
+       }
 #endif
 
+#ifdef WL_ESCAN
+       if (acs & ACS_DRV_BIT)
+               channel = wl_ext_drv_apcs(dev, band);
+#endif /* WL_ESCAN */
+
+       if (channel == 0) {
+               wl_ext_get_default_chan(dev, &chan_2g, &chan_5g, TRUE);
+               if (band == WLC_BAND_5G) {
+                       channel = chan_5g;
+               } else {
+                       channel = chan_2g;
+               }
+               AEXT_ERROR(dev->name, "ACS failed. Fall back to default channel (%d) \n", channel);
+       }
+
+       return channel;
+}
+
 #if defined(RSSIAVG)
 void
 wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
@@ -5215,7 +6992,7 @@ wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr)
        }
        return (int16)rssi;
 }
-#endif
+#endif /* RSSIAVG */
 
 #if defined(RSSIOFFSET)
 int
@@ -5223,7 +7000,7 @@ wl_update_rssi_offset(struct net_device *net, int rssi)
 {
 #if defined(RSSIOFFSET_NEW)
        int j;
-#endif
+#endif /* RSSIOFFSET_NEW */
 
        if (!g_wifi_on)
                return rssi;
@@ -5236,10 +7013,10 @@ wl_update_rssi_offset(struct net_device *net, int rssi)
        rssi += j;
 #else
        rssi += RSSI_OFFSET;
-#endif
+#endif /* RSSIOFFSET_NEW */
        return MIN(rssi, RSSI_MAXVAL);
 }
-#endif
+#endif /* RSSIOFFSET */
 
 #if defined(BSSCACHE)
 void
@@ -5358,7 +7135,7 @@ wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
 void dump_bss_cache(
 #if defined(RSSIAVG)
        wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
-#endif
+#endif /* RSSIAVG */
        wl_bss_cache_t *node)
 {
        int k = 0;
@@ -5369,7 +7146,7 @@ void dump_bss_cache(
                rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
 #else
                rssi = dtoh16(node->results.bss_info->RSSI);
-#endif
+#endif /* RSSIAVG */
                AEXT_TRACE("wlan", "dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
                        k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID);
                k++;
@@ -5381,7 +7158,7 @@ void
 wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
 #if defined(RSSIAVG)
        wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
-#endif
+#endif /* RSSIAVG */
        wl_scan_results_t *ss_list)
 {
        wl_bss_cache_t *node, *prev, *leaf, **bss_head;
@@ -5389,7 +7166,7 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
        int i, k=0;
 #if defined(SORT_BSS_BY_RSSI)
        int16 rssi, rssi_node;
-#endif
+#endif /* SORT_BSS_BY_RSSI */
        struct osl_timespec now, timeout;
 
        if (!ss_list->count)
@@ -5461,14 +7238,14 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
                        rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID);
 #else
                        rssi = dtoh16(leaf->results.bss_info->RSSI);
-#endif
+#endif /* RSSIAVG */
                        for (;node;) {
 #if defined(RSSIAVG)
                                rssi_node = wl_get_avg_rssi(rssi_cache_ctrl,
                                        &node->results.bss_info->BSSID);
 #else
                                rssi_node = dtoh16(node->results.bss_info->RSSI);
-#endif
+#endif /* RSSIAVG */
                                if (rssi > rssi_node) {
                                        leaf->next = node;
                                        if (node == *bss_head)
@@ -5485,13 +7262,13 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
 #else
                        leaf->next = *bss_head;
                        *bss_head = leaf;
-#endif
+#endif /* SORT_BSS_BY_RSSI */
                }
        }
        dump_bss_cache(
 #if defined(RSSIAVG)
                rssi_cache_ctrl,
-#endif
+#endif /* RSSIAVG */
                *bss_head);
 }
 
@@ -5501,6 +7278,6 @@ wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl)
        AEXT_TRACE("wlan", "Enter\n");
        wl_free_bss_cache(bss_cache_ctrl);
 }
-#endif
+#endif /* BSSCACHE */
 
 
index 7a5823776fc1a77815358bcae2760902dea0dc1f..b7427b3abc6daf5300dbce9fa6fdb5656ec3a815 100644 (file)
@@ -554,6 +554,9 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev,
        struct cfg80211_pmksa *pmksa);
 static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy,
        struct net_device *dev);
+#ifdef WL_CLIENT_SAE
+static bool wl_is_pmkid_available(struct net_device *dev, const u8 *bssid);
+#endif /* WL_CLIENT_SAE */
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0)) || defined(WL_COMPAT_WIRELESS)
 #if (defined(CONFIG_ARCH_MSM) && defined(TDLS_MGMT_VERSION2)) || (LINUX_VERSION_CODE < \
        KERNEL_VERSION(3, 16, 0) && LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0))
@@ -680,6 +683,15 @@ wl_mbo_event_handler(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
        const wl_event_msg_t *e, void *data);
 #endif /* WL_MBO */
 
+#ifdef WL_CLIENT_SAE
+static s32 wl_notify_connect_status_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+       const wl_event_msg_t *e, void *data);
+static s32 wl_notify_start_auth(struct bcm_cfg80211 *cfg,
+       bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data);
+static s32 wl_cfg80211_external_auth(struct wiphy *wiphy,
+       struct net_device *dev, struct cfg80211_external_auth_params *ext_auth);
+#endif /* WL_CLIENT_SAE */
+
 /*
  * register/deregister parent device
  */
@@ -747,6 +759,14 @@ static int wl_cfg80211_get_rsn_capa(const bcm_tlv_t *wpa2ie, const u8** rsn_cap)
 
 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev, dhd_pub_t *data);
 static void wl_free_wdev(struct bcm_cfg80211 *cfg);
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
+static int
+#else
+static void
+#endif /* kernel version < 3.10.11 */
+wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request);
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
 
 static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, wl_bss_info_t *bi, bool update_ssid);
 static s32 wl_update_bss_info(struct bcm_cfg80211 *cfg, struct net_device *ndev, bool update_ssid);
@@ -1417,6 +1437,13 @@ wl_cfg80211_ether_atoe(const char *a, struct ether_addr *n)
 /* There isn't a lot of sense in it, but you can transmit anything you like */
 static const struct ieee80211_txrx_stypes
 wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
+#ifdef WLMESH_CFG80211
+       [NL80211_IFTYPE_MESH_POINT] = {
+               .tx = 0xffff,
+               .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
+               BIT(IEEE80211_STYPE_AUTH >> 4)
+       },
+#endif /* WLMESH_CFG80211 */
        [NL80211_IFTYPE_ADHOC] = {
                .tx = 0xffff,
                .rx = BIT(IEEE80211_STYPE_ACTION >> 4)
@@ -1425,6 +1452,9 @@ wl_cfg80211_default_mgmt_stypes[NUM_NL80211_IFTYPES] = {
                .tx = 0xffff,
                .rx = BIT(IEEE80211_STYPE_ACTION >> 4) |
                BIT(IEEE80211_STYPE_PROBE_REQ >> 4)
+#ifdef WL_CLIENT_SAE
+               | BIT(IEEE80211_STYPE_AUTH >> 4)
+#endif /* WL_CLIENT_SAE */
        },
        [NL80211_IFTYPE_AP] = {
                .tx = 0xffff,
@@ -4110,77 +4140,6 @@ exit:
        return ret;
 }
 
-bool
-wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
-       struct net_device *ndev)
-{
-       u32 chipnum;
-       wlc_rev_info_t revinfo;
-       int ret;
-
-       /* Get the device rev info */
-       memset(&revinfo, 0, sizeof(revinfo));
-       ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
-       if (ret < 0) {
-               WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
-               ASSERT(0);
-               return false;
-       }
-
-       WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
-               dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
-       chipnum = revinfo.chipnum;
-       if ((chipnum == BCM4350_CHIP_ID) || (chipnum == BCM4355_CHIP_ID) ||
-               (chipnum == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) ||
-               (chipnum == BCM43362_CHIP_ID) || (chipnum == BCM43012_CHIP_ID) ||
-               (chipnum == BCM4356_CHIP_ID)) {
-               /* WAR required */
-               return true;
-       }
-
-       return false;
-}
-
-void
-wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
-       struct net_device *ndev, s32 *val)
-{
-       u32 chipnum;
-       wlc_rev_info_t revinfo;
-       int ret;
-       bool need_war = false;
-
-       /* Get the device rev info */
-       memset(&revinfo, 0, sizeof(revinfo));
-       ret = wldev_ioctl_get(ndev, WLC_GET_REVINFO, &revinfo, sizeof(revinfo));
-       if (ret < 0) {
-               WL_ERR(("%s: GET revinfo FAILED. ret:%d\n", __FUNCTION__, ret));
-       } else {
-               WL_DBG(("%s: GET_REVINFO device 0x%x, vendor 0x%x, chipnum 0x%x\n", __FUNCTION__,
-                       dtoh32(revinfo.deviceid), dtoh32(revinfo.vendorid), dtoh32(revinfo.chipnum)));
-               chipnum = revinfo.chipnum;
-               if ((chipnum == BCM4359_CHIP_ID) || (chipnum == BCM43596_CHIP_ID)) { 
-                       /* WAR required */
-                       need_war = true;
-               }
-       }
-
-       if (wl_customer6_legacy_chip_check(cfg, ndev) || need_war) {
-               /* Few firmware branches have issues in bss iovar handling and
-                * that can't be changed since they are in production.
-                */
-               if (*val == WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE) {
-                       *val = WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE;
-               } else if (*val == WLC_AP_IOV_OP_MANUAL_STA_BSSCFG_CREATE) {
-                       *val = WLC_AP_IOV_OP_MANUAL_AP_BSSCFG_CREATE;
-               } else {
-                       /* Ignore for other bss enums */
-                       return;
-               }
-               WL_DBG(("wl bss %d\n", *val));
-       }
-}
-
 s32
 wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
        struct net_device *ndev, s32 bsscfg_idx,
@@ -4216,7 +4175,7 @@ wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
        }
 
        if (!del) {
-               wl_bss_iovar_war(cfg, ndev, &val);
+               wl_ext_bss_iovar_war(ndev, &val);
        }
 
        bss_setbuf.cfg = htod32(bsscfg_idx);
@@ -4226,7 +4185,7 @@ wl_cfg80211_add_del_bss(struct bcm_cfg80211 *cfg,
                memcpy(&bss_setbuf.ea.octet, addr, ETH_ALEN);
        }
 
-       WL_INFORM_MEM(("wl bss %d bssidx:%d iface:%s \n", val, bsscfg_idx, ndev->name));
+       WL_MSG(ndev->name, "wl bss %d bssidx:%d\n", val, bsscfg_idx);
        ret = wldev_iovar_setbuf(ndev, "bss", &bss_setbuf, sizeof(bss_setbuf),
                cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
        if (ret != 0)
@@ -4307,6 +4266,11 @@ wl_iftype_to_mode(wl_iftype_t iftype)
                case WL_IF_TYPE_IBSS:
                        mode = WL_MODE_IBSS;
                        break;
+#ifdef WLMESH_CFG80211
+               case WL_IF_TYPE_MESH:
+                       mode = WL_MODE_MESH;
+                       break;
+#endif /* WLMESH_CFG80211 */
                default:
                        WL_ERR(("Unsupported type:%d\n", iftype));
                        break;
@@ -4353,6 +4317,12 @@ cfg80211_to_wl_iftype(uint16 type, uint16 *role, uint16 *mode)
                        *mode = WL_MODE_NAN;
                        break;
 #endif // endif
+#ifdef WLMESH_CFG80211
+               case NL80211_IFTYPE_MESH_POINT:
+                       *role = WLC_E_IF_ROLE_AP;
+                       *mode = WL_MODE_MESH;
+                       break;
+#endif /* WLMESH_CFG80211 */
                default:
                        WL_ERR(("Unknown interface type:0x%x\n", type));
                        return BCME_ERROR;
@@ -4402,6 +4372,12 @@ wl_role_to_cfg80211_type(uint16 role, uint16 *wl_iftype, uint16 *mode)
                *mode = WL_MODE_AP;
                return NL80211_IFTYPE_AP;
 #endif
+#ifdef WLMESH_CFG80211
+       case WLC_E_IF_ROLE_MESH:
+               *wl_iftype = WL_IF_TYPE_MESH;
+               *mode = WL_MODE_MESH;
+               return NL80211_IFTYPE_MESH_POINT;
+#endif /* WLMESH_CFG80211 */
 
        default:
                WL_ERR(("Unknown interface role:0x%x. Forcing type station\n", role));
@@ -4444,6 +4420,13 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
                return NULL;
        }
 
+#if defined(WLMESH_CFG80211) && defined(WL_EXT_IAPSTA)
+       if (wl_ext_iapsta_mesh_creating(ndev)) {
+               event->role = WLC_E_IF_ROLE_MESH;
+               WL_MSG(ndev->name, "change role to WLC_E_IF_ROLE_MESH\n");
+       }
+#endif /* WLMESH_CFG80211 && WL_EXT_IAPSTA */
+
        iface_type = wl_role_to_cfg80211_type(event->role, &wl_iftype, &mode);
        if (iface_type < 0) {
                /* Unknown iface type */
@@ -4451,13 +4434,6 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
                return NULL;
        }
 
-#ifdef WL_EXT_IAPSTA
-       if (wl_ext_check_mesh_creating(ndev)) {
-               WL_MSG(ndev->name, "change iface_type to NL80211_IFTYPE_MESH_POINT\n");
-               iface_type = NL80211_IFTYPE_MESH_POINT;
-       }
-#endif
-
        WL_DBG(("mac_ptr:%p name:%s role:%d nl80211_iftype:%d " MACDBG "\n",
                addr, name, event->role, iface_type, MAC2STRDBG(event->mac)));
        if (!name) {
@@ -4484,9 +4460,6 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
                        return NULL;
                }
                wdev = new_ndev->ieee80211_ptr;
-#ifdef WL_EXT_IAPSTA
-               wl_ext_iapsta_update_iftype(new_ndev, event->ifidx, wl_iftype);
-#endif
        } else
 #endif /* WL_STATIC_IF */
        {
@@ -4521,6 +4494,9 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
                SET_NETDEV_DEV(new_ndev, wiphy_dev(wdev->wiphy));
 
                memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
+#ifdef WL_EXT_IAPSTA
+               wl_ext_iapsta_ifadding(new_ndev, event->ifidx);
+#endif /* WL_EXT_IAPSTA */
                if (wl_cfg80211_register_if(cfg, event->ifidx, new_ndev, rtnl_lock_reqd)
                        != BCME_OK) {
                        WL_ERR(("IFACE register failed \n"));
@@ -4550,6 +4526,9 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
        if (mode == WL_MODE_AP) {
                wl_set_drv_status(cfg, AP_CREATING, new_ndev);
        }
+#ifdef WL_EXT_IAPSTA
+       wl_ext_iapsta_update_iftype(new_ndev, event->ifidx, wl_iftype);
+#endif
 
        WL_INFORM_MEM(("Network Interface (%s) registered with host."
                " cfg_iftype:%d wl_role:%d " MACDBG "\n",
@@ -5345,6 +5324,19 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
                val = WL_AUTH_FILS_PUBLIC;
                break;
 #endif /* WL_FILS */
+#ifdef WL_CLIENT_SAE
+       case NL80211_AUTHTYPE_SAE:
+               if (!wl_is_pmkid_available(dev, sme->bssid)) {
+                       val = WL_AUTH_SAE_KEY;
+               } else {
+                       /* Fw will choose right auth type
+                       * dynamically based on PMKID availability
+                       */
+                       val = WL_AUTH_OPEN_SHARED;
+               }
+               WL_DBG(("sae auth type %d\n", val));
+               break;
+#endif /* WL_CLIENT_SAE */
        default:
                val = 2;
                WL_ERR(("invalid auth type (%d)\n", sme->auth_type));
@@ -5362,6 +5354,28 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme)
        return err;
 }
 
+#ifdef WL_CLIENT_SAE
+static bool
+wl_is_pmkid_available(struct net_device *dev, const u8 *bssid)
+{
+       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+       int i;
+       int npmkids = (cfg->pmk_list->pmkids.length - sizeof(uint16)*2) / sizeof(pmkid_v2_t);
+
+       /* check the bssid is null or not */
+       if (!bssid) return FALSE;
+
+       for (i = 0; i < npmkids; i++) {
+               if (!memcmp(bssid, &cfg->pmk_list->pmkids.pmkid[i].bssid, ETHER_ADDR_LEN)) {
+                       WL_DBG(("FOUND PMKID\n"));
+                       return TRUE;
+               }
+       }
+       WL_ERR(("PMKID NOT FOUND\n"));
+       return FALSE;
+}
+#endif /* WL_CLIENT_SAE */
+
 static u32
 wl_rsn_cipher_wsec_algo_lookup(uint32 cipher)
 {
@@ -5535,9 +5549,7 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme)
                return err;
        }
 #ifdef WL_GCMP
-       if (wl_set_wsec_info_algos(dev, algos, mask)) {
-               WL_ERR(("set wsec_info error (%d)\n", err));
-       }
+       wl_set_wsec_info_algos(dev, algos, mask);
 #endif /* WL_GCMP */
        sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
        sec->cipher_pairwise = sme->crypto.ciphers_pairwise[0];
@@ -5580,10 +5592,12 @@ wl_set_wsec_info_algos(struct net_device *dev, uint32 algos, uint32 mask)
        tlv_data_len = sizeof(tlv_data);
        err = memcpy_s(tlv_data, sizeof(tlv_data), &algos, sizeof(algos));
        if (err) {
+               WL_ERR(("memcpy_s algos error (%d)\n", err));
                goto exit;
        }
        err = memcpy_s(tlv_data + sizeof(algos), sizeof(mask), &mask, sizeof(mask));
        if (err) {
+               WL_ERR(("memcpy_s mask error (%d)\n", err));
                goto exit;
        }
        bcm_xtlv_pack_xtlv(wsec_info_tlv, WL_WSEC_INFO_BSS_ALGOS, tlv_data_len, tlv_data, 0);
@@ -5942,9 +5956,6 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
 #ifdef WL_OWE
                        case WLAN_AKM_SUITE_OWE:
 #endif /* WL_OWE */
-#ifdef WL_SAE
-                       case WLAN_AKM_SUITE_SAE:
-#endif /* WL_SAE */
                        case WLAN_AKM_SUITE_FT_8021X_SHA384:
                                val = wl_rsn_akm_wpa_auth_lookup(sme->crypto.akm_suites[0]);
                                break;
@@ -5954,6 +5965,11 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme)
                        case WLAN_AKM_SUITE_FT_FILS_SHA384:
                                val = WPA2_AUTH_FILS_SHA384 | WPA2_AUTH_FT;
                                break;
+#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
+                       case WLAN_AKM_SUITE_SAE:
+                               val = WPA3_AUTH_SAE_PSK;
+                               break;
+#endif /* WL_SAE || WL_CLIENT_SAE */
                        default:
                                WL_ERR(("invalid akm suite (0x%x)\n",
                                        sme->crypto.akm_suites[0]));
@@ -6829,10 +6845,10 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev,
        s32 bssidx = 0;
        dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
 
-       WL_MSG(dev->name, "Reason %d\n", reason_code);
        RETURN_EIO_IF_NOT_UP(cfg);
        act = *(bool *) wl_read_prof(cfg, dev, WL_PROF_ACT);
        curbssid = wl_read_prof(cfg, dev, WL_PROF_BSSID);
+       WL_MSG(dev->name, "Reason %d, act %d\n", reason_code, act);
 
        BCM_REFERENCE(dhdp);
        DHD_STATLOG_CTRL(dhdp, ST(DISASSOC_START),
@@ -8388,7 +8404,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev,
                if (pmksa->pmk_len) {
                        if (memcpy_s(&cfg->pmk_list->pmkids.pmkid[i].pmk, PMK_LEN_MAX, pmksa->pmk,
                                pmksa->pmk_len)) {
-                               WL_ERR(("invalid pmk len = %lu", pmksa->pmk_len));
+                               WL_ERR(("invalid pmk len = %zu", pmksa->pmk_len));
                        } else {
                                cfg->pmk_list->pmkids.pmkid[i].pmk_len = pmksa->pmk_len;
                        }
@@ -9638,7 +9654,39 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, bcm_struct_cfgdev *cfgdev,
                        wl_cfg80211_cancel_scan(cfg);
 #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */
                }
+#ifdef WL_CLIENT_SAE
+               else if (ieee80211_is_auth(mgmt->frame_control)) {
+                       int err = 0;
+                       wl_assoc_mgr_cmd_t *cmd;
+                       char *ambuf = NULL;
+                       int param_len;
 
+                       ack = true;
+                       if ((dev == bcmcfg_to_prmry_ndev(cfg)) && cfg->p2p) {
+                               bssidx = wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_DEVICE);
+                       }
+                       param_len = sizeof(wl_assoc_mgr_cmd_t) + len;
+                       ambuf = MALLOCZ(cfg->osh, param_len);
+                       if (ambuf == NULL) {
+                               WL_ERR(("unable to allocate frame\n"));
+                               return -ENOMEM;
+                       }
+                       cmd = (wl_assoc_mgr_cmd_t*)ambuf;
+                       cmd->version = WL_ASSOC_MGR_CURRENT_VERSION;
+                       cmd->length = len;
+                       cmd->cmd = WL_ASSOC_MGR_CMD_SEND_AUTH;
+                       memcpy(&cmd->params, buf, len);
+                       err = wldev_iovar_setbuf(dev, "assoc_mgr_cmd", ambuf, param_len,
+                               cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+                       if (unlikely(err)) {
+                               WL_ERR(("Failed to send auth(%d)\n", err));
+                               ack = false;
+                       }
+                       MFREE(cfg->osh, ambuf, param_len);
+                       cfg80211_mgmt_tx_status(cfgdev, *cookie, buf, len, ack, GFP_KERNEL);
+                       goto exit;
+               }
+#endif /* WL_CLIENT_SAE */
        } else {
                WL_ERR(("Driver only allows MGMT packet type\n"));
                goto exit;
@@ -9824,7 +9872,10 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev,
        dev = ndev_to_wlc_ndev(dev, cfg);
        _chan = ieee80211_frequency_to_channel(chan->center_freq);
 #ifdef WL_EXT_IAPSTA
-       _chan = wl_ext_iapsta_update_channel(dhd, dev, _chan);
+       if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_AP) {
+               wl_ext_iapsta_update_iftype(dev, dhd_net2idx(dhd->info, dev), WL_IF_TYPE_AP);
+               _chan = wl_ext_iapsta_update_channel(dhd, dev, _chan);
+       }
 #endif
        WL_MSG(dev->name, "netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
                dev->ifindex, channel_type, _chan);
@@ -10924,9 +10975,6 @@ wl_cfg80211_set_ap_role(
        }
 
        if (!ap) {
-#ifdef WLEASYMESH
-               WL_ERR(("ap should not be 0\n"));
-#endif
                /* AP mode switch not supported. Try setting up AP explicitly */
                err = wldev_iovar_getint(dev, "apsta", (s32 *)&apsta);
                if (unlikely(err)) {
@@ -10934,9 +10982,6 @@ wl_cfg80211_set_ap_role(
                        return err;
                }
                if (apsta == 0) {
-#ifdef WLEASYMESH
-                       WL_ERR(("apsta should not be 0\n"));
-#endif
                        /* If apsta is not set, set it */
 
                        /* Check for any connected interfaces before wl down */
@@ -11044,9 +11089,9 @@ wl_cfg80211_bcn_bringup_ap(
        /* Do abort scan before creating GO */
        wl_cfg80211_scan_abort(cfg);
 
-       wl_ext_get_sec(dev, 0, sec, sizeof(sec));
-       WL_MSG(dev->name, "Creating AP/GO with sec=%s\n", sec);
        if (dev_role == NL80211_IFTYPE_P2P_GO) {
+               wl_ext_get_sec(dev, 0, sec, sizeof(sec));
+               WL_MSG(dev->name, "Creating GO with sec=%s\n", sec);
                is_bssup = wl_cfg80211_bss_isup(dev, bssidx);
                if (!is_bssup && (ies->wpa2_ie != NULL)) {
 
@@ -11136,8 +11181,9 @@ wl_cfg80211_bcn_bringup_ap(
                        WL_ERR(("Could not get wsec %d\n", err));
                        goto exit;
                }
-               if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 && wsec >= 2) {
-                       wsec |= 0x8; // terence 20180628: fix me, this is a workaround
+               if (dhdp->conf->chip == BCM43430_CHIP_ID && bssidx > 0 &&
+                               (wsec & (TKIP_ENABLED|AES_ENABLED))) {
+                       wsec |= WSEC_SWFLAG; // terence 20180628: fix me, this is a workaround
                        err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
                        if (err < 0) {
                                WL_ERR(("wsec error %d\n", err));
@@ -11182,6 +11228,8 @@ wl_cfg80211_bcn_bringup_ap(
                        join_params.ssid.SSID_len);
                join_params.ssid.SSID_len = htod32(join_params.ssid.SSID_len);
 
+               wl_ext_get_sec(dev, 0, sec, sizeof(sec));
+               WL_MSG(dev->name, "Creating AP with sec=%s\n", sec);
                /* create softap */
                if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
                        join_params_size)) != 0) {
@@ -11620,18 +11668,17 @@ wl_cfg80211_del_station(
                } else
 #endif /* WL_WPS_SYNC */
                {
-
+                       scb_val.val = DOT11_RC_DEAUTH_LEAVING;
+                       WL_MSG(dev->name, "Disconnect STA : " MACDBG " scb_val.val %d\n",
+                               MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr,
+                               eabuf)), scb_val.val);
                        /* need to guarantee EAP-Failure send out before deauth */
                        dhd_wait_pend8021x(dev);
-                       scb_val.val = DOT11_RC_DEAUTH_LEAVING;
                        err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
                                sizeof(scb_val_t));
                        if (err < 0) {
                                WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err));
                        }
-                       WL_MSG(dev->name, "Disconnect STA : " MACDBG " scb_val.val %d\n",
-                               MAC2STRDBG(bcm_ether_ntoa((const struct ether_addr *)mac_addr,
-                               eabuf)), scb_val.val);
                }
 #ifdef CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0))
@@ -11795,6 +11842,9 @@ wl_cfg80211_start_ap(
                if (err) {
                        WL_ERR(("Disabling NDO Failed %d\n", err));
                }
+#ifdef WL_EXT_IAPSTA
+               wl_ext_iapsta_update_iftype(dev, dhd_net2idx(dhd->info, dev), WL_IF_TYPE_AP);
+#endif /* WL_EXT_IAPSTA */
 #ifdef PKT_FILTER_SUPPORT
                /* Disable packet filter */
                if (dhd->early_suspended) {
@@ -11929,6 +11979,9 @@ fail:
                wl_flush_fw_log_buffer(dev, FW_LOGSET_MASK_ALL);
                wl_cfg80211_stop_ap(wiphy, dev);
                if (dev_role == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+               if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
                        dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
 #ifdef PKT_FILTER_SUPPORT
                        /* Enable packet filter */
@@ -11950,6 +12003,9 @@ fail:
 #ifdef DISABLE_WL_FRAMEBURST_SOFTAP
                        wl_cfg80211_set_frameburst(cfg, TRUE);
 #endif /* DISABLE_WL_FRAMEBURST_SOFTAP */
+#ifdef WL_EXT_IAPSTA
+               }
+#endif /* WL_EXT_IAPSTA */
                }
 #ifdef WLTDLS
                if (bssidx == 0) {
@@ -12090,8 +12146,14 @@ exit:
 #endif /* WLTDLS */
 
        if (dev_role == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+               if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
                /* clear the AP mode */
                dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+#ifdef WL_EXT_IAPSTA
+               }
+#endif /* WL_EXT_IAPSTA */
        }
        return err;
 }
@@ -12342,8 +12404,14 @@ fail:
        if (err) {
                WL_ERR(("ADD/SET beacon failed\n"));
                if (dev_role == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+               if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
                        /* clear the AP mode */
                        dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+#ifdef WL_EXT_IAPSTA
+               }
+#endif /* WL_EXT_IAPSTA */
                }
        }
        return err;
@@ -12397,8 +12465,14 @@ wl_cfg80211_del_beacon(struct wiphy *wiphy, struct net_device *dev)
         wl_cfg80211_clear_per_bss_ies(cfg, dev->ieee80211_ptr);
 
        if (wdev->iftype == NL80211_IFTYPE_AP) {
+#ifdef WL_EXT_IAPSTA
+               if (!wl_ext_iapsta_iftype_enabled(dev, WL_IF_TYPE_AP)) {
+#endif /* WL_EXT_IAPSTA */
                /* clear the AP mode */
                dhd->op_mode &= ~DHD_FLAG_HOSTAP_MODE;
+#ifdef WL_EXT_IAPSTA
+               }
+#endif /* WL_EXT_IAPSTA */
        }
 
        return 0;
@@ -12693,6 +12767,9 @@ static struct cfg80211_ops wl_cfg80211_ops = {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
        .channel_switch = wl_cfg80211_channel_switch,
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0) */
+#ifdef WL_CLIENT_SAE
+       .external_auth = wl_cfg80211_external_auth,
+#endif /* WL_CLIENT_SAE */
 };
 
 s32 wl_mode_to_nl80211_iftype(s32 mode)
@@ -12706,6 +12783,10 @@ s32 wl_mode_to_nl80211_iftype(s32 mode)
                return NL80211_IFTYPE_ADHOC;
        case WL_MODE_AP:
                return NL80211_IFTYPE_AP;
+#ifdef WLMESH_CFG80211
+       case WL_MODE_MESH:
+               return NL80211_IFTYPE_MESH_POINT;
+#endif /* WLMESH_CFG80211 */
        default:
                return NL80211_IFTYPE_UNSPECIFIED;
        }
@@ -12741,6 +12822,61 @@ wl_cfg80211_set_country_code(struct net_device *net, char *country_code,
        return ret;
 }
 
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 9, 0))
+#define WL_CFG80211_REG_NOTIFIER() static int wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+#else
+#define WL_CFG80211_REG_NOTIFIER() static void wl_cfg80211_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
+#endif /* kernel version < 3.9.0 */
+#endif
+
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+WL_CFG80211_REG_NOTIFIER()
+{
+       struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)wiphy_priv(wiphy);
+       int ret = 0;
+       int revinfo = -1;
+
+       if (!request || !cfg) {
+               WL_ERR(("Invalid arg\n"));
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
+               return -EINVAL;
+#else
+               return;
+#endif /* kernel version < 3.10.11 */
+       }
+
+       WL_DBG(("ccode: %c%c Initiator: %d\n",
+               request->alpha2[0], request->alpha2[1], request->initiator));
+
+       /* We support only REGDOM_SET_BY_USER as of now */
+       if ((request->initiator != NL80211_REGDOM_SET_BY_USER) &&
+               (request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE)) {
+               WL_ERR(("reg_notifier for intiator:%d not supported : set default\n",
+                       request->initiator));
+               /* in case of no supported country by regdb
+                    lets driver setup platform default Locale
+               */
+       }
+
+       WL_ERR(("Set country code %c%c from %s\n",
+               request->alpha2[0], request->alpha2[1],
+               ((request->initiator == NL80211_REGDOM_SET_BY_COUNTRY_IE) ? " 11d AP" : "User")));
+
+       if ((ret = wldev_set_country(bcmcfg_to_prmry_ndev(cfg), request->alpha2,
+               false, (request->initiator == NL80211_REGDOM_SET_BY_USER ? true : false),
+               revinfo)) < 0) {
+               WL_ERR(("set country Failed :%d\n", ret));
+       }
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 11))
+       return ret;
+#else
+       return;
+#endif /* kernel version < 3.10.11 */
+}
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
 #ifdef CONFIG_PM
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
 static const struct wiphy_wowlan_support brcm_wowlan_support = {
@@ -12807,6 +12943,9 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
        wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN;
 #endif /* LINUX_VER < 4.12 */
 #endif /* WL_SCHED_SCAN */
+#ifdef WLMESH_CFG80211
+       wdev->wiphy->flags |= WIPHY_FLAG_MESH_AUTH;
+#endif /* WLMESH_CFG80211 */
        wdev->wiphy->interface_modes =
                BIT(NL80211_IFTYPE_STATION)
                | BIT(NL80211_IFTYPE_ADHOC)
@@ -12820,6 +12959,9 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
 #if defined(WL_CFG80211_P2P_DEV_IF)
                | BIT(NL80211_IFTYPE_P2P_DEVICE)
 #endif /* WL_CFG80211_P2P_DEV_IF */
+#ifdef WLMESH_CFG80211
+               | BIT(NL80211_IFTYPE_MESH_POINT)
+#endif /* WLMESH_CFG80211 */
                | BIT(NL80211_IFTYPE_AP);
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
@@ -12958,7 +13100,7 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
        wiphy_ext_feature_set(wdev->wiphy, NL80211_EXT_FEATURE_FILS_SK_OFFLOAD);
 #endif /* WL_FILS */
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 17, 0))
        wdev->wiphy->flags |= WIPHY_FLAG_HAS_CHANNEL_SWITCH;
        wdev->wiphy->max_num_csa_counters = WL_MAX_NUM_CSA_COUNTERS;
 #endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 12, 0) */
@@ -12975,9 +13117,9 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
        wdev->wiphy->flags &= ~WIPHY_FLAG_ENFORCE_COMBINATIONS;
 #endif // endif
 
-#ifdef WL_SAE
-               wdev->wiphy->features |= NL80211_FEATURE_SAE;
-#endif /* WL_SAE */
+#if defined(WL_SAE) || defined(WL_CLIENT_SAE)
+       wdev->wiphy->features |= NL80211_FEATURE_SAE;
+#endif /* WL_SAE || WL_CLIENT_SAE */
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 13, 0)) && defined(BCMSUP_4WAY_HANDSHAKE)
        if (FW_SUPPORTED(dhd, idsup)) {
                err = wiphy_ext_feature_set(wdev->wiphy,
@@ -13032,7 +13174,11 @@ static void wl_free_wdev(struct bcm_cfg80211 *cfg)
 
        wl_delete_all_netinfo(cfg);
        if (wiphy) {
+               if (wdev->netdev)
+                       wdev->netdev->ieee80211_ptr = NULL;
+               wdev->netdev = NULL;
                MFREE(cfg->osh, wdev, sizeof(*wdev));
+               cfg->wdev = NULL;
                wiphy_free(wiphy);
        }
 
@@ -13041,21 +13187,13 @@ static void wl_free_wdev(struct bcm_cfg80211 *cfg)
         */
 }
 
-s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
+#if defined(BSSCACHE) || defined(RSSIAVG)
+void wl_cfg80211_update_bss_cache(struct bcm_cfg80211 *cfg)
 {
-       struct wl_scan_results *bss_list;
-       wl_bss_info_t *bi = NULL;       /* must be initialized */
-       s32 err = 0;
-       s32 i;
-       struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
 #if defined(RSSIAVG)
        int rssi;
 #endif
-#if defined(BSSCACHE)
-       wl_bss_cache_t *node;
-#endif
-
-       bss_list = cfg->bss_list;
+       struct wl_scan_results *bss_list = cfg->bss_list;
 
        /* Free cache in p2p scanning*/
        if (p2p_is_on(cfg) && p2p_scan(cfg)) {
@@ -13069,9 +13207,11 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
 
        /* Delete disconnected cache */
 #if defined(BSSCACHE)
-       wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+       wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl,
+               (u8*)&cfg->disconnected_bssid);
 #if defined(RSSIAVG)
-       wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+       wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl,
+               (u8*)&cfg->disconnected_bssid);
 #endif
        if (cfg->p2p_disconnected == 0)
                memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
@@ -13101,7 +13241,21 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
        wl_reset_bss_cache(&cfg->g_bss_cache_ctrl);
 #endif
 
+}
+#endif
+
+#if defined(BSSCACHE)
+s32 wl_inform_bss_cache(struct bcm_cfg80211 *cfg)
+{
+       struct wl_scan_results *bss_list = cfg->bss_list;
+       wl_bss_info_t *bi = NULL;       /* must be initialized */
+       s32 err = 0;
+       s32 i;
+       struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
 #if defined(BSSCACHE)
+       wl_bss_cache_t *node;
+#endif
+
        if (cfg->p2p_disconnected > 0) {
                // terence 20130703: Fix for wrong group_capab (timing issue)
                wl_delete_disconnected_bss_cache(&cfg->g_bss_cache_ctrl, (u8*)&cfg->disconnected_bssid);
@@ -13119,7 +13273,29 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
        if (cfg->autochannel)
                wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
                        &cfg->best_2g_ch, &cfg->best_5g_ch);
+
+       return err;
+}
+#endif
+
+s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
+{
+#if !defined(BSSCACHE)
+       struct wl_scan_results *bss_list;
+       wl_bss_info_t *bi = NULL;       /* must be initialized */
+       s32 i;
+       struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+#endif
+       s32 err = 0;
+
+#if defined(BSSCACHE) || defined(RSSIAVG)
+       wl_cfg80211_update_bss_cache(cfg);
+#endif
+
+#if defined(BSSCACHE)
+       err = wl_inform_bss_cache(cfg);
 #else
+       bss_list = cfg->bss_list;
        WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
 #ifdef ESCAN_CHANNEL_CACHE
        reset_roam_cache(cfg);
@@ -13127,8 +13303,11 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
        preempt_disable();
        bi = next_bss(bss_list, bi);
        for_each_bss(bss_list, bi, i) {
-               if (cfg->p2p_disconnected > 0 && !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN))
+               if (cfg->p2p_disconnected > 0 &&
+                               !memcmp(&bi->BSSID, &cfg->disconnected_bssid, ETHER_ADDR_LEN)) {
+                       WL_SCAN(("Skip %pM\n", &bi->BSSID));
                        continue;
+               }
 #ifdef ESCAN_CHANNEL_CACHE
                add_roam_cache(cfg, bi);
 #endif /* ESCAN_CHANNEL_CACHE */
@@ -13146,7 +13325,7 @@ s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
        if (cfg->p2p_disconnected > 0) {
                // terence 20130703: Fix for wrong group_capab (timing issue)
                cfg->p2p_disconnected++;
-               if (cfg->p2p_disconnected >= REPEATED_SCAN_RESULT_CNT+1) {
+               if (cfg->p2p_disconnected >= 2) {
                        cfg->p2p_disconnected = 0;
                        memset(&cfg->disconnected_bssid, 0, ETHER_ADDR_LEN);
                }
@@ -13626,8 +13805,9 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
        }
 
        if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
-               WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n",
-               bcmevent_get_name(event), event, ntoh32(e->status), reason);
+               WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
+                       "event %s(%d) status %d reason %d\n",
+                       bcmevent_get_name(event), event, ntoh32(e->status), reason);
        }
 
 #if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
@@ -13759,8 +13939,8 @@ exit:
        } else if ((event == WLC_E_DEAUTH_IND) ||
                ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) ||
                (event == WLC_E_DISASSOC_IND)) {
-               WL_MSG(ndev->name, "del sta event for "MACDBG "\n",
-                       MAC2STRDBG(e->addr.octet));
+               WL_MSG_RLMT(ndev->name, &e->addr, ETHER_ADDR_LEN,
+                       "del sta event for "MACDBG "\n", MAC2STRDBG(e->addr.octet));
                wl_cfg80211_check_in4way(cfg, ndev, DONT_DELETE_GC_AFTER_WPS,
                        WL_EXT_STATUS_STA_DISCONNECTED, NULL);
                cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
@@ -13772,37 +13952,248 @@ exit:
        return err;
 }
 
+#ifdef WL_CLIENT_SAE
 static s32
-wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+wl_notify_start_auth(struct bcm_cfg80211 *cfg,
+       bcm_struct_cfgdev *cfgdev, const wl_event_msg_t *e, void *data)
+{
+       struct cfg80211_external_auth_params ext_auth_param;
+       struct net_device *ndev = cfgdev_to_wlc_ndev(cfgdev, cfg);
+       u32 datalen = be32_to_cpu(e->datalen);
+       wl_ext_auth_evt_t *evt_data = (wl_ext_auth_evt_t *)data;
+       wl_assoc_mgr_cmd_t cmd;
+       int err;
+
+       WL_DBG(("Enter\n"));
+
+       if (!datalen || !data)
+               return BCME_ERROR;
+
+       ext_auth_param.ssid.ssid_len = MIN(evt_data->ssid.SSID_len, DOT11_MAX_SSID_LEN);
+       if (ext_auth_param.ssid.ssid_len)
+               memcpy(&ext_auth_param.ssid.ssid, evt_data->ssid.SSID,
+                       ext_auth_param.ssid.ssid_len);
+
+       memcpy(&ext_auth_param.bssid, &evt_data->bssid, ETHER_ADDR_LEN);
+       ext_auth_param.action = NL80211_EXTERNAL_AUTH_START;
+       ext_auth_param.key_mgmt_suite = ntoh32(WLAN_AKM_SUITE_SAE_SHA256);
+
+       WL_MSG(ndev->name, "BSSID: "MACDBG"\n", MAC2STRDBG(&evt_data->bssid));
+
+       cfg80211_external_auth_request(ndev, &ext_auth_param, GFP_KERNEL);
+
+       cmd.version = WL_ASSOC_MGR_CURRENT_VERSION;
+       cmd.length = sizeof(cmd);
+       cmd.cmd = WL_ASSOC_MGR_CMD_PAUSE_ON_EVT;
+       cmd.params = WL_ASSOC_MGR_PARAMS_PAUSE_EVENT_AUTH_RESP;
+       err = wldev_iovar_setbuf(ndev, "assoc_mgr_cmd", (void *)&cmd, sizeof(cmd),
+               cfg->ioctl_buf, WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+       if (unlikely(err)) {
+               WL_ERR(("Failed to pause assoc(%d)\n", err));
+       }
+
+       return BCME_OK;
+}
+
+static s32
+wl_notify_connect_status_bss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
        const wl_event_msg_t *e, void *data)
 {
        s32 err = 0;
        u32 event = ntoh32(e->event_type);
-       u16 flags = ntoh16(e->flags);
-       u32 status =  ntoh32(e->status);
-       bool active;
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-       struct ieee80211_channel *channel = NULL;
+       u32 reason = ntoh32(e->reason);
+       u32 len = ntoh32(e->datalen);
+       u32 status = ntoh32(e->status);
+
+       bool isfree = false;
+       u8 *mgmt_frame;
+       u8 bsscfgidx = e->bsscfgidx;
+       s32 freq;
+       s32 channel;
+       u8 *body = NULL;
+       u16 fc = 0, rssi = 0;
+       bcm_struct_cfgdev *cfgdev = ndev_to_cfgdev(ndev);
+
+       struct ieee80211_supported_band *band;
+       struct ether_addr da;
+       struct ether_addr bssid;
        struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
-       u32 chanspec, chan;
-       u32 freq, band;
-#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+       channel_info_t ci;
 
-       if (event == WLC_E_JOIN) {
-               WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name));
+       WL_DBG(("event %d status %d reason %d\n", event, status, reason));
+
+       if (event == WLC_E_AUTH) {
+               struct wl_security *sec;
+               sec = wl_read_prof(cfg, ndev, WL_PROF_SEC);
+
+               if (!(sec->auth_type == NL80211_AUTHTYPE_SAE)) {
+                       WL_DBG(("Abort AUTH processing due to NOT SAE\n"));
+                       return 0;
+               } else {
+                       if (status != WLC_E_STATUS_SUCCESS && !len) {
+                               WL_ERR(("SAE AUTH FAIL EVENT\n"));
+                               wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED,
+                                       WL_EXT_STATUS_DISCONNECTED, NULL);
+                               return 0;
+                       }
+               }
        }
-       if (event == WLC_E_START) {
-               WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name));
+
+       if (!len && (event == WLC_E_DEAUTH)) {
+               len = 2; /* reason code field */
+               data = &reason;
        }
-       if (event == WLC_E_JOIN || event == WLC_E_START ||
-               (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
-               err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
-               if (unlikely(err)) {
-                       WL_ERR(("Could not get chanspec %d\n", err));
-                       return err;
-               }
-               chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
+
+       if (len) {
+               body = kzalloc(len, GFP_KERNEL);
+               if (body == NULL) {
+                       WL_ERR(("wl_notify_connect_status: Failed to allocate body\n"));
+                       return WL_INVALID;
+               }
+       }
+
+       memset(&bssid, 0, ETHER_ADDR_LEN);
+       if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
+               kfree(body);
+               return WL_INVALID;
+       }
+       if (len)
+               memcpy(body, data, len);
+
+       wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+               NULL, 0, cfg->ioctl_buf, WLC_IOCTL_SMLEN, bsscfgidx, &cfg->ioctl_buf_sync);
+       memcpy(da.octet, cfg->ioctl_buf, ETHER_ADDR_LEN);
+       err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
+       /* Use e->addr as bssid for Sta case , before association completed */
+       if (err == BCME_NOTASSOCIATED)
+               memcpy(&bssid, &e->addr, ETHER_ADDR_LEN);
+
+       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_DISASSOC;
+                       break;
+               case WLC_E_DEAUTH:
+                       fc = FC_DISASSOC;
+                       break;
+               case WLC_E_AUTH:
+                       fc = FC_AUTH;
+                       break;
+               default:
+                       fc = 0;
+                       goto exit;
+       }
+       if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
+               kfree(body);
+               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 (!band) {
+               WL_ERR(("No valid band\n"));
+               if (body)
+                       kfree(body);
+               return -EINVAL;
+       }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
+       freq = ieee80211_channel_to_frequency(channel);
+       (void)band->band;
+#else
+       freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif
+
+       err = wl_frame_get_mgmt(cfg, 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) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+               cfg80211_rx_mgmt(cfgdev, freq, rssi,  mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+               cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+       } else if (event == WLC_E_DISASSOC_IND) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+               cfg80211_rx_mgmt(cfgdev, freq, rssi,  mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+               cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+       } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+               cfg80211_rx_mgmt(cfgdev, freq, rssi,  mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+               cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+       } else if (event == WLC_E_AUTH) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+               cfg80211_rx_mgmt(cfgdev, freq, rssi,  mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0))
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+               cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif
+       }
+exit:
+       if (isfree)
+               kfree(mgmt_frame);
+       if (body)
+               kfree(body);
+       return err;
+}
+#endif /* WL_CLIENT_SAE */
+
+static s32
+wl_notify_connect_status_ibss(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+       const wl_event_msg_t *e, void *data)
+{
+       s32 err = 0;
+       u32 event = ntoh32(e->event_type);
+       u16 flags = ntoh16(e->flags);
+       u32 status =  ntoh32(e->status);
+       bool active;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+       struct ieee80211_channel *channel = NULL;
+       struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+       u32 chanspec, chan;
+       u32 freq, band;
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0) */
+
+       if (event == WLC_E_JOIN) {
+               WL_INFORM_MEM(("[%s] joined in IBSS network\n", ndev->name));
+       }
+       if (event == WLC_E_START) {
+               WL_INFORM_MEM(("[%s] started IBSS network\n", ndev->name));
+       }
+       if (event == WLC_E_JOIN || event == WLC_E_START ||
+               (event == WLC_E_LINK && (flags == WLC_EVENT_MSG_LINK))) {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 15, 0)
+               err = wldev_iovar_getint(ndev, "chanspec", (s32 *)&chanspec);
+               if (unlikely(err)) {
+                       WL_ERR(("Could not get chanspec %d\n", err));
+                       return err;
+               }
+               chan = wf_chspec_ctlchan(wl_chspec_driver_to_host(chanspec));
                band = (chan <= CH_MAX_2G_CHANNEL) ? IEEE80211_BAND_2GHZ : IEEE80211_BAND_5GHZ;
                freq = ieee80211_channel_to_frequency(chan, band);
                channel = ieee80211_get_channel(wiphy, freq);
@@ -13980,6 +14371,193 @@ wl_cache_assoc_resp_ies(struct bcm_cfg80211 *cfg, struct net_device *ndev,
        }
 }
 
+#ifdef WLMESH_CFG80211
+static s32
+wl_notify_connect_status_mesh(struct bcm_cfg80211 *cfg, struct net_device *ndev,
+       const wl_event_msg_t *e, void *data)
+{
+       s32 err = 0;
+       u32 event = ntoh32(e->event_type);
+       u32 reason = ntoh32(e->reason);
+       u32 len = ntoh32(e->datalen);
+       u32 status = ntoh32(e->status);
+
+#if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
+       (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+       bool isfree = false;
+       u8 *mgmt_frame;
+       u8 bsscfgidx = e->bsscfgidx;
+       s32 freq;
+       s32 channel;
+       u8 *body = NULL;
+       u16 fc = 0;
+       u32 body_len = 0;
+
+       struct ieee80211_supported_band *band;
+       struct ether_addr da;
+       struct ether_addr bssid;
+       struct wiphy *wiphy = bcmcfg_to_wiphy(cfg);
+       channel_info_t ci;
+       u8 ioctl_buf[WLC_IOCTL_SMLEN];
+#else
+       struct station_info sinfo;
+#endif /* (LINUX_VERSION < VERSION(3,2,0)) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+
+       WL_INFORM_MEM(("[%s] Mode Mesh. Event:%d status:%d reason:%d\n",
+               ndev->name, event, ntoh32(e->status), reason));
+
+       /* if link down, bsscfg is disabled. */
+       if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS &&
+                       (ndev != bcmcfg_to_prmry_ndev(cfg))) {
+               WL_MSG(ndev->name, "Mesh mode link down !! \n");
+               return 0;
+       }
+
+       if ((event == WLC_E_LINK) && (status == WLC_E_STATUS_SUCCESS) &&
+                       (reason == WLC_E_REASON_INITIAL_ASSOC)) {
+               /* AP/GO brought up successfull in firmware */
+               WL_MSG(ndev->name, "Mesh Link up\n");
+               return 0;
+       }
+
+       if (event == WLC_E_DISASSOC_IND || event == WLC_E_DEAUTH_IND || event == WLC_E_DEAUTH) {
+               WL_MSG(ndev->name, "event %s(%d) status %d reason %d\n",
+               bcmevent_get_name(event), event, ntoh32(e->status), reason);
+       }
+
+#if !defined(WL_CFG80211_STA_EVENT) && !defined(WL_COMPAT_WIRELESS) && \
+       (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+       WL_DBG(("Enter \n"));
+       if (!len && (event == WLC_E_DEAUTH)) {
+               len = 2; /* reason code field */
+               data = &reason;
+       }
+       if (len) {
+               body = (u8 *)MALLOCZ(cfg->osh, len);
+               if (body == NULL) {
+                       WL_ERR(("Failed to allocate body\n"));
+                       return WL_INVALID;
+               }
+       }
+       bzero(&bssid, ETHER_ADDR_LEN);
+       WL_DBG(("Enter event %d ndev %p\n", event, ndev));
+       if (wl_get_mode_by_netdev(cfg, ndev) == WL_INVALID) {
+               MFREE(cfg->osh, body, len);
+               return WL_INVALID;
+       }
+       if (len)
+               memcpy(body, data, len);
+
+       wldev_iovar_getbuf_bsscfg(ndev, "cur_etheraddr",
+               NULL, 0, ioctl_buf, sizeof(ioctl_buf), bsscfgidx, NULL);
+       memcpy(da.octet, ioctl_buf, ETHER_ADDR_LEN);
+       bzero(&bssid, sizeof(bssid));
+       err = wldev_ioctl_get(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN);
+       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_DISASSOC;
+                       break;
+               case WLC_E_DEAUTH:
+                       fc = FC_DISASSOC;
+                       break;
+               default:
+                       fc = 0;
+                       goto exit;
+       }
+       bzero(&ci, sizeof(ci));
+       if ((err = wldev_ioctl_get(ndev, WLC_GET_CHANNEL, &ci, sizeof(ci)))) {
+               MFREE(cfg->osh, body, len);
+               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 (!band) {
+               WL_ERR(("No valid band\n"));
+               if (body) {
+                       MFREE(cfg->osh, body, len);
+               }
+               return -EINVAL;
+       }
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
+       freq = ieee80211_channel_to_frequency(channel);
+       (void)band->band;
+#else
+       freq = ieee80211_channel_to_frequency(channel, band->band);
+#endif // endif
+       body_len = len;
+       err = wl_frame_get_mgmt(cfg, 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) ||
+                       (event == WLC_E_DISASSOC_IND) ||
+                       ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH))) {
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 18, 0))
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 12, 0))
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, 0, GFP_ATOMIC);
+#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) || \
+               defined(WL_COMPAT_WIRELESS)
+               cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC);
+#else
+               cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC);
+#endif /* LINUX_VERSION >= VERSION(3, 18,0) || WL_COMPAT_WIRELESS */
+       }
+
+exit:
+       if (isfree) {
+               MFREE(cfg->osh, mgmt_frame, len);
+       }
+       if (body) {
+               MFREE(cfg->osh, body, body_len);
+       }
+#else /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+       memset(&sinfo, 0, sizeof(struct station_info));
+       sinfo.filled = 0;
+       if (((event == WLC_E_ASSOC_IND) || (event == WLC_E_REASSOC_IND)) &&
+               reason == DOT11_SC_SUCCESS) {
+               /* Linux ver >= 4.0 assoc_req_ies_len is used instead of
+                * STATION_INFO_ASSOC_REQ_IES flag
+                */
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(4, 0, 0))
+               sinfo.filled = STA_INFO_BIT(INFO_ASSOC_REQ_IES);
+#endif /*  (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0)) */
+               if (!data) {
+                       WL_ERR(("No IEs present in ASSOC/REASSOC_IND"));
+                       return -EINVAL;
+               }
+               sinfo.assoc_req_ies = data;
+               sinfo.assoc_req_ies_len = len;
+               WL_MSG(ndev->name, "new sta event for "MACDBG "\n",
+                       MAC2STRDBG(e->addr.octet));
+               cfg80211_new_sta(ndev, e->addr.octet, &sinfo, GFP_ATOMIC);
+       } else if ((event == WLC_E_DEAUTH_IND) ||
+               ((event == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED)) ||
+               (event == WLC_E_DISASSOC_IND)) {
+               WL_MSG(ndev->name, "del sta event for "MACDBG "\n",
+                       MAC2STRDBG(e->addr.octet));
+               cfg80211_del_sta(ndev, e->addr.octet, GFP_ATOMIC);
+       }
+#endif /* LINUX_VERSION < VERSION(3,2,0) && !WL_CFG80211_STA_EVENT && !WL_COMPAT_WIRELESS */
+       return err;
+}
+#endif /* WLMESH_CFG80211 */
+
 static s32
 wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
        const wl_event_msg_t *e, void *data)
@@ -14025,6 +14603,10 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                ntoh32(e->status),  ntoh32(e->reason)));
        if (mode == WL_MODE_AP) {
                err = wl_notify_connect_status_ap(cfg, ndev, e, data);
+#ifdef WLMESH_CFG80211
+       } else if (mode == WL_MODE_MESH) {
+               err = wl_notify_connect_status_mesh(cfg, ndev, e, data);
+#endif /* WLMESH_CFG80211 */
        } else if (mode == WL_MODE_IBSS) {
                err = wl_notify_connect_status_ibss(cfg, ndev, e, data);
        } else if (mode == WL_MODE_BSS) {
@@ -14041,6 +14623,10 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                " connect state. Ignore\n"));
                        return BCME_OK;
                }
+#ifdef WL_CLIENT_SAE
+               if (event == WLC_E_AUTH)
+                       wl_notify_connect_status_bss(cfg, ndev, e, data);
+#endif /* WL_CLIENT_SAE */
 
                if (event == WLC_E_ASSOC || event == WLC_E_AUTH) {
                        wl_get_auth_assoc_status(cfg, ndev, e, data);
@@ -14286,7 +14872,8 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                dhd_dev_set_rssi_monitor_cfg(bcmcfg_to_prmry_ndev(cfg),
                                    FALSE, 0, 0);
 #endif /* RSSI_MONITOR_SUPPORT */
-                               if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
+                               if (dhdp->conf->eapol_status == EAPOL_STATUS_4WAY_DONE &&
+                                               !memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
                                        // terence 20130703: Fix for wrong group_capab (timing issue)
                                        cfg->p2p_disconnected = 1;
                                }
@@ -15158,7 +15745,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
        if ((*channel == cur_channel) && ((memcmp(curbssid, &e->addr,
                ETHER_ADDR_LEN) == 0) || (memcmp(&cfg->last_roamed_addr,
                &e->addr, ETHER_ADDR_LEN) == 0))) {
-               WL_ERR(("BSS already present, Skipping roamed event to"
+               WL_DBG(("BSS already present, Skipping roamed event to"
                " upper layer\n"));
                goto fail;
        }
@@ -15499,6 +16086,14 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                        completed = false;
                        sec->auth_assoc_res_status = WLAN_STATUS_UNSPECIFIED_FAILURE;
                }
+               if (completed) {
+                       WL_MSG(ndev->name, "Report connect result - connection succeeded\n");
+                       wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
+               } else {
+                       WL_MSG(ndev->name, "Report connect result - connection failed\n");
+                       wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED,
+                               WL_EXT_STATUS_DISCONNECTED, NULL);
+               }
 #ifdef WL_FILS
                if ((sec->auth_type == DOT11_FILS_SKEY_PFS)||(sec->auth_type == DOT11_FILS_SKEY)) {
                        wl_get_fils_connect_params(cfg, ndev);
@@ -15551,15 +16146,6 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                                WLAN_STATUS_UNSPECIFIED_FAILURE,
                                GFP_KERNEL);
                }
-               if (completed) {
-                       WL_MSG(ndev->name, "Report connect result - "
-                               "connection succeeded\n");
-                       wl_cfg80211_check_in4way(cfg, ndev, 0, WL_EXT_STATUS_CONNECTED, NULL);
-               } else {
-                       WL_MSG(ndev->name, "Report connect result - connection failed\n");
-                       wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY|NO_BTC_IN4WAY|WAIT_DISCONNECTED,
-                               WL_EXT_STATUS_DISCONNECTED, NULL);
-               }
        } else {
                WL_INFORM_MEM(("[%s] Ignore event:%d. drv status"
                        " connecting:%x. connected:%d\n",
@@ -16233,8 +16819,43 @@ static void wl_init_event_handler(struct bcm_cfg80211 *cfg)
 #ifdef WL_CHAN_UTIL
        cfg->evt_handler[WLC_E_BSS_LOAD] = wl_cfg80211_bssload_report_event_handler;
 #endif /* WL_CHAN_UTIL */
+#ifdef WL_CLIENT_SAE
+       cfg->evt_handler[WLC_E_JOIN_START] = wl_notify_start_auth;
+#endif /* WL_CLIENT_SAE */
 }
 
+#ifdef WL_CLIENT_SAE
+/** Called by the cfg80211 framework */
+static s32
+wl_cfg80211_external_auth(struct wiphy *wiphy,
+       struct net_device *ndev, struct cfg80211_external_auth_params *ext_auth_param)
+{
+       int err = 0;
+       struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+       wl_assoc_mgr_cmd_t cmd;
+
+       WL_DBG(("Enter\n"));
+
+       if (!ext_auth_param ||
+               ETHER_ISNULLADDR(ext_auth_param->bssid)) {
+               WL_ERR(("Invalid wl_cfg80211_external_auth param\n"));
+               return -EINVAL;
+       }
+
+       cmd.version = WL_ASSOC_MGR_CURRENT_VERSION;
+       cmd.length = sizeof(cmd);
+       cmd.cmd = WL_ASSOC_MGR_CMD_PAUSE_ON_EVT;
+       cmd.params = WL_ASSOC_MGR_PARAMS_EVENT_NONE;
+       err = wldev_iovar_setbuf(ndev, "assoc_mgr_cmd", (void *)&cmd, sizeof(cmd), cfg->ioctl_buf,
+               WLC_IOCTL_SMLEN, &cfg->ioctl_buf_sync);
+       if (unlikely(err)) {
+               WL_ERR(("Failed to pause assoc(%d)\n", err));
+       }
+
+       return err;
+}
+#endif /* WL_CLIENT_SAE */
+
 #if defined(STATIC_WL_PRIV_STRUCT)
 static int
 wl_init_escan_result_buf(struct bcm_cfg80211 *cfg)
@@ -17173,7 +17794,11 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
                MFREE(dhd->osh, wdev, sizeof(*wdev));
                return -ENOMEM;
        }
+#ifdef WLMESH_CFG80211
+       wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_MESH);
+#else
        wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS);
+#endif
        cfg = wiphy_priv(wdev->wiphy);
        cfg->wdev = wdev;
        cfg->pub = context;
@@ -17224,6 +17849,10 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *context)
                goto cfg80211_attach_out;
 #endif // endif
 
+#ifdef CONFIG_CFG80211_INTERNAL_REGDB
+       wdev->wiphy->reg_notifier = wl_cfg80211_reg_notifier;
+#endif /* CONFIG_CFG80211_INTERNAL_REGDB */
+
 #if defined(WL_ENABLE_P2P_IF)
        err = wl_cfg80211_attach_p2p(cfg);
        if (err)
@@ -17620,6 +18249,11 @@ static s32 wl_config_infra(struct bcm_cfg80211 *cfg, struct net_device *ndev, u1
                        /* Intentional fall through */
                        infra = 1;
                        break;
+#ifdef WLMESH_CFG80211
+       case NL80211_IFTYPE_MESH_POINT:
+               infra = WL_BSSTYPE_MESH;
+               break;
+#endif /* WLMESH_CFG80211 */
                case WL_IF_TYPE_MONITOR:
                case WL_IF_TYPE_NAN:
                        /* Intentionall fall through */
@@ -18528,6 +19162,9 @@ s32 wl_cfg80211_up(struct net_device *net)
                        return err;
                }
        }
+#ifdef WLMESH_CFG80211
+       cfg->wdev->wiphy->features |= NL80211_FEATURE_USERSPACE_MPM;
+#endif /* WLMESH_CFG80211 */
 #if defined(BCMSUP_4WAY_HANDSHAKE)
        if (dhd->fw_4way_handshake) {
                /* This is a hacky method to indicate fw 4WHS support and
@@ -24203,6 +24840,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg,
                                        mutex_lock(&cfg->in4way_sync);
                                        max_wait_cnt--;
                                }
+                               wake_up_interruptible(&dhdp->conf->event_complete);
                        }
                        break;
                case WL_EXT_STATUS_CONNECTING:
@@ -24236,12 +24874,14 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg,
                                        mutex_lock(&cfg->in4way_sync);
                                        max_wait_cnt--;
                                }
+                               wake_up_interruptible(&dhdp->conf->event_complete);
                        }
                        break;
                case WL_EXT_STATUS_CONNECTED:
                        ifidx = dhd_net2idx(dhdp->info, dev);
                        if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_STATION && ifidx >= 0) {
                                dhd_conf_set_wme(cfg->pub, ifidx, 0);
+                               wake_up_interruptible(&dhdp->conf->event_complete);
                        }
                        else if (dev->ieee80211_ptr->iftype == NL80211_IFTYPE_P2P_CLIENT) {
                                dhd_conf_set_mchan_bw(cfg->pub, WL_P2P_IF_CLIENT, -1);
@@ -24270,6 +24910,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg,
                        if (action & WAIT_DISCONNECTED) {
                                cfg->disconnected_jiffies = jiffies;
                        }
+                       wake_up_interruptible(&dhdp->conf->event_complete);
                        break;
                case WL_EXT_STATUS_ADD_KEY:
                        dhdp->conf->eapol_status = EAPOL_STATUS_4WAY_DONE;
@@ -24283,6 +24924,7 @@ wl_cfg80211_check_in4way(struct bcm_cfg80211 *cfg,
                                        cfg->handshaking = 0;
                                }
                        }
+                       wake_up_interruptible(&dhdp->conf->event_complete);
                        break;
                case WL_EXT_STATUS_AP_ENABLED:
                        ifidx = dhd_net2idx(dhdp->info, dev);
index 7c9f86a466eff25d6e13e2ee124b2f5d72fa4877..0aefc1c079de657f9363fde18afbe64e0a17f6c3 100644 (file)
@@ -74,9 +74,24 @@ struct bcm_cfg80211;
 struct wl_security;
 struct wl_ibss;
 
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) && !defined(WL_SAE))
-#define WL_SAE
-#endif // endif
+#if !defined(WL_CLIENT_SAE) && (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0))
+#define WL_CLIENT_SAE
+#endif
+#if defined(WL_SAE) && (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+#error "Can not support WL_SAE befor kernel 3.14"
+#endif
+#if defined(WL_CLIENT_SAE) && (LINUX_VERSION_CODE < KERNEL_VERSION(4, 17, 0))
+#error "Can not support WL_CLIENT_SAE before kernel 4.17"
+#endif
+#if defined(WL_CLIENT_SAE) && defined(WL_SAE)
+#error "WL_SAE is for dongle-offload and WL_CLIENT_SAE is for wpa_supplicant. Please choose one."
+#endif
+
+#if defined(WL_CLIENT_SAE)
+#ifndef WL_ASSOC_MGR_CMD_SEND_AUTH
+#define WL_ASSOC_MGR_CMD_SEND_AUTH 3
+#endif /* WL_ASSOC_MGR_CMD_SEND_AUTH */
+#endif
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 17, 0) && !defined(WL_SCAN_TYPE))
 #define WL_SCAN_TYPE
@@ -382,6 +397,8 @@ do {                                                                        \
 #define WLAN_AKM_SUITE_FT_PSK                  0x000FAC04
 #endif /* WLAN_AKM_SUITE_FT_PSK */
 
+#define WLAN_AKM_SUITE_SAE_SHA256      0x000FAC08
+
 #ifndef WLAN_AKM_SUITE_8021X_SUITE_B
 #define WLAN_AKM_SUITE_8021X_SUITE_B           0x000FAC0B
 #define WLAN_AKM_SUITE_8021X_SUITE_B_192       0x000FAC0C
@@ -507,6 +524,9 @@ enum wl_status {
 typedef enum wl_iftype {
        WL_IF_TYPE_STA = 0,
        WL_IF_TYPE_AP = 1,
+#ifdef WLMESH_CFG80211
+       WL_IF_TYPE_MESH = 2,
+#endif /* WLMESH_CFG80211 */
        WL_IF_TYPE_NAN_NMI = 3,
        WL_IF_TYPE_NAN = 4,
        WL_IF_TYPE_P2P_GO = 5,
@@ -534,6 +554,9 @@ enum wl_mode {
        WL_MODE_IBSS = 1,
        WL_MODE_AP = 2,
        WL_MODE_NAN = 4,
+#ifdef WLMESH_CFG80211
+       WL_MODE_MESH = 5,
+#endif /* WLMESH_CFG80211 */
        WL_MODE_MAX
 };
 
index 988913291fc5c3556c75f449312b0e67d473202e..edcedc67124bf879daa378c906417b50a6d265bd 100644 (file)
@@ -459,7 +459,7 @@ wl_cfgp2p_ifadd(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
        err = wldev_iovar_setbuf(ndev, "p2p_ifadd", &ifreq, sizeof(ifreq),
                cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
        if (unlikely(err < 0)) {
-               printk("'cfg p2p_ifadd' error %d\n", err);
+               CFGP2P_ERR(("'cfg p2p_ifadd' error %d\n", err));
                return err;
        }
 
@@ -482,7 +482,7 @@ wl_cfgp2p_ifdisable(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
        ret = wldev_iovar_setbuf(netdev, "p2p_ifdis", mac, sizeof(*mac),
                cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
        if (unlikely(ret < 0)) {
-               printk("'cfg p2p_ifdis' error %d\n", ret);
+               CFGP2P_ERR(("'cfg p2p_ifdis' error %d\n", ret));
        }
        return ret;
 }
@@ -506,7 +506,7 @@ wl_cfgp2p_ifdel(struct bcm_cfg80211 *cfg, struct ether_addr *mac)
        ret = wldev_iovar_setbuf(netdev, "p2p_ifdel", mac, sizeof(*mac),
                cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
        if (unlikely(ret < 0)) {
-               printk("'cfg p2p_ifdel' error %d\n", ret);
+               CFGP2P_ERR(("'cfg p2p_ifdel' error %d\n", ret));
        }
 #ifdef WL_DISABLE_HE_P2P
        if ((bssidx = wl_get_bssidx_by_wdev(cfg, netdev->ieee80211_ptr)) < 0) {
@@ -551,7 +551,7 @@ wl_cfgp2p_ifchange(struct bcm_cfg80211 *cfg, struct ether_addr *mac, u8 if_type,
        err = wldev_iovar_setbuf(netdev, "p2p_ifupd", &ifreq, sizeof(ifreq),
                cfg->ioctl_buf, WLC_IOCTL_MAXLEN, &cfg->ioctl_buf_sync);
        if (unlikely(err < 0)) {
-               printk("'cfg p2p_ifupd' error %d\n", err);
+               CFGP2P_ERR(("'cfg p2p_ifupd' error %d\n", err));
        } else if (if_type == WL_P2P_IF_GO) {
                cfg->p2p->p2p_go_count++;
        }
@@ -2403,7 +2403,7 @@ wl_cfgp2p_register_ndev(struct bcm_cfg80211 *cfg)
        cfg->p2p_wdev = wdev;
        cfg->p2p_net = net;
 
-       printk("%s: P2P Interface Registered\n", net->name);
+       WL_MSG(net->name, "P2P Interface Registered\n");
 
        return ret;
 }
index 128ab5bcf7792f95ad75854728f76466de91acd7..f4186ae6fbc2bfddc3e221578794c2f93328f62c 100644 (file)
@@ -134,70 +134,67 @@ enum wl_cfgp2p_status {
 /* dword align allocation */
 #define WLC_IOCTL_MAXLEN 8192
 
-#define CFGP2P_ERROR_TEXT              "CFGP2P-ERROR) "
+#define CFGP2P_ERROR_TEXT              "[dhd] CFGP2P-ERROR) "
 
 #ifdef DHD_LOG_DUMP
-#define CFGP2P_ERR(args)                                                                       \
-       do {                                                                            \
-               if (wl_dbg_level & WL_DBG_ERR) {                                \
-                       printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__);  \
-                       printk args;                                            \
-                       DHD_LOG_DUMP_WRITE("[%s] %s: ", \
-                       dhd_log_dump_get_timestamp(), __func__);        \
-                       DHD_LOG_DUMP_WRITE args;        \
-               }                                                                       \
+#define        CFGP2P_ERR_MSG(x, args...)      \
+       do {    \
+               if (wl_dbg_level & WL_DBG_ERR) {        \
+                       printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : " x, __func__, ## args);       \
+                       DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);        \
+                       DHD_LOG_DUMP_WRITE(x, ## args); \
+               }       \
        } while (0)
-#define        CFGP2P_INFO(args)                                                                       \
+#define CFGP2P_ERR(x) CFGP2P_ERR_MSG x
+#define        CFGP2P_INFO_MSG(x, args...)                                                                     \
        do {                                                                            \
                if (wl_dbg_level & WL_DBG_INFO) {                               \
-                       printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__);       \
-                       printk args;                                            \
-                       DHD_LOG_DUMP_WRITE("[%s] %s: ", \
-                       dhd_log_dump_get_timestamp(), __func__);        \
-                       DHD_LOG_DUMP_WRITE args;        \
+                       printk(KERN_INFO "[dhd] CFGP2P-INFO) %s : " x, __func__, ## args);      \
+                       DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);        \
+                       DHD_LOG_DUMP_WRITE(x, ## args); \
                }                                                                       \
        } while (0)
-#define        CFGP2P_ACTION(args)                                                             \
+#define CFGP2P_INFO(x) CFGP2P_INFO_MSG x
+#define        CFGP2P_ACTION_MSG(x, args...)                                                           \
        do {                                                                    \
                if (wl_dbg_level & WL_DBG_P2P_ACTION) {                 \
-                       printk(KERN_DEBUG "CFGP2P-ACTION) %s :", __func__);     \
-                       printk args;                                                    \
-                       DHD_LOG_DUMP_WRITE("[%s] %s: ", \
-                       dhd_log_dump_get_timestamp(), __func__);        \
-                       DHD_LOG_DUMP_WRITE args;        \
+                       printk(KERN_INFO "[dhd] CFGP2P-ACTION) %s :" x, __func__, ## args);     \
+                       DHD_LOG_DUMP_WRITE("[%s] %s: ", dhd_log_dump_get_timestamp(), __func__);        \
+                       DHD_LOG_DUMP_WRITE(x, ## args); \
                }                                                                       \
        } while (0)
+#define CFGP2P_ACTION(x) CFGP2P_ACTION_MSG x
 #else
-#define CFGP2P_ERR(args)                                                                       \
+#define CFGP2P_ERR_MSG(x, args...)                                                                     \
        do {                                                                            \
                if (wl_dbg_level & WL_DBG_ERR) {                                \
-                       printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__);  \
-                       printk args;                                            \
+                       printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : " x, __func__, ## args);       \
                }                                                                       \
        } while (0)
-#define        CFGP2P_INFO(args)                                                                       \
+#define CFGP2P_ERR(x) CFGP2P_ERR_MSG x
+#define        CFGP2P_INFO_MSG(x, args...)                                                                     \
        do {                                                                            \
                if (wl_dbg_level & WL_DBG_INFO) {                               \
-                       printk(KERN_INFO "CFGP2P-INFO) %s : ", __func__);       \
-                       printk args;                                            \
+                       printk(KERN_INFO "[dhd] CFGP2P-INFO) %s : " x, __func__, ## args);      \
                }                                                                       \
        } while (0)
-#define        CFGP2P_ACTION(args)                                                             \
+#define CFGP2P_INFO(x) CFGP2P_INFO_MSG x
+#define        CFGP2P_ACTION_MSG(x, args...)                                                           \
        do {                                                                    \
                if (wl_dbg_level & WL_DBG_P2P_ACTION) {                 \
-                       printk(KERN_INFO "CFGP2P-ACTION) %s :", __func__);      \
-                       printk args;                                                    \
+                       printk(KERN_INFO "[dhd] CFGP2P-ACTION) %s :" x, __func__, ## args);     \
                }                                                                       \
        } while (0)
+#define CFGP2P_ACTION(x) CFGP2P_ACTION_MSG x
 #endif /* DHD_LOG_DUMP */
 
-#define        CFGP2P_DBG(args)                                                                \
+#define        CFGP2P_DBG_MSG(x, args...)                                                              \
        do {                                                                    \
                if (wl_dbg_level & WL_DBG_DBG) {                        \
-                       printk(KERN_INFO "CFGP2P-DEBUG) %s :", __func__);       \
-                       printk args;                                                    \
+                       printk(KERN_INFO "[dhd] CFGP2P-DEBUG) %s :" x, __func__, ## args);      \
                }                                                                       \
        } while (0)
+#define CFGP2P_DBG(x) CFGP2P_DBG_MSG x
 
 #define INIT_TIMER(timer, func, duration, extra_delay) \
        do {                               \
index dcaebe5d10b1df4b9dc2f45bb88de79ee1a5398b..7ab8712a22c4d8f28be3993cea9720c22205ff57 100644 (file)
@@ -1890,7 +1890,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                         return -ENODEV;
                }
        }
-       err = wl_cfg80211_check_in4way(cfg, ndev, NO_SCAN_IN4WAY,
+       err = wl_cfg80211_check_in4way(cfg, ndev_to_wlc_ndev(ndev, cfg), NO_SCAN_IN4WAY,
                WL_EXT_STATUS_SCAN, NULL);
        if (err)
                return err;
@@ -2068,7 +2068,7 @@ s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
 #if defined(ESCAN_RESULT_PATCH)
        if (likely(cfg->scan_request)) {
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
-               if (aborted && p2p_scan(cfg) &&
+               if (aborted && cfg->p2p && p2p_scan(cfg) &&
                        (cfg->scan_request->flags & NL80211_SCAN_FLAG_FLUSH)) {
                        WL_ERR(("scan list is changed"));
                        cfg->bss_list = wl_escan_get_buf(cfg, !aborted);
@@ -2106,6 +2106,7 @@ s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
        if (p2p_is_on(cfg))
                wl_clr_p2p_status(cfg, SCANNING);
        wl_clr_drv_status(cfg, SCANNING, dev);
+       wake_up_interruptible(&dhdp->conf->event_complete);
 
        DHD_OS_SCAN_WAKE_UNLOCK((dhd_pub_t *)(cfg->pub));
        DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)(cfg->pub));
@@ -2730,12 +2731,12 @@ static void wl_scan_timeout(unsigned long data)
                dhdp->memdump_type = DUMP_TYPE_SCAN_TIMEOUT;
                dhd_bus_mem_dump(dhdp);
        }
+#endif /* DHD_FW_COREDUMP */
        /*
         * For the memdump sanity, blocking bus transactions for a while
         * Keeping it TRUE causes the sequential private cmd error
         */
        dhdp->scan_timeout_occurred = FALSE;
-#endif /* DHD_FW_COREDUMP */
        msg.event_type = hton32(WLC_E_ESCAN_RESULT);
        msg.status = hton32(WLC_E_STATUS_TIMEOUT);
        msg.reason = 0xFFFFFFFF;
index 1cafa0696ba36826192796e06a5a447cdba26cb9..157bb80ae7c6b800b2ed2a5a9fc834faa10676ff 100644 (file)
@@ -6685,6 +6685,14 @@ wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy,
                }
        }
        if (buf_len > 0 && user_buf) {
+#if 0
+               mem_buf = vmalloc(buf_len);
+               if (!mem_buf) {
+                       WL_ERR(("failed to allocate mem_buf with size : %d\n", buf_len));
+                       ret = BCME_NOMEM;
+                       goto exit;
+               }
+#endif
                ret = dhd_os_get_socram_dump(bcmcfg_to_prmry_ndev(cfg), &mem_buf, &buf_len);
                if (ret) {
                        WL_ERR(("failed to get_socram_dump : %d\n", ret));
@@ -6736,6 +6744,7 @@ wl_cfgvendor_dbg_get_mem_dump(struct wiphy *wiphy,
        }
 
 free_mem:
+//     vfree(mem_buf);
        /* Free skb memory */
        if (skb) {
                kfree_skb(skb);
@@ -7803,6 +7812,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = BRCM_VENDOR_SCMD_PRIV_STR
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_priv_string_handler
        },
 #ifdef BCM_PRIV_CMD_SUPPORT
@@ -7812,6 +7824,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = BRCM_VENDOR_SCMD_BCM_STR
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_priv_bcm_handler
        },
 #endif /* BCM_PRIV_CMD_SUPPORT */
@@ -7822,6 +7837,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = BRCM_VENDOR_SCMD_BCM_PSK
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_sae_password
        },
 #endif /* WL_SAE */
@@ -7832,6 +7850,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_GET_CAPABILITIES
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_gscan_get_capabilities
        },
        {
@@ -7840,6 +7861,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_SET_CONFIG
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_scan_cfg
        },
        {
@@ -7848,6 +7872,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_SET_SCAN_CONFIG
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_batch_scan_cfg
        },
        {
@@ -7856,6 +7883,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_ENABLE_GSCAN
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_initiate_gscan
        },
        {
@@ -7864,6 +7894,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_ENABLE_FULL_SCAN_RESULTS
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_enable_full_scan_result
        },
        {
@@ -7872,6 +7905,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_SET_HOTLIST
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_hotlist_cfg
        },
        {
@@ -7880,6 +7916,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_GET_SCAN_RESULTS
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_gscan_get_batch_results
        },
 #endif /* GSCAN_SUPPORT */
@@ -7890,6 +7929,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_GET_CHANNEL_LIST
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_gscan_get_channel_list
        },
 #endif /* GSCAN_SUPPORT || DHD_GET_VALID_CHANNELS */
@@ -7900,6 +7942,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = RTT_SUBCMD_SET_CONFIG
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_rtt_set_config
        },
        {
@@ -7908,6 +7953,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = RTT_SUBCMD_CANCEL_CONFIG
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_rtt_cancel_config
        },
        {
@@ -7916,6 +7964,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = RTT_SUBCMD_GETCAPABILITY
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_rtt_get_capability
        },
        {
@@ -7924,6 +7975,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = RTT_SUBCMD_GETAVAILCHANNEL
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_rtt_get_responder_info
        },
        {
@@ -7932,6 +7986,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = RTT_SUBCMD_SET_RESPONDER
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_rtt_set_responder
        },
        {
@@ -7940,6 +7997,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = RTT_SUBCMD_CANCEL_RESPONDER
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_rtt_cancel_responder
        },
 #endif /* RTT_SUPPORT */
@@ -7949,6 +8009,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_get_feature_set
        },
        {
@@ -7957,6 +8020,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = ANDR_WIFI_SUBCMD_GET_FEATURE_SET_MATRIX
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_get_feature_set_matrix
        },
        {
@@ -7965,6 +8031,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = ANDR_WIFI_RANDOM_MAC_OUI
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_rand_mac_oui
        },
 #ifdef CUSTOM_FORCE_NODFS_FLAG
@@ -7974,6 +8043,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = ANDR_WIFI_NODFS_CHANNELS
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_nodfs_flag
        },
 #endif /* CUSTOM_FORCE_NODFS_FLAG */
@@ -7983,6 +8055,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = ANDR_WIFI_SET_COUNTRY
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_country
        },
 #ifdef LINKSTAT_SUPPORT
@@ -7992,6 +8067,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = LSTATS_SUBCMD_GET_INFO
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_lstats_get_info
        },
 #endif /* LINKSTAT_SUPPORT */
@@ -8003,6 +8081,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = GSCAN_SUBCMD_SET_EPNO_SSID
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_epno_cfg
 
        },
@@ -8012,6 +8093,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_SET_LAZY_ROAM_PARAMS
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_lazy_roam_cfg
 
        },
@@ -8021,6 +8105,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_ENABLE_LAZY_ROAM
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_enable_lazy_roam
 
        },
@@ -8030,6 +8117,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_SET_BSSID_PREF
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_bssid_pref
 
        },
@@ -8041,6 +8131,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_SET_SSID_WHITELIST
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_ssid_whitelist
 
        },
@@ -8050,6 +8143,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_SET_BSSID_BLACKLIST
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_bssid_blacklist
        },
 #endif /* GSCAN_SUPPORT || ROAMEXP_SUPPORT */
@@ -8060,6 +8156,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_FW_ROAM_POLICY
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_fw_roaming_state
        },
        {
@@ -8068,6 +8167,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_ROAM_CAPABILITY
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_fw_roam_get_capability
        },
 #endif /* ROAMEXP_SUPPORT */
@@ -8077,6 +8179,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_VER
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_version
        },
 #ifdef DHD_LOG_DUMP
@@ -8086,6 +8191,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_FILE_DUMP_BUF
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_file_dump
        },
 #endif /* DHD_LOG_DUMP */
@@ -8097,6 +8205,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_TRIGGER_MEM_DUMP
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_trigger_mem_dump
        },
        {
@@ -8105,6 +8216,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_MEM_DUMP
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_mem_dump
        },
        {
@@ -8113,6 +8227,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_START_LOGGING
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_start_logging
        },
        {
@@ -8121,6 +8238,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_RESET_LOGGING
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_reset_logging
        },
        {
@@ -8129,6 +8249,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_RING_STATUS
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_ring_status
        },
        {
@@ -8137,6 +8260,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_RING_DATA
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_ring_data
        },
 #endif /* DEBUGABILITY */
@@ -8146,6 +8272,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_FEATURE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_feature
        },
 #ifdef DBG_PKT_MON
@@ -8155,6 +8284,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_START_PKT_FATE_MONITORING
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_start_pkt_fate_monitoring
        },
        {
@@ -8163,6 +8295,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_TX_PKT_FATES
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_tx_pkt_fates
        },
        {
@@ -8171,6 +8306,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_RX_PKT_FATES
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_dbg_get_rx_pkt_fates
        },
 #endif /* DBG_PKT_MON */
@@ -8181,6 +8319,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_OFFLOAD_SUBCMD_START_MKEEP_ALIVE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_start_mkeep_alive
        },
        {
@@ -8189,6 +8330,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_OFFLOAD_SUBCMD_STOP_MKEEP_ALIVE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_stop_mkeep_alive
        },
 #endif /* KEEP_ALIVE */
@@ -8199,6 +8343,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_ENABLE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_start_handler
        },
        {
@@ -8207,6 +8354,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DISABLE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_stop_handler
        },
        {
@@ -8215,6 +8365,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_CONFIG
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_config_handler
        },
        {
@@ -8223,6 +8376,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_REQUEST_PUBLISH
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_req_publish
        },
        {
@@ -8231,6 +8387,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_REQUEST_SUBSCRIBE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_req_subscribe
        },
        {
@@ -8239,6 +8398,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_CANCEL_PUBLISH
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_cancel_publish
        },
        {
@@ -8247,6 +8409,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_CANCEL_SUBSCRIBE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_cancel_subscribe
        },
        {
@@ -8255,6 +8420,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_TRANSMIT
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_transmit
        },
        {
@@ -8263,6 +8431,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_GET_CAPABILITIES
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_get_capablities
        },
 
@@ -8272,6 +8443,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_CREATE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_data_path_iface_create
        },
        {
@@ -8280,6 +8454,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_IFACE_DELETE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_data_path_iface_delete
        },
        {
@@ -8288,6 +8465,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_REQUEST
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_data_path_request
        },
        {
@@ -8296,6 +8476,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_RESPONSE
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_data_path_response
        },
        {
@@ -8304,6 +8487,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_END
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_data_path_end
        },
 #ifdef WL_NAN_DISC_CACHE
@@ -8313,6 +8499,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_DATA_PATH_SEC_INFO
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_data_path_sec_info
        },
 #endif /* WL_NAN_DISC_CACHE */
@@ -8322,6 +8511,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = NAN_WIFI_SUBCMD_VERSION_INFO
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_nan_version_info
        },
 #endif /* WL_NAN */
@@ -8332,6 +8524,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = APF_SUBCMD_GET_CAPABILITIES
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_apf_get_capabilities
        },
 
@@ -8341,6 +8536,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = APF_SUBCMD_SET_FILTER
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_apf_set_filter
        },
 #endif /* PKT_FILTER_SUPPORT && APF */
@@ -8351,6 +8549,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_CONFIG_ND_OFFLOAD
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_configure_nd_offload
        },
 #endif /* NDO_CONFIG_SUPPORT */
@@ -8361,6 +8562,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_SET_RSSI_MONITOR
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_rssi_monitor
        },
 #endif /* RSSI_MONITOR_SUPPORT */
@@ -8371,6 +8575,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_GET_WAKE_REASON_STATS
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_get_wake_reason_stats
        },
 #endif /* DHD_WAKE_STATUS */
@@ -8381,6 +8588,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = WIFI_SUBCMD_CONFIG_TCPACK_SUP
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_tcpack_sup_mode
        },
 #endif /* DHDTCPACK_SUPPRESS */
@@ -8391,6 +8601,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = BRCM_VENDOR_SCMD_SET_PMK
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_pmk
        },
 #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(4, 13, 0) */
@@ -8400,6 +8613,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = BRCM_VENDOR_SCMD_GET_FEATURES
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_get_driver_feature
        },
 #if defined(WL_CFG80211) && defined(DHD_FILE_DUMP_EVENT)
@@ -8409,6 +8625,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_FILE_DUMP_DONE_IND
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_notify_dump_completion
        },
 #endif /* WL_CFG80211 && DHD_FILE_DUMP_EVENT */
@@ -8419,6 +8638,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_SET_HAL_START
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_set_hal_started
        },
        {
@@ -8427,6 +8649,9 @@ static const struct wiphy_vendor_command wl_vendor_cmds [] = {
                        .subcmd = DEBUG_SET_HAL_STOP
                },
                .flags = WIPHY_VENDOR_CMD_NEED_WDEV | WIPHY_VENDOR_CMD_NEED_NETDEV,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 3, 0))
+               .policy = VENDOR_CMD_RAW_DATA,
+#endif
                .doit = wl_cfgvendor_stop_hal
        }
 #endif /* WL_CFG80211 */
index 82d5c5b1f45a366878828aba6218bfa3638a4a7f..2775379c7db3e6fb511b85e7e14468430e190c3a 100644 (file)
 #define ESCAN_TRACE(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_TRACE_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] ESCAN-TRACE) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 #define ESCAN_SCAN(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_SCAN_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] ESCAN-SCAN) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 #define ESCAN_DBG(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_DBG_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] ESCAN-DBG) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 
@@ -181,7 +181,7 @@ wl_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec)
  * Returns INVCHANSPEC on error
  */
 static chanspec_t
-wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel)
+wl_ch_host_to_driver(int ioctl_ver, u16 channel)
 {
        chanspec_t chanspec;
 
@@ -206,6 +206,7 @@ static inline struct wl_bss_info *next_bss(struct wl_scan_results *list,
                (struct wl_bss_info *)((uintptr) bss + dtoh32(bss->length)) : list->bss_info;
 }
 
+#if defined(ESCAN_RESULT_PATCH)
 static s32
 wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan)
 {
@@ -253,7 +254,7 @@ wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan)
        wl_reset_bss_cache(&escan->g_bss_cache_ctrl);
        if (escan->autochannel)
                wl_ext_get_best_channel(dev, &escan->g_bss_cache_ctrl,
-                       escan->ioctl_ver &escan->best_2g_ch, &escan->best_5g_ch);
+                       escan->ioctl_ver, &escan->best_2g_ch, &escan->best_5g_ch);
 #else
        if (escan->autochannel)
                wl_ext_get_best_channel(dev, bss_list, escan->ioctl_ver,
@@ -262,6 +263,7 @@ wl_escan_inform_bss(struct net_device *dev, struct wl_escan_info *escan)
 
        return err;
 }
+#endif /* ESCAN_RESULT_PATCH */
 
 static wl_scan_params_t *
 wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan,
@@ -270,7 +272,6 @@ wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan,
        wl_scan_params_t *params;
        int params_size;
        int num_chans;
-       int bssidx = 0;
 
        *out_params_size = 0;
 
@@ -296,7 +297,7 @@ wl_escan_alloc_params(struct net_device *dev, struct wl_escan_info *escan,
        if (channel == -1)
                params->channel_list[0] = htodchanspec(channel);
        else
-               params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, bssidx, channel);
+               params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, channel);
 
        /* Our scan params have 1 channel and 0 ssids */
        params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
@@ -341,6 +342,7 @@ wl_escan_notify_complete(struct net_device *dev,
        char extra[IW_CUSTOM_MAX + 1];
 #endif
 #endif
+       struct dhd_pub *dhd = dhd_get_pub(dev);
 
        ESCAN_TRACE(dev->name, "Enter\n");
 
@@ -349,11 +351,15 @@ wl_escan_notify_complete(struct net_device *dev,
 
        if (timer_pending(&escan->scan_timeout))
                del_timer_sync(&escan->scan_timeout);
+
 #if defined(ESCAN_RESULT_PATCH)
        escan->bss_list = wl_escan_get_buf(escan);
        wl_escan_inform_bss(dev, escan);
 #endif /* ESCAN_RESULT_PATCH */
 
+       escan->escan_state = ESCAN_STATE_IDLE;
+       wake_up_interruptible(&dhd->conf->event_complete);
+
 #if defined(WL_WIRELESS_EXT)
 #if WIRELESS_EXT > 13
 #if WIRELESS_EXT > 14
@@ -433,8 +439,8 @@ wl_escan_remove_lowRSSI_info(struct net_device *dev, struct wl_escan_info *escan
 }
 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
 
-s32
-wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan,
+static s32
+wl_escan_handler(struct net_device *dev, struct wl_escan_info *escan,
        const wl_event_msg_t *e, void *data)
 {
        s32 err = BCME_OK;
@@ -618,9 +624,7 @@ wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan,
                escan->bss_list = wl_escan_get_buf(escan);
                ESCAN_DBG(dev->name, "SCAN COMPLETED: scanned AP count=%d\n",
                        escan->bss_list->count);
-               wl_escan_inform_bss(dev, escan);
                wl_escan_notify_complete(dev, escan, false);
-               escan->escan_state = ESCAN_STATE_IDLE;
        } else if ((status == WLC_E_STATUS_ABORT) || (status == WLC_E_STATUS_NEWSCAN) ||
                (status == WLC_E_STATUS_11HQUIET) || (status == WLC_E_STATUS_CS_ABORT) ||
                (status == WLC_E_STATUS_NEWASSOC)) {
@@ -629,24 +633,19 @@ wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan,
                escan->bss_list = wl_escan_get_buf(escan);
                ESCAN_DBG(dev->name, "SCAN ABORT: scanned AP count=%d\n",
                        escan->bss_list->count);
-               wl_escan_inform_bss(dev, escan);
                wl_escan_notify_complete(dev, escan, false);
-               escan->escan_state = ESCAN_STATE_IDLE;
        } else if (status == WLC_E_STATUS_TIMEOUT) {
                ESCAN_ERROR(dev->name, "WLC_E_STATUS_TIMEOUT\n");
                ESCAN_ERROR(dev->name, "reason[0x%x]\n", e->reason);
                if (e->reason == 0xFFFFFFFF) {
                        wl_escan_notify_complete(dev, escan, true);
                }
-               escan->escan_state = ESCAN_STATE_IDLE;
        } else {
                ESCAN_ERROR(dev->name, "unexpected Escan Event %d : abort\n", status);
                escan->bss_list = wl_escan_get_buf(escan);
                ESCAN_DBG(dev->name, "SCAN ABORTED(UNEXPECTED): scanned AP count=%d\n",
                        escan->bss_list->count);
-               wl_escan_inform_bss(dev, escan);
                wl_escan_notify_complete(dev, escan, false);
-               escan->escan_state = ESCAN_STATE_IDLE;
        }
 exit:
        mutex_unlock(&escan->usr_sync);
@@ -801,6 +800,7 @@ wl_escan_timeout(unsigned long data)
        bzero(&msg, sizeof(wl_event_msg_t));
        ESCAN_ERROR(escan->dev->name, "timer expired\n");
 
+       msg.ifidx = dhd_net2idx(escan->pub->info, escan->dev);
        msg.event_type = hton32(WLC_E_ESCAN_RESULT);
        msg.status = hton32(WLC_E_STATUS_TIMEOUT);
        msg.reason = 0xFFFFFFFF;
@@ -809,7 +809,7 @@ wl_escan_timeout(unsigned long data)
 
 int
 wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,
-       wlc_ssid_t *ssid, bool bcast)
+       wlc_ssid_t *ssid, uint16 channel, bool bcast)
 {
        struct wl_escan_info *escan = dhdp->escan;
        s32 err = BCME_OK;
@@ -824,11 +824,12 @@ wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,
        mutex_lock(&escan->usr_sync);
        if (escan->escan_state == ESCAN_STATE_DOWN) {
                ESCAN_ERROR(dev->name, "STATE is down\n");
-               err = -EIO;
+               err = -EINVAL;
                goto exit2;
        }
-       if (escan->escan_state == ESCAN_STATE_SCANING) {
-               ESCAN_ERROR(dev->name, "Scanning already\n");
+
+       if (wl_ext_check_scan(dev, dhdp)) {
+               err = -EBUSY;
                goto exit;
        }
 
@@ -837,13 +838,20 @@ wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,
        /* if scan request is not empty parse scan request paramters */
        memset(valid_chan_list, 0, sizeof(valid_chan_list));
        list = (wl_uint32_list_t *)(void *) valid_chan_list;
-       list->count = htod32(WL_NUMCHANNELS);
-       err = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
-               sizeof(valid_chan_list), false);
-       if (err != 0) {
-               ESCAN_ERROR(dev->name, "get channels failed with %d\n", err);
-               goto exit;
+
+       if (channel) {
+               list->count = htod32(1);
+               list->element[0] = htod32(channel);
+       } else {
+               list->count = htod32(WL_NUMCHANNELS);
+               err = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+                       sizeof(valid_chan_list), false);
+               if (err != 0) {
+                       ESCAN_ERROR(dev->name, "get channels failed with %d\n", err);
+                       goto exit;
+               }
        }
+
        n_channels = dtoh32(list->count);
        /* Allocate space for populating ssids in wl_escan_params_t struct */
        if (dtoh32(list->count) % 2)
@@ -883,14 +891,12 @@ wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,
                        ESCAN_TRACE(dev->name, "Escan not permitted at this time (%d)\n", err);
                else
                        ESCAN_ERROR(dev->name, "Escan set error (%d)\n", err);
-               wl_escan_reset(escan);
        }
        kfree(params);
 
-exit:
        if (unlikely(err)) {
                /* Don't print Error incase of Scan suppress */
-               if ((err == BCME_EPERM))
+               if (err == BCME_EPERM)
                        ESCAN_TRACE(dev->name, "Escan failed: Scan Suppressed\n");
                else {
                        cnt++;
@@ -907,6 +913,10 @@ exit:
                cnt = 0;
                escan->dev = dev;
        }
+exit:
+       if (unlikely(err)) {
+               wl_escan_reset(escan);
+       }
 exit2:
        mutex_unlock(&escan->usr_sync);
        return err;
@@ -940,6 +950,7 @@ wl_escan_merge_scan_results(struct net_device *dev, struct wl_escan_info *escan,
        char *event = extra, *end = extra + max_size - WE_ADD_EVENT_FIX, *value;
        int16 rssi;
        int channel;
+       chanspec_t chanspec;
 
        /* overflow check cover fields before wpa IEs */
        if (event + ETHER_ADDR_LEN + bi->SSID_len + IW_EV_UINT_LEN + IW_EV_FREQ_LEN +
@@ -956,9 +967,14 @@ wl_escan_merge_scan_results(struct net_device *dev, struct wl_escan_info *escan,
        // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
        rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
 #endif
-       channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
-       ESCAN_SCAN(dev->name, "BSSID=%pM, channel=%3d, RSSI=%3d, SSID=\"%s\"\n",
-               &bi->BSSID, channel, rssi, bi->SSID);
+       chanspec = wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec);
+       channel = wf_chspec_ctlchan(chanspec);
+       ESCAN_SCAN(dev->name, "BSSID %pM, channel %3d(%3d %sMHz), rssi %3d, SSID \"%s\"\n",
+               &bi->BSSID, channel, CHSPEC_CHANNEL(chanspec),
+               CHSPEC_IS20(chanspec)?"20":
+               CHSPEC_IS40(chanspec)?"40":
+               CHSPEC_IS80(chanspec)?"80":"160",
+               rssi, bi->SSID);
 
        /* First entry must be the BSSID */
        iwe.cmd = SIOCGIWAP;
@@ -1055,6 +1071,7 @@ wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp,
 #endif
        char *buf = NULL;
        struct ether_addr cur_bssid;
+       u8 ioctl_buf[WLC_IOCTL_SMLEN];
 
        if (!extra) {
                ESCAN_TRACE(dev->name, "extra is null\n");
@@ -1082,8 +1099,11 @@ wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp,
 
        ESCAN_SCAN(dev->name, "SIOCGIWSCAN, len=%d\n", dwrq->length);
 
+       wldev_iovar_getbuf(dev, "cur_etheraddr", NULL, 0, ioctl_buf, WLC_IOCTL_SMLEN, NULL);
        err = wldev_ioctl(dev, WLC_GET_BSSID, &cur_bssid, sizeof(cur_bssid), false);
-       if (err != BCME_NOTASSOCIATED && memcmp(&ether_null, &cur_bssid, ETHER_ADDR_LEN)) {
+       if (err != BCME_NOTASSOCIATED &&
+                       memcmp(&ether_null, &cur_bssid, ETHER_ADDR_LEN) &&
+                       memcmp(ioctl_buf, &cur_bssid, ETHER_ADDR_LEN)) {
                // merge current connected bss
                buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_ATOMIC);
                if (!buf) {
@@ -1149,7 +1169,248 @@ exit:
        mutex_unlock(&escan->usr_sync);
        return err;
 }
-#endif
+#endif /* WL_WIRELESS_EXT */
+
+#ifdef WLMESH
+bool
+wl_escan_meshid_ie(u8 *parse, u32 len, wlc_ssid_t *mesh_id)
+{
+       bcm_tlv_t *ie;
+
+       if((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_MESH_ID)) != NULL) {
+               mesh_id->SSID_len = ie->len;
+               if (ie->len) {
+                       strncpy(mesh_id->SSID, ie->data, ie->len);
+               }
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool
+wl_escan_rsn_ie(u8 *parse, u32 len)
+{
+       if (bcm_parse_tlvs(parse, (u32)len, DOT11_MNG_RSN_ID)) {
+               return TRUE;
+       }
+       return FALSE;
+}
+
+bool
+wl_escan_mesh_info_ie(struct net_device *dev, u8 *parse, u32 len,
+       struct wl_mesh_params *mesh_info)
+{
+       bcm_tlv_t *ie;
+       uchar mesh_oui[]={0x00, 0x22, 0xf4};
+       int totl_len;
+       uint8 *pie;
+       uint max_len;
+       bool found = FALSE;
+
+       memset(mesh_info, 0, sizeof(struct wl_mesh_params));
+       if((ie = bcm_parse_tlvs(parse, (int)len, DOT11_MNG_VS_ID)) != NULL) {
+               totl_len = ie->len;
+               if (!memcmp(ie->data, &mesh_oui, sizeof(mesh_oui))) {
+                       pie = ie->data + sizeof(mesh_oui);
+                       ie = (bcm_tlv_t *)pie;
+                       totl_len -= sizeof(mesh_oui);
+                       while (totl_len > 2 && ie->len) {
+                               if (ie->id == MESH_INFO_MASTER_BSSID && ie->len == ETHER_ADDR_LEN) {
+                                       memcpy(&mesh_info->master_bssid, ie->data, ETHER_ADDR_LEN);
+                               } else if (ie->id == MESH_INFO_MASTER_CHANNEL) {
+                                       mesh_info->master_channel = ie->data[0];
+                                       found = TRUE;
+                               } else if (ie->id == MESH_INFO_HOP_CNT) {
+                                       mesh_info->hop_cnt = ie->data[0];
+                               } else if (ie->id == MESH_INFO_PEER_BSSID) {
+                                       max_len = min(MAX_HOP_LIST*ETHER_ADDR_LEN, (int)ie->len);
+                                       memcpy(mesh_info->peer_bssid, ie->data, max_len);
+                               }
+                               totl_len -= (ie->len + 2);
+                               pie = ie->data + ie->len;
+                               ie = (bcm_tlv_t *)pie;
+                       }
+               }
+       }
+
+       return found;
+}
+
+bool
+wl_escan_mesh_info(struct net_device *dev, struct wl_escan_info *escan, 
+       struct ether_addr *peer_bssid, struct wl_mesh_params *mesh_info)
+{
+       int i = 0;
+       wl_bss_info_t *bi = NULL;
+       struct wl_scan_results *bss_list;
+       int16 bi_rssi, bi_chan;
+       wlc_ssid_t bi_meshid;
+       bool is_mesh_peer = FALSE, found = FALSE;
+       struct wl_mesh_params peer_mesh_info;
+
+       mutex_lock(&escan->usr_sync);
+
+       /* Check for scan in progress */
+       if (escan->escan_state == ESCAN_STATE_SCANING) {
+               ESCAN_ERROR(dev->name, "SIOCGIWSCAN GET still scanning\n");
+               goto exit;
+       }
+       if (!escan->bss_list) {
+               ESCAN_ERROR(dev->name, "scan not ready\n");
+               goto exit;
+       }
+       if (dev != escan->dev) {
+               ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name);
+               goto exit;
+       }
+
+       bss_list = escan->bss_list;
+       bi = next_bss(bss_list, bi);
+       ESCAN_SCAN(dev->name, "scanned AP/Mesh count (%d)\n", bss_list->count);
+       for_each_bss(bss_list, bi, i)
+       {
+               memset(&bi_meshid, 0, sizeof(bi_meshid));
+               is_mesh_peer = FALSE;
+               bi_chan = wf_chspec_ctlchan(
+                       wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
+               bi_rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
+               is_mesh_peer = wl_escan_meshid_ie(((u8*)bi)+bi->ie_offset,
+                       bi->ie_length, &bi_meshid);
+               if (!(bi->capability & (DOT11_CAP_ESS|DOT11_CAP_IBSS)) && is_mesh_peer) {
+                       bool bi_sae = FALSE, bss_found = FALSE, prefer = FALSE;
+                       if (!memcmp(peer_bssid, &bi->BSSID, ETHER_ADDR_LEN)) {
+                               bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length);
+                               bss_found = wl_escan_mesh_info_ie(dev, ((u8*)bi)+bi->ie_offset,
+                                       bi->ie_length, &peer_mesh_info);
+                               if (bss_found) {
+                                       memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+                                               ETHER_ADDR_LEN);
+                                       mesh_info->master_channel = peer_mesh_info.master_channel;
+                                       mesh_info->hop_cnt = peer_mesh_info.hop_cnt;
+                                       memcpy(mesh_info->peer_bssid, peer_mesh_info.peer_bssid,
+                                               sizeof(peer_mesh_info.peer_bssid));
+                                       prefer = TRUE;
+                                       found = TRUE;
+                               }
+                       }
+                       ESCAN_SCAN(dev->name,
+                               "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, "
+                               "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n",
+                               prefer?"*":" ", &bi->BSSID, bi_chan, bi_rssi, bi_sae?"SAE":"OPEN",
+                               &peer_mesh_info.master_bssid, peer_mesh_info.master_channel,
+                               peer_mesh_info.hop_cnt, &peer_mesh_info.peer_bssid, bi_meshid.SSID);
+               }
+       }
+
+exit:
+       mutex_unlock(&escan->usr_sync);
+       return found;
+}
+
+bool
+wl_escan_mesh_peer(struct net_device *dev, struct wl_escan_info *escan, 
+       wlc_ssid_t *cur_ssid, uint16 cur_chan, bool sae,
+       struct wl_mesh_params *mesh_info)
+{
+       int i = 0;
+       wl_bss_info_t *bi = NULL;
+       struct wl_scan_results *bss_list;
+       int16 bi_rssi, bi_chan, max_rssi = -100;
+       uint min_hop_cnt = 255;
+       wlc_ssid_t bi_meshid;
+       bool is_mesh_peer = FALSE, chan_matched = FALSE, found = FALSE;
+       struct wl_mesh_params peer_mesh_info;
+
+       mutex_lock(&escan->usr_sync);
+
+       /* Check for scan in progress */
+       if (escan->escan_state == ESCAN_STATE_SCANING) {
+               ESCAN_ERROR(dev->name, "SIOCGIWSCAN GET still scanning\n");
+               goto exit;
+       }
+       if (!escan->bss_list) {
+               ESCAN_ERROR(dev->name, "scan not ready\n");
+               goto exit;
+       }
+       if (dev != escan->dev) {
+               ESCAN_ERROR(dev->name, "not my scan from %s\n", escan->dev->name);
+               goto exit;
+       }
+
+       bss_list = escan->bss_list;
+       bi = next_bss(bss_list, bi);
+       ESCAN_SCAN(dev->name, "scanned AP/Mesh count (%d)\n", bss_list->count);
+       for_each_bss(bss_list, bi, i)
+       {
+               memset(&bi_meshid, 0, sizeof(bi_meshid));
+               is_mesh_peer = FALSE;
+               bi_chan = wf_chspec_ctlchan(
+                       wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
+               bi_rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
+               is_mesh_peer = wl_escan_meshid_ie(((u8*)bi)+bi->ie_offset,
+                       bi->ie_length, &bi_meshid);
+               if (!(bi->capability & (DOT11_CAP_ESS|DOT11_CAP_IBSS)) && is_mesh_peer) {
+                       bool meshid_matched = FALSE, sec_matched = FALSE, bi_sae = FALSE,
+                               bss_found = FALSE, prefer = FALSE;
+
+                       if (cur_ssid->SSID_len && cur_ssid->SSID_len == bi_meshid.SSID_len &&
+                                       !memcmp(cur_ssid->SSID, bi_meshid.SSID, bi_meshid.SSID_len))
+                               meshid_matched = TRUE;
+
+                       bi_sae = wl_escan_rsn_ie(((u8*)bi)+bi->ie_offset, bi->ie_length);
+                       if (bi_sae == sae)
+                               sec_matched = TRUE;
+
+                       bss_found = wl_escan_mesh_info_ie(dev, ((u8*)bi)+bi->ie_offset, bi->ie_length,
+                               &peer_mesh_info);
+                       if (meshid_matched && sec_matched && bss_found &&
+                                       (cur_chan == bi_chan)) {
+                               if (peer_mesh_info.hop_cnt < min_hop_cnt) {
+                                       memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+                                               ETHER_ADDR_LEN);
+                                       mesh_info->master_channel = peer_mesh_info.master_channel;
+                                       mesh_info->hop_cnt = peer_mesh_info.hop_cnt;
+                                       memcpy(mesh_info->peer_bssid, peer_mesh_info.peer_bssid,
+                                               sizeof(peer_mesh_info.peer_bssid));
+                                       min_hop_cnt = peer_mesh_info.hop_cnt;
+                                       prefer = TRUE;
+                                       chan_matched = TRUE;
+                                       found = TRUE;
+                               }
+                       }
+                       else if (meshid_matched && sec_matched && bss_found &&
+                                       (cur_chan != bi_chan) && !chan_matched) {
+                               if (bi_rssi > max_rssi) {
+                                       memcpy(&mesh_info->master_bssid, &peer_mesh_info.master_bssid,
+                                               ETHER_ADDR_LEN);
+                                       mesh_info->master_channel = peer_mesh_info.master_channel;
+                                       mesh_info->hop_cnt = peer_mesh_info.hop_cnt;
+                                       memcpy(mesh_info->peer_bssid, peer_mesh_info.peer_bssid,
+                                               sizeof(peer_mesh_info.peer_bssid));
+                                       max_rssi = bi_rssi;
+                                       prefer = TRUE;
+                                       found = TRUE;
+                               }
+                       }
+
+                       ESCAN_SCAN(dev->name,
+                               "%s[Mesh] BSSID=%pM, channel=%d, RSSI=%d, sec=%s, "
+                               "mbssid=%pM, mchannel=%d, hop=%d, pbssid=%pM, MeshID=\"%s\"\n",
+                               prefer?"*":" ", &bi->BSSID, bi_chan, bi_rssi, bi_sae?"SAE":"OPEN",
+                               &peer_mesh_info.master_bssid, peer_mesh_info.master_channel,
+                               peer_mesh_info.hop_cnt, &peer_mesh_info.peer_bssid, bi_meshid.SSID);
+               } else {
+                       ESCAN_SCAN(dev->name,
+                               "[AP] BSSID=%pM, channel=%d, RSSI=%d, SSID=\"%s\"\n",
+                               &bi->BSSID, bi_chan, bi_rssi, bi->SSID);
+               }
+       }
+
+exit:
+       mutex_unlock(&escan->usr_sync);
+       return found;
+}
+#endif /* WLMESH */
 
 static void
 wl_escan_deinit(struct net_device *dev, struct wl_escan_info *escan)
@@ -1242,7 +1503,7 @@ wl_escan_event_dettach(struct net_device *dev, dhd_pub_t *dhdp)
                return ret;
        }
 
-       wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2);
+       wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler);
 
        return 0;
 }
@@ -1258,7 +1519,7 @@ wl_escan_event_attach(struct net_device *dev, dhd_pub_t *dhdp)
                return ret;
        }
 
-       ret = wl_ext_event_register(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2,
+       ret = wl_ext_event_register(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler,
                escan, PRIO_EVENT_ESCAN);
        if (ret) {
                ESCAN_ERROR(dev->name, "wl_ext_event_register err %d\n", ret);
@@ -1282,7 +1543,7 @@ wl_escan_detach(struct net_device *dev, dhd_pub_t *dhdp)
                kfree(escan->escan_ioctl_buf);
                escan->escan_ioctl_buf = NULL;
        }
-       wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler2);
+       wl_ext_event_deregister(dev, dhdp, WLC_E_ESCAN_RESULT, wl_escan_handler);
 
        DHD_OS_PREFREE(dhdp, escan, sizeof(struct wl_escan_info));
        dhdp->escan = NULL;
index f31ccead43d296874f211b1183249ffedb5b22c9..080f333f5c11323a1b65ae45bc83b1bb40b0c131 100644 (file)
@@ -1,6 +1,7 @@
 \r
 #ifndef _wl_escan_\r
 #define _wl_escan_\r
+#include <linuxver.h>\r
 #include <wl_iw.h>\r
 \r
 #define ESCAN_BUF_SIZE (64 * 1024)\r
@@ -17,14 +18,14 @@ enum escan_state {
 typedef struct wl_escan_info {\r
        struct net_device *dev;\r
        dhd_pub_t *pub;\r
-       struct timer_list scan_timeout;   /* Timer for catch scan event timeout */\r
+       timer_list_compat_t scan_timeout; /* Timer for catch scan event timeout */\r
        int escan_state;\r
        int ioctl_ver;\r
        u8 escan_buf[ESCAN_BUF_SIZE];\r
        struct wl_scan_results *bss_list;\r
        struct ether_addr disconnected_bssid;\r
        u8 *escan_ioctl_buf;\r
-       struct mutex usr_sync;  /* maily for up/down synchronization */\r
+       struct mutex usr_sync; /* maily for up/down synchronization */\r
        int autochannel;\r
        int best_2g_ch;\r
        int best_5g_ch;\r
@@ -37,12 +38,34 @@ typedef struct wl_escan_info {
 #endif\r
 } wl_escan_info_t;\r
 \r
+#if defined(WLMESH)\r
+enum mesh_info_id {\r
+       MESH_INFO_MASTER_BSSID = 1,\r
+       MESH_INFO_MASTER_CHANNEL,\r
+       MESH_INFO_HOP_CNT,\r
+       MESH_INFO_PEER_BSSID\r
+};\r
+\r
+#define MAX_HOP_LIST 10\r
+typedef struct wl_mesh_params {\r
+       struct ether_addr master_bssid;\r
+       uint16 master_channel;\r
+       uint hop_cnt;\r
+       struct ether_addr peer_bssid[MAX_HOP_LIST];\r
+       uint16 scan_channel;\r
+} wl_mesh_params_t;\r
+bool wl_escan_mesh_info(struct net_device *dev,\r
+       struct wl_escan_info *escan, struct ether_addr *peer_bssid,\r
+       struct wl_mesh_params *mesh_info);\r
+bool wl_escan_mesh_peer(struct net_device *dev,\r
+       struct wl_escan_info *escan, wlc_ssid_t *cur_ssid, uint16 cur_chan, bool sae,\r
+       struct wl_mesh_params *mesh_info);\r
+#endif /* WLMESH */\r
+\r
 int wl_escan_set_scan(struct net_device *dev, dhd_pub_t *dhdp,\r
-       wlc_ssid_t *ssid, bool bcast);\r
+       wlc_ssid_t *ssid, uint16 channel, bool bcast);\r
 int wl_escan_get_scan(struct net_device *dev, dhd_pub_t *dhdp,\r
        struct iw_request_info *info, struct iw_point *dwrq, char *extra);\r
-s32 wl_escan_handler2(struct net_device *dev, struct wl_escan_info *escan,\r
-       const wl_event_msg_t *e, void *data);\r
 int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp);\r
 void wl_escan_detach(struct net_device *dev, dhd_pub_t *dhdp);\r
 int wl_escan_event_attach(struct net_device *dev, dhd_pub_t *dhdp);\r
index c9e3d569dc4f7b9ffcee87033d7bcdf93f886439..5f75d6571fdcf977e9f76d5750da905ef6964df9 100644 (file)
 #define EVENT_TRACE(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_TRACE_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] EVENT-TRACE) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] EVENT-TRACE) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 #define EVENT_DBG(name, arg1, args...) \
        do { \
                if (android_msg_level & ANDROID_DBG_LEVEL) { \
-                       printk(KERN_ERR "[dhd-%s] EVENT-DBG) %s : " arg1, name, __func__, ## args); \
+                       printk(KERN_INFO "[dhd-%s] EVENT-DBG) %s : " arg1, name, __func__, ## args); \
                } \
        } while (0)
 
@@ -200,6 +200,7 @@ wl_ext_event_handler(struct work_struct *work_data)
        struct net_device *dev = NULL;
        struct event_handler_list *evt_node;
        dhd_pub_t *dhd;
+       unsigned long flags = 0;
 
        BCM_SET_CONTAINER_OF(event_params, work_data, struct wl_event_params, event_work);
        DHD_EVENT_WAKE_LOCK(event_params->pub);
@@ -218,10 +219,13 @@ wl_ext_event_handler(struct work_struct *work_data)
                        EVENT_TRACE(dev->name, "Unknown Event (%d): ignoring\n", e->etype);
                        goto fail;
                }
-               if (dhd->busstate == DHD_BUS_DOWN) {
+               DHD_GENERAL_LOCK(dhd, flags);
+               if (DHD_BUS_CHECK_DOWN_OR_DOWN_IN_PROGRESS(dhd)) {
                        EVENT_ERROR(dev->name, "BUS is DOWN.\n");
+                       DHD_GENERAL_UNLOCK(dhd, flags);
                        goto fail;
                }
+               DHD_GENERAL_UNLOCK(dhd, flags);
                EVENT_DBG(dev->name, "event type (%d)\n", e->etype);
                mutex_lock(&event_params->event_sync);
                evt_node = event_params->evt_head.evt_head;
index f02173b3eed0cdf25074f52fcc3431d36a4dd7dd..4f926c73fb24f5ebe95fc17a416dbf81899c605b 100644 (file)
@@ -62,19 +62,19 @@ uint iw_msg_level = WL_ERROR_LEVEL;
 #define WL_TRACE_MSG(x, args...) \
        do { \
                if (iw_msg_level & WL_TRACE_LEVEL) { \
-                       printk(KERN_ERR "[dhd] WEXT-TRACE) %s : " x, __func__, ## args); \
+                       printk(KERN_INFO "[dhd] WEXT-TRACE) %s : " x, __func__, ## args); \
                } \
        } while (0)
 #define WL_SCAN_MSG(x, args...) \
        do { \
                if (iw_msg_level & WL_SCAN_LEVEL) { \
-                       printk(KERN_ERR "[dhd] WEXT-SCAN) %s : " x, __func__, ## args); \
+                       printk(KERN_INFO "[dhd] WEXT-SCAN) %s : " x, __func__, ## args); \
                } \
        } while (0)
 #define WL_WSEC_MSG(x, args...) \
        do { \
                if (iw_msg_level & WL_WSEC_LEVEL) { \
-                       printk(KERN_ERR "[dhd] WEXT-WSEC) %s : " x, __func__, ## args); \
+                       printk(KERN_INFO "[dhd] WEXT-WSEC) %s : " x, __func__, ## args); \
                } \
        } while (0)
 #define WL_ERROR(x) WL_ERROR_MSG x
@@ -194,7 +194,7 @@ typedef struct iscan_buf {
 
 typedef struct iscan_info {
        struct net_device *dev;
-       struct timer_list timer;
+       timer_list_compat_t timer;
        uint32 timer_ms;
        uint32 timer_on;
        int    iscan_state;
@@ -514,97 +514,6 @@ wl_iw_set_pm(
 }
 #endif /* WIRELESS_EXT > 12 */
 
-#define WL_PM_ENABLE_TIMEOUT 10000
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-       4 && __GNUC_MINOR__ >= 6))
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
-_Pragma("GCC diagnostic push") \
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"") \
-entry = container_of((ptr), type, member); \
-_Pragma("GCC diagnostic pop")
-#else
-#define BCM_SET_CONTAINER_OF(entry, ptr, type, member) \
-entry = container_of((ptr), type, member);
-#endif /* STRICT_GCC_WARNINGS */
-
-void wl_ext_pm_work_handler(struct work_struct *work)
-{
-       struct wl_wext_info *wext_info;
-       s32 pm = PM_FAST;
-       dhd_pub_t *dhd;
-       int ret = 0;
-
-       BCM_SET_CONTAINER_OF(wext_info, work, struct wl_wext_info, pm_enable_work.work);
-
-       WL_TRACE(("%s: Enter\n", __FUNCTION__));
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-       4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic push")
-_Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
-#endif
-
-       dhd = (dhd_pub_t *)(wext_info->dhd);
-       if (!dhd || !wext_info->dhd->up) {
-               WL_TRACE(("%s: dhd is null or not up\n", __FUNCTION__));
-               return;
-       }
-       if (dhd_conf_get_pm(dhd) >= 0)
-               pm = dhd_conf_get_pm(dhd);
-       ret = dev_wlc_ioctl(wext_info->dev, WLC_SET_PM, &pm, sizeof(pm));
-       if (ret)
-               WL_ERROR(("%s: WLC_SET_PM failed %d\n", __FUNCTION__, ret));
-#if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
-       4 && __GNUC_MINOR__ >= 6))
-_Pragma("GCC diagnostic pop")
-#endif
-       DHD_PM_WAKE_UNLOCK(wext_info->dhd);
-
-}
-
-void wl_ext_add_remove_pm_enable_work(struct wl_wext_info *wext_info,
-       bool add)
-{
-       u16 wq_duration = 0;
-       s32 pm = PM_OFF;
-       int ret = 0;
-
-       if (wext_info == NULL || wext_info->dhd == NULL)
-               return;
-
-       mutex_lock(&wext_info->pm_sync);
-       /*
-        * Make cancel and schedule work part mutually exclusive
-        * so that while cancelling, we are sure that there is no
-        * work getting scheduled.
-        */
-
-       if (delayed_work_pending(&wext_info->pm_enable_work)) {
-               cancel_delayed_work_sync(&wext_info->pm_enable_work);
-               DHD_PM_WAKE_UNLOCK(wext_info->dhd);
-       }
-
-       if (add) {
-               wq_duration = (WL_PM_ENABLE_TIMEOUT);
-       }
-
-       /* It should schedule work item only if driver is up */
-       if (wq_duration && wext_info->dhd->up) {
-               if (dhd_conf_get_pm(wext_info->dhd) >= 0)
-                       pm = dhd_conf_get_pm(wext_info->dhd);
-               ret = dev_wlc_ioctl(wext_info->dev, WLC_SET_PM, &pm, sizeof(pm));
-               if (ret)
-                       WL_ERROR(("%s: WLC_SET_PM failed %d\n", __FUNCTION__, ret));
-               if (schedule_delayed_work(&wext_info->pm_enable_work,
-                               msecs_to_jiffies((const unsigned int)wq_duration))) {
-                       DHD_PM_WAKE_LOCK_TIMEOUT(wext_info->dhd, wq_duration);
-               } else {
-                       WL_ERROR(("%s: Can't schedule pm work handler\n", __FUNCTION__));
-               }
-       }
-       mutex_unlock(&wext_info->pm_sync);
-
-}
-
 static void
 wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status)
 {
@@ -621,7 +530,9 @@ wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status)
        cur_eapol_status = dhd->conf->eapol_status;
 
        if (status == WL_EXT_STATUS_CONNECTING) {
-               wl_ext_add_remove_pm_enable_work(wext_info, TRUE);
+#ifdef WL_EXT_IAPSTA
+               wl_ext_add_remove_pm_enable_work(dev, TRUE);
+#endif /* WL_EXT_IAPSTA */
                if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &wpa_auth))) {
                        WL_ERROR(("wpa_auth get error %d\n", error));
                        return;
@@ -632,8 +543,11 @@ wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status)
                        dhd->conf->eapol_status = EAPOL_STATUS_NONE;
        } else if (status == WL_EXT_STATUS_ADD_KEY) {
                dhd->conf->eapol_status = EAPOL_STATUS_4WAY_DONE;
+               wake_up_interruptible(&dhd->conf->event_complete);
        } else if (status == WL_EXT_STATUS_DISCONNECTING) {
-               wl_ext_add_remove_pm_enable_work(wext_info, FALSE);
+#ifdef WL_EXT_IAPSTA
+               wl_ext_add_remove_pm_enable_work(dev, FALSE);
+#endif /* WL_EXT_IAPSTA */
                if (cur_eapol_status >= EAPOL_STATUS_4WAY_START &&
                                cur_eapol_status < EAPOL_STATUS_4WAY_DONE) {
                        WL_ERROR(("WPA failed at %d\n", cur_eapol_status));
@@ -648,6 +562,7 @@ wl_iw_update_connect_status(struct net_device *dev, enum wl_ext_status status)
                                cur_eapol_status < EAPOL_STATUS_4WAY_DONE) {
                        WL_ERROR(("WPA failed at %d\n", cur_eapol_status));
                        dhd->conf->eapol_status = EAPOL_STATUS_NONE;
+                       wake_up_interruptible(&dhd->conf->event_complete);
                } else if (cur_eapol_status >= EAPOL_STATUS_WSC_START &&
                                cur_eapol_status < EAPOL_STATUS_WSC_DONE) {
                        WL_ERROR(("WPS failed at %d\n", cur_eapol_status));
@@ -1533,7 +1448,7 @@ wl_iw_iscan_set_scan(
                }
        }
 #endif
-       return wl_escan_set_scan(dev, dhd, &ssid, TRUE);
+       return wl_escan_set_scan(dev, dhd, &ssid, 0, TRUE);
 #else
        iscan = &wext_info->iscan;
        WL_TRACE(("%s: SIOCSIWSCAN iscan=%p\n", dev->name, iscan));
@@ -3747,7 +3662,8 @@ wl_iw_event(struct net_device *dev, struct wl_wext_info *wext_info,
        case WLC_E_DEAUTH:
        case WLC_E_DISASSOC:
                wl_iw_update_connect_status(dev, WL_EXT_STATUS_DISCONNECTED);
-               WL_MSG(dev->name, "disconnected with "MACSTR", event %d, reason %d\n",
+               WL_MSG_RLMT(dev->name, &e->addr, ETHER_ADDR_LEN,
+                       "disconnected with "MACSTR", event %d, reason %d\n",
                        MAC2STR((u8 *)wrqu.addr.sa_data), event_type, reason);
                break;
        case WLC_E_DEAUTH_IND:
@@ -3971,7 +3887,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
 
        phy_noise = 0;
        if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) {
-               WL_ERROR(("WLC_GET_PHY_NOISE error=%d\n", res));
+               WL_TRACE(("WLC_GET_PHY_NOISE error=%d\n", res));
                goto done;
        }
 
@@ -3980,7 +3896,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
 
        memset(&scb_val, 0, sizeof(scb_val));
        if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) {
-               WL_ERROR(("WLC_GET_RSSI error=%d\n", res));
+               WL_TRACE(("WLC_GET_RSSI error=%d\n", res));
                goto done;
        }
 
@@ -4076,10 +3992,9 @@ done:
 
 #ifndef WL_ESCAN
 static void
-wl_iw_timerfunc(unsigned long data)
+wl_iw_timerfunc(ulong data)
 {
        iscan_info_t *iscan = (iscan_info_t *)data;
-
        iscan->timer_on = 0;
        if (iscan->iscan_state != ISCAN_STATE_IDLE) {
                WL_TRACE(("timer trigger\n"));
@@ -4315,7 +4230,6 @@ wl_iw_detach(struct net_device *dev, dhd_pub_t *dhdp)
                iscan->list_hdr = buf;
        }
 #endif
-       wl_ext_add_remove_pm_enable_work(wext_info, FALSE);
        wl_ext_event_deregister(dev, dhdp, WLC_E_LAST, wl_iw_event);
        if (wext_info) {
                kfree(wext_info);
@@ -4357,7 +4271,7 @@ wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp)
 
        /* Set up the timer */
        iscan->timer_ms    = 2000;
-       init_timer_compat(&iscan->scan_timeout, wl_iw_timerfunc, iscan);
+       init_timer_compat(&iscan->timer, wl_iw_timerfunc, iscan);
 
        sema_init(&iscan->sysioc_sem, 0);
        init_completion(&iscan->sysioc_exited);
@@ -4372,8 +4286,6 @@ wl_iw_attach(struct net_device *dev, dhd_pub_t *dhdp)
                goto exit;
        }
 #endif
-       mutex_init(&wext_info->pm_sync);
-       INIT_DELAYED_WORK(&wext_info->pm_enable_work, wl_ext_pm_work_handler);
        ret = wl_ext_event_register(dev, dhdp, WLC_E_LAST, wl_iw_event, dhdp->wext_info,
                PRIO_EVENT_WEXT);
        if (ret) {
@@ -4398,7 +4310,6 @@ wl_iw_down(struct net_device *dev, dhd_pub_t *dhdp)
                WL_ERROR (("dhd is NULL\n"));
                return;
        }
-       wl_ext_add_remove_pm_enable_work(wext_info, FALSE);
 }
 
 int
index 44745e9a0f7d61b728d507cb090f9731cfda8eb6..31d581152dae69e0aa0da230e4e44a8b27e93062 100644 (file)
 #include <dngl_stats.h>
 #include <dhd.h>
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(5, 0, 0)
+#define get_ds()    (KERNEL_DS)
+#endif
+
 #define WL_SCAN_PARAMS_SSID_MAX        10
 #define GET_SSID                       "SSID="
 #define GET_CHANNEL                    "CH="
@@ -109,7 +113,7 @@ typedef struct wl_iw {
 } wl_iw_t;
 
 struct wl_ctrl {
-       struct timer_list *timer;
+       timer_list_compat_t *timer;
        struct net_device *dev;
        long sysioc_pid;
        struct semaphore sysioc_sem;
index 7d89a9eb0df3d1b46233511ac108f0be793fd718..4181b28098436cafda9b4d42af6d3ee36f4cdb19 100644 (file)
 #define htodchanspec(i) (i)
 #define dtohchanspec(i) (i)
 
-#define        WLDEV_ERROR(args)                                               \
-       do {                                                                            \
-               printk(KERN_ERR "WLDEV-ERROR) ");       \
-               printk args;                                                    \
+#define        WLDEV_ERROR_MSG(x, args...)                                             \
+       do {                                                                                            \
+               printk(KERN_INFO "[dhd] WLDEV-ERROR) " x, ## args);     \
        } while (0)
+#define WLDEV_ERROR(x) WLDEV_ERROR_MSG x
 
-#define        WLDEV_INFO(args)                                                \
-       do {                                                                            \
-               printk(KERN_INFO "WLDEV-INFO) ");       \
-               printk args;                                                    \
+#define        WLDEV_INFO_MSG(x, args...)                                              \
+       do {                                                                                            \
+               printk(KERN_INFO "[dhd] WLDEV-INFO) " x, ## args);      \
        } while (0)
+#define WLDEV_INFO(x) WLDEV_INFO_MSG x
 
 extern int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd);