wifi: update bcmdhd.1.579.77.41.1.cn from ampak[3/3]
authorlibo <bo.li@amlogic.com>
Wed, 19 Sep 2018 08:49:31 +0000 (16:49 +0800)
committerlibo <bo.li@amlogic.com>
Thu, 20 Sep 2018 06:02:17 +0000 (14:02 +0800)
PD# 171947

Change-Id: Ife58252353890336d59c93384cf2bd2c04c02d65
Signed-off-by: libo <bo.li@amlogic.com>
38 files changed:
bcmdhd.1.579.77.41.1.cn/Kconfig [changed mode: 0755->0644]
bcmdhd.1.579.77.41.1.cn/Makefile
bcmdhd.1.579.77.41.1.cn/dbus.c
bcmdhd.1.579.77.41.1.cn/dbus_usb.c
bcmdhd.1.579.77.41.1.cn/dbus_usb_linux.c
bcmdhd.1.579.77.41.1.cn/dhd.h
bcmdhd.1.579.77.41.1.cn/dhd_bus.h
bcmdhd.1.579.77.41.1.cn/dhd_cdc.c
bcmdhd.1.579.77.41.1.cn/dhd_common.c
bcmdhd.1.579.77.41.1.cn/dhd_config.c
bcmdhd.1.579.77.41.1.cn/dhd_config.h
bcmdhd.1.579.77.41.1.cn/dhd_gpio.c
bcmdhd.1.579.77.41.1.cn/dhd_ip.c
bcmdhd.1.579.77.41.1.cn/dhd_linux.c
bcmdhd.1.579.77.41.1.cn/dhd_linux.h
bcmdhd.1.579.77.41.1.cn/dhd_linux_platdev.c
bcmdhd.1.579.77.41.1.cn/dhd_pcie_linux.c
bcmdhd.1.579.77.41.1.cn/dhd_sdio.c
bcmdhd.1.579.77.41.1.cn/dhd_static_buf.c
bcmdhd.1.579.77.41.1.cn/dhd_wlfc.c
bcmdhd.1.579.77.41.1.cn/include/dbus.h
bcmdhd.1.579.77.41.1.cn/include/epivers.h
bcmdhd.1.579.77.41.1.cn/include/linux_osl.h
bcmdhd.1.579.77.41.1.cn/linux_osl.c
bcmdhd.1.579.77.41.1.cn/siutils.c
bcmdhd.1.579.77.41.1.cn/wl_android.c
bcmdhd.1.579.77.41.1.cn/wl_android.h
bcmdhd.1.579.77.41.1.cn/wl_android_ext.c
bcmdhd.1.579.77.41.1.cn/wl_cfg80211.c
bcmdhd.1.579.77.41.1.cn/wl_cfg80211.h
bcmdhd.1.579.77.41.1.cn/wl_cfg_btcoex.c
bcmdhd.1.579.77.41.1.cn/wl_cfgp2p.c
bcmdhd.1.579.77.41.1.cn/wl_cfgp2p.h
bcmdhd.1.579.77.41.1.cn/wl_cfgvendor.c
bcmdhd.1.579.77.41.1.cn/wl_escan.c
bcmdhd.1.579.77.41.1.cn/wl_escan.h
bcmdhd.1.579.77.41.1.cn/wl_iw.c
bcmdhd.1.579.77.41.1.cn/wldev_common.c

old mode 100755 (executable)
new mode 100644 (file)
index bba8b4f..f49ae76
@@ -37,6 +37,9 @@ config BCMDHD_SDIO
 config BCMDHD_PCIE
                bool "PCIe bus interface support"
                depends on BCMDHD && PCI
+config BCMDHD_USB
+               bool "USB bus interface support"
+               depends on BCMDHD && USB
 endchoice
 
 choice
index 25511753e15c84bdf3b5c10651bbf69c6835f834..5669d5cc665174be13ccb75c8cf1e1c354479302 100755 (executable)
@@ -7,9 +7,12 @@ ifeq ($(CONFIG_BCMDHD_PCIE),)
 $(info bcm SDIO driver configured)
 CONFIG_DHD_USE_STATIC_BUF :=y
 endif
-#CONFIG_BCMDHD_SDIOO := y
+
+#CONFIG_BCMDHD_SDIO := y
 #CONFIG_BCMDHD_PCIE := y
 #CONFIG_BCMDHD_USB := y
+
+#CONFIG_BCMDHD_CUSB := y
 CONFIG_BCMDHD_PROPTXSTATUS := y
 
 CONFIG_MACH_PLATFORM := y
@@ -19,37 +22,30 @@ export CONFIG_BCMDHD = m
 export CONFIG_BCMDHD_OOB = y
 export CONFIG_VTS_SUPPORT = y
 
-DHDCFLAGS = -Wall -Wstrict-prototypes -Wno-maybe-uninitialized  \
-       -Dlinux -DBCMDRIVER                 \
+DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER                 \
+       -Wno-maybe-uninitialized                                              \
        -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE            \
        -DDHDTHREAD -DDHD_DEBUG -DSHOW_EVENTS -DBCMDBG -DGET_OTP_MAC_ENABLE   \
        -DWIFI_ACT_FRAME -DARP_OFFLOAD_SUPPORT -DSUPPORT_PM2_ONLY             \
        -DKEEP_ALIVE -DPKT_FILTER_SUPPORT -DPNO_SUPPORT -DDHDTCPACK_SUPPRESS  \
-       -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT -DRXFRAME_THREAD          \
-       -DTSQ_MULTIPLIER -DMFP                                                \
+       -DDHD_DONOT_FORWARD_BCMEVENT_AS_NETWORK_PKT                           \
+       -DMULTIPLE_SUPPLICANT -DTSQ_MULTIPLIER -DMFP                          \
        -DWL_EXT_IAPSTA                                                       \
+       -DENABLE_INSMOD_NO_FW_LOAD                                            \
        -I$(src) -I$(src)/include
 
 DHDOFILES = aiutils.o siutils.o sbutils.o bcmutils.o bcmwifi_channels.o   \
        dhd_linux.o dhd_linux_platdev.o dhd_linux_sched.o dhd_pno.o           \
        dhd_common.o dhd_ip.o dhd_linux_wq.o dhd_custom_gpio.o                \
        bcmevent.o hndpmu.o linux_osl.o wldev_common.o wl_android.o           \
+       dhd_debug_linux.o dhd_debug.o dhd_mschdbg.o                           \
        hnd_pktq.o hnd_pktpool.o dhd_config.o wl_android_ext.o
 
-ifeq ($(BCM_USB_COMPOSITE),true)
-DHDCFLAGS += -DBCMUSBDEV_COMPOSITE
-endif
-
+#BCMDHD_SDIO
 ifneq ($(CONFIG_BCMDHD_SDIO),)
-DHDCFLAGS += \
-       -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR          \
+DHDCFLAGS += -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR \
        -DSDTEST -DBDC -DDHD_USE_IDLECOUNT -DCUSTOM_SDIO_F2_BLKSIZE=256       \
-       -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT
-DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD
-
-DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o  \
-       dhd_sdio.o dhd_cdc.o dhd_wlfc.o
-
+       -DBCMSDIOH_TXGLOM -DBCMSDIOH_TXGLOM_EXT -DRXFRAME_THREAD
 ifeq ($(CONFIG_BCMDHD_OOB),y)
        DHDCFLAGS += -DOOB_INTR_ONLY -DCUSTOMER_OOB -DHW_OOB
 ifeq ($(CONFIG_BCMDHD_DISABLE_WOWLAN),y)
@@ -58,33 +54,39 @@ endif
 else
        DHDCFLAGS += -DSDIO_ISR_THREAD
 endif
+
+DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o  \
+       dhd_sdio.o dhd_cdc.o dhd_wlfc.o
 endif
 
+#BCMDHD_PCIE
 ifneq ($(CONFIG_BCMDHD_PCIE),)
-DHDCFLAGS += \
-       -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1             \
+DHDCFLAGS += -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1    \
        -DDONGLE_ENABLE_ISOLATION
-DHDCFLAGS += -DENABLE_INSMOD_NO_FW_LOAD
+ifneq ($(CONFIG_PCI_MSI),)
+       DHDCFLAGS += -DDHD_USE_MSI
+endif
 DHDCFLAGS += -DDHD_PCIE_BAR1_WIN_BASE_FIX=0x200000
 
 DHDOFILES += dhd_pcie.o dhd_pcie_linux.o pcie_core.o dhd_flowring.o       \
        dhd_msgbuf.o
-
-ifneq ($(CONFIG_PCI_MSI),)
-       DHDCFLAGS += -DDHD_USE_MSI
-endif
-ifeq ($(CONFIG_DHD_USE_STATIC_BUF),y)
-       DHDCFLAGS += -DDHD_USE_STATIC_CTRLBUF
-endif
 endif
 
+#BCMDHD_USB
 ifneq ($(CONFIG_BCMDHD_USB),)
 DHDCFLAGS += -DUSBOS_TX_THREAD -DBCMDBUS -DBCMTRXV2 -DDBUS_USB_LOOPBACK   \
        -DBDC
+DHDCFLAGS += -DBCM_REQUEST_FW -DEXTERNAL_FW_PATH
+#DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS))
+ifneq ($(CONFIG_BCMDHD_CUSB),)
+       DHDCFLAGS += -DBCMUSBDEV_COMPOSITE
+       DHDCFLAGS :=$(filter-out -DENABLE_INSMOD_NO_FW_LOAD,$(DHDCFLAGS))
+endif
 
 DHDOFILES += dbus.o dbus_usb.o dbus_usb_linux.o dhd_cdc.o dhd_wlfc.o
 endif
 
+#PROPTXSTATUS
 ifeq ($(CONFIG_BCMDHD_PROPTXSTATUS),y)
 ifneq ($(CONFIG_BCMDHD_USB),)
        DHDCFLAGS += -DPROP_TXSTATUS
@@ -97,15 +99,16 @@ ifneq ($(CONFIG_CFG80211),)
 endif
 endif
 
+#VTS_SUPPORT
 ifeq ($(CONFIG_VTS_SUPPORT),y)
-DHDCFLAGS += \
-       -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG               \
+ifneq ($(CONFIG_CFG80211),)
+DHDCFLAGS += -DGSCAN_SUPPORT -DRTT_SUPPORT -DCUSTOM_FORCE_NODFS_FLAG      \
        -DLINKSTAT_SUPPORT -DDEBUGABILITY -DDBG_PKT_MON -DPKT_FILTER_SUPPORT  \
        -DAPF -DNDO_CONFIG_SUPPORT -DRSSI_MONITOR_SUPPORT -DDHD_WAKE_STATUS   \
        -DCUSTOM_COUNTRY_CODE -DDHD_FW_COREDUMP -DEXPLICIT_DISCIF_CLEANUP
 
-DHDOFILES += dhd_debug_linux.o dhd_debug.o bcmxtlv.o dhd_rtt.o            \
-       bcm_app_utils.o
+DHDOFILES += bcmxtlv.o dhd_rtt.o bcm_app_utils.o
+endif
 endif
 
 # MESH support for kernel 3.10 later
@@ -118,6 +121,7 @@ endif
        DHDCFLAGS :=$(filter-out -DDHD_FW_COREDUMP,$(DHDCFLAGS))
        DHDCFLAGS :=$(filter-out -DSET_RANDOM_MAC_SOFTAP,$(DHDCFLAGS))
 endif
+
 ifeq ($(CONFIG_BCMDHD_SDIO),y)
 obj-$(CONFIG_BCMDHD) += dhd.o
 dhd-objs += $(DHDOFILES)
@@ -142,6 +146,7 @@ ifeq ($(CONFIG_BCMDHD_AG),y)
 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
 endif
@@ -168,10 +173,7 @@ ifneq ($(CONFIG_CFG80211),)
 endif
 EXTRA_CFLAGS = $(DHDCFLAGS)
 ifeq ($(CONFIG_BCMDHD),m)
-       DHDCFLAGS += -DMULTIPLE_SUPPLICANT
 EXTRA_LDFLAGS += --strip-debug
-else
-       DHDCFLAGS += -DBUILD_IN_KERNEL
 endif
 
 ARCH ?= arm64
index 5e3b64c97d2ba072897368cede83d197a2087370..cea6c7f1c87d589714c9becb49975ec2d93c96c6 100644 (file)
 #include "osl.h"
 #include "dbus.h"
 #include <bcmutils.h>
+#include <dngl_stats.h>
+#include <dhd.h>
+#include <dhd_proto.h>
+#ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */
+#include <dhd_wlfc.h>
+#endif
+#include <dhd_config.h>
 
 #if defined(BCM_REQUEST_FW)
 #include <bcmsrom_fmt.h>
@@ -66,11 +73,12 @@ typedef struct dbus_irbq {
 } dbus_irbq_t;
 
 /**
- * This private structure dbus_info_t is also declared in dbus_usb_linux.c.
+ * This private structure dhd_bus_t is also declared in dbus_usb_linux.c.
  * All the fields must be consistent in both declarations.
  */
-typedef struct dbus_info {
+typedef struct dhd_bus {
        dbus_pub_t   pub; /* MUST BE FIRST */
+       dhd_pub_t *dhd;
 
        void        *cbarg;
        dbus_callbacks_t *cbs; /* callbacks to higher level, e.g. dhd_linux.c */
@@ -103,7 +111,9 @@ typedef struct dbus_info {
        void         *firmware;
        void         *nvfile;
 #endif
-} dbus_info_t;
+       char            *fw_path;               /* module_param: path to firmware image */
+       char            *nv_path;               /* module_param: path to nvram vars file */
+} dhd_bus_t;
 
 struct exec_parms {
        union {
@@ -122,10 +132,10 @@ struct exec_parms {
 };
 
 #define EXEC_RXLOCK(info, fn, a) \
-       info->drvintf->exec_rxlock(dbus_info->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
+       info->drvintf->exec_rxlock(dhd_bus->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
 
 #define EXEC_TXLOCK(info, fn, a) \
-       info->drvintf->exec_txlock(dbus_info->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
+       info->drvintf->exec_txlock(dhd_bus->bus_info, ((exec_cb_t)fn), ((struct exec_parms *) a))
 
 /*
  * Callbacks common for all BUS
@@ -141,6 +151,11 @@ static void dbus_if_pktfree(void *handle, void *p, bool send);
 static struct dbus_irb *dbus_if_getirb(void *cbarg, bool send);
 static void dbus_if_rxerr_indicate(void *handle, bool on);
 
+void * dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
+       uint16 bus_no, uint16 slot, uint32 hdrlen);
+void dhd_dbus_disconnect_cb(void *arg);
+void dbus_detach(dhd_bus_t *pub);
+
 /** functions in this file that are called by lower DBUS levels, e.g. dbus_usb.c */
 static dbus_intf_callbacks_t dbus_intf_cbs = {
        dbus_if_send_irb_timeout,
@@ -178,51 +193,50 @@ static void* q_enq(dbus_irbq_t *q, dbus_irb_t *b);
 static void* q_enq_exec(struct exec_parms *args);
 static dbus_irb_t*q_deq(dbus_irbq_t *q);
 static void* q_deq_exec(struct exec_parms *args);
-static int   dbus_tx_timer_init(dbus_info_t *dbus_info);
-static int   dbus_tx_timer_start(dbus_info_t *dbus_info, uint timeout);
-static int   dbus_tx_timer_stop(dbus_info_t *dbus_info);
-static int   dbus_irbq_init(dbus_info_t *dbus_info, dbus_irbq_t *q, int nq, int size_irb);
-static int   dbus_irbq_deinit(dbus_info_t *dbus_info, dbus_irbq_t *q, int size_irb);
-static int   dbus_rxirbs_fill(dbus_info_t *dbus_info);
+static int   dbus_tx_timer_init(dhd_bus_t *dhd_bus);
+static int   dbus_tx_timer_start(dhd_bus_t *dhd_bus, uint timeout);
+static int   dbus_tx_timer_stop(dhd_bus_t *dhd_bus);
+static int   dbus_irbq_init(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int nq, int size_irb);
+static int   dbus_irbq_deinit(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int size_irb);
+static int   dbus_rxirbs_fill(dhd_bus_t *dhd_bus);
 static int   dbus_send_irb(dbus_pub_t *pub, uint8 *buf, int len, void *pkt, void *info);
 static void  dbus_disconnect(void *handle);
-static void *dbus_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+static void *dbus_probe(void *arg, const char *desc, uint32 bustype,
+       uint16 bus_no, uint16 slot, uint32 hdrlen);
 
-#if defined(BCM_REQUEST_FW)
 #if defined(BCM_REQUEST_FW)
 extern char * dngl_firmware;
 extern unsigned int dngl_fwlen;
-#endif  /* #if defined(BCM_REQUEST_FW) */
-static int dbus_get_nvram(dbus_info_t *dbus_info);
-static int dbus_jumbo_nvram(dbus_info_t *dbus_info);
-static int dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev);
-static int dbus_select_nvram(dbus_info_t *dbus_info, int8 *jumbonvram, int jumbolen,
+#ifndef EXTERNAL_FW_PATH
+static int dbus_get_nvram(dhd_bus_t *dhd_bus);
+static int dbus_jumbo_nvram(dhd_bus_t *dhd_bus);
+static int dbus_otp(dhd_bus_t *dhd_bus, uint16 *boardtype, uint16 *boardrev);
+static int dbus_select_nvram(dhd_bus_t *dhd_bus, int8 *jumbonvram, int jumbolen,
 uint16 boardtype, uint16 boardrev, int8 **nvram, int *nvram_len);
-#ifndef BCM_REQUEST_FW
-static int dbus_zlib_decomp(dbus_info_t *dbus_info);
+#endif /* !EXTERNAL_FW_PATH */
+extern int dbus_zlib_decomp(dhd_bus_t *dhd_bus);
 extern void *dbus_zlib_calloc(int num, int size);
 extern void dbus_zlib_free(void *ptr);
 #endif
-#endif 
 
 /* function */
 void
 dbus_flowctrl_tx(void *dbi, bool on)
 {
-       dbus_info_t *dbus_info = dbi;
+       dhd_bus_t *dhd_bus = dbi;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
        DBUSTRACE(("%s on %d\n", __FUNCTION__, on));
 
-       if (dbus_info->txoff == on)
+       if (dhd_bus->txoff == on)
                return;
 
-       dbus_info->txoff = on;
+       dhd_bus->txoff = on;
 
-       if (dbus_info->cbs && dbus_info->cbs->txflowcontrol)
-               dbus_info->cbs->txflowcontrol(dbus_info->cbarg, on);
+       if (dhd_bus->cbs && dhd_bus->cbs->txflowcontrol)
+               dhd_bus->cbs->txflowcontrol(dhd_bus->cbarg, on);
 }
 
 /**
@@ -232,20 +246,20 @@ dbus_flowctrl_tx(void *dbi, bool on)
 static void
 dbus_if_rxerr_indicate(void *handle, bool on)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
 
        DBUSTRACE(("%s, on %d\n", __FUNCTION__, on));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
-       if (dbus_info->txoverride == on)
+       if (dhd_bus->txoverride == on)
                return;
 
-       dbus_info->txoverride = on;     /* flow control */
+       dhd_bus->txoverride = on;       /* flow control */
 
        if (!on)
-               dbus_rxirbs_fill(dbus_info);
+               dbus_rxirbs_fill(dhd_bus);
 
 }
 
@@ -299,29 +313,29 @@ q_deq_exec(struct exec_parms *args)
 
 /**
  * called during attach phase. Status @ Dec 2012: this function does nothing since for all of the
- * lower DBUS levels dbus_info->drvintf->tx_timer_init is NULL.
+ * lower DBUS levels dhd_bus->drvintf->tx_timer_init is NULL.
  */
 static int
-dbus_tx_timer_init(dbus_info_t *dbus_info)
+dbus_tx_timer_init(dhd_bus_t *dhd_bus)
 {
-       if (dbus_info && dbus_info->drvintf && dbus_info->drvintf->tx_timer_init)
-               return dbus_info->drvintf->tx_timer_init(dbus_info->bus_info);
+       if (dhd_bus && dhd_bus->drvintf && dhd_bus->drvintf->tx_timer_init)
+               return dhd_bus->drvintf->tx_timer_init(dhd_bus->bus_info);
        else
                return DBUS_ERR;
 }
 
 static int
-dbus_tx_timer_start(dbus_info_t *dbus_info, uint timeout)
+dbus_tx_timer_start(dhd_bus_t *dhd_bus, uint timeout)
 {
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (dbus_info->tx_timer_ticking)
+       if (dhd_bus->tx_timer_ticking)
                return DBUS_OK;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->tx_timer_start) {
-               if (dbus_info->drvintf->tx_timer_start(dbus_info->bus_info, timeout) == DBUS_OK) {
-                       dbus_info->tx_timer_ticking = TRUE;
+       if (dhd_bus->drvintf && dhd_bus->drvintf->tx_timer_start) {
+               if (dhd_bus->drvintf->tx_timer_start(dhd_bus->bus_info, timeout) == DBUS_OK) {
+                       dhd_bus->tx_timer_ticking = TRUE;
                        return DBUS_OK;
                }
        }
@@ -330,17 +344,17 @@ dbus_tx_timer_start(dbus_info_t *dbus_info, uint timeout)
 }
 
 static int
-dbus_tx_timer_stop(dbus_info_t *dbus_info)
+dbus_tx_timer_stop(dhd_bus_t *dhd_bus)
 {
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (!dbus_info->tx_timer_ticking)
+       if (!dhd_bus->tx_timer_ticking)
                return DBUS_OK;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->tx_timer_stop) {
-               if (dbus_info->drvintf->tx_timer_stop(dbus_info->bus_info) == DBUS_OK) {
-                       dbus_info->tx_timer_ticking = FALSE;
+       if (dhd_bus->drvintf && dhd_bus->drvintf->tx_timer_stop) {
+               if (dhd_bus->drvintf->tx_timer_stop(dhd_bus->bus_info) == DBUS_OK) {
+                       dhd_bus->tx_timer_ticking = FALSE;
                        return DBUS_OK;
                }
        }
@@ -350,17 +364,17 @@ dbus_tx_timer_stop(dbus_info_t *dbus_info)
 
 /** called during attach phase. */
 static int
-dbus_irbq_init(dbus_info_t *dbus_info, dbus_irbq_t *q, int nq, int size_irb)
+dbus_irbq_init(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int nq, int size_irb)
 {
        int i;
        dbus_irb_t *irb;
 
        ASSERT(q);
-       ASSERT(dbus_info);
+       ASSERT(dhd_bus);
 
        for (i = 0; i < nq; i++) {
                /* MALLOC dbus_irb_tx or dbus_irb_rx, but cast to simple dbus_irb_t linkedlist */
-               irb = (dbus_irb_t *) MALLOC(dbus_info->pub.osh, size_irb);
+               irb = (dbus_irb_t *) MALLOC(dhd_bus->pub.osh, size_irb);
                if (irb == NULL) {
                        ASSERT(irb);
                        return DBUS_ERR;
@@ -376,18 +390,18 @@ dbus_irbq_init(dbus_info_t *dbus_info, dbus_irbq_t *q, int nq, int size_irb)
 
 /** called during detach phase or when attach failed */
 static int
-dbus_irbq_deinit(dbus_info_t *dbus_info, dbus_irbq_t *q, int size_irb)
+dbus_irbq_deinit(dhd_bus_t *dhd_bus, dbus_irbq_t *q, int size_irb)
 {
        dbus_irb_t *irb;
 
        ASSERT(q);
-       ASSERT(dbus_info);
+       ASSERT(dhd_bus);
 
        /* q_deq() does not need to go through EXEC_xxLOCK()
         * during deinit(); all callbacks are stopped by this time
         */
        while ((irb = q_deq(q)) != NULL) {
-               MFREE(dbus_info->pub.osh, irb, size_irb);
+               MFREE(dhd_bus->pub.osh, irb, size_irb);
        }
 
        if (q->cnt)
@@ -397,7 +411,7 @@ dbus_irbq_deinit(dbus_info_t *dbus_info, dbus_irbq_t *q, int size_irb)
 
 /** multiple code paths require the rx queue to be filled with more free IRBs */
 static int
-dbus_rxirbs_fill(dbus_info_t *dbus_info)
+dbus_rxirbs_fill(dhd_bus_t *dhd_bus)
 {
        int err = DBUS_OK;
 
@@ -405,11 +419,11 @@ dbus_rxirbs_fill(dbus_info_t *dbus_info)
        dbus_irb_rx_t *rxirb;
        struct exec_parms args;
 
-       ASSERT(dbus_info);
-       if (dbus_info->pub.busstate != DBUS_STATE_UP) {
+       ASSERT(dhd_bus);
+       if (dhd_bus->pub.busstate != DBUS_STATE_UP) {
                DBUSERR(("dbus_rxirbs_fill: DBUS not up \n"));
                return DBUS_ERR;
-       } else if (!dbus_info->drvintf || (dbus_info->drvintf->recv_irb == NULL)) {
+       } else if (!dhd_bus->drvintf || (dhd_bus->drvintf->recv_irb == NULL)) {
                /* Lower edge bus interface does not support recv_irb().
                 * No need to pre-submit IRBs in this case.
                 */
@@ -420,18 +434,18 @@ dbus_rxirbs_fill(dbus_info_t *dbus_info)
         *  refill) can run in parallel. While the rxoff condition is triggered outside,
         *  below while loop has to check and abort posting more to avoid RPC rxq overflow.
         */
-       args.qdeq.q = dbus_info->rx_q;
-       while ((!dbus_info->rxoff) &&
-              (rxirb = (EXEC_RXLOCK(dbus_info, q_deq_exec, &args))) != NULL) {
-               err = dbus_info->drvintf->recv_irb(dbus_info->bus_info, rxirb);
+       args.qdeq.q = dhd_bus->rx_q;
+       while ((!dhd_bus->rxoff) &&
+              (rxirb = (EXEC_RXLOCK(dhd_bus, q_deq_exec, &args))) != NULL) {
+               err = dhd_bus->drvintf->recv_irb(dhd_bus->bus_info, rxirb);
                if (err == DBUS_ERR_RXDROP || err == DBUS_ERR_RXFAIL) {
                        /* Add the the free rxirb back to the queue
                         * and wait till later
                         */
                        bzero(rxirb, sizeof(dbus_irb_rx_t));
-                       args.qenq.q = dbus_info->rx_q;
+                       args.qenq.q = dhd_bus->rx_q;
                        args.qenq.b = (dbus_irb_t *) rxirb;
-                       EXEC_RXLOCK(dbus_info, q_enq_exec, &args);
+                       EXEC_RXLOCK(dhd_bus, q_enq_exec, &args);
                        break;
                } else if (err != DBUS_OK) {
                        int i = 0;
@@ -447,30 +461,30 @@ dbus_rxirbs_fill(dbus_info_t *dbus_info)
 void
 dbus_flowctrl_rx(dbus_pub_t *pub, bool on)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info->rxoff == on)
+       if (dhd_bus->rxoff == on)
                return;
 
-       dbus_info->rxoff = on;
+       dhd_bus->rxoff = on;
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP) {
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
                if (!on) {
                        /* post more irbs, resume rx if necessary */
-                       dbus_rxirbs_fill(dbus_info);
-                       if (dbus_info && dbus_info->drvintf->recv_resume) {
-                               dbus_info->drvintf->recv_resume(dbus_info->bus_info);
+                       dbus_rxirbs_fill(dhd_bus);
+                       if (dhd_bus && dhd_bus->drvintf->recv_resume) {
+                               dhd_bus->drvintf->recv_resume(dhd_bus->bus_info);
                        }
                } else {
                        /* ??? cancell posted irbs first */
 
-                       if (dbus_info && dbus_info->drvintf->recv_stop) {
-                               dbus_info->drvintf->recv_stop(dbus_info->bus_info);
+                       if (dhd_bus && dhd_bus->drvintf->recv_stop) {
+                               dhd_bus->drvintf->recv_stop(dhd_bus->bus_info);
                        }
                }
        }
@@ -483,22 +497,22 @@ dbus_flowctrl_rx(dbus_pub_t *pub, bool on)
 static int
 dbus_send_irb(dbus_pub_t *pub, uint8 *buf, int len, void *pkt, void *info)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_OK;
        dbus_irb_tx_t *txirb = NULL;
        int txirb_pending;
        struct exec_parms args;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP ||
-               dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
-               args.qdeq.q = dbus_info->tx_q;
-               if (dbus_info->drvintf)
-                       txirb = EXEC_TXLOCK(dbus_info, q_deq_exec, &args);
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+               dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+               args.qdeq.q = dhd_bus->tx_q;
+               if (dhd_bus->drvintf)
+                       txirb = EXEC_TXLOCK(dhd_bus, q_deq_exec, &args);
 
                if (txirb == NULL) {
                        DBUSERR(("Out of tx dbus_bufs\n"));
@@ -520,21 +534,21 @@ dbus_send_irb(dbus_pub_t *pub, uint8 *buf, int len, void *pkt, void *info)
                txirb->arg = NULL;
                txirb->retry_count = 0;
 
-               if (dbus_info->drvintf && dbus_info->drvintf->send_irb) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->send_irb) {
                        /* call lower DBUS level send_irb function */
-                       err = dbus_info->drvintf->send_irb(dbus_info->bus_info, txirb);
+                       err = dhd_bus->drvintf->send_irb(dhd_bus->bus_info, txirb);
                        if (err == DBUS_ERR_TXDROP) {
                                /* tx fail and no completion routine to clean up, reclaim irb NOW */
                                DBUSERR(("%s: send_irb failed, status = %d\n", __FUNCTION__, err));
                                bzero(txirb, sizeof(dbus_irb_tx_t));
-                               args.qenq.q = dbus_info->tx_q;
+                               args.qenq.q = dhd_bus->tx_q;
                                args.qenq.b = (dbus_irb_t *) txirb;
-                               EXEC_TXLOCK(dbus_info, q_enq_exec, &args);
+                               EXEC_TXLOCK(dhd_bus, q_enq_exec, &args);
                        } else {
-                               dbus_tx_timer_start(dbus_info, DBUS_TX_TIMEOUT_INTERVAL);
-                               txirb_pending = dbus_info->pub.ntxq - dbus_info->tx_q->cnt;
-                               if (txirb_pending > (dbus_info->tx_low_watermark * 3)) {
-                                       dbus_flowctrl_tx(dbus_info, TRUE);
+                               dbus_tx_timer_start(dhd_bus, DBUS_TX_TIMEOUT_INTERVAL);
+                               txirb_pending = dhd_bus->pub.ntxq - dhd_bus->tx_q->cnt;
+                               if (txirb_pending > (dhd_bus->tx_low_watermark * 3)) {
+                                       dbus_flowctrl_tx(dhd_bus, TRUE);
                                }
                        }
                }
@@ -585,6 +599,177 @@ check_file(osl_t *osh, unsigned char *headers)
        return -1;
 }
 
+#ifdef EXTERNAL_FW_PATH
+static int
+dbus_get_fw_nvram(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path)
+{
+       int bcmerror = -1, i;
+       uint len, total_len;
+       void *nv_image = NULL, *fw_image = NULL;
+       char *nv_memblock = NULL, *fw_memblock = NULL;
+       char *bufp;
+       bool file_exists;
+       uint8 nvram_words_pad = 0;
+       uint memblock_size = 2048;
+       uint8 *memptr;
+       int     actual_fwlen;
+       struct trx_header *hdr;
+       uint32 img_offset = 0;
+       int offset = 0;
+
+       /* For Get nvram */
+       file_exists = ((pnv_path != NULL) && (pnv_path[0] != '\0'));
+       if (file_exists) {
+               nv_image = dhd_os_open_image(pnv_path);
+               if (nv_image == NULL) {
+                       printf("%s: Open nvram file failed %s\n", __FUNCTION__, pnv_path);
+                       goto err;
+               }
+       }
+       nv_memblock = MALLOC(dhd_bus->pub.osh, MAX_NVRAMBUF_SIZE);
+       if (nv_memblock == NULL) {
+               DBUSERR(("%s: Failed to allocate memory %d bytes\n",
+                          __FUNCTION__, MAX_NVRAMBUF_SIZE));
+               goto err;
+       }
+       len = dhd_os_get_image_block(nv_memblock, MAX_NVRAMBUF_SIZE, nv_image);
+       if (len > 0 && len < MAX_NVRAMBUF_SIZE) {
+               bufp = (char *)nv_memblock;
+               bufp[len] = 0;
+               dhd_bus->nvram_len = process_nvram_vars(bufp, len);
+               if (dhd_bus->nvram_len % 4)
+                       nvram_words_pad = 4 - dhd_bus->nvram_len % 4;
+       } else {
+               DBUSERR(("%s: error reading nvram file: %d\n", __FUNCTION__, len));
+               bcmerror = DBUS_ERR_NVRAM;
+               goto err;
+       }
+       if (nv_image)
+               dhd_os_close_image(nv_image);
+
+       /* For Get first block of fw to calculate total_len */
+       file_exists = ((pfw_path != NULL) && (pfw_path[0] != '\0'));
+       if (file_exists) {
+               fw_image = dhd_os_open_image(pfw_path);
+               if (fw_image == NULL) {
+                       printf("%s: Open fw file failed %s\n", __FUNCTION__, pfw_path);
+                       goto err;
+               }
+       }
+       memptr = fw_memblock = MALLOC(dhd_bus->pub.osh, memblock_size);
+       if (fw_memblock == NULL) {
+               DBUSERR(("%s: Failed to allocate memory %d bytes\n", __FUNCTION__,
+                       memblock_size));
+               goto err;
+       }
+       len = dhd_os_get_image_block((char*)memptr, memblock_size, fw_image);
+       if ((actual_fwlen = check_file(dhd_bus->pub.osh, memptr)) <= 0) {
+               DBUSERR(("%s: bad firmware format!\n", __FUNCTION__));
+               goto err;
+       }
+
+       total_len = actual_fwlen + dhd_bus->nvram_len + nvram_words_pad;
+       dhd_bus->image = MALLOC(dhd_bus->pub.osh, total_len);
+       dhd_bus->image_len = total_len;
+       if (dhd_bus->image == NULL) {
+               DBUSERR(("%s: malloc failed!\n", __FUNCTION__));
+               goto err;
+       }
+
+       /* Step1: Copy trx header + firmwre */
+       memptr = fw_memblock;
+       do {
+               if (len < 0) {
+                       DBUSERR(("%s: dhd_os_get_image_block failed (%d)\n", __FUNCTION__, len));
+                       bcmerror = BCME_ERROR;
+                       goto err;
+               }
+               bcopy(memptr, dhd_bus->image+offset, len);
+               offset += len;
+       } while ((len = dhd_os_get_image_block((char*)memptr, memblock_size, fw_image)));
+       /* Step2: Copy NVRAM + pad */
+       hdr = (struct trx_header *)dhd_bus->image;
+       img_offset = SIZEOF_TRX(hdr) + hdr->offsets[TRX_OFFSETS_DLFWLEN_IDX];
+       bcopy(nv_memblock, (uint8 *)(dhd_bus->image + img_offset),
+               dhd_bus->nvram_len);
+       img_offset += dhd_bus->nvram_len;
+       if (nvram_words_pad) {
+               bzero(&dhd_bus->image[img_offset], nvram_words_pad);
+               img_offset += nvram_words_pad;
+       }
+#ifdef BCMTRXV2
+       /* Step3: Copy DSG/CFG for V2 */
+       if (ISTRX_V2(hdr) &&
+               (hdr->offsets[TRX_OFFSETS_DSG_LEN_IDX] ||
+               hdr->offsets[TRX_OFFSETS_CFG_LEN_IDX])) {
+               DBUSERR(("%s: fix me\n", __FUNCTION__));
+       }
+#endif /* BCMTRXV2 */
+       /* Step4: update TRX header for nvram size */
+       hdr = (struct trx_header *)dhd_bus->image;
+       hdr->len = htol32(total_len);
+       /* Pass the actual fw len */
+       hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX] =
+               htol32(dhd_bus->nvram_len + nvram_words_pad);
+       /* Calculate CRC over header */
+       hdr->crc32 = hndcrc32((uint8 *)&hdr->flag_version,
+               SIZEOF_TRX(hdr) - OFFSETOF(struct trx_header, flag_version),
+               CRC32_INIT_VALUE);
+
+       /* Calculate CRC over data */
+       for (i = SIZEOF_TRX(hdr); i < total_len; ++i)
+                       hdr->crc32 = hndcrc32((uint8 *)&dhd_bus->image[i], 1, hdr->crc32);
+       hdr->crc32 = htol32(hdr->crc32);
+
+       bcmerror = DBUS_OK;
+
+err:
+       if (fw_memblock)
+               MFREE(dhd_bus->pub.osh, fw_memblock, MAX_NVRAMBUF_SIZE);
+       if (fw_image)
+               dhd_os_close_image(fw_image);
+       if (nv_memblock)
+               MFREE(dhd_bus->pub.osh, nv_memblock, MAX_NVRAMBUF_SIZE);
+       if (nv_image)
+               dhd_os_close_image(nv_image);
+
+       return bcmerror;
+}
+
+/**
+ * during driver initialization ('attach') or after PnP 'resume', firmware needs to be loaded into
+ * the dongle
+ */
+static int
+dbus_do_download(dhd_bus_t *dhd_bus, char *pfw_path, char *pnv_path)
+{
+       int err = DBUS_OK;
+
+       err = dbus_get_fw_nvram(dhd_bus, pfw_path, pnv_path);
+       if (err) {
+               DBUSERR(("dbus_do_download: fail to get nvram %d\n", err));
+               return err;
+       }
+
+       if (dhd_bus->drvintf->dlstart && dhd_bus->drvintf->dlrun) {
+               err = dhd_bus->drvintf->dlstart(dhd_bus->bus_info,
+                       dhd_bus->image, dhd_bus->image_len);
+               if (err == DBUS_OK) {
+                       err = dhd_bus->drvintf->dlrun(dhd_bus->bus_info);
+               }
+       } else
+               err = DBUS_ERR;
+
+       if (dhd_bus->image) {
+               MFREE(dhd_bus->pub.osh, dhd_bus->image, dhd_bus->image_len);
+               dhd_bus->image = NULL;
+               dhd_bus->image_len = 0;
+       }
+
+       return err;
+} /* dbus_do_download */
+#else
+
 /**
  * It is easy for the user to pass one jumbo nvram file to the driver than a set of smaller files.
  * The 'jumbo nvram' file format is essentially a set of nvram files. Before commencing firmware
@@ -592,7 +777,7 @@ check_file(osl_t *osh, unsigned char *headers)
  * file is selected.
  */
 static int
-dbus_jumbo_nvram(dbus_info_t *dbus_info)
+dbus_jumbo_nvram(dhd_bus_t *dhd_bus)
 {
        int8 *nvram = NULL;
        int nvram_len = 0;
@@ -604,9 +789,9 @@ dbus_jumbo_nvram(dbus_info_t *dbus_info)
        * if boardtype/rev are present in otp
        * select nvram data for that boardtype/rev
        */
-       dbus_otp(dbus_info, &boardtype, &boardrev);
+       dbus_otp(dhd_bus, &boardtype, &boardrev);
 
-       ret = dbus_select_nvram(dbus_info, dbus_info->extdl.vars, dbus_info->extdl.varslen,
+       ret = dbus_select_nvram(dhd_bus, dhd_bus->extdl.vars, dhd_bus->extdl.varslen,
                boardtype, boardrev, &nvram, &nvram_len);
 
        if (ret == DBUS_JUMBO_BAD_FORMAT)
@@ -617,69 +802,69 @@ dbus_jumbo_nvram(dbus_info_t *dbus_info)
                                boardtype, boardrev));
                        return DBUS_ERR_NVRAM;
        }
-       dbus_info->nvram = nvram;
-       dbus_info->nvram_len =  nvram_len;
+       dhd_bus->nvram = nvram;
+       dhd_bus->nvram_len =  nvram_len;
 
        return DBUS_OK;
 }
 
 /** before commencing fw download, the correct NVRAM image to download has to be picked */
 static int
-dbus_get_nvram(dbus_info_t *dbus_info)
+dbus_get_nvram(dhd_bus_t *dhd_bus)
 {
        int len, i;
        struct trx_header *hdr;
        int     actual_fwlen;
        uint32 img_offset = 0;
 
-       dbus_info->nvram_len = 0;
-       if (dbus_info->extdl.varslen) {
-               if (DBUS_OK != dbus_jumbo_nvram(dbus_info))
+       dhd_bus->nvram_len = 0;
+       if (dhd_bus->extdl.varslen) {
+               if (DBUS_OK != dbus_jumbo_nvram(dhd_bus))
                        return DBUS_ERR_NVRAM;
-               DBUSERR(("NVRAM %d bytes downloaded\n", dbus_info->nvram_len));
+               DBUSERR(("NVRAM %d bytes downloaded\n", dhd_bus->nvram_len));
        }
 #if defined(BCM_REQUEST_FW)
        else if (nonfwnvram) {
-               dbus_info->nvram = nonfwnvram;
-               dbus_info->nvram_len = nonfwnvramlen;
-               DBUSERR(("NVRAM %d bytes downloaded\n", dbus_info->nvram_len));
+               dhd_bus->nvram = nonfwnvram;
+               dhd_bus->nvram_len = nonfwnvramlen;
+               DBUSERR(("NVRAM %d bytes downloaded\n", dhd_bus->nvram_len));
        }
 #endif
-       if (dbus_info->nvram) {
+       if (dhd_bus->nvram) {
                uint8 nvram_words_pad = 0;
                /* Validate the format/length etc of the file */
-               if ((actual_fwlen = check_file(dbus_info->pub.osh, dbus_info->fw)) <= 0) {
+               if ((actual_fwlen = check_file(dhd_bus->pub.osh, dhd_bus->fw)) <= 0) {
                        DBUSERR(("%s: bad firmware format!\n", __FUNCTION__));
                        return DBUS_ERR_NVRAM;
                }
 
-               if (!dbus_info->nvram_nontxt) {
+               if (!dhd_bus->nvram_nontxt) {
                        /* host supplied nvram could be in .txt format
                        * with all the comments etc...
                        */
-                       dbus_info->nvram_len = process_nvram_vars(dbus_info->nvram,
-                               dbus_info->nvram_len);
+                       dhd_bus->nvram_len = process_nvram_vars(dhd_bus->nvram,
+                               dhd_bus->nvram_len);
                }
-               if (dbus_info->nvram_len % 4)
-                       nvram_words_pad = 4 - dbus_info->nvram_len % 4;
+               if (dhd_bus->nvram_len % 4)
+                       nvram_words_pad = 4 - dhd_bus->nvram_len % 4;
 
-               len = actual_fwlen + dbus_info->nvram_len + nvram_words_pad;
-               dbus_info->image = MALLOC(dbus_info->pub.osh, len);
-               dbus_info->image_len = len;
-               if (dbus_info->image == NULL) {
+               len = actual_fwlen + dhd_bus->nvram_len + nvram_words_pad;
+               dhd_bus->image = MALLOC(dhd_bus->pub.osh, len);
+               dhd_bus->image_len = len;
+               if (dhd_bus->image == NULL) {
                        DBUSERR(("%s: malloc failed!\n", __FUNCTION__));
                        return DBUS_ERR_NVRAM;
                }
-               hdr = (struct trx_header *)dbus_info->fw;
+               hdr = (struct trx_header *)dhd_bus->fw;
                /* Step1: Copy trx header + firmwre */
                img_offset = SIZEOF_TRX(hdr) + hdr->offsets[TRX_OFFSETS_DLFWLEN_IDX];
-               bcopy(dbus_info->fw, dbus_info->image, img_offset);
+               bcopy(dhd_bus->fw, dhd_bus->image, img_offset);
                /* Step2: Copy NVRAM + pad */
-               bcopy(dbus_info->nvram, (uint8 *)(dbus_info->image + img_offset),
-                       dbus_info->nvram_len);
-               img_offset += dbus_info->nvram_len;
+               bcopy(dhd_bus->nvram, (uint8 *)(dhd_bus->image + img_offset),
+                       dhd_bus->nvram_len);
+               img_offset += dhd_bus->nvram_len;
                if (nvram_words_pad) {
-                       bzero(&dbus_info->image[img_offset],
+                       bzero(&dhd_bus->image[img_offset],
                                nvram_words_pad);
                        img_offset += nvram_words_pad;
                }
@@ -689,10 +874,10 @@ dbus_get_nvram(dbus_info_t *dbus_info)
                        (hdr->offsets[TRX_OFFSETS_DSG_LEN_IDX] ||
                        hdr->offsets[TRX_OFFSETS_CFG_LEN_IDX])) {
 
-                       bcopy(dbus_info->fw + SIZEOF_TRX(hdr) +
+                       bcopy(dhd_bus->fw + SIZEOF_TRX(hdr) +
                                hdr->offsets[TRX_OFFSETS_DLFWLEN_IDX] +
                                hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX],
-                               dbus_info->image + img_offset,
+                               dhd_bus->image + img_offset,
                                hdr->offsets[TRX_OFFSETS_DSG_LEN_IDX] +
                                hdr->offsets[TRX_OFFSETS_CFG_LEN_IDX]);
 
@@ -701,11 +886,11 @@ dbus_get_nvram(dbus_info_t *dbus_info)
                }
 #endif /* BCMTRXV2 */
                /* Step4: update TRX header for nvram size */
-               hdr = (struct trx_header *)dbus_info->image;
+               hdr = (struct trx_header *)dhd_bus->image;
                hdr->len = htol32(len);
                /* Pass the actual fw len */
                hdr->offsets[TRX_OFFSETS_NVM_LEN_IDX] =
-                       htol32(dbus_info->nvram_len + nvram_words_pad);
+                       htol32(dhd_bus->nvram_len + nvram_words_pad);
                /* Calculate CRC over header */
                hdr->crc32 = hndcrc32((uint8 *)&hdr->flag_version,
                        SIZEOF_TRX(hdr) - OFFSETOF(struct trx_header, flag_version),
@@ -713,11 +898,11 @@ dbus_get_nvram(dbus_info_t *dbus_info)
 
                /* Calculate CRC over data */
                for (i = SIZEOF_TRX(hdr); i < len; ++i)
-                               hdr->crc32 = hndcrc32((uint8 *)&dbus_info->image[i], 1, hdr->crc32);
+                               hdr->crc32 = hndcrc32((uint8 *)&dhd_bus->image[i], 1, hdr->crc32);
                hdr->crc32 = htol32(hdr->crc32);
        } else {
-               dbus_info->image = dbus_info->fw;
-               dbus_info->image_len = (uint32)dbus_info->fwlen;
+               dhd_bus->image = dhd_bus->fw;
+               dhd_bus->image_len = (uint32)dhd_bus->fwlen;
        }
 
        return DBUS_OK;
@@ -728,7 +913,7 @@ dbus_get_nvram(dbus_info_t *dbus_info)
  * the dongle
  */
 static int
-dbus_do_download(dbus_info_t *dbus_info)
+dbus_do_download(dhd_bus_t *dhd_bus)
 {
        int err = DBUS_OK;
 #ifndef BCM_REQUEST_FW
@@ -741,19 +926,19 @@ dbus_do_download(dbus_info_t *dbus_info)
 #endif
 
 #if defined(BCM_REQUEST_FW)
-       dbus_info->firmware = dbus_get_fw_nvfile(dbus_info->pub.attrib.devid,
-               dbus_info->pub.attrib.chiprev, &dbus_info->fw, &dbus_info->fwlen,
+       dhd_bus->firmware = dbus_get_fw_nvfile(dhd_bus->pub.attrib.devid,
+               dhd_bus->pub.attrib.chiprev, &dhd_bus->fw, &dhd_bus->fwlen,
                DBUS_FIRMWARE, 0, 0);
-       if (!dbus_info->firmware)
+       if (!dhd_bus->firmware)
                return DBUS_ERR;
 #endif 
 
-       dbus_info->image = dbus_info->fw;
-       dbus_info->image_len = (uint32)dbus_info->fwlen;
+       dhd_bus->image = dhd_bus->fw;
+       dhd_bus->image_len = (uint32)dhd_bus->fwlen;
 
 #ifndef BCM_REQUEST_FW
-       if (UNZIP_ENAB(dbus_info) && !decomp_override) {
-               err = dbus_zlib_decomp(dbus_info);
+       if (UNZIP_ENAB(dhd_bus) && !decomp_override) {
+               err = dbus_zlib_decomp(dhd_bus);
                if (err) {
                        DBUSERR(("dbus_attach: fw decompress fail %d\n", err));
                        return err;
@@ -763,15 +948,15 @@ dbus_do_download(dbus_info_t *dbus_info)
 
 #if defined(BCM_REQUEST_FW)
        /* check if firmware is appended with nvram file */
-       err = dbus_otp(dbus_info, &boardtype, &boardrev);
+       err = dbus_otp(dhd_bus, &boardtype, &boardrev);
        /* check if nvram is provided as separte file */
        nonfwnvram = NULL;
        nonfwnvramlen = 0;
-       dbus_info->nvfile = dbus_get_fw_nvfile(dbus_info->pub.attrib.devid,
-               dbus_info->pub.attrib.chiprev, (void *)&temp_nvram, &temp_len,
+       dhd_bus->nvfile = dbus_get_fw_nvfile(dhd_bus->pub.attrib.devid,
+               dhd_bus->pub.attrib.chiprev, (void *)&temp_nvram, &temp_len,
                DBUS_NVFILE, boardtype, boardrev);
-       if (dbus_info->nvfile) {
-               int8 *tmp = MALLOC(dbus_info->pub.osh, temp_len);
+       if (dhd_bus->nvfile) {
+               int8 *tmp = MALLOC(dhd_bus->pub.osh, temp_len);
                if (tmp) {
                        bcopy(temp_nvram, tmp, temp_len);
                        nonfwnvram = tmp;
@@ -783,56 +968,56 @@ dbus_do_download(dbus_info_t *dbus_info)
        }
 #endif /* defined(BCM_REQUEST_FW) */
 
-       err = dbus_get_nvram(dbus_info);
+       err = dbus_get_nvram(dhd_bus);
        if (err) {
                DBUSERR(("dbus_do_download: fail to get nvram %d\n", err));
                return err;
        }
 
 
-       if (dbus_info->drvintf->dlstart && dbus_info->drvintf->dlrun) {
-               err = dbus_info->drvintf->dlstart(dbus_info->bus_info,
-                       dbus_info->image, dbus_info->image_len);
+       if (dhd_bus->drvintf->dlstart && dhd_bus->drvintf->dlrun) {
+               err = dhd_bus->drvintf->dlstart(dhd_bus->bus_info,
+                       dhd_bus->image, dhd_bus->image_len);
 
                if (err == DBUS_OK)
-                       err = dbus_info->drvintf->dlrun(dbus_info->bus_info);
+                       err = dhd_bus->drvintf->dlrun(dhd_bus->bus_info);
        } else
                err = DBUS_ERR;
 
-       if (dbus_info->nvram) {
-               MFREE(dbus_info->pub.osh, dbus_info->image, dbus_info->image_len);
-               dbus_info->image = dbus_info->fw;
-               dbus_info->image_len = (uint32)dbus_info->fwlen;
+       if (dhd_bus->nvram) {
+               MFREE(dhd_bus->pub.osh, dhd_bus->image, dhd_bus->image_len);
+               dhd_bus->image = dhd_bus->fw;
+               dhd_bus->image_len = (uint32)dhd_bus->fwlen;
        }
 
 #ifndef BCM_REQUEST_FW
-       if (UNZIP_ENAB(dbus_info) && (!decomp_override) && dbus_info->orig_fw) {
-               MFREE(dbus_info->pub.osh, dbus_info->fw, dbus_info->decomp_memsize);
-               dbus_info->image = dbus_info->fw = dbus_info->orig_fw;
-               dbus_info->image_len = dbus_info->fwlen = dbus_info->origfw_len;
+       if (UNZIP_ENAB(dhd_bus) && (!decomp_override) && dhd_bus->orig_fw) {
+               MFREE(dhd_bus->pub.osh, dhd_bus->fw, dhd_bus->decomp_memsize);
+               dhd_bus->image = dhd_bus->fw = dhd_bus->orig_fw;
+               dhd_bus->image_len = dhd_bus->fwlen = dhd_bus->origfw_len;
        }
 #endif
 
 #if defined(BCM_REQUEST_FW)
 fail:
-       if (dbus_info->firmware) {
-               dbus_release_fw_nvfile(dbus_info->firmware);
-               dbus_info->firmware = NULL;
+       if (dhd_bus->firmware) {
+               dbus_release_fw_nvfile(dhd_bus->firmware);
+               dhd_bus->firmware = NULL;
        }
-       if (dbus_info->nvfile) {
-               dbus_release_fw_nvfile(dbus_info->nvfile);
-               dbus_info->nvfile = NULL;
+       if (dhd_bus->nvfile) {
+               dbus_release_fw_nvfile(dhd_bus->nvfile);
+               dhd_bus->nvfile = NULL;
        }
        if (nonfwnvram) {
-               MFREE(dbus_info->pub.osh, nonfwnvram, nonfwnvramlen);
+               MFREE(dhd_bus->pub.osh, nonfwnvram, nonfwnvramlen);
                nonfwnvram = NULL;
                nonfwnvramlen = 0;
        }
 #endif
        return err;
 } /* dbus_do_download */
-
-#endif 
+#endif /* EXTERNAL_FW_PATH */
+#endif
 
 /** required for DBUS deregistration */
 static void
@@ -851,9 +1036,9 @@ dbus_disconnect(void *handle)
 static void
 dbus_if_send_irb_timeout(void *handle, dbus_irb_tx_t *txirb)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
 
-       if ((dbus_info == NULL) || (dbus_info->drvintf == NULL) || (txirb == NULL)) {
+       if ((dhd_bus == NULL) || (dhd_bus->drvintf == NULL) || (txirb == NULL)) {
                return;
        }
 
@@ -870,41 +1055,41 @@ dbus_if_send_irb_timeout(void *handle, dbus_irb_tx_t *txirb)
 static void BCMFASTPATH
 dbus_if_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
        int txirb_pending;
        struct exec_parms args;
        void *pktinfo;
 
-       if ((dbus_info == NULL) || (txirb == NULL)) {
+       if ((dhd_bus == NULL) || (txirb == NULL)) {
                return;
        }
 
        DBUSTRACE(("%s: status = %d\n", __FUNCTION__, status));
 
-       dbus_tx_timer_stop(dbus_info);
+       dbus_tx_timer_stop(dhd_bus);
 
        /* re-queue BEFORE calling send_complete which will assume that this irb
           is now available.
         */
        pktinfo = txirb->info;
        bzero(txirb, sizeof(dbus_irb_tx_t));
-       args.qenq.q = dbus_info->tx_q;
+       args.qenq.q = dhd_bus->tx_q;
        args.qenq.b = (dbus_irb_t *) txirb;
-       EXEC_TXLOCK(dbus_info, q_enq_exec, &args);
+       EXEC_TXLOCK(dhd_bus, q_enq_exec, &args);
 
-       if (dbus_info->pub.busstate != DBUS_STATE_DOWN) {
+       if (dhd_bus->pub.busstate != DBUS_STATE_DOWN) {
                if ((status == DBUS_OK) || (status == DBUS_ERR_NODEVICE)) {
-                       if (dbus_info->cbs && dbus_info->cbs->send_complete)
-                               dbus_info->cbs->send_complete(dbus_info->cbarg, pktinfo,
+                       if (dhd_bus->cbs && dhd_bus->cbs->send_complete)
+                               dhd_bus->cbs->send_complete(dhd_bus->cbarg, pktinfo,
                                        status);
 
                        if (status == DBUS_OK) {
-                               txirb_pending = dbus_info->pub.ntxq - dbus_info->tx_q->cnt;
+                               txirb_pending = dhd_bus->pub.ntxq - dhd_bus->tx_q->cnt;
                                if (txirb_pending)
-                                       dbus_tx_timer_start(dbus_info, DBUS_TX_TIMEOUT_INTERVAL);
-                               if ((txirb_pending < dbus_info->tx_low_watermark) &&
-                                       dbus_info->txoff && !dbus_info->txoverride) {
-                                       dbus_flowctrl_tx(dbus_info, OFF);
+                                       dbus_tx_timer_start(dhd_bus, DBUS_TX_TIMEOUT_INTERVAL);
+                               if ((txirb_pending < dhd_bus->tx_low_watermark) &&
+                                       dhd_bus->txoff && !dhd_bus->txoverride) {
+                                       dbus_flowctrl_tx(dhd_bus, OFF);
                                }
                        }
                } else {
@@ -912,11 +1097,11 @@ dbus_if_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status)
                                pktinfo));
 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC)
                        if (pktinfo)
-                               if (dbus_info->cbs && dbus_info->cbs->send_complete)
-                                       dbus_info->cbs->send_complete(dbus_info->cbarg, pktinfo,
+                               if (dhd_bus->cbs && dhd_bus->cbs->send_complete)
+                                       dhd_bus->cbs->send_complete(dhd_bus->cbarg, pktinfo,
                                                status);
 #else
-                       dbus_if_pktfree(dbus_info, (void*)pktinfo, TRUE);
+                       dbus_if_pktfree(dhd_bus, (void*)pktinfo, TRUE);
 #endif /* defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC) */
                }
        } else {
@@ -924,11 +1109,11 @@ dbus_if_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status)
                        pktinfo));
 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) || defined(BCM_RPC_TOC)
                if (pktinfo)
-                       if (dbus_info->cbs && dbus_info->cbs->send_complete)
-                               dbus_info->cbs->send_complete(dbus_info->cbarg, pktinfo,
+                       if (dhd_bus->cbs && dhd_bus->cbs->send_complete)
+                               dhd_bus->cbs->send_complete(dhd_bus->cbarg, pktinfo,
                                        status);
 #else
-               dbus_if_pktfree(dbus_info, (void*)pktinfo, TRUE);
+               dbus_if_pktfree(dhd_bus, (void*)pktinfo, TRUE);
 #endif /* defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_TXNOCOPY) defined(BCM_RPC_TOC) */
        }
 } /* dbus_if_send_irb_complete */
@@ -941,16 +1126,16 @@ dbus_if_send_irb_complete(void *handle, dbus_irb_tx_t *txirb, int status)
 static void BCMFASTPATH
 dbus_if_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
        int rxirb_pending;
        struct exec_parms args;
 
-       if ((dbus_info == NULL) || (rxirb == NULL)) {
+       if ((dhd_bus == NULL) || (rxirb == NULL)) {
                return;
        }
        DBUSTRACE(("%s\n", __FUNCTION__));
-       if (dbus_info->pub.busstate != DBUS_STATE_DOWN &&
-               dbus_info->pub.busstate != DBUS_STATE_SLEEP) {
+       if (dhd_bus->pub.busstate != DBUS_STATE_DOWN &&
+               dhd_bus->pub.busstate != DBUS_STATE_SLEEP) {
                if (status == DBUS_OK) {
                        if ((rxirb->buf != NULL) && (rxirb->actual_len > 0)) {
 #ifdef DBUS_USB_LOOPBACK
@@ -958,33 +1143,33 @@ dbus_if_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
                                        matches_loopback_pkt(rxirb->buf);
                                } else
 #endif
-                               if (dbus_info->cbs && dbus_info->cbs->recv_buf) {
-                                       dbus_info->cbs->recv_buf(dbus_info->cbarg, rxirb->buf,
+                               if (dhd_bus->cbs && dhd_bus->cbs->recv_buf) {
+                                       dhd_bus->cbs->recv_buf(dhd_bus->cbarg, rxirb->buf,
                                        rxirb->actual_len);
                                }
                        } else if (rxirb->pkt != NULL) {
-                               if (dbus_info->cbs && dbus_info->cbs->recv_pkt)
-                                       dbus_info->cbs->recv_pkt(dbus_info->cbarg, rxirb->pkt);
+                               if (dhd_bus->cbs && dhd_bus->cbs->recv_pkt)
+                                       dhd_bus->cbs->recv_pkt(dhd_bus->cbarg, rxirb->pkt);
                        } else {
                                ASSERT(0); /* Should not happen */
                        }
 
-                       rxirb_pending = dbus_info->pub.nrxq - dbus_info->rx_q->cnt - 1;
-                       if ((rxirb_pending <= dbus_info->rx_low_watermark) &&
-                               !dbus_info->rxoff) {
+                       rxirb_pending = dhd_bus->pub.nrxq - dhd_bus->rx_q->cnt - 1;
+                       if ((rxirb_pending <= dhd_bus->rx_low_watermark) &&
+                               !dhd_bus->rxoff) {
                                DBUSTRACE(("Low watermark so submit more %d <= %d \n",
-                                       dbus_info->rx_low_watermark, rxirb_pending));
-                               dbus_rxirbs_fill(dbus_info);
-                       } else if (dbus_info->rxoff)
+                                       dhd_bus->rx_low_watermark, rxirb_pending));
+                               dbus_rxirbs_fill(dhd_bus);
+                       } else if (dhd_bus->rxoff)
                                DBUSTRACE(("rx flow controlled. not filling more. cut_rxq=%d\n",
-                                       dbus_info->rx_q->cnt));
+                                       dhd_bus->rx_q->cnt));
                } else if (status == DBUS_ERR_NODEVICE) {
                        DBUSERR(("%s: %d status = %d, buf %p\n", __FUNCTION__, __LINE__, status,
                                rxirb->buf));
 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
                        if (rxirb->buf) {
-                               PKTFRMNATIVE(dbus_info->pub.osh, rxirb->buf);
-                               PKTFREE(dbus_info->pub.osh, rxirb->buf, FALSE);
+                               PKTFRMNATIVE(dhd_bus->pub.osh, rxirb->buf);
+                               PKTFREE(dhd_bus->pub.osh, rxirb->buf, FALSE);
                        }
 #endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY || BCM_RPC_TOC */
                } else {
@@ -993,8 +1178,8 @@ dbus_if_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
                                        status, rxirb->buf));
 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
                        if (rxirb->buf) {
-                               PKTFRMNATIVE(dbus_info->pub.osh, rxirb->buf);
-                               PKTFREE(dbus_info->pub.osh, rxirb->buf, FALSE);
+                               PKTFRMNATIVE(dhd_bus->pub.osh, rxirb->buf);
+                               PKTFREE(dhd_bus->pub.osh, rxirb->buf, FALSE);
                        }
 #endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY || BCM_RPC_TOC */
                }
@@ -1003,18 +1188,18 @@ dbus_if_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
                        rxirb->buf));
 #if defined(BCM_RPC_NOCOPY) || defined(BCM_RPC_RXNOCOPY)
                if (rxirb->buf) {
-                       PKTFRMNATIVE(dbus_info->pub.osh, rxirb->buf);
-                       PKTFREE(dbus_info->pub.osh, rxirb->buf, FALSE);
+                       PKTFRMNATIVE(dhd_bus->pub.osh, rxirb->buf);
+                       PKTFREE(dhd_bus->pub.osh, rxirb->buf, FALSE);
                }
 #endif /* BCM_RPC_NOCOPY || BCM_RPC_TXNOCOPY || BCM_RPC_TOC */
        }
-       if (dbus_info->rx_q != NULL) {
+       if (dhd_bus->rx_q != NULL) {
                bzero(rxirb, sizeof(dbus_irb_rx_t));
-               args.qenq.q = dbus_info->rx_q;
+               args.qenq.q = dhd_bus->rx_q;
                args.qenq.b = (dbus_irb_t *) rxirb;
-               EXEC_RXLOCK(dbus_info, q_enq_exec, &args);
+               EXEC_RXLOCK(dhd_bus, q_enq_exec, &args);
        } else
-               MFREE(dbus_info->pub.osh, rxirb, sizeof(dbus_irb_tx_t));
+               MFREE(dhd_bus->pub.osh, rxirb, sizeof(dbus_irb_tx_t));
 } /* dbus_if_recv_irb_complete */
 
 /**
@@ -1024,35 +1209,35 @@ dbus_if_recv_irb_complete(void *handle, dbus_irb_rx_t *rxirb, int status)
 static void
 dbus_if_errhandler(void *handle, int err)
 {
-       dbus_info_t *dbus_info = handle;
+       dhd_bus_t *dhd_bus = handle;
        uint32 mask = 0;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
        switch (err) {
                case DBUS_ERR_TXFAIL:
-                       dbus_info->pub.stats.tx_errors++;
+                       dhd_bus->pub.stats.tx_errors++;
                        mask |= ERR_CBMASK_TXFAIL;
                        break;
                case DBUS_ERR_TXDROP:
-                       dbus_info->pub.stats.tx_dropped++;
+                       dhd_bus->pub.stats.tx_dropped++;
                        mask |= ERR_CBMASK_TXFAIL;
                        break;
                case DBUS_ERR_RXFAIL:
-                       dbus_info->pub.stats.rx_errors++;
+                       dhd_bus->pub.stats.rx_errors++;
                        mask |= ERR_CBMASK_RXFAIL;
                        break;
                case DBUS_ERR_RXDROP:
-                       dbus_info->pub.stats.rx_dropped++;
+                       dhd_bus->pub.stats.rx_dropped++;
                        mask |= ERR_CBMASK_RXFAIL;
                        break;
                default:
                        break;
        }
 
-       if (dbus_info->cbs && dbus_info->cbs->errhandler && (dbus_info->errmask & mask))
-               dbus_info->cbs->errhandler(dbus_info->cbarg, err);
+       if (dhd_bus->cbs && dhd_bus->cbs->errhandler && (dhd_bus->errmask & mask))
+               dhd_bus->cbs->errhandler(dhd_bus->cbarg, err);
 }
 
 /**
@@ -1062,18 +1247,18 @@ dbus_if_errhandler(void *handle, int err)
 static void
 dbus_if_ctl_complete(void *handle, int type, int status)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL) {
-               DBUSERR(("%s: dbus_info is NULL\n", __FUNCTION__));
+       if (dhd_bus == NULL) {
+               DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
                return;
        }
 
-       if (dbus_info->pub.busstate != DBUS_STATE_DOWN) {
-               if (dbus_info->cbs && dbus_info->cbs->ctl_complete)
-                       dbus_info->cbs->ctl_complete(dbus_info->cbarg, type, status);
+       if (dhd_bus->pub.busstate != DBUS_STATE_DOWN) {
+               if (dhd_bus->cbs && dhd_bus->cbs->ctl_complete)
+                       dhd_bus->cbs->ctl_complete(dhd_bus->cbarg, type, status);
        }
 }
 
@@ -1085,15 +1270,15 @@ dbus_if_ctl_complete(void *handle, int type, int status)
 static void
 dbus_if_state_change(void *handle, int state)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
        int old_state;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
-       if (dbus_info->pub.busstate == state)
+       if (dhd_bus->pub.busstate == state)
                return;
-       old_state = dbus_info->pub.busstate;
+       old_state = dhd_bus->pub.busstate;
        if (state == DBUS_STATE_DISCONNECT) {
                DBUSERR(("DBUS disconnected\n"));
        }
@@ -1106,32 +1291,32 @@ dbus_if_state_change(void *handle, int state)
 
        /* Don't update state if it's PnP firmware re-download */
        if (state != DBUS_STATE_PNP_FWDL)
-               dbus_info->pub.busstate = state;
+               dhd_bus->pub.busstate = state;
        else
                dbus_flowctrl_rx(handle, FALSE);
        if (state == DBUS_STATE_SLEEP)
                dbus_flowctrl_rx(handle, TRUE);
        if (state == DBUS_STATE_UP) {
-               dbus_rxirbs_fill(dbus_info);
+               dbus_rxirbs_fill(dhd_bus);
                dbus_flowctrl_rx(handle, FALSE);
        }
 
-       if (dbus_info->cbs && dbus_info->cbs->state_change)
-               dbus_info->cbs->state_change(dbus_info->cbarg, state);
+       if (dhd_bus->cbs && dhd_bus->cbs->state_change)
+               dhd_bus->cbs->state_change(dhd_bus->cbarg, state);
 }
 
 /** Forward request for packet from lower DBUS layer to higher layer (e.g. dhd_linux.c) */
 static void *
 dbus_if_pktget(void *handle, uint len, bool send)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
        void *p = NULL;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return NULL;
 
-       if (dbus_info->cbs && dbus_info->cbs->pktget)
-               p = dbus_info->cbs->pktget(dbus_info->cbarg, len, send);
+       if (dhd_bus->cbs && dhd_bus->cbs->pktget)
+               p = dhd_bus->cbs->pktget(dhd_bus->cbarg, len, send);
        else
                ASSERT(0);
 
@@ -1142,13 +1327,13 @@ dbus_if_pktget(void *handle, uint len, bool send)
 static void
 dbus_if_pktfree(void *handle, void *p, bool send)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) handle;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) handle;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
-       if (dbus_info->cbs && dbus_info->cbs->pktfree)
-               dbus_info->cbs->pktfree(dbus_info->cbarg, p, send);
+       if (dhd_bus->cbs && dhd_bus->cbs->pktfree)
+               dhd_bus->cbs->pktfree(dhd_bus->cbarg, p, send);
        else
                ASSERT(0);
 }
@@ -1157,19 +1342,19 @@ dbus_if_pktfree(void *handle, void *p, bool send)
 static struct dbus_irb*
 dbus_if_getirb(void *cbarg, bool send)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) cbarg;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) cbarg;
        struct exec_parms args;
        struct dbus_irb *irb;
 
-       if ((dbus_info == NULL) || (dbus_info->pub.busstate != DBUS_STATE_UP))
+       if ((dhd_bus == NULL) || (dhd_bus->pub.busstate != DBUS_STATE_UP))
                return NULL;
 
        if (send == TRUE) {
-               args.qdeq.q = dbus_info->tx_q;
-               irb = EXEC_TXLOCK(dbus_info, q_deq_exec, &args);
+               args.qdeq.q = dhd_bus->tx_q;
+               irb = EXEC_TXLOCK(dhd_bus, q_deq_exec, &args);
        } else {
-               args.qdeq.q = dbus_info->rx_q;
-               irb = EXEC_RXLOCK(dbus_info, q_deq_exec, &args);
+               args.qdeq.q = dhd_bus->rx_q;
+               irb = EXEC_RXLOCK(dhd_bus, q_deq_exec, &args);
        }
 
        return irb;
@@ -1180,11 +1365,12 @@ dbus_if_getirb(void *cbarg, bool send)
  * function.
  */
 static void *
-dbus_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
+dbus_probe(void *arg, const char *desc, uint32 bustype, uint16 bus_no,
+       uint16 slot, uint32 hdrlen)
 {
        DBUSTRACE(("%s\n", __FUNCTION__));
        if (probe_cb) {
-               disc_arg = probe_cb(probe_arg, desc, bustype, hdrlen);
+               disc_arg = probe_cb(probe_arg, desc, bustype, bus_no, slot, hdrlen);
                return disc_arg;
        }
 
@@ -1196,45 +1382,54 @@ dbus_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
  * action.
  */
 int
-dbus_register(int vid, int pid, probe_cb_t prcb,
-       disconnect_cb_t discb, void *prarg, void *param1, void *param2)
+dhd_bus_register(void)
 {
        int err;
 
-       DBUSTRACE(("%s\n", __FUNCTION__));
+       DBUSTRACE(("%s: Enter\n", __FUNCTION__));
 
-       probe_cb = prcb;
-       disconnect_cb = discb;
-       probe_arg = prarg;
+       probe_cb = dhd_dbus_probe_cb;
+       disconnect_cb = dhd_dbus_disconnect_cb;
+       probe_arg = NULL;
+
+       err = dbus_bus_register(0xa5c, 0x48f, dbus_probe, /* call lower DBUS level register function */
+               dbus_disconnect, NULL, &g_busintf, NULL, NULL);
 
-       err = dbus_bus_register(vid, pid, dbus_probe, /* call lower DBUS level register function */
-               dbus_disconnect, NULL, &g_busintf, param1, param2);
+       /* Device not detected */
+       if (err == DBUS_ERR_NODEVICE)
+               err = DBUS_OK;
 
        return err;
 }
 
-int
-dbus_deregister()
+dhd_pub_t *g_pub = NULL;
+void
+dhd_bus_unregister(void)
 {
        int ret;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
+       DHD_MUTEX_LOCK();
+       if (g_pub) {
+               g_pub->dhd_remove = TRUE;
+               if (!g_pub->bus) {
+                       dhd_dbus_disconnect_cb(g_pub->bus);
+               }
+       }
        probe_cb = NULL;
+       DHD_MUTEX_UNLOCK();
        ret = dbus_bus_deregister();
        disconnect_cb = NULL;
        probe_arg = NULL;
-
-       return ret;
-
 }
 
 /** As part of initialization, data structures have to be allocated and initialized */
-dbus_pub_t *
-dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, void *cbarg,
+dhd_bus_t *
+dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, dhd_pub_t *pub,
        dbus_callbacks_t *cbs, dbus_extdl_t *extdl, struct shared_info *sh)
 {
-       dbus_info_t *dbus_info;
+       dhd_bus_t *dhd_bus;
        int err;
 
        if ((g_busintf == NULL) || (g_busintf->attach == NULL) || (cbs == NULL))
@@ -1245,154 +1440,179 @@ dbus_attach(osl_t *osh, int rxsize, int nrxq, int ntxq, void *cbarg,
        if ((nrxq <= 0) || (ntxq <= 0))
                return NULL;
 
-       dbus_info = MALLOC(osh, sizeof(dbus_info_t));
-       if (dbus_info == NULL)
+       dhd_bus = MALLOC(osh, sizeof(dhd_bus_t));
+       if (dhd_bus == NULL) {
+               DBUSERR(("%s: malloc failed %d\n", __FUNCTION__, (int)sizeof(dhd_bus_t)));
                return NULL;
+       }
 
-       bzero(dbus_info, sizeof(dbus_info_t));
+       bzero(dhd_bus, sizeof(dhd_bus_t));
 
        /* BUS-specific driver interface (at a lower DBUS level) */
-       dbus_info->drvintf = g_busintf;
-       dbus_info->cbarg = cbarg;
-       dbus_info->cbs = cbs;
-
-       dbus_info->pub.sh = sh;
-       dbus_info->pub.osh = osh;
-       dbus_info->pub.rxsize = rxsize;
+       dhd_bus->drvintf = g_busintf;
+       dhd_bus->cbarg = pub;
+       dhd_bus->cbs = cbs;
 
+       dhd_bus->pub.sh = sh;
+       dhd_bus->pub.osh = osh;
+       dhd_bus->pub.rxsize = rxsize;
 
-       dbus_info->pub.nrxq = nrxq;
-       dbus_info->rx_low_watermark = nrxq / 2; /* keep enough posted rx urbs */
-       dbus_info->pub.ntxq = ntxq;
-       dbus_info->tx_low_watermark = ntxq / 4; /* flow control when too many tx urbs posted */
+       dhd_bus->pub.nrxq = nrxq;
+       dhd_bus->rx_low_watermark = nrxq / 2;   /* keep enough posted rx urbs */
+       dhd_bus->pub.ntxq = ntxq;
+       dhd_bus->tx_low_watermark = ntxq / 4;   /* flow control when too many tx urbs posted */
 
-       dbus_info->tx_q = MALLOC(osh, sizeof(dbus_irbq_t));
-       if (dbus_info->tx_q == NULL)
+       dhd_bus->tx_q = MALLOC(osh, sizeof(dbus_irbq_t));
+       if (dhd_bus->tx_q == NULL)
                goto error;
        else {
-               bzero(dbus_info->tx_q, sizeof(dbus_irbq_t));
-               err = dbus_irbq_init(dbus_info, dbus_info->tx_q, ntxq, sizeof(dbus_irb_tx_t));
+               bzero(dhd_bus->tx_q, sizeof(dbus_irbq_t));
+               err = dbus_irbq_init(dhd_bus, dhd_bus->tx_q, ntxq, sizeof(dbus_irb_tx_t));
                if (err != DBUS_OK)
                        goto error;
        }
 
-       dbus_info->rx_q = MALLOC(osh, sizeof(dbus_irbq_t));
-       if (dbus_info->rx_q == NULL)
+       dhd_bus->rx_q = MALLOC(osh, sizeof(dbus_irbq_t));
+       if (dhd_bus->rx_q == NULL)
                goto error;
        else {
-               bzero(dbus_info->rx_q, sizeof(dbus_irbq_t));
-               err = dbus_irbq_init(dbus_info, dbus_info->rx_q, nrxq, sizeof(dbus_irb_rx_t));
+               bzero(dhd_bus->rx_q, sizeof(dbus_irbq_t));
+               err = dbus_irbq_init(dhd_bus, dhd_bus->rx_q, nrxq, sizeof(dbus_irb_rx_t));
                if (err != DBUS_OK)
                        goto error;
        }
 
 
-       dbus_info->bus_info = (void *)g_busintf->attach(&dbus_info->pub,
-               dbus_info, &dbus_intf_cbs);
-       if (dbus_info->bus_info == NULL)
+       dhd_bus->bus_info = (void *)g_busintf->attach(&dhd_bus->pub,
+               dhd_bus, &dbus_intf_cbs);
+       if (dhd_bus->bus_info == NULL)
                goto error;
 
-       dbus_tx_timer_init(dbus_info);
+       dbus_tx_timer_init(dhd_bus);
 
 #if defined(BCM_REQUEST_FW)
        /* Need to copy external image for re-download */
        if (extdl && extdl->fw && (extdl->fwlen > 0)) {
-               dbus_info->extdl.fw = MALLOC(osh, extdl->fwlen);
-               if (dbus_info->extdl.fw) {
-                       bcopy(extdl->fw, dbus_info->extdl.fw, extdl->fwlen);
-                       dbus_info->extdl.fwlen = extdl->fwlen;
+               dhd_bus->extdl.fw = MALLOC(osh, extdl->fwlen);
+               if (dhd_bus->extdl.fw) {
+                       bcopy(extdl->fw, dhd_bus->extdl.fw, extdl->fwlen);
+                       dhd_bus->extdl.fwlen = extdl->fwlen;
                }
        }
 
        if (extdl && extdl->vars && (extdl->varslen > 0)) {
-               dbus_info->extdl.vars = MALLOC(osh, extdl->varslen);
-               if (dbus_info->extdl.vars) {
-                       bcopy(extdl->vars, dbus_info->extdl.vars, extdl->varslen);
-                       dbus_info->extdl.varslen = extdl->varslen;
+               dhd_bus->extdl.vars = MALLOC(osh, extdl->varslen);
+               if (dhd_bus->extdl.vars) {
+                       bcopy(extdl->vars, dhd_bus->extdl.vars, extdl->varslen);
+                       dhd_bus->extdl.varslen = extdl->varslen;
                }
        }
-
-       if (dbus_download_firmware(&dbus_info->pub) != DBUS_OK)
-               goto error;
 #endif 
 
-       return (dbus_pub_t *)dbus_info;
+       return (dhd_bus_t *)dhd_bus;
 
 error:
-       dbus_detach((dbus_pub_t *)dbus_info);
+       DBUSERR(("%s: Failed\n", __FUNCTION__));
+       dbus_detach(dhd_bus);
        return NULL;
 } /* dbus_attach */
 
 void
-dbus_detach(dbus_pub_t *pub)
+dbus_detach(dhd_bus_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        osl_t *osh;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return;
 
-       dbus_tx_timer_stop(dbus_info);
+       dbus_tx_timer_stop(dhd_bus);
 
-       osh = pub->osh;
+       osh = pub->pub.osh;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->detach)
-                dbus_info->drvintf->detach((dbus_pub_t *)dbus_info, dbus_info->bus_info);
+       if (dhd_bus->drvintf && dhd_bus->drvintf->detach)
+                dhd_bus->drvintf->detach((dbus_pub_t *)dhd_bus, dhd_bus->bus_info);
 
-       if (dbus_info->tx_q) {
-               dbus_irbq_deinit(dbus_info, dbus_info->tx_q, sizeof(dbus_irb_tx_t));
-               MFREE(osh, dbus_info->tx_q, sizeof(dbus_irbq_t));
-               dbus_info->tx_q = NULL;
+       if (dhd_bus->tx_q) {
+               dbus_irbq_deinit(dhd_bus, dhd_bus->tx_q, sizeof(dbus_irb_tx_t));
+               MFREE(osh, dhd_bus->tx_q, sizeof(dbus_irbq_t));
+               dhd_bus->tx_q = NULL;
        }
 
-       if (dbus_info->rx_q) {
-               dbus_irbq_deinit(dbus_info, dbus_info->rx_q, sizeof(dbus_irb_rx_t));
-               MFREE(osh, dbus_info->rx_q, sizeof(dbus_irbq_t));
-               dbus_info->rx_q = NULL;
+       if (dhd_bus->rx_q) {
+               dbus_irbq_deinit(dhd_bus, dhd_bus->rx_q, sizeof(dbus_irb_rx_t));
+               MFREE(osh, dhd_bus->rx_q, sizeof(dbus_irbq_t));
+               dhd_bus->rx_q = NULL;
        }
 
 
-       if (dbus_info->extdl.fw && (dbus_info->extdl.fwlen > 0)) {
-               MFREE(osh, dbus_info->extdl.fw, dbus_info->extdl.fwlen);
-               dbus_info->extdl.fw = NULL;
-               dbus_info->extdl.fwlen = 0;
+       if (dhd_bus->extdl.fw && (dhd_bus->extdl.fwlen > 0)) {
+               MFREE(osh, dhd_bus->extdl.fw, dhd_bus->extdl.fwlen);
+               dhd_bus->extdl.fw = NULL;
+               dhd_bus->extdl.fwlen = 0;
        }
 
-       if (dbus_info->extdl.vars && (dbus_info->extdl.varslen > 0)) {
-               MFREE(osh, dbus_info->extdl.vars, dbus_info->extdl.varslen);
-               dbus_info->extdl.vars = NULL;
-               dbus_info->extdl.varslen = 0;
+       if (dhd_bus->extdl.vars && (dhd_bus->extdl.varslen > 0)) {
+               MFREE(osh, dhd_bus->extdl.vars, dhd_bus->extdl.varslen);
+               dhd_bus->extdl.vars = NULL;
+               dhd_bus->extdl.varslen = 0;
        }
 
-       MFREE(osh, dbus_info, sizeof(dbus_info_t));
+       MFREE(osh, dhd_bus, sizeof(dhd_bus_t));
 } /* dbus_detach */
 
-#if defined(BCM_REQUEST_FW)
+int dbus_dlneeded(dhd_bus_t *pub)
+{
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
+       int dlneeded = DBUS_ERR;
 
-int dbus_download_firmware(dbus_pub_t *pub)
+       if (!dhd_bus) {
+               DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
+               return DBUS_ERR;
+       }
+
+       DBUSTRACE(("%s: state %d\n", __FUNCTION__, dhd_bus->pub.busstate));
+
+       if (dhd_bus->drvintf->dlneeded) {
+               dlneeded = dhd_bus->drvintf->dlneeded(dhd_bus->bus_info);
+       }
+       printf("%s: dlneeded=%d\n", __FUNCTION__, dlneeded);
+
+       /* dlneeded > 0: need to download
+         * dlneeded = 0: downloaded
+         * dlneeded < 0: bus error*/
+       return dlneeded;
+}
+
+#if defined(BCM_REQUEST_FW)
+int dbus_download_firmware(dhd_bus_t *pub, char *pfw_path, char *pnv_path)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_OK;
 
-       DBUSTRACE(("%s: state %d\n", __FUNCTION__, dbus_info->pub.busstate));
+       if (!dhd_bus) {
+               DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
+               return DBUS_ERR;
+       }
+
+       DBUSTRACE(("%s: state %d\n", __FUNCTION__, dhd_bus->pub.busstate));
 
-       if (dbus_info->drvintf->dlneeded) {
-               if (dbus_info->drvintf->dlneeded(dbus_info->bus_info)) {
-                       dbus_info->pub.busstate = DBUS_STATE_DL_PENDING;
-                       err = dbus_do_download(dbus_info);
-                       if (err == DBUS_OK) {
-                               dbus_info->pub.busstate = DBUS_STATE_DL_DONE;
-                       } else {
-                               DBUSERR(("%s: download failed (%d)\n", __FUNCTION__, err));
-                       }
-               }
+       dhd_bus->pub.busstate = DBUS_STATE_DL_PENDING;
+#ifdef EXTERNAL_FW_PATH
+       err = dbus_do_download(dhd_bus, pfw_path, pnv_path);
+#else
+       err = dbus_do_download(dhd_bus);
+#endif /* EXTERNAL_FW_PATH */
+       if (err == DBUS_OK) {
+               dhd_bus->pub.busstate = DBUS_STATE_DL_DONE;
+       } else {
+               DBUSERR(("%s: download failed (%d)\n", __FUNCTION__, err));
        }
 
        return err;
 }
-
 #endif 
 
 /**
@@ -1400,24 +1620,26 @@ int dbus_download_firmware(dbus_pub_t *pub)
  * bootloader) must be active in the dongle.
  */
 int
-dbus_up(dbus_pub_t *pub)
+dbus_up(struct dhd_bus *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_OK;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL) {
+               DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
                return DBUS_ERR;
+       }
 
-       if ((dbus_info->pub.busstate == DBUS_STATE_DL_DONE) ||
-               (dbus_info->pub.busstate == DBUS_STATE_DOWN) ||
-               (dbus_info->pub.busstate == DBUS_STATE_SLEEP)) {
-               if (dbus_info->drvintf && dbus_info->drvintf->up) {
-                       err = dbus_info->drvintf->up(dbus_info->bus_info);
+       if ((dhd_bus->pub.busstate == DBUS_STATE_DL_DONE) ||
+               (dhd_bus->pub.busstate == DBUS_STATE_DOWN) ||
+               (dhd_bus->pub.busstate == DBUS_STATE_SLEEP)) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->up) {
+                       err = dhd_bus->drvintf->up(dhd_bus->bus_info);
 
                        if (err == DBUS_OK) {
-                               dbus_rxirbs_fill(dbus_info);
+                               dbus_rxirbs_fill(dhd_bus);
                        }
                }
        } else
@@ -1430,19 +1652,19 @@ dbus_up(dbus_pub_t *pub)
 int
 dbus_down(dbus_pub_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       dbus_tx_timer_stop(dbus_info);
+       dbus_tx_timer_stop(dhd_bus);
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP ||
-               dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
-               if (dbus_info->drvintf && dbus_info->drvintf->down)
-                       return dbus_info->drvintf->down(dbus_info->bus_info);
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+               dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->down)
+                       return dhd_bus->drvintf->down(dhd_bus->bus_info);
        }
 
        return DBUS_ERR;
@@ -1451,33 +1673,33 @@ dbus_down(dbus_pub_t *pub)
 int
 dbus_shutdown(dbus_pub_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->shutdown)
-               return dbus_info->drvintf->shutdown(dbus_info->bus_info);
+       if (dhd_bus->drvintf && dhd_bus->drvintf->shutdown)
+               return dhd_bus->drvintf->shutdown(dhd_bus->bus_info);
 
        return DBUS_OK;
 }
 
 int
-dbus_stop(dbus_pub_t *pub)
+dbus_stop(struct dhd_bus *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP ||
-               dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
-               if (dbus_info->drvintf && dbus_info->drvintf->stop)
-                       return dbus_info->drvintf->stop(dbus_info->bus_info);
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+               dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->stop)
+                       return dhd_bus->drvintf->stop(dhd_bus->bus_info);
        }
 
        return DBUS_ERR;
@@ -1501,34 +1723,38 @@ dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info)
 }
 
 int
-dbus_send_ctl(dbus_pub_t *pub, uint8 *buf, int len)
+dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL) {
+               DBUSERR(("%s: dhd_bus is NULL\n", __FUNCTION__));
                return DBUS_ERR;
+       }
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP ||
-               dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
-               if (dbus_info->drvintf && dbus_info->drvintf->send_ctl)
-                       return dbus_info->drvintf->send_ctl(dbus_info->bus_info, buf, len);
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+               dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->send_ctl)
+                       return dhd_bus->drvintf->send_ctl(dhd_bus->bus_info, buf, len);
+       } else {
+               DBUSERR(("%s: bustate=%d\n", __FUNCTION__, dhd_bus->pub.busstate));
        }
 
        return DBUS_ERR;
 }
 
 int
-dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len)
+dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if ((dbus_info == NULL) || (buf == NULL))
+       if ((dhd_bus == NULL) || (buf == NULL))
                return DBUS_ERR;
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP ||
-               dbus_info->pub.busstate == DBUS_STATE_SLEEP) {
-               if (dbus_info->drvintf && dbus_info->drvintf->recv_ctl)
-                       return dbus_info->drvintf->recv_ctl(dbus_info->bus_info, buf, len);
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP ||
+               dhd_bus->pub.busstate == DBUS_STATE_SLEEP) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->recv_ctl)
+                       return dhd_bus->drvintf->recv_ctl(dhd_bus->bus_info, buf, len);
        }
 
        return DBUS_ERR;
@@ -1538,27 +1764,27 @@ dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len)
 int
 dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
        dbus_irb_rx_t *rxirb;
        struct exec_parms args;
        int status;
 
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       args.qdeq.q = dbus_info->rx_q;
-       if (dbus_info->pub.busstate == DBUS_STATE_UP) {
-               if (dbus_info->drvintf && dbus_info->drvintf->recv_irb_from_ep) {
-                       if ((rxirb = (EXEC_RXLOCK(dbus_info, q_deq_exec, &args))) != NULL) {
-                               status = dbus_info->drvintf->recv_irb_from_ep(dbus_info->bus_info,
+       args.qdeq.q = dhd_bus->rx_q;
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->recv_irb_from_ep) {
+                       if ((rxirb = (EXEC_RXLOCK(dhd_bus, q_deq_exec, &args))) != NULL) {
+                               status = dhd_bus->drvintf->recv_irb_from_ep(dhd_bus->bus_info,
                                        rxirb, ep_idx);
                                if (status == DBUS_ERR_RXDROP) {
                                        bzero(rxirb, sizeof(dbus_irb_rx_t));
-                                       args.qenq.q = dbus_info->rx_q;
+                                       args.qenq.q = dhd_bus->rx_q;
                                        args.qenq.b = (dbus_irb_t *) rxirb;
-                                       EXEC_RXLOCK(dbus_info, q_enq_exec, &args);
+                                       EXEC_RXLOCK(dhd_bus, q_enq_exec, &args);
                                }
                        }
                }
@@ -1571,16 +1797,16 @@ dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx)
 int
 dbus_poll_intr(dbus_pub_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
        int status = DBUS_ERR;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP) {
-               if (dbus_info->drvintf && dbus_info->drvintf->recv_irb_from_ep) {
-                       status = dbus_info->drvintf->recv_irb_from_ep(dbus_info->bus_info,
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
+               if (dhd_bus->drvintf && dhd_bus->drvintf->recv_irb_from_ep) {
+                       status = dhd_bus->drvintf->recv_irb_from_ep(dhd_bus->bus_info,
                                NULL, 0xff);
                }
        }
@@ -1591,86 +1817,86 @@ dbus_poll_intr(dbus_pub_t *pub)
 void *
 dbus_pktget(dbus_pub_t *pub, int len)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if ((dbus_info == NULL) || (len < 0))
+       if ((dhd_bus == NULL) || (len < 0))
                return NULL;
 
-       return PKTGET(dbus_info->pub.osh, len, TRUE);
+       return PKTGET(dhd_bus->pub.osh, len, TRUE);
 }
 
 /** called by nobody (Dec 2012) */
 void
 dbus_pktfree(dbus_pub_t *pub, void* pkt)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if ((dbus_info == NULL) || (pkt == NULL))
+       if ((dhd_bus == NULL) || (pkt == NULL))
                return;
 
-       PKTFREE(dbus_info->pub.osh, pkt, TRUE);
+       PKTFREE(dhd_bus->pub.osh, pkt, TRUE);
 }
 
 /** called by nobody (Dec 2012) */
 int
 dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if ((dbus_info == NULL) || (stats == NULL))
+       if ((dhd_bus == NULL) || (stats == NULL))
                return DBUS_ERR;
 
-       bcopy(&dbus_info->pub.stats, stats, sizeof(dbus_stats_t));
+       bcopy(&dhd_bus->pub.stats, stats, sizeof(dbus_stats_t));
 
        return DBUS_OK;
 }
 
 int
-dbus_get_attrib(dbus_pub_t *pub, dbus_attrib_t *attrib)
+dbus_get_attrib(dhd_bus_t *pub, dbus_attrib_t *attrib)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_ERR;
 
-       if ((dbus_info == NULL) || (attrib == NULL))
+       if ((dhd_bus == NULL) || (attrib == NULL))
                return DBUS_ERR;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->get_attrib) {
-               err = dbus_info->drvintf->get_attrib(dbus_info->bus_info,
-               &dbus_info->pub.attrib);
+       if (dhd_bus->drvintf && dhd_bus->drvintf->get_attrib) {
+               err = dhd_bus->drvintf->get_attrib(dhd_bus->bus_info,
+               &dhd_bus->pub.attrib);
        }
 
-       bcopy(&dbus_info->pub.attrib, attrib, sizeof(dbus_attrib_t));
+       bcopy(&dhd_bus->pub.attrib, attrib, sizeof(dbus_attrib_t));
        return err;
 }
 
 int
 dbus_get_device_speed(dbus_pub_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return INVALID_SPEED;
 
-       return (dbus_info->pub.device_speed);
+       return (dhd_bus->pub.device_speed);
 }
 
 int
 dbus_set_config(dbus_pub_t *pub, dbus_config_t *config)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_ERR;
 
-       if ((dbus_info == NULL) || (config == NULL))
+       if ((dhd_bus == NULL) || (config == NULL))
                return DBUS_ERR;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->set_config) {
-               err = dbus_info->drvintf->set_config(dbus_info->bus_info,
+       if (dhd_bus->drvintf && dhd_bus->drvintf->set_config) {
+               err = dhd_bus->drvintf->set_config(dhd_bus->bus_info,
                        config);
 
                if ((config->config_id == DBUS_CONFIG_ID_AGGR_LIMIT) &&
                        (!err) &&
-                       (dbus_info->pub.busstate == DBUS_STATE_UP)) {
-                       dbus_rxirbs_fill(dbus_info);
+                       (dhd_bus->pub.busstate == DBUS_STATE_UP)) {
+                       dbus_rxirbs_fill(dhd_bus);
                }
        }
 
@@ -1680,14 +1906,14 @@ dbus_set_config(dbus_pub_t *pub, dbus_config_t *config)
 int
 dbus_get_config(dbus_pub_t *pub, dbus_config_t *config)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_ERR;
 
-       if ((dbus_info == NULL) || (config == NULL))
+       if ((dhd_bus == NULL) || (config == NULL))
                return DBUS_ERR;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->get_config) {
-               err = dbus_info->drvintf->get_config(dbus_info->bus_info,
+       if (dhd_bus->drvintf && dhd_bus->drvintf->get_config) {
+               err = dhd_bus->drvintf->get_config(dhd_bus->bus_info,
                config);
        }
 
@@ -1697,43 +1923,43 @@ dbus_get_config(dbus_pub_t *pub, dbus_config_t *config)
 int
 dbus_set_errmask(dbus_pub_t *pub, uint32 mask)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_OK;
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       dbus_info->errmask = mask;
+       dhd_bus->errmask = mask;
        return err;
 }
 
 int
 dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_ERR;
        bool fwdl = FALSE;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (dbus_info->pub.busstate == DBUS_STATE_UP) {
+       if (dhd_bus->pub.busstate == DBUS_STATE_UP) {
                return DBUS_OK;
        }
 
 
 
-       if (dbus_info->drvintf->pnp) {
-               err = dbus_info->drvintf->pnp(dbus_info->bus_info,
+       if (dhd_bus->drvintf->pnp) {
+               err = dhd_bus->drvintf->pnp(dhd_bus->bus_info,
                        DBUS_PNP_RESUME);
        }
 
-       if (dbus_info->drvintf->recv_needed) {
-               if (dbus_info->drvintf->recv_needed(dbus_info->bus_info)) {
+       if (dhd_bus->drvintf->recv_needed) {
+               if (dhd_bus->drvintf->recv_needed(dhd_bus->bus_info)) {
                        /* Refill after sleep/hibernate */
-                       dbus_rxirbs_fill(dbus_info);
+                       dbus_rxirbs_fill(dhd_bus);
                }
        }
 
@@ -1747,18 +1973,18 @@ dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload)
 int
 dbus_pnp_sleep(dbus_pub_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_ERR;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       dbus_tx_timer_stop(dbus_info);
+       dbus_tx_timer_stop(dhd_bus);
 
-       if (dbus_info->drvintf && dbus_info->drvintf->pnp) {
-               err = dbus_info->drvintf->pnp(dbus_info->bus_info,
+       if (dhd_bus->drvintf && dhd_bus->drvintf->pnp) {
+               err = dhd_bus->drvintf->pnp(dhd_bus->bus_info,
                        DBUS_PNP_SLEEP);
        }
 
@@ -1768,18 +1994,18 @@ dbus_pnp_sleep(dbus_pub_t *pub)
 int
 dbus_pnp_disconnect(dbus_pub_t *pub)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) pub;
        int err = DBUS_ERR;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       dbus_tx_timer_stop(dbus_info);
+       dbus_tx_timer_stop(dhd_bus);
 
-       if (dbus_info->drvintf && dbus_info->drvintf->pnp) {
-               err = dbus_info->drvintf->pnp(dbus_info->bus_info,
+       if (dhd_bus->drvintf && dhd_bus->drvintf->pnp) {
+               err = dhd_bus->drvintf->pnp(dhd_bus->bus_info,
                        DBUS_PNP_DISCONNECT);
        }
 
@@ -1787,19 +2013,19 @@ dbus_pnp_disconnect(dbus_pub_t *pub)
 }
 
 int
-dbus_iovar_op(dbus_pub_t *pub, const char *name,
+dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
        void *params, int plen, void *arg, int len, bool set)
 {
-       dbus_info_t *dbus_info = (dbus_info_t *) pub;
+       dhd_bus_t *dhd_bus = (dhd_bus_t *) dhdp->bus;
        int err = DBUS_ERR;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
-       if (dbus_info == NULL)
+       if (dhd_bus == NULL)
                return DBUS_ERR;
 
-       if (dbus_info->drvintf && dbus_info->drvintf->iovar_op) {
-               err = dbus_info->drvintf->iovar_op(dbus_info->bus_info,
+       if (dhd_bus->drvintf && dhd_bus->drvintf->iovar_op) {
+               err = dhd_bus->drvintf->iovar_op(dhd_bus->bus_info,
                        name, params, plen, arg, len, set);
        }
 
@@ -1825,10 +2051,9 @@ dbus_get_devinfo(dbus_pub_t *pub)
        return pub->dev_info;
 }
 
-#if defined(BCM_REQUEST_FW)
-
+#if defined(BCM_REQUEST_FW) && !defined(EXTERNAL_FW_PATH)
 static int
-dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
+dbus_otp(dhd_bus_t *dhd_bus, uint16 *boardtype, uint16 *boardrev)
 {
        uint32 value = 0;
        uint8 *cis;
@@ -1844,11 +2069,11 @@ dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
        uint16 brev = 0;
        uint32 otp_size = 0, otp_addr = 0, otp_sw_rgn = 0;
 
-       if (dbus_info == NULL || dbus_info->drvintf == NULL ||
-               dbus_info->drvintf->readreg == NULL)
+       if (dhd_bus == NULL || dhd_bus->drvintf == NULL ||
+               dhd_bus->drvintf->readreg == NULL)
                return DBUS_ERR;
 
-       devid = dbus_info->pub.attrib.devid;
+       devid = dhd_bus->pub.attrib.devid;
 
        if ((devid == BCM43234_CHIP_ID) || (devid == BCM43235_CHIP_ID) ||
                (devid == BCM43236_CHIP_ID)) {
@@ -1861,7 +2086,7 @@ dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
                return DBUS_ERR_NVRAM;
        }
 
-       cis = MALLOC(dbus_info->pub.osh, otp_size * 2);
+       cis = MALLOC(dhd_bus->pub.osh, otp_size * 2);
        if (cis == NULL)
                return DBUS_ERR;
 
@@ -1869,11 +2094,11 @@ dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
 
        for (i = 0; i < otp_size; i++) {
 
-               ret = dbus_info->drvintf->readreg(dbus_info->bus_info,
+               ret = dhd_bus->drvintf->readreg(dhd_bus->bus_info,
                        otp_addr + ((otp_sw_rgn + i) << 1), 2, &value);
 
                if (ret != DBUS_OK) {
-                       MFREE(dbus_info->pub.osh, cis, otp_size * 2);
+                       MFREE(dhd_bus->pub.osh, cis, otp_size * 2);
                        return ret;
                }
                otpinfo[i] = (uint16) value;
@@ -1939,7 +2164,7 @@ dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
                i += tlen;
        }
 
-       MFREE(dbus_info->pub.osh, cis, otp_size * 2);
+       MFREE(dhd_bus->pub.osh, cis, otp_size * 2);
 
        if (btype_present == TRUE && brev_present == TRUE) {
                *boardtype = btype;
@@ -1954,7 +2179,7 @@ dbus_otp(dbus_info_t *dbus_info, uint16 *boardtype, uint16 *boardrev)
 } /* dbus_otp */
 
 static int
-dbus_select_nvram(dbus_info_t *dbus_info, int8 *jumbonvram, int jumbolen,
+dbus_select_nvram(dhd_bus_t *dhd_bus, int8 *jumbonvram, int jumbolen,
 uint16 boardtype, uint16 boardrev, int8 **nvram, int *nvram_len)
 {
        /* Multi board nvram file format is contenation of nvram info with \r
@@ -1987,7 +2212,7 @@ uint16 boardtype, uint16 boardrev, int8 **nvram, int *nvram_len)
                return DBUS_JUMBO_BAD_FORMAT;
        }
 
-       dbus_info->nvram_nontxt = DBUS_NVRAM_NONTXT;
+       dhd_bus->nvram_nontxt = DBUS_NVRAM_NONTXT;
 
        nvram_start = jumbonvram;
 
@@ -2090,6 +2315,580 @@ uint16 boardtype, uint16 boardrev, int8 **nvram, int *nvram_len)
 
 #endif 
 
+#define DBUS_NRXQ      50
+#define DBUS_NTXQ      100
+
+static void
+dhd_dbus_send_complete(void *handle, void *info, int status)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+       void *pkt = info;
+
+       if ((dhd == NULL) || (pkt == NULL)) {
+               DBUSERR(("dhd or pkt is NULL\n"));
+               return;
+       }
+
+       if (status == DBUS_OK) {
+               dhd->dstats.tx_packets++;
+       } else {
+               DBUSERR(("TX error=%d\n", status));
+               dhd->dstats.tx_errors++;
+       }
+#ifdef PROP_TXSTATUS
+       if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) &&
+               (dhd_wlfc_txcomplete(dhd, pkt, status == 0) != WLFC_UNSUPPORTED)) {
+               return;
+       }
+#endif /* PROP_TXSTATUS */
+       PKTFREE(dhd->osh, pkt, TRUE);
+}
+
+static void
+dhd_dbus_recv_pkt(void *handle, void *pkt)
+{
+       uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
+       uint reorder_info_len;
+       uint pkt_count;
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+       int ifidx = 0;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       /* If the protocol uses a data header, check and remove it */
+       if (dhd_prot_hdrpull(dhd, &ifidx, pkt, reorder_info_buf,
+               &reorder_info_len) != 0) {
+               DBUSERR(("rx protocol error\n"));
+               PKTFREE(dhd->osh, pkt, FALSE);
+               dhd->rx_errors++;
+               return;
+       }
+
+       if (reorder_info_len) {
+               /* Reordering info from the firmware */
+               dhd_process_pkt_reorder_info(dhd, reorder_info_buf, reorder_info_len,
+                       &pkt, &pkt_count);
+               if (pkt_count == 0)
+                       return;
+       }
+       else {
+               pkt_count = 1;
+       }
+       dhd_rx_frame(dhd, ifidx, pkt, pkt_count, 0);
+}
+
+static void
+dhd_dbus_recv_buf(void *handle, uint8 *buf, int len)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+       void *pkt;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       if ((pkt = PKTGET(dhd->osh, len, FALSE)) == NULL) {
+               DBUSERR(("PKTGET (rx) failed=%d\n", len));
+               return;
+       }
+
+       bcopy(buf, PKTDATA(dhd->osh, pkt), len);
+       dhd_dbus_recv_pkt(dhd, pkt);
+}
+
+static void
+dhd_dbus_txflowcontrol(void *handle, bool onoff)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+       bool wlfc_enabled = FALSE;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return;
+       }
+
+#ifdef PROP_TXSTATUS
+       wlfc_enabled = (dhd_wlfc_flowcontrol(dhd, onoff, !onoff) != WLFC_UNSUPPORTED);
+#endif
+
+       if (!wlfc_enabled) {
+               dhd_txflowcontrol(dhd, ALL_INTERFACES, onoff);
+       }
+}
+
+static void
+dhd_dbus_errhandler(void *handle, int err)
+{
+}
+
+static void
+dhd_dbus_ctl_complete(void *handle, int type, int status)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       if (type == DBUS_CBCTL_READ) {
+               if (status == DBUS_OK)
+                       dhd->rx_ctlpkts++;
+               else
+                       dhd->rx_ctlerrs++;
+       } else if (type == DBUS_CBCTL_WRITE) {
+               if (status == DBUS_OK)
+                       dhd->tx_ctlpkts++;
+               else
+                       dhd->tx_ctlerrs++;
+       }
+
+       dhd_prot_ctl_complete(dhd);
+}
+
+static void
+dhd_dbus_state_change(void *handle, int state)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       switch (state) {
+
+               case DBUS_STATE_DL_NEEDED:
+                       DBUSERR(("%s: firmware request cannot be handled\n", __FUNCTION__));
+                       break;
+               case DBUS_STATE_DOWN:
+                       DBUSTRACE(("%s: DBUS is down\n", __FUNCTION__));
+                       dhd->busstate = DHD_BUS_DOWN;
+                       break;
+               case DBUS_STATE_UP:
+                       DBUSTRACE(("%s: DBUS is up\n", __FUNCTION__));
+                       dhd->busstate = DHD_BUS_DATA;
+                       break;
+               default:
+                       break;
+       }
+
+       DBUSERR(("%s: DBUS current state=%d\n", __FUNCTION__, state));
+}
+
+static void *
+dhd_dbus_pktget(void *handle, uint len, bool send)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+       void *p = NULL;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return NULL;
+       }
+
+       if (send == TRUE) {
+               dhd_os_sdlock_txq(dhd);
+               p = PKTGET(dhd->osh, len, TRUE);
+               dhd_os_sdunlock_txq(dhd);
+       } else {
+               dhd_os_sdlock_rxq(dhd);
+               p = PKTGET(dhd->osh, len, FALSE);
+               dhd_os_sdunlock_rxq(dhd);
+       }
+
+       return p;
+}
+
+static void
+dhd_dbus_pktfree(void *handle, void *p, bool send)
+{
+       dhd_pub_t *dhd = (dhd_pub_t *)handle;
+
+       if (dhd == NULL) {
+               DBUSERR(("%s: dhd is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       if (send == TRUE) {
+#ifdef PROP_TXSTATUS
+               if (DHD_PKTTAG_WLFCPKT(PKTTAG(p)) &&
+                       (dhd_wlfc_txcomplete(dhd, p, FALSE) != WLFC_UNSUPPORTED)) {
+                       return;
+               }
+#endif /* PROP_TXSTATUS */
+
+               dhd_os_sdlock_txq(dhd);
+               PKTFREE(dhd->osh, p, TRUE);
+               dhd_os_sdunlock_txq(dhd);
+       } else {
+               dhd_os_sdlock_rxq(dhd);
+               PKTFREE(dhd->osh, p, FALSE);
+               dhd_os_sdunlock_rxq(dhd);
+       }
+}
+
+
+static dbus_callbacks_t dhd_dbus_cbs = {
+       dhd_dbus_send_complete,
+       dhd_dbus_recv_buf,
+       dhd_dbus_recv_pkt,
+       dhd_dbus_txflowcontrol,
+       dhd_dbus_errhandler,
+       dhd_dbus_ctl_complete,
+       dhd_dbus_state_change,
+       dhd_dbus_pktget,
+       dhd_dbus_pktfree
+};
+
+uint
+dhd_bus_chip(struct dhd_bus *bus)
+{
+       ASSERT(bus != NULL);
+       return bus->pub.attrib.devid;
+}
+
+uint
+dhd_bus_chiprev(struct dhd_bus *bus)
+{
+       ASSERT(bus);
+       ASSERT(bus != NULL);
+       return bus->pub.attrib.chiprev;
+}
+
+void
+dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
+{
+       bcm_bprintf(strbuf, "Bus USB\n");
+}
+
+void
+dhd_bus_clearcounts(dhd_pub_t *dhdp)
+{
+}
+
+int
+dhd_bus_txdata(struct dhd_bus *bus, void *pktbuf)
+{
+       DBUSTRACE(("%s\n", __FUNCTION__));
+       if (bus->txoff) {
+               DBUSTRACE(("txoff\n"));
+               return BCME_EPERM;
+       }
+       return dbus_send_txdata(&bus->pub, pktbuf);
+}
+
+static void
+dhd_dbus_advertise_bus_cleanup(dhd_pub_t *dhdp)
+{
+       unsigned long flags;
+       int timeleft;
+
+       DHD_LINUX_GENERAL_LOCK(dhdp, flags);
+       dhdp->busstate = DHD_BUS_DOWN_IN_PROGRESS;
+       DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
+
+       timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
+       if ((timeleft == 0) || (timeleft == 1)) {
+               DBUSERR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
+                               __FUNCTION__, dhdp->dhd_bus_busy_state));
+               ASSERT(0);
+       }
+
+       return;
+}
+
+static void
+dhd_dbus_advertise_bus_remove(dhd_pub_t *dhdp)
+{
+       unsigned long flags;
+       int timeleft;
+
+       DHD_LINUX_GENERAL_LOCK(dhdp, flags);
+       dhdp->busstate = DHD_BUS_REMOVE;
+       DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
+
+       timeleft = dhd_os_busbusy_wait_negation(dhdp, &dhdp->dhd_bus_busy_state);
+       if ((timeleft == 0) || (timeleft == 1)) {
+               DBUSERR(("%s : Timeout due to dhd_bus_busy_state=0x%x\n",
+                               __FUNCTION__, dhdp->dhd_bus_busy_state));
+               ASSERT(0);
+       }
+
+       return;
+}
+
+int
+dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
+{
+       int bcmerror = 0;
+       unsigned long flags;
+       wifi_adapter_info_t *adapter = (wifi_adapter_info_t *)dhdp->adapter;
+
+       if (flag == TRUE) {
+               if (!dhdp->dongle_reset) {
+                       DBUSERR(("%s: == Power OFF ==\n", __FUNCTION__));
+                       dhd_dbus_advertise_bus_cleanup(dhdp);
+                       dhd_os_wd_timer(dhdp, 0);
+#if !defined(IGNORE_ETH0_DOWN)
+                       /* Force flow control as protection when stop come before ifconfig_down */
+                       dhd_txflowcontrol(dhdp, ALL_INTERFACES, ON);
+#endif /* !defined(IGNORE_ETH0_DOWN) */
+                       dbus_stop(dhdp->bus);
+
+                       dhdp->dongle_reset = TRUE;
+                       dhdp->up = FALSE;
+
+                       DHD_LINUX_GENERAL_LOCK(dhdp, flags);
+                       dhdp->busstate = DHD_BUS_DOWN;
+                       DHD_LINUX_GENERAL_UNLOCK(dhdp, flags);
+                       wifi_clr_adapter_status(adapter, WIFI_STATUS_FW_READY);
+
+                       printf("%s:  WLAN OFF DONE\n", __FUNCTION__);
+                       /* App can now remove power from device */
+               } else
+                       bcmerror = BCME_ERROR;
+       } else {
+               /* App must have restored power to device before calling */
+               printf("\n\n%s: == WLAN ON ==\n", __FUNCTION__);
+               if (dhdp->dongle_reset) {
+                       /* Turn on WLAN */
+                       DHD_MUTEX_UNLOCK();
+                       wait_event_interruptible_timeout(adapter->status_event,
+                               wifi_get_adapter_status(adapter, WIFI_STATUS_FW_READY),
+                               msecs_to_jiffies(DHD_FW_READY_TIMEOUT));
+                       DHD_MUTEX_LOCK();
+                       bcmerror = dbus_up(dhdp->bus);
+                       if (bcmerror == BCME_OK) {
+                               dhdp->dongle_reset = FALSE;
+                               dhdp->up = TRUE;
+#if !defined(IGNORE_ETH0_DOWN)
+                               /* Restore flow control  */
+                               dhd_txflowcontrol(dhdp, ALL_INTERFACES, OFF);
+#endif 
+                               dhd_os_wd_timer(dhdp, dhd_watchdog_ms);
+
+                               DBUSTRACE(("%s: WLAN ON DONE\n", __FUNCTION__));
+                       } else {
+                               DBUSERR(("%s: failed to dbus_up with code %d\n", __FUNCTION__, bcmerror));
+                       }
+               }
+       }
+
+#ifdef PKT_STATICS
+       memset((uint8*) &tx_statics, 0, sizeof(pkt_statics_t));
+#endif
+       return bcmerror;
+}
+
+void
+dhd_set_path_params(struct dhd_bus *bus)
+{
+       /* External conf takes precedence if specified */
+       dhd_conf_preinit(bus->dhd);
+
+       if (bus->dhd->conf_path[0] == '\0') {
+               dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_path);
+       }
+       if (bus->dhd->clm_path[0] == '\0') {
+               dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path);
+       }
+#ifdef CONFIG_PATH_AUTO_SELECT
+       dhd_conf_set_conf_name_by_chip(bus->dhd, bus->dhd->conf_path);
+#endif
+
+       dhd_conf_read_config(bus->dhd, bus->dhd->conf_path);
+
+       dhd_conf_set_fw_name_by_chip(bus->dhd, bus->fw_path);
+       dhd_conf_set_nv_name_by_chip(bus->dhd, bus->nv_path);
+       dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path);
+
+       printf("Final fw_path=%s\n", bus->fw_path);
+       printf("Final nv_path=%s\n", bus->nv_path);
+       printf("Final clm_path=%s\n", bus->dhd->clm_path);
+       printf("Final conf_path=%s\n", bus->dhd->conf_path);
+
+}
+
+void
+dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path,
+       char *pnv_path, char *pclm_path, char *pconf_path)
+{
+       DBUSTRACE(("%s\n", __FUNCTION__));
+
+       if (bus == NULL) {
+               DBUSERR(("%s: bus is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       bus->fw_path = pfw_path;
+       bus->nv_path = pnv_path;
+       bus->dhd->clm_path = pclm_path;
+       bus->dhd->conf_path = pconf_path;
+
+       dhd_set_path_params(bus);
+
+}
+
+/*
+ * hdrlen is space to reserve in pkt headroom for DBUS
+ */
+void *
+dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype,
+       uint16 bus_no, uint16 slot, uint32 hdrlen)
+{
+       osl_t *osh = NULL;
+       dhd_bus_t *bus = NULL;
+       dhd_pub_t *pub = NULL;
+       uint rxsz;
+       int dlneeded = 0;
+       wifi_adapter_info_t *adapter = NULL;
+
+       DBUSTRACE(("%s: Enter\n", __FUNCTION__));
+
+       adapter = dhd_wifi_platform_get_adapter(bustype, bus_no, slot);
+
+       if (!g_pub) {
+               /* Ask the OS interface part for an OSL handle */
+               if (!(osh = osl_attach(NULL, bustype, TRUE))) {
+                       DBUSERR(("%s: OSL attach failed\n", __FUNCTION__));
+                       goto fail;
+               }
+
+               /* Attach to the dhd/OS interface */
+               if (!(pub = dhd_attach(osh, bus, hdrlen, adapter))) {
+                       DBUSERR(("%s: dhd_attach failed\n", __FUNCTION__));
+                       goto fail;
+               }
+       } else {
+               pub = g_pub;
+       }
+
+       if (pub->bus) {
+               DBUSERR(("%s: wrong probe\n", __FUNCTION__));
+               goto fail;
+       }
+
+       rxsz = dhd_get_rxsz(pub);
+       bus = dbus_attach(osh, rxsz, DBUS_NRXQ, DBUS_NTXQ, pub, &dhd_dbus_cbs, NULL, NULL);
+       if (bus) {
+               pub->bus = bus;
+               bus->dhd = pub;
+
+               dlneeded = dbus_dlneeded(bus);
+               if (dlneeded >= 0) {
+                       if (!g_pub) {
+                               dhd_conf_reset(pub);
+                               dhd_conf_set_chiprev(pub, bus->pub.attrib.devid, bus->pub.attrib.chiprev);
+                               dhd_conf_preinit(pub);
+                       }
+               }
+
+               if (g_pub || dhd_download_fw_on_driverload) {
+                       if (dlneeded == 0) {
+                               wifi_set_adapter_status(adapter, WIFI_STATUS_FW_READY);
+#ifdef BCM_REQUEST_FW
+                       } else if (dlneeded > 0) {
+                               dhd_set_path(bus->dhd);
+                               if (dbus_download_firmware(bus, bus->fw_path, bus->nv_path) != DBUS_OK)
+                                       goto fail;
+#endif
+                       }
+               }
+       } else {
+               DBUSERR(("%s: dbus_attach failed\n", __FUNCTION__));
+       }
+
+       if (!g_pub) {
+               /* Ok, finish the attach to the OS network interface */
+               if (dhd_register_if(pub, 0, TRUE) != 0) {
+                       DBUSERR(("%s: dhd_register_if failed\n", __FUNCTION__));
+                       goto fail;
+               }
+               pub->hang_report  = TRUE;
+#if defined(MULTIPLE_SUPPLICANT)
+               wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
+#endif
+               g_pub = pub;
+       }
+
+       DBUSTRACE(("%s: Exit\n", __FUNCTION__));
+       wifi_clr_adapter_status(adapter, WIFI_STATUS_DETTACH);
+       wifi_set_adapter_status(adapter, WIFI_STATUS_ATTACH);
+       wake_up_interruptible(&adapter->status_event);
+       /* This is passed to dhd_dbus_disconnect_cb */
+       return bus;
+
+fail:
+       if (pub && pub->bus) {
+               dbus_detach(pub->bus);
+               pub->bus = NULL;
+       }
+       /* Release resources in reverse order */
+       if (!g_pub) {
+               if (pub) {
+                       dhd_detach(pub);
+                       dhd_free(pub);
+               }
+               if (osh) {
+                       osl_detach(osh);
+               }
+       }
+
+       printf("%s: Failed\n", __FUNCTION__);
+       return NULL;
+}
+
+void
+dhd_dbus_disconnect_cb(void *arg)
+{
+       dhd_bus_t *bus = (dhd_bus_t *)arg;
+       dhd_pub_t *pub = g_pub;
+       osl_t *osh;
+       wifi_adapter_info_t *adapter = NULL;
+
+       adapter = (wifi_adapter_info_t *)pub->adapter;
+
+       if (pub && !pub->dhd_remove && bus == NULL) {
+               DBUSERR(("%s: bus is NULL\n", __FUNCTION__));
+               return;
+       }
+       if (!adapter) {
+               DBUSERR(("%s: adapter is NULL\n", __FUNCTION__));
+               return;
+       }
+
+       printf("%s: Enter dhd_remove=%d on %s\n", __FUNCTION__,
+               pub->dhd_remove, adapter->name);
+       if (!pub->dhd_remove) {
+               /* Advertise bus remove during rmmod */
+               dhd_dbus_advertise_bus_remove(bus->dhd);
+               dbus_detach(pub->bus);
+               pub->bus = NULL;
+               wifi_clr_adapter_status(adapter, WIFI_STATUS_ATTACH);
+               wifi_set_adapter_status(adapter, WIFI_STATUS_DETTACH);
+               wake_up_interruptible(&adapter->status_event);
+       } else {
+               osh = pub->osh;
+               dhd_detach(pub);
+               if (pub->bus) {
+                       dbus_detach(pub->bus);
+                       pub->bus = NULL;
+               }
+               dhd_free(pub);
+               g_pub = NULL;
+               if (MALLOCED(osh)) {
+                       DBUSERR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)));
+               }
+               osl_detach(osh);
+       }
+
+       DBUSTRACE(("%s: Exit\n", __FUNCTION__));
+}
 
 #ifdef LINUX_EXTERNAL_MODULE_DBUS
 
@@ -2108,7 +2907,6 @@ bcm_dbus_module_exit(void)
 }
 
 EXPORT_SYMBOL(dbus_pnp_sleep);
-EXPORT_SYMBOL(dbus_register);
 EXPORT_SYMBOL(dbus_get_devinfo);
 EXPORT_SYMBOL(dbus_detach);
 EXPORT_SYMBOL(dbus_get_attrib);
@@ -2121,7 +2919,6 @@ EXPORT_SYMBOL(dbus_get_device_speed);
 EXPORT_SYMBOL(dbus_send_pkt);
 EXPORT_SYMBOL(dbus_recv_ctl);
 EXPORT_SYMBOL(dbus_attach);
-EXPORT_SYMBOL(dbus_deregister);
 
 MODULE_LICENSE("GPL");
 
index 237e016981d83fd7593b95f7cbd01feb15284cc0..8a496dd1e8bd826817ee77e6efdd863548de905d 100644 (file)
@@ -77,7 +77,9 @@ static void dbus_usb_ctl_complete(void *handle, int type, int status);
 static void dbus_usb_state_change(void *handle, int state);
 static struct dbus_irb* dbus_usb_getirb(void *handle, bool send);
 static void dbus_usb_rxerr_indicate(void *handle, bool on);
+#if !defined(BCM_REQUEST_FW)
 static int dbus_usb_resetcfg(usb_info_t *usbinfo);
+#endif
 static int dbus_usb_iovar_op(void *bus, const char *name,
        void *params, int plen, void *arg, int len, bool set);
 static int dbus_iovar_process(usb_info_t* usbinfo, const char *name,
@@ -88,7 +90,7 @@ static int dhdusb_downloadvars(usb_info_t *bus, void *arg, int len);
 
 static int dbus_usb_dl_writeimage(usb_info_t *usbinfo, uint8 *fw, int fwlen);
 static int dbus_usb_dlstart(void *bus, uint8 *fw, int len);
-static bool dbus_usb_dlneeded(void *bus);
+static int dbus_usb_dlneeded(void *bus);
 static int dbus_usb_dlrun(void *bus);
 static int dbus_usb_rdl_dwnld_state(usb_info_t *usbinfo);
 
@@ -157,7 +159,8 @@ static dbus_intf_t  dbus_usb_intf; /** functions called by higher layer DBUS into
  */
 static void *dbus_usb_attach(dbus_pub_t *pub, void *cbarg, dbus_intf_callbacks_t *cbs);
 static void dbus_usb_detach(dbus_pub_t *pub, void *info);
-static void * dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+static void * dbus_usb_probe(void *arg, const char *desc, uint32 bustype,
+       uint16 bus_no, uint16 slot, uint32 hdrlen);
 
 /* functions */
 
@@ -166,7 +169,8 @@ static void * dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint32
  * lower level DBUS functions to call (in both dbus_usb.c and dbus_usb_os.c).
  */
 static void *
-dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
+dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint16 bus_no,
+       uint16 slot, uint32 hdrlen)
 {
        DBUSTRACE(("%s(): \n", __FUNCTION__));
        if (probe_cb) {
@@ -186,7 +190,7 @@ dbus_usb_probe(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
                        dbus_usb_intf.dlrun = dbus_usb_dlrun;
                }
 
-               disc_arg = probe_cb(probe_arg, "DBUS USB", USB_BUS, hdrlen);
+               disc_arg = probe_cb(probe_arg, "DBUS USB", USB_BUS, bus_no, slot, hdrlen);
                return disc_arg;
        }
 
@@ -259,10 +263,9 @@ dbus_usb_attach(dbus_pub_t *pub, void *cbarg, dbus_intf_callbacks_t *cbs)
        usb_info->drvintf = g_dbusintf;
 
        pub->bus = usb_info;
-#if  !defined(BCM_REQUEST_FW)
-
+#if !defined(BCM_REQUEST_FW)
        if (!dbus_usb_resetcfg(usb_info)) {
-       usb_info->pub->busstate = DBUS_STATE_DL_DONE;
+               usb_info->pub->busstate = DBUS_STATE_DL_DONE;
        }
 #endif
        /* Return Lower layer info */
@@ -648,6 +651,7 @@ err:
        return bcmerror;
 } /* dbus_usb_doiovar */
 
+#if !defined(BCM_REQUEST_FW)
 /**
  * After downloading firmware into dongle and starting it, we need to know if the firmware is
  * indeed up and running.
@@ -704,6 +708,7 @@ dbus_usb_resetcfg(usb_info_t *usbinfo)
 
        return DBUS_OK;
 }
+#endif
 
 /** before firmware download, the dongle has to be prepared to receive the fw image */
 static int
@@ -864,11 +869,11 @@ dbus_usb_dlstart(void *bus, uint8 *fw, int len)
        err = dbus_usb_rdl_dwnld_state(usbinfo);
 
        if (DBUS_OK == err) {
-       err = dbus_usb_dl_writeimage(usbinfo, fw, len);
-       if (err == DBUS_OK)
-               usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
-       else
-               usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
+               err = dbus_usb_dl_writeimage(usbinfo, fw, len);
+               if (err == DBUS_OK)
+                       usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
+               else
+                       usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
        } else
                usbinfo->pub->busstate = DBUS_STATE_DL_PENDING;
 
@@ -948,18 +953,18 @@ dbus_usb_update_chipinfo(usb_info_t *usbinfo, uint32 chip)
 } /* dbus_usb_update_chipinfo */
 
 /** higher DBUS level (dbus.c) wants to know if firmware download is required. */
-static bool
+static int
 dbus_usb_dlneeded(void *bus)
 {
        usb_info_t *usbinfo = BUS_INFO(bus, usb_info_t);
        void *osinfo;
        bootrom_id_t id;
-       bool dl_needed = TRUE;
+       int dl_needed = 1;
 
        DBUSTRACE(("%s\n", __FUNCTION__));
 
        if (usbinfo == NULL)
-               return FALSE;
+               return DBUS_ERR;
 
        osinfo = usbinfo->usbosl_info;
        ASSERT(osinfo);
@@ -972,7 +977,7 @@ dbus_usb_dlneeded(void *bus)
        id.chiprev = ltoh32(id.chiprev);
 
        if (FALSE == dbus_usb_update_chipinfo(usbinfo, id.chip)) {
-               dl_needed = FALSE;
+               dl_needed = DBUS_ERR;
                goto exit;
        }
 
@@ -982,7 +987,7 @@ dbus_usb_dlneeded(void *bus)
                DBUSERR(("%s: Firmware already downloaded\n", __FUNCTION__));
 
                dbus_usbos_dl_cmd(osinfo, DL_RESETCFG, &id, sizeof(bootrom_id_t));
-               dl_needed = FALSE;
+               dl_needed = DBUS_OK;
                if (usbinfo->pub->busstate == DBUS_STATE_DL_PENDING)
                        usbinfo->pub->busstate = DBUS_STATE_DL_DONE;
        } else {
@@ -1028,7 +1033,7 @@ dbus_usb_dlrun(void *bus)
                if (usbinfo->pub->attrib.devid == TEST_CHIP)
                        dbus_usbos_wait(osinfo, USB_DLGO_SPINWAIT);
 
-               dbus_usb_resetcfg(usbinfo);
+//             dbus_usb_resetcfg(usbinfo);
                /* The Donlge may go for re-enumeration. */
        } else {
                DBUSERR(("%s: Dongle not runnable\n", __FUNCTION__));
index 893760b98c4b99e9453466f5b751228e28c1c58e..10927d89463dd4f42a602835090aba005cb85543 100644 (file)
@@ -82,6 +82,8 @@
 #include <linux/usb.h>
 #include <usbrdl.h>
 #include <linux/firmware.h>
+#include <dngl_stats.h>
+#include <dhd.h>
 
 #if defined(USBOS_THREAD) || defined(USBOS_TX_THREAD)
 
@@ -1295,8 +1297,18 @@ DBUS_USBOS_PROBE()
        int wlan_if = -1;
        bool intr_ep = FALSE;
 #endif /* BCMUSBDEV_COMPOSITE */
+       wifi_adapter_info_t *adapter;
 
-       printf("%s: Enter\n", __FUNCTION__);
+       DHD_MUTEX_LOCK();
+
+       DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
+               usb->bus->busnum, usb->portnum));
+       adapter = dhd_wifi_platform_attach_adapter(USB_BUS, usb->bus->busnum,
+               usb->portnum, WIFI_STATUS_POWER_ON);
+       if (adapter == NULL) {
+               DBUSERR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
+               goto fail;
+       }
 
 #ifdef BCMUSBDEV_COMPOSITE
        wlan_if = dbus_usbos_intf_wlan(usb);
@@ -1541,7 +1553,7 @@ DBUS_USBOS_PROBE()
                DBUSERR(("full speed device detected\n"));
        }
        if (g_probe_info.dereged == FALSE && probe_cb) {
-               disc_arg = probe_cb(probe_arg, "", USB_BUS, 0);
+               disc_arg = probe_cb(probe_arg, "", USB_BUS, usb->bus->busnum, usb->portnum, 0);
        }
 
        g_probe_info.disc_cb_done = FALSE;
@@ -1549,7 +1561,7 @@ DBUS_USBOS_PROBE()
 #ifdef KERNEL26
        intf->needs_remote_wakeup = 1;
 #endif /* KERNEL26 */
-       printf("%s: Exit ret=%d\n", __FUNCTION__, ret);
+       DHD_MUTEX_UNLOCK();
 
        /* Success */
 #ifdef KERNEL26
@@ -1574,6 +1586,7 @@ fail:
 #endif /* BCMUSBDEV_COMPOSITE */
 #endif /* !KERNEL26 */
 
+       DHD_MUTEX_UNLOCK();
 #ifdef KERNEL26
        usb_set_intfdata(intf, NULL);
        return ret;
@@ -1593,7 +1606,10 @@ DBUS_USBOS_DISCONNECT()
 #endif
        usbos_info_t *usbos_info;
 
-       printf("%s: Enter\n", __FUNCTION__);
+       DHD_MUTEX_LOCK();
+
+       DBUSERR(("%s: bus num(busnum)=%d, slot num (portnum)=%d\n", __FUNCTION__,
+               usb->bus->busnum, usb->portnum));
 
        if (probe_usb_init_data) {
                usbos_info = (usbos_info_t *) probe_usb_init_data->usbos_info;
@@ -1616,7 +1632,7 @@ DBUS_USBOS_DISCONNECT()
                usb_dec_dev_use(usb);
 #endif /* !KERNEL26 */
        }
-       printf("%s: Exit\n", __FUNCTION__);
+       DHD_MUTEX_UNLOCK();
 } /* dbus_usbos_disconnect */
 
 #define LOOPBACK_PKT_START 0xBABE1234
@@ -2560,10 +2576,12 @@ dbus_bus_osl_deregister()
 {
        g_probe_info.dereged = TRUE;
 
+       DHD_MUTEX_LOCK();
        if (disconnect_cb && disc_arg && (g_probe_info.disc_cb_done == FALSE)) {
                disconnect_cb(disc_arg);
                disc_arg = NULL;
        }
+       DHD_MUTEX_UNLOCK();
 
        USB_DEREGISTER();
 
index 8fd55eefe398023553d5cd9fd2fce896b7c8f6e7..2ce59b20267a3c322878830f424e0395ed889eb0 100644 (file)
@@ -1036,9 +1036,13 @@ typedef struct dhd_pub {
 #if defined(STAT_REPORT)
        void *stat_report_info;
 #endif
-       char            *clm_path;              /* module_param: path to clm vars file */
-       char            *conf_path;             /* module_param: path to config vars file */
+       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 */
+       void *adapter;                  /* adapter information, interrupt, fw path etc. */
+#ifdef BCMDBUS
+       bool dhd_remove;
+#endif /* BCMDBUS */
 } dhd_pub_t;
 
 typedef struct {
@@ -1358,12 +1362,36 @@ typedef enum dhd_ioctl_recieved_status
  */
 void dhd_net_if_lock(struct net_device *dev);
 void dhd_net_if_unlock(struct net_device *dev);
-
 #if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
-extern struct mutex _dhd_sdio_mutex_lock_;
+extern void wl_android_post_init(void); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
+#endif
+
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && defined(MULTIPLE_SUPPLICANT)
+extern struct mutex _dhd_mutex_lock_;
+#define DHD_MUTEX_IS_LOCK_RETURN() \
+       if (mutex_is_locked(&_dhd_mutex_lock_) != 0) { \
+               printf("%s : probe is already running! return.\n", __FUNCTION__); \
+               return 0; \
+       }
+#define DHD_MUTEX_LOCK() \
+       do { \
+               if (mutex_is_locked(&_dhd_mutex_lock_) == 0) { \
+                       printf("%s : no mutex held. set lock\n", __FUNCTION__); \
+               } else { \
+                       printf("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__); \
+               } \
+               mutex_lock(&_dhd_mutex_lock_); \
+       } while (0)
+#define DHD_MUTEX_UNLOCK() \
+       do { \
+               mutex_unlock(&_dhd_mutex_lock_); \
+               printf("%s : the lock is released.\n", __FUNCTION__); \
+       } while (0)
+#else
+#define DHD_MUTEX_IS_LOCK_RETURN(a)    do {} while (0)
+#define DHD_MUTEX_LOCK(a)      do {} while (0)
+#define DHD_MUTEX_UNLOCK(a)    do {} while (0)
 #endif
-#endif /* MULTIPLE_SUPPLICANT */
 
 typedef enum dhd_attach_states
 {
@@ -1397,7 +1425,11 @@ typedef enum dhd_attach_states
  * Returned structure should have bus and prot pointers filled in.
  * bus_hdrlen specifies required headroom for bus module header.
  */
-extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen);
+extern dhd_pub_t *dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
+#ifdef BCMDBUS
+       , void *adapter
+#endif
+);
 #if defined(WLP2P) && defined(WL_CFG80211)
 /* To allow attach/detach calls corresponding to p2p0 interface  */
 extern int dhd_attach_p2p(dhd_pub_t *);
@@ -2246,6 +2278,8 @@ extern void dhd_os_general_spin_unlock(dhd_pub_t *pub, unsigned long flags);
 extern void dhd_dump_to_kernelog(dhd_pub_t *dhdp);
 
 #ifdef BCMDBUS
+extern uint dhd_get_rxsz(dhd_pub_t *pub);
+extern void dhd_set_path(dhd_pub_t *pub);
 extern void dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf);
 extern void dhd_bus_clearcounts(dhd_pub_t *dhdp);
 #endif /* BCMDBUS */
index c785f1210997609f6692b02699ecb5379a14b36a..e0f048333077f41893df262358da1076b622891f 100644 (file)
 #ifndef _dhd_bus_h_
 #define _dhd_bus_h_
 
+extern int dbus_up(struct dhd_bus *pub);
+extern int dbus_stop(struct dhd_bus *pub);
+extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len);
+extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len);
 /*
  * Exported from dhd bus module (dhd_usb, dhd_sdio)
  */
index db30d9b01c70910cdc216a7b59468b9c9366ff7f..3fb5e457040a8dddee02704b5b11dcc32ccf5e74 100644 (file)
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <dhd_proto.h>
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
 #include <dhd_bus.h>
-#endif /* BCMDBUS */
 #include <dhd_dbg.h>
 
 
@@ -53,6 +49,9 @@
 #include <wlfc_proto.h>
 #include <dhd_wlfc.h>
 #endif
+#ifdef BCMDBUS
+#include <dhd_config.h>
+#endif /* BCMDBUS */
 
 #ifdef DHD_ULP
 #include <dhd_ulp.h>
@@ -80,10 +79,6 @@ typedef struct dhd_prot {
        unsigned char buf[WLC_IOCTL_MAXLEN + ROUND_UP_MARGIN];
 } dhd_prot_t;
 
-#if defined(BCMDBUS)
-extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf);
-#endif /* BCMDBUS */
-
 static int
 dhdcdc_msg(dhd_pub_t *dhd)
 {
@@ -109,9 +104,9 @@ dhdcdc_msg(dhd_pub_t *dhd)
 #ifdef BCMDBUS
        DHD_OS_IOCTL_RESP_LOCK(dhd);
        prot->ctl_completed = FALSE;
-       err = dbus_send_ctl(dhd->dbus, (void *)&prot->msg, len);
+       err = dbus_send_ctl(dhd->bus, (void *)&prot->msg, len);
        if (err) {
-               DHD_ERROR(("dbus_send_ctl error=0x%x\n", err));
+               DHD_ERROR(("dbus_send_ctl error=%d\n", err));
                DHD_OS_IOCTL_RESP_UNLOCK(dhd);
                DHD_OS_WAKE_UNLOCK(dhd);
                return err;
@@ -171,7 +166,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len)
 #ifdef BCMDBUS
                DHD_OS_IOCTL_RESP_LOCK(dhd);
                prot->ctl_completed = FALSE;
-               ret = dbus_recv_ctl(dhd->dbus, (uchar*)&prot->msg, cdc_len);
+               ret = dbus_recv_ctl(dhd->bus, (uchar*)&prot->msg, cdc_len);
                if (ret) {
                        DHD_ERROR(("dbus_recv_ctl error=0x%x(%d)\n", ret, ret));
                        DHD_OS_IOCTL_RESP_UNLOCK(dhd);
@@ -594,7 +589,7 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in
 #ifdef BCMDBUS
 #ifndef DHD_WLFC_THREAD
                dhd_wlfc_commit_packets(dhd,
-                       (f_commitpkt_t)dhd_dbus_txdata, (void *)dhd, NULL, FALSE);
+                       (f_commitpkt_t)dhd_bus_txdata, dhd->bus, NULL, FALSE);
 #endif /* DHD_WLFC_THREAD */
 #endif /* BCMDBUS */
        }
@@ -682,6 +677,14 @@ dhd_sync_with_dongle(dhd_pub_t *dhd)
        ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_REVINFO, &revinfo, sizeof(revinfo), FALSE, 0);
        if (ret < 0)
                goto done;
+#if defined(BCMDBUS)
+       if (dhd_download_fw_on_driverload) {
+               dhd_conf_reset(dhd);
+               dhd_conf_set_chiprev(dhd, revinfo.chipnum, revinfo.chiprev);
+               dhd_conf_preinit(dhd);
+               dhd_conf_read_config(dhd, dhd->conf_path);
+       }
+#endif /* BCMDBUS */
 
 
        DHD_SSSR_DUMP_INIT(dhd);
index 80fcbd92cec42a395aa0f3baf55a1d1dbab0354b..bbab84aebdc6d0f57f4ab0c48440d2416220d9d3 100644 (file)
 #include <dhd_flowring.h>
 #endif
 
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
 #include <dhd_bus.h>
-#endif /* BCMDBUS */
 #include <dhd_proto.h>
 #include <dhd_config.h>
 #include <bcmsdbus.h>
@@ -2400,21 +2396,11 @@ dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void *buf, uint buflen)
 
                                /* if still not found, try bus module */
                                if (ioc->cmd == DHD_GET_VAR) {
-#ifdef BCMDBUS
-                                       bcmerror = dbus_iovar_op(dhd_pub->dbus, buf,
-                                               arg, arglen, buf, buflen, IOV_GET);
-#else
                                        bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
                                                        arg, arglen, buf, buflen, IOV_GET);
-#endif /* BCMDBUS */
                                } else {
-#ifdef BCMDBUS
-                                       bcmerror = dbus_iovar_op(dhd_pub->dbus, buf,
-                                               NULL, 0, arg, arglen, IOV_SET);
-#else
                                        bcmerror = dhd_bus_iovar_op(dhd_pub, buf,
                                                        NULL, 0, arg, arglen, IOV_SET);
-#endif /* BCMDBUS */
                                }
                                if (bcmerror != BCME_UNSUPPORTED) {
                                        goto unlock_exit;
@@ -3614,7 +3600,7 @@ dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg)
                                        htod16(WL_PKT_FILTER_MFLAG_NEG);
                                (argv[i])++;
                        }
-                       if (argv[i] == '\0') {
+                       if (*argv[i] == '\0') {
                                printf("Pattern not provided\n");
                                goto fail;
                        }
@@ -4901,7 +4887,7 @@ dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path)
        char iovbuf[WLC_IOCTL_SMLEN] = {0};
        int status = FALSE;
 
-       if (clm_path[0] != '\0') {
+       if (clm_path && clm_path[0] != '\0') {
                if (strlen(clm_path) > MOD_PARAM_PATHLEN) {
                        DHD_ERROR(("clm path exceeds max len\n"));
                        return BCME_ERROR;
index f1aae8aa4111a46222df768c8d3f8beaacfb6fd0..798fc6b0b3e3286dfd561b1d3042194222dc02fa 100644 (file)
@@ -64,27 +64,27 @@ const cihp_name_map_t chip_name_map [] = {
        {BCM43362_CHIP_ID,      1,      DONT_CARE,      FALSE,  "bcm40181a2",           ""},\r
        {BCM4330_CHIP_ID,       4,      FW_TYPE_G,      FALSE,  "bcm40183b2",           ""},\r
        {BCM4330_CHIP_ID,       4,      FW_TYPE_AG,     FALSE,  "bcm40183b2_ag",        ""},\r
-       {BCM43430_CHIP_ID,      0,      DONT_CARE,      FALSE,  "bcm43438a0",           "nvram_ap6212.txt"},\r
-       {BCM43430_CHIP_ID,      1,      DONT_CARE,      FALSE,  "bcm43438a1",           "nvram_ap6212a.txt"},\r
-       {BCM43430_CHIP_ID,      2,      DONT_CARE,      FALSE,  "bcm43436b0",           "nvram_ap6236.txt"},\r
+       {BCM43430_CHIP_ID,      0,      DONT_CARE,      FALSE,  "bcm43438a0",           "ap6212"},\r
+       {BCM43430_CHIP_ID,      1,      DONT_CARE,      FALSE,  "bcm43438a1",           "ap6212a"},\r
+       {BCM43430_CHIP_ID,      2,      DONT_CARE,      FALSE,  "bcm43436b0",           "ap6236"},\r
        {BCM43012_CHIP_ID,      1,      DONT_CARE,      TRUE,   "bcm43013b0",           ""},\r
        {BCM4334_CHIP_ID,       3,      DONT_CARE,      FALSE,  "bcm4334b1_ag",         ""},\r
        {BCM43340_CHIP_ID,      2,      DONT_CARE,      FALSE,  "bcm43341b0_ag",        ""},\r
        {BCM43341_CHIP_ID,      2,      DONT_CARE,      FALSE,  "bcm43341b0_ag",        ""},\r
        {BCM4324_CHIP_ID,       5,      DONT_CARE,      FALSE,  "bcm43241b4_ag",        ""},\r
        {BCM4335_CHIP_ID,       2,      DONT_CARE,      FALSE,  "bcm4339a0_ag",         ""},\r
-       {BCM4339_CHIP_ID,       1,      DONT_CARE,      FALSE,  "bcm4339a0_ag",         "nvram_ap6335.txt"},\r
-       {BCM4345_CHIP_ID,       6,      DONT_CARE,      FALSE,  "bcm43455c0_ag",        "nvram_ap6255.txt"},\r
+       {BCM4339_CHIP_ID,       1,      DONT_CARE,      FALSE,  "bcm4339a0_ag",         "ap6335"},\r
+       {BCM4345_CHIP_ID,       6,      DONT_CARE,      FALSE,  "bcm43455c0_ag",        "ap6255"},\r
        {BCM43454_CHIP_ID,      6,      DONT_CARE,      FALSE,  "bcm43455c0_ag",        ""},\r
-       {BCM4345_CHIP_ID,       9,      DONT_CARE,      FALSE,  "bcm43456c5_ag",        "nvram_ap6256.txt"},\r
-       {BCM43454_CHIP_ID,      9,      DONT_CARE,      FALSE,  "bcm43455c5_ag",        ""},\r
+       {BCM4345_CHIP_ID,       9,      DONT_CARE,      FALSE,  "bcm43456c5_ag",        "ap6256"},\r
+       {BCM43454_CHIP_ID,      9,      DONT_CARE,      FALSE,  "bcm43456c5_ag",        ""},\r
        {BCM4354_CHIP_ID,       1,      DONT_CARE,      FALSE,  "bcm4354a1_ag",         ""},\r
-       {BCM4354_CHIP_ID,       2,      DONT_CARE,      FALSE,  "bcm4356a2_ag",         "nvram_ap6356.txt"},\r
+       {BCM4354_CHIP_ID,       2,      DONT_CARE,      FALSE,  "bcm4356a2_ag",         "ap6356"},\r
        {BCM4356_CHIP_ID,       2,      DONT_CARE,      FALSE,  "bcm4356a2_ag",         ""},\r
        {BCM4371_CHIP_ID,       2,      DONT_CARE,      FALSE,  "bcm4356a2_ag",         ""},\r
        {BCM43569_CHIP_ID,      3,      DONT_CARE,      FALSE,  "bcm4358a3_ag",         ""},\r
        {BCM4359_CHIP_ID,       5,      DONT_CARE,      FALSE,  "bcm4359b1_ag",         ""},\r
-       {BCM4359_CHIP_ID,       9,      DONT_CARE,      FALSE,  "bcm4359c0_ag",         "nvram_ap6398.txt"},\r
+       {BCM4359_CHIP_ID,       9,      DONT_CARE,      FALSE,  "bcm4359c0_ag",         "ap6398s"},\r
        {BCM4362_CHIP_ID,       0,      DONT_CARE,      TRUE,   "bcm43752a0_ag",        ""},\r
 #endif\r
 #ifdef BCMPCIE\r
@@ -93,6 +93,11 @@ const cihp_name_map_t chip_name_map [] = {
        {BCM4359_CHIP_ID,       9,      DONT_CARE,      FALSE,  "bcm4359c0_pcie_ag",    ""},\r
        {BCM4362_CHIP_ID,       0,      DONT_CARE,      TRUE,   "bcm43752a0_pcie_ag",   ""},\r
 #endif\r
+#ifdef BCMDBUS\r
+       {BCM43143_CHIP_ID,      2,      DONT_CARE,      FALSE,  "bcm43143b0",           ""},\r
+       {BCM43242_CHIP_ID,      1,      DONT_CARE,      FALSE,  "bcm43242a1_ag",        ""},\r
+       {BCM43569_CHIP_ID,      2,      DONT_CARE,      FALSE,  "bcm4358u_ag",          "ap62x8"},\r
+#endif\r
 };\r
 \r
 #ifdef BCMSDIO\r
@@ -474,6 +479,9 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
                        (row->ag_type == ag_type || row->ag_type == DONT_CARE)) {\r
                        strcpy(name_ptr, "fw_");\r
                        strcat(fw_path, row->chip_name);\r
+#ifdef BCMUSBDEV_COMPOSITE\r
+                       strcat(fw_path, "_cusb");\r
+#endif\r
                        if (fw_type == FW_TYPE_APSTA)\r
                                strcat(fw_path, "_apsta.bin");\r
                        else if (fw_type == FW_TYPE_P2P)\r
@@ -567,7 +575,12 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path)
        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 && strlen(row->module_name)) {\r
-                       strcpy(name_ptr, row->module_name);\r
+                       strcpy(name_ptr, "nvram_");\r
+                       strcat(name_ptr, row->module_name);\r
+#ifdef BCMUSBDEV_COMPOSITE\r
+                       strcat(name_ptr, "_cusb");\r
+#endif\r
+                       strcat(name_ptr, ".txt");\r
                }\r
        }\r
 \r
@@ -751,28 +764,23 @@ dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec)
 }\r
 \r
 int\r
-dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec, int nodfs)\r
+dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec)\r
 {\r
        int bcmerror = -1, i;\r
        struct dhd_conf *conf = dhd->conf;\r
-       conf_country_list_t *country_list;\r
-\r
-       if ((nodfs > 0 || dhd->op_mode & DHD_FLAG_HOSTAP_MODE) &&\r
-                       conf->country_list_nodfs.count > 0) {\r
-               country_list = &conf->country_list_nodfs;\r
-       } else {\r
-               country_list = &conf->country_list;\r
-       }\r
+       conf_country_list_t *country_list = &conf->country_list;\r
 \r
        for (i = 0; i < country_list->count; i++) {\r
                if (!strncmp(cspec->country_abbrev, 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
-                       printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev);\r
-                       return 0;\r
+                       bcmerror = 0;\r
                }\r
        }\r
 \r
+       if (!bcmerror)\r
+               printf("%s: %s/%d\n", __FUNCTION__, cspec->ccode, cspec->rev);\r
+\r
        return bcmerror;\r
 }\r
 \r
@@ -817,12 +825,12 @@ dhd_conf_fix_country(dhd_pub_t *dhd)
                        dtoh32(list->count)<11)) {\r
                CONFIG_ERROR(("%s: bcmerror=%d, # of channels %d\n",\r
                        __FUNCTION__, bcmerror, dtoh32(list->count)));\r
-               dhd_conf_map_country_list(dhd, &dhd->conf->cspec, 0);\r
+               dhd_conf_map_country_list(dhd, &dhd->conf->cspec);\r
                if ((bcmerror = dhd_conf_set_country(dhd, &dhd->conf->cspec)) < 0) {\r
                        strcpy(cspec.country_abbrev, "US");\r
                        cspec.rev = 0;\r
                        strcpy(cspec.ccode, "US");\r
-                       dhd_conf_map_country_list(dhd, &cspec, 0);\r
+                       dhd_conf_map_country_list(dhd, &cspec);\r
                        dhd_conf_set_country(dhd, &cspec);\r
                }\r
        }\r
@@ -887,17 +895,19 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd)
                u32 bw_cap;\r
        } param = {0, 0};\r
 \r
-       if (dhd->conf->bw_cap_2g >= 0) {\r
+       if (dhd->conf->bw_cap[0] >= 0) {\r
+               memset(&param, 0, sizeof(param));\r
                param.band = WLC_BAND_2G;\r
-               param.bw_cap = (uint)dhd->conf->bw_cap_2g;\r
-               printf("%s: set bw_cap 2g %d\n", __FUNCTION__, param.bw_cap);\r
+               param.bw_cap = (uint)dhd->conf->bw_cap[0];\r
+               printf("%s: set bw_cap 2g 0x%x\n", __FUNCTION__, param.bw_cap);\r
                dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)&param, sizeof(param), TRUE);\r
        }\r
 \r
-       if (dhd->conf->bw_cap_5g >= 0) {\r
+       if (dhd->conf->bw_cap[1] >= 0) {\r
+               memset(&param, 0, sizeof(param));\r
                param.band = WLC_BAND_5G;\r
-               param.bw_cap = (uint)dhd->conf->bw_cap_5g;\r
-               printf("%s: set bw_cap 5g %d\n", __FUNCTION__, param.bw_cap);\r
+               param.bw_cap = (uint)dhd->conf->bw_cap[1];\r
+               printf("%s: set bw_cap 5g 0x%x\n", __FUNCTION__, param.bw_cap);\r
                dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)&param, sizeof(param), TRUE);\r
        }\r
 }\r
@@ -1145,10 +1155,7 @@ int
 dhd_conf_get_pm(dhd_pub_t *dhd)\r
 {\r
        if (dhd && dhd->conf) {\r
-               if (dhd->conf->fw_type == FW_TYPE_MESH)\r
-                       return PM_OFF;\r
-               else\r
-                       return dhd->conf->pm;\r
+               return dhd->conf->pm;\r
        }\r
        return -1;\r
 }\r
@@ -1312,8 +1319,6 @@ 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>0 && pickbuf[pick_column-1]==' ' && varbuf[n]==' ')\r
-                               continue;\r
                        pickbuf[pick_column] = varbuf[n];\r
                        pick_column++;\r
                }\r
@@ -1674,8 +1679,6 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)
         */\r
        if (!strncmp("country_list=", full_param, len_param)) {\r
                country_list = &dhd->conf->country_list;\r
-       } else if (!strncmp("country_list_nodfs=", full_param, len_param)) {\r
-               country_list = &dhd->conf->country_list_nodfs;\r
        }\r
        if (country_list) {\r
                pick_tmp = data;\r
@@ -1713,8 +1716,6 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)
                }\r
                if (!strncmp("country_list=", full_param, len_param)) {\r
                        printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count);\r
-               } else if (!strncmp("country_list_nodfs=", full_param, len_param)) {\r
-                       printf("%s: %d nodfs country in list\n", __FUNCTION__, conf->country_list.count);\r
                }\r
        }\r
        else\r
@@ -1853,33 +1854,33 @@ dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param)
 }\r
 #endif\r
 \r
-#ifdef IAPSTA_PREINIT\r
+#ifdef ISAM_PREINIT\r
 /*\r
- * iapsta_init=mode [sta|ap|apsta|dualap] vifname [wlan1]\r
- * iapsta_config=ifname [wlan0|wlan1] ssid [xxx] chan [x]\r
+ * isam_init=mode [sta|ap|apsta|dualap] vifname [wlan1]\r
+ * isam_config=ifname [wlan0|wlan1] ssid [xxx] chan [x]\r
                 hidden [y|n] maxassoc [x]\r
                 amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\r
                 emode [none|wep|tkip|aes|tkipaes]\r
                 key [xxxxx]\r
- * iapsta_enable=ifname [wlan0|wlan1]\r
+ * isam_enable=ifname [wlan0|wlan1]\r
 */\r
 bool\r
-dhd_conf_read_iapsta(dhd_pub_t *dhd, char *full_param, uint len_param)\r
+dhd_conf_read_isam(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
        struct dhd_conf *conf = dhd->conf;\r
        char *data = full_param+len_param;\r
 \r
-       if (!strncmp("iapsta_init=", full_param, len_param)) {\r
-               sprintf(conf->iapsta_init, "iapsta_init %s", data);\r
-               printf("%s: iapsta_init=%s\n", __FUNCTION__, conf->iapsta_init);\r
+       if (!strncmp("isam_init=", full_param, len_param)) {\r
+               sprintf(conf->isam_init, "isam_init %s", data);\r
+               printf("%s: isam_init=%s\n", __FUNCTION__, conf->isam_init);\r
        }\r
-       else if (!strncmp("iapsta_config=", full_param, len_param)) {\r
-               sprintf(conf->iapsta_config, "iapsta_config %s", data);\r
-               printf("%s: iapsta_config=%s\n", __FUNCTION__, conf->iapsta_config);\r
+       else if (!strncmp("isam_config=", full_param, len_param)) {\r
+               sprintf(conf->isam_config, "isam_config %s", data);\r
+               printf("%s: isam_config=%s\n", __FUNCTION__, conf->isam_config);\r
        }\r
-       else if (!strncmp("iapsta_enable=", full_param, len_param)) {\r
-               sprintf(conf->iapsta_enable, "iapsta_enable %s", data);\r
-               printf("%s: iapsta_enable=%s\n", __FUNCTION__, conf->iapsta_enable);\r
+       else if (!strncmp("isam_enable=", full_param, len_param)) {\r
+               sprintf(conf->isam_enable, "isam_enable %s", data);\r
+               printf("%s: isam_enable=%s\n", __FUNCTION__, conf->isam_enable);\r
        }\r
        else\r
                return false;\r
@@ -2029,13 +2030,6 @@ dhd_conf_read_sdio_params(dhd_pub_t *dhd, char *full_param, uint len_param)
                conf->txctl_tmo_fix = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix);\r
        }\r
-       else if (!strncmp("tx_in_rx=", full_param, len_param)) {\r
-               if (!strncmp(data, "0", 1))\r
-                       conf->tx_in_rx = FALSE;\r
-               else\r
-                       conf->tx_in_rx = TRUE;\r
-               printf("%s: tx_in_rx = %d\n", __FUNCTION__, conf->tx_in_rx);\r
-       }\r
        else if (!strncmp("tx_max_offset=", full_param, len_param)) {\r
                conf->tx_max_offset = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset);\r
@@ -2160,12 +2154,25 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
                printf("%s: band = %d\n", __FUNCTION__, conf->band);\r
        }\r
        else if (!strncmp("bw_cap_2g=", full_param, len_param)) {\r
-               conf->bw_cap_2g = (uint)simple_strtol(data, NULL, 0);\r
-               printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap_2g);\r
+               conf->bw_cap[0] = (uint)simple_strtol(data, NULL, 0);\r
+               printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap[0]);\r
        }\r
        else if (!strncmp("bw_cap_5g=", full_param, len_param)) {\r
-               conf->bw_cap_5g = (uint)simple_strtol(data, NULL, 0);\r
-               printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap_5g);\r
+               conf->bw_cap[1] = (uint)simple_strtol(data, NULL, 0);\r
+               printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap[1]);\r
+       }\r
+       else if (!strncmp("bw_cap=", full_param, len_param)) {\r
+               pick_tmp = data;\r
+               pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+               if (pch != NULL) {\r
+                       conf->bw_cap[0] = (uint32)simple_strtol(pch, NULL, 0);\r
+                       printf("%s: bw_cap 2g = %d\n", __FUNCTION__, conf->bw_cap[0]);\r
+               }\r
+               pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+               if (pch != NULL) {\r
+                       conf->bw_cap[1] = (uint32)simple_strtol(pch, NULL, 0);\r
+                       printf("%s: bw_cap 5g = %d\n", __FUNCTION__, conf->bw_cap[1]);\r
+               }\r
        }\r
        else if (!strncmp("ccode=", full_param, len_param)) {\r
                memset(&conf->cspec, 0, sizeof(wl_country_t));\r
@@ -2245,10 +2252,6 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
                printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound);\r
        }\r
 #endif\r
-       else if (!strncmp("num_different_channels=", full_param, len_param)) {\r
-               conf->num_different_channels = (int)simple_strtol(data, NULL, 10);\r
-               printf("%s: num_different_channels = %d\n", __FUNCTION__, conf->num_different_channels);\r
-       }\r
        else if (!strncmp("tsq=", full_param, len_param)) {\r
                conf->tsq = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: tsq = %d\n", __FUNCTION__, conf->tsq);\r
@@ -2261,11 +2264,15 @@ dhd_conf_read_others(dhd_pub_t *dhd, char *full_param, uint len_param)
                conf->dhd_ioctl_timeout_msec = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: dhd_ioctl_timeout_msec = %d\n", __FUNCTION__, conf->dhd_ioctl_timeout_msec);\r
        }\r
+       else if (!strncmp("in4way=", full_param, len_param)) {\r
+               conf->in4way = (int)simple_strtol(data, NULL, 0);\r
+               printf("%s: in4way = 0x%x\n", __FUNCTION__, conf->in4way);\r
+       }\r
        else if (!strncmp("wl_preinit=", full_param, len_param)) {\r
-               if (!(conf->wl_preinit = kmalloc(len_param, GFP_KERNEL))) {\r
+               if (!(conf->wl_preinit = kmalloc(len_param+1, GFP_KERNEL))) {\r
                        CONFIG_ERROR(("%s: kmalloc failed\n", __FUNCTION__));\r
                } else {\r
-                       memset(conf->wl_preinit, 0, len_param);\r
+                       memset(conf->wl_preinit, 0, len_param+1);\r
                        strcpy(conf->wl_preinit, data);\r
                        printf("%s: wl_preinit = %s\n", __FUNCTION__, conf->wl_preinit);\r
                }\r
@@ -2358,10 +2365,10 @@ dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)
                        else if (dhd_conf_read_pkt_filter(dhd, pick, len_param))\r
                                continue;\r
 #endif /* PKT_FILTER_SUPPORT */\r
-#ifdef IAPSTA_PREINIT\r
-                       else if (dhd_conf_read_iapsta(dhd, pick, len_param))\r
+#ifdef ISAM_PREINIT\r
+                       else if (dhd_conf_read_isam(dhd, pick, len_param))\r
                                continue;\r
-#endif /* IAPSTA_PREINIT */\r
+#endif /* ISAM_PREINIT */\r
 #ifdef IDHCP\r
                        else if (dhd_conf_read_dhcp_params(dhd, pick, len_param))\r
                                continue;\r
@@ -2455,45 +2462,101 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable)
        if (conf->txglom_ext)\r
                printf("%s: txglom_ext=%d, txglom_bucket_size=%d\n", __FUNCTION__,\r
                        conf->txglom_ext, conf->txglom_bucket_size);\r
-       printf("%s: txglom_mode=%s, use_rxchain=%d\n", __FUNCTION__,\r
-               conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy", conf->use_rxchain);\r
+       printf("%s: txglom_mode=%s\n", __FUNCTION__,\r
+               conf->txglom_mode==SDPCM_TXGLOM_MDESC?"multi-desc":"copy");\r
        printf("%s: txglomsize=%d, deferred_tx_len=%d\n", __FUNCTION__,\r
                conf->txglomsize, conf->deferred_tx_len);\r
-       printf("%s: tx_in_rx=%d, txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__,\r
-               conf->tx_in_rx, conf->txinrx_thres, conf->dhd_txminmax);\r
+       printf("%s: txinrx_thres=%d, dhd_txminmax=%d\n", __FUNCTION__,\r
+               conf->txinrx_thres, conf->dhd_txminmax);\r
        printf("%s: tx_max_offset=%d, txctl_tmo_fix=%d\n", __FUNCTION__,\r
                conf->tx_max_offset, conf->txctl_tmo_fix);\r
 \r
 }\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, WLC_SET_VAR, "rsdb_mode", (char *)&rsdb_mode_cfg,\r
+                       sizeof(rsdb_mode_cfg), TRUE);\r
+               printf("%s: rsdb_mode %d\n", __FUNCTION__, 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;\r
-       char name[50], *pch, *pick_tmp, *pick_tmp2;\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=85/0, mpc/0\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
+       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
+               pch = bcmstrtok(&pick_tmp2, ",", 0);\r
                if (!pch) {\r
                        break;\r
                }\r
-               val = (int)simple_strtol(pch, NULL, 0);\r
-               dhd_conf_set_intiovar(dhd, cmd, name, val, -1, TRUE);\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
@@ -2505,7 +2568,7 @@ dhd_conf_postinit_ioctls(dhd_pub_t *dhd)
        struct dhd_conf *conf = dhd->conf;\r
 \r
        dhd_conf_set_intiovar(dhd, WLC_UP, "up", 0, 0, FALSE);\r
-       dhd_conf_map_country_list(dhd, &conf->cspec, 0);\r
+       dhd_conf_map_country_list(dhd, &conf->cspec);\r
        dhd_conf_set_country(dhd, &conf->cspec);\r
        dhd_conf_fix_country(dhd);\r
        dhd_conf_get_country(dhd, &dhd->dhd_cspec);\r
@@ -2563,15 +2626,17 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        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_country_list(&conf->country_list_nodfs);\r
-       if (conf->magic_pkt_filter_add)\r
+       if (conf->magic_pkt_filter_add) {\r
                kfree(conf->magic_pkt_filter_add);\r
-       if (conf->wl_preinit)\r
+               conf->magic_pkt_filter_add = NULL;\r
+       }\r
+       if (conf->wl_preinit) {\r
                kfree(conf->wl_preinit);\r
+               conf->wl_preinit = NULL;\r
+       }\r
        memset(&conf->country_list, 0, sizeof(conf_country_list_t));\r
        conf->band = -1;\r
-       conf->bw_cap_2g = -1;\r
-       conf->bw_cap_5g = -1;\r
+       memset(&conf->bw_cap, -1, sizeof(conf->bw_cap));\r
        if (conf->chip == BCM43362_CHIP_ID || conf->chip == BCM4330_CHIP_ID) {\r
                strcpy(conf->cspec.country_abbrev, "ALL");\r
                strcpy(conf->cspec.ccode, "ALL");\r
@@ -2637,7 +2702,6 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->tx_max_offset = 0;\r
        conf->txglomsize = SDPCM_DEFGLOM_SIZE;\r
        conf->txctl_tmo_fix = 300;\r
-       conf->tx_in_rx = TRUE;\r
        conf->txglom_mode = SDPCM_TXGLOM_CPY;\r
        conf->deferred_tx_len = 0;\r
        conf->dhd_txminmax = 1;\r
@@ -2656,7 +2720,6 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->pm = -1;\r
        conf->pm_in_suspend = -1;\r
        conf->suspend_bcn_li_dtim = -1;\r
-       conf->num_different_channels = -1;\r
        conf->xmit_in_suspend = TRUE;\r
        conf->ap_in_suspend = 0;\r
 #ifdef SUSPEND_EVENT\r
@@ -2674,19 +2737,20 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->tsq = 0;\r
 #endif\r
 #ifdef DHDTCPACK_SUPPRESS\r
-#ifdef BCMSDIO\r
-       conf->tcpack_sup_mode = TCPACK_SUP_OFF;\r
-#elif defined(BCMPCIE)\r
+#ifdef BCMPCIE\r
        conf->tcpack_sup_mode = TCPACK_SUP_DEFAULT;\r
+#else\r
+       conf->tcpack_sup_mode = TCPACK_SUP_OFF;\r
 #endif\r
 #endif\r
        conf->pktprio8021x = -1;\r
        conf->ctrl_resched = 2;\r
        conf->dhd_ioctl_timeout_msec = 0;\r
-#ifdef IAPSTA_PREINIT\r
-       memset(conf->iapsta_init, 0, sizeof(conf->iapsta_init));\r
-       memset(conf->iapsta_config, 0, sizeof(conf->iapsta_config));\r
-       memset(conf->iapsta_enable, 0, sizeof(conf->iapsta_enable));\r
+       conf->in4way = NO_SCAN_IN4WAY;\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
@@ -2756,11 +2820,14 @@ dhd_conf_reset(dhd_pub_t *dhd)
        dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
 #endif\r
        dhd_conf_free_country_list(&dhd->conf->country_list);\r
-       dhd_conf_free_country_list(&dhd->conf->country_list_nodfs);\r
-       if (dhd->conf->magic_pkt_filter_add)\r
+       if (dhd->conf->magic_pkt_filter_add) {\r
                kfree(dhd->conf->magic_pkt_filter_add);\r
-       if (dhd->conf->wl_preinit)\r
+               dhd->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
+       }\r
        memset(dhd->conf, 0, sizeof(dhd_conf_t));\r
        return 0;\r
 }\r
@@ -2805,11 +2872,14 @@ dhd_conf_detach(dhd_pub_t *dhd)
                dhd_conf_free_chip_nv_path_list(&dhd->conf->nv_by_chip);\r
 #endif\r
                dhd_conf_free_country_list(&dhd->conf->country_list);\r
-               dhd_conf_free_country_list(&dhd->conf->country_list_nodfs);\r
-               if (dhd->conf->magic_pkt_filter_add)\r
+               if (dhd->conf->magic_pkt_filter_add) {\r
                        kfree(dhd->conf->magic_pkt_filter_add);\r
-               if (dhd->conf->wl_preinit)\r
+                       dhd->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
+               }\r
                MFREE(dhd->osh, dhd->conf, sizeof(dhd_conf_t));\r
        }\r
        dhd->conf = NULL;\r
index f62c8efec3dc6ecd851c2859c1c3f07bfdcaf8de..8d592ff8b89205c5f603e49fe7e0c791bd81155f 100644 (file)
@@ -101,6 +101,11 @@ typedef struct mchan_params {
        int miracast_mode;
 } mchan_params_t;
 
+enum in4way_flags {
+       NO_SCAN_IN4WAY  = (1 << (0)),
+       NO_BTC_IN4WAY   = (1 << (1))
+};
+
 typedef struct dhd_conf {
        uint chip;
        uint chiprev;
@@ -109,10 +114,8 @@ typedef struct dhd_conf {
        wl_mac_list_ctrl_t nv_by_mac;
        wl_chip_nv_path_list_ctrl_t nv_by_chip;
        conf_country_list_t country_list;
-       conf_country_list_t country_list_nodfs;
        int band;
-       int bw_cap_2g;
-       int bw_cap_5g;
+       int bw_cap[2];
        wl_country_t cspec;
        wl_channel_list_t channels;
        uint roam_off;
@@ -149,7 +152,6 @@ typedef struct dhd_conf {
        int tx_max_offset;
        uint txglomsize;
        int txctl_tmo_fix;
-       bool tx_in_rx;
        bool txglom_mode;
        uint deferred_tx_len;
        /*txglom_bucket_size:
@@ -177,7 +179,6 @@ typedef struct dhd_conf {
        uint8 tcpack_sup_mode;
 #endif
        int pktprio8021x;
-       int num_different_channels;
        int xmit_in_suspend;
        int ap_in_suspend;
 #ifdef SUSPEND_EVENT
@@ -193,16 +194,17 @@ typedef struct dhd_conf {
        struct ipv4_addr dhcpd_ip_start;
        struct ipv4_addr dhcpd_ip_end;
 #endif
-#ifdef IAPSTA_PREINIT
-       char iapsta_init[50];
-       char iapsta_config[300];
-       char iapsta_enable[50];
+#ifdef ISAM_PREINIT
+       char isam_init[50];
+       char isam_config[300];
+       char isam_enable[50];
 #endif
        int ctrl_resched;
        int dhd_ioctl_timeout_msec;
        struct mchan_params mchan[MCHAN_MAX_NUM];
        char *wl_preinit;
        int tsq;
+       uint in4way;
 } dhd_conf_t;
 
 #ifdef BCMSDIO
@@ -228,7 +230,7 @@ int dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf, int l
 uint 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, int nodfs);
+int dhd_conf_map_country_list(dhd_pub_t *dhd, wl_country_t *cspec);
 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 mode);
index abe37a4b5919007eaf2a90cf7c8c34f67f620e28..525a4b91ecaaa3c714c18f05d6bdb46fd9335e06 100644 (file)
@@ -112,8 +112,8 @@ dhd_wlan_set_power(int on
                        }
                }
 #ifdef CUSTOMER_HW_AMLOGIC
-//             extern_wifi_set_enable(0);
-//             mdelay(200);
+               extern_wifi_set_enable(0);
+               mdelay(200);
 #endif
        }
 
index ee7d105d231711c1d4c7f5cd73fb2301379441b8..d8be26cd8cef804d60a96ee8034dc68d454c3cd9 100644 (file)
@@ -287,10 +287,20 @@ static void _tdata_psh_info_pool_deinit(dhd_pub_t *dhdp,
        return;
 }
 
-static void dhd_tcpack_send(ulong data)
+static void dhd_tcpack_send(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       ulong data
+#endif
+)
 {
        tcpack_sup_module_t *tcpack_sup_mod;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       tcpack_info_t *cur_tbl = from_timer(cur_tbl, t, timer);
+#else
        tcpack_info_t *cur_tbl = (tcpack_info_t *)data;
+#endif
        dhd_pub_t *dhdp;
        int ifidx;
        void* pkt;
@@ -464,9 +474,13 @@ int dhd_tcpack_suppress_set(dhd_pub_t *dhdp, uint8 mode)
                                tcpack_info_t *tcpack_info_tbl =
                                        &tcpack_sup_module->tcpack_info_tbl[i];
                                tcpack_info_tbl->dhdp = dhdp;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+                               timer_setup(&tcpack_info_tbl->timer, dhd_tcpack_send, 0);
+#else
                                init_timer(&tcpack_info_tbl->timer);
                                tcpack_info_tbl->timer.data = (ulong)tcpack_info_tbl;
                                tcpack_info_tbl->timer.function = dhd_tcpack_send;
+#endif
                        }
                        break;
        }
index e3b6eb5ec7d1b957457c565a5d59b3e3bacf2e33..cde26666db637ed528cf88f60d150471e68ac05a 100644 (file)
@@ -350,7 +350,7 @@ MODULE_LICENSE("GPL and additional rights");
 
 #if defined(MULTIPLE_SUPPLICANT)
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-DEFINE_MUTEX(_dhd_sdio_mutex_lock_);
+DEFINE_MUTEX(_dhd_mutex_lock_);
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
 #endif 
 
@@ -358,11 +358,7 @@ DEFINE_MUTEX(_dhd_sdio_mutex_lock_);
 #define MAX_CONSECUTIVE_HANG_COUNTS 5
 #endif /* CONFIG_BCM_DETECT_CONSECUTIVE_HANG */
 
-#ifdef BCMDBUS
-#include <dbus.h>
-#else
 #include <dhd_bus.h>
-#endif /* BCMDBUS */
 
 #ifdef DHD_ULP
 #include <dhd_ulp.h>
@@ -613,7 +609,7 @@ typedef struct dhd_info {
        dhd_pub_t pub;
        dhd_if_t *iflist[DHD_MAX_IFS]; /* for supporting multiple interfaces */
 
-       void *adapter;                  /* adapter information, interrupt, fw path etc. */
+       wifi_adapter_info_t *adapter;                   /* adapter information, interrupt, fw path etc. */
        char fw_path[PATH_MAX];         /* path to firmware image */
        char nv_path[PATH_MAX];         /* path to nvram vars file */
        char clm_path[PATH_MAX];                /* path to clm vars file */
@@ -961,7 +957,7 @@ int op_mode = 0;
 int disable_proptx = 0;
 module_param(op_mode, int, 0644);
 extern int wl_control_wl_start(struct net_device *dev);
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(BCMLXSDMMC)
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (defined(BCMLXSDMMC) || defined(BCMDBUS))
 struct semaphore dhd_registration_sem;
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
 
@@ -1978,9 +1974,6 @@ void dhd_os_wd_timer_extend(void *bus, bool extend);
 static int dhd_toe_get(dhd_info_t *dhd, int idx, uint32 *toe_ol);
 static int dhd_toe_set(dhd_info_t *dhd, int idx, uint32 toe_ol);
 #endif /* TOE */
-#ifdef BCMDBUS
-int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf);
-#endif /* BCMDBUS */
 
 static int dhd_wl_host_event(dhd_info_t *dhd, int ifidx, void *pktdata, uint16 pktlen,
                wl_event_msg_t *event_ptr, void **data_ptr);
@@ -3239,8 +3232,8 @@ int dhd_process_cid_mac(dhd_pub_t *dhdp, bool prepost)
 }
 
 // terence 20160615: fix building error if ARP_OFFLOAD_SUPPORT removed
-#if defined(PKT_FILTER_SUPPORT) && defined(ARP_OFFLOAD_SUPPORT)
-#ifndef GAN_LITE_NAT_KEEPALIVE_FILTER
+#if defined(PKT_FILTER_SUPPORT)
+#if defined(ARP_OFFLOAD_SUPPORT) && !defined(GAN_LITE_NAT_KEEPALIVE_FILTER)
 static bool
 _turn_on_arp_filter(dhd_pub_t *dhd, int op_mode_param)
 {
@@ -3946,255 +3939,6 @@ dhd_bssidx2bssid(dhd_pub_t *dhdp, int idx)
        return NULL;
 }
 
-#ifdef BCMDBUS
-#define DBUS_NRXQ      50
-#define DBUS_NTXQ      100
-
-static void
-dhd_dbus_send_complete(void *handle, void *info, int status)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-       void *pkt = info;
-
-       if ((dhd == NULL) || (pkt == NULL))
-               return;
-
-       if (status == DBUS_OK) {
-               dhd->pub.dstats.tx_packets++;
-       } else {
-               DHD_ERROR(("TX error=%d\n", status));
-               dhd->pub.dstats.tx_errors++;
-       }
-#ifdef PROP_TXSTATUS
-       if (DHD_PKTTAG_WLFCPKT(PKTTAG(pkt)) &&
-               (dhd_wlfc_txcomplete(&dhd->pub, pkt, status == 0) != WLFC_UNSUPPORTED)) {
-               return;
-       }
-#endif /* PROP_TXSTATUS */
-       PKTFREE(dhd->pub.osh, pkt, TRUE);
-}
-
-static void
-dhd_dbus_recv_pkt(void *handle, void *pkt)
-{
-       uchar reorder_info_buf[WLHOST_REORDERDATA_TOTLEN];
-       uint reorder_info_len;
-       uint pkt_count;
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-       int ifidx = 0;
-
-       if (dhd == NULL)
-               return;
-
-       /* If the protocol uses a data header, check and remove it */
-       if (dhd_prot_hdrpull(&dhd->pub, &ifidx, pkt, reorder_info_buf,
-               &reorder_info_len) != 0) {
-               DHD_ERROR(("rx protocol error\n"));
-               PKTFREE(dhd->pub.osh, pkt, FALSE);
-               dhd->pub.rx_errors++;
-               return;
-       }
-
-       if (reorder_info_len) {
-               /* Reordering info from the firmware */
-               dhd_process_pkt_reorder_info(&dhd->pub, reorder_info_buf, reorder_info_len,
-                       &pkt, &pkt_count);
-               if (pkt_count == 0)
-                       return;
-       }
-       else {
-               pkt_count = 1;
-       }
-       dhd_rx_frame(&dhd->pub, ifidx, pkt, pkt_count, 0);
-}
-
-static void
-dhd_dbus_recv_buf(void *handle, uint8 *buf, int len)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-       void *pkt;
-
-       if (dhd == NULL)
-               return;
-
-       if ((pkt = PKTGET(dhd->pub.osh, len, FALSE)) == NULL) {
-               DHD_ERROR(("PKTGET (rx) failed=%d\n", len));
-               return;
-       }
-
-       bcopy(buf, PKTDATA(dhd->pub.osh, pkt), len);
-       dhd_dbus_recv_pkt(dhd, pkt);
-}
-
-static void
-dhd_dbus_txflowcontrol(void *handle, bool onoff)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-       bool wlfc_enabled = FALSE;
-
-       if (dhd == NULL)
-               return;
-
-#ifdef PROP_TXSTATUS
-       wlfc_enabled = (dhd_wlfc_flowcontrol(&dhd->pub, onoff, !onoff) != WLFC_UNSUPPORTED);
-#endif
-
-       if (!wlfc_enabled) {
-               dhd_txflowcontrol(&dhd->pub, ALL_INTERFACES, onoff);
-       }
-}
-
-static void
-dhd_dbus_errhandler(void *handle, int err)
-{
-}
-
-static void
-dhd_dbus_ctl_complete(void *handle, int type, int status)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-
-       if (dhd == NULL)
-               return;
-
-       if (type == DBUS_CBCTL_READ) {
-               if (status == DBUS_OK)
-                       dhd->pub.rx_ctlpkts++;
-               else
-                       dhd->pub.rx_ctlerrs++;
-       } else if (type == DBUS_CBCTL_WRITE) {
-               if (status == DBUS_OK)
-                       dhd->pub.tx_ctlpkts++;
-               else
-                       dhd->pub.tx_ctlerrs++;
-       }
-
-       dhd_prot_ctl_complete(&dhd->pub);
-}
-
-static void
-dhd_dbus_state_change(void *handle, int state)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-
-       if (dhd == NULL)
-               return;
-
-       switch (state) {
-
-               case DBUS_STATE_DL_NEEDED:
-#if defined(BCM_REQUEST_FW)
-#if defined(BCMDBUS)
-                       DHD_TRACE(("%s: firmware request\n", __FUNCTION__));
-                       up(&dhd->fw_download_lock);
-#endif /* BCMDBUS */
-#else
-                       DHD_ERROR(("%s: firmware request cannot be handled\n", __FUNCTION__));
-#endif 
-                       break;
-               case DBUS_STATE_DOWN:
-                       DHD_TRACE(("%s: DBUS is down\n", __FUNCTION__));
-                       dhd->pub.busstate = DHD_BUS_DOWN;
-                       break;
-               case DBUS_STATE_UP:
-                       DHD_TRACE(("%s: DBUS is up\n", __FUNCTION__));
-                       dhd->pub.busstate = DHD_BUS_DATA;
-                       break;
-               default:
-                       break;
-       }
-
-       printf("%s: DBUS current state=%d\n", __FUNCTION__, state);
-}
-
-static void *
-dhd_dbus_pktget(void *handle, uint len, bool send)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-       void *p = NULL;
-
-       if (dhd == NULL)
-               return NULL;
-
-       if (send == TRUE) {
-               dhd_os_sdlock_txq(&dhd->pub);
-               p = PKTGET(dhd->pub.osh, len, TRUE);
-               dhd_os_sdunlock_txq(&dhd->pub);
-       } else {
-               dhd_os_sdlock_rxq(&dhd->pub);
-               p = PKTGET(dhd->pub.osh, len, FALSE);
-               dhd_os_sdunlock_rxq(&dhd->pub);
-       }
-
-       return p;
-}
-
-static void
-dhd_dbus_pktfree(void *handle, void *p, bool send)
-{
-       dhd_info_t *dhd = (dhd_info_t *)handle;
-
-       if (dhd == NULL)
-               return;
-
-       if (send == TRUE) {
-#ifdef PROP_TXSTATUS
-               if (DHD_PKTTAG_WLFCPKT(PKTTAG(p)) &&
-                       (dhd_wlfc_txcomplete(&dhd->pub, p, FALSE) != WLFC_UNSUPPORTED)) {
-                       return;
-               }
-#endif /* PROP_TXSTATUS */
-
-               dhd_os_sdlock_txq(&dhd->pub);
-               PKTFREE(dhd->pub.osh, p, TRUE);
-               dhd_os_sdunlock_txq(&dhd->pub);
-       } else {
-               dhd_os_sdlock_rxq(&dhd->pub);
-               PKTFREE(dhd->pub.osh, p, FALSE);
-               dhd_os_sdunlock_rxq(&dhd->pub);
-       }
-}
-
-
-static dbus_callbacks_t dhd_dbus_cbs = {
-       dhd_dbus_send_complete,
-       dhd_dbus_recv_buf,
-       dhd_dbus_recv_pkt,
-       dhd_dbus_txflowcontrol,
-       dhd_dbus_errhandler,
-       dhd_dbus_ctl_complete,
-       dhd_dbus_state_change,
-       dhd_dbus_pktget,
-       dhd_dbus_pktfree
-};
-
-void
-dhd_bus_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf)
-{
-       bcm_bprintf(strbuf, "Bus USB\n");
-}
-
-void
-dhd_bus_clearcounts(dhd_pub_t *dhdp)
-{
-}
-
-bool
-dhd_bus_dpc(struct dhd_bus *bus)
-{
-       return FALSE;
-}
-
-int
-dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf)
-{
-
-       if (dhdp->txoff)
-               return BCME_EPERM;
-       return dbus_send_txdata(dhdp->dbus, pktbuf);
-}
-
-#endif /* BCMDBUS */
 
 static void
 _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx)
@@ -4968,10 +4712,6 @@ dhd_tx_dump(struct net_device *ndev, osl_t *osh, void *pkt)
 
        DHD_ERROR(("TX DUMP[%s] - %s\n", ifname, _get_packet_type_str(protocol)));
 
-       if (protocol == ETHER_TYPE_802_1X) {
-               dhd_dump_eapol_4way_message(ifname, dump_data, TRUE);
-       }
-
 #if defined(DHD_TX_FULL_DUMP)
        {
                int i;
@@ -5202,8 +4942,7 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
 #endif
 
 #if defined(DHD_TX_DUMP)
-       ndev = dhd_idx2net(dhdp, ifidx);
-       dhd_tx_dump(ndev, dhdp->osh, pktbuf);
+       dhd_tx_dump(dhd_idx2net(dhdp, ifidx), dhdp->osh, pktbuf);
 #endif
        /* terence 20150901: Micky add to ajust the 802.1X priority */
        /* Set the 802.1X packet with the highest priority 7 */
@@ -5235,20 +4974,6 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
 #ifdef WLMEDIA_HTSF
        dhd_htsf_addtxts(dhdp, pktbuf);
 #endif
-
-#ifdef BCMDBUS
-#ifdef PROP_TXSTATUS
-       if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_dbus_txdata,
-               dhdp, pktbuf, TRUE) == WLFC_UNSUPPORTED) {
-               /* non-proptxstatus way */
-               ret = dhd_dbus_txdata(dhdp, pktbuf);
-       }
-#else
-       ret = dhd_dbus_txdata(dhdp, pktbuf);
-#endif /* PROP_TXSTATUS */
-       if (ret)
-               PKTCFREE(dhdp->osh, pktbuf, TRUE);
-#else
 #ifdef PROP_TXSTATUS
        {
                if (dhd_wlfc_commit_packets(dhdp, (f_commitpkt_t)dhd_bus_txdata,
@@ -5268,8 +4993,11 @@ __dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf)
        ret = dhd_bus_txdata(dhdp->bus, pktbuf);
 #endif /* BCMPCIE */
 #endif /* PROP_TXSTATUS */
-
+#ifdef BCMDBUS
+       if (ret)
+               PKTCFREE(dhdp->osh, pktbuf, TRUE);
 #endif /* BCMDBUS */
+
        return ret;
 }
 
@@ -5413,9 +5141,10 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
 #endif /* DHD_PCIE_RUNTIMEPM */
 
        DHD_GENERAL_LOCK(&dhd->pub, flags);
+#ifdef BCMPCIE
        if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(&dhd->pub)) {
-       //      DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n",
-       //              __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state));
+               DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n",
+                       __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state));
                DHD_BUS_BUSY_CLEAR_IN_TX(&dhd->pub);
 #ifdef PCIE_FULL_DONGLE
                /* Stop tx queues if suspend is in progress */
@@ -5431,6 +5160,12 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
                return NETDEV_TX_BUSY;
 #endif
        }
+#else
+       if (DHD_BUS_CHECK_SUSPEND_OR_SUSPEND_IN_PROGRESS(&dhd->pub)) {
+               DHD_ERROR(("%s: bus is in suspend(%d) or suspending(0x%x) state!!\n",
+                       __FUNCTION__, dhd->pub.busstate, dhd->pub.dhd_bus_busy_state));
+       }
+#endif
 
        DHD_OS_WAKE_LOCK(&dhd->pub);
        DHD_PERIM_LOCK_TRY(DHD_FWDER_UNIT(dhd), lock_taken);
@@ -6694,9 +6429,19 @@ dhd_watchdog_thread(void *data)
        complete_and_exit(&tsk->completed, 0);
 }
 
-static void dhd_watchdog(ulong data)
+static void dhd_watchdog(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       ulong data
+#endif
+)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       dhd_info_t *dhd = from_timer(dhd, t, timer);
+#else
        dhd_info_t *dhd = (dhd_info_t *)data;
+#endif
        unsigned long flags;
 
        if (dhd->pub.dongle_reset) {
@@ -6776,9 +6521,19 @@ dhd_rpm_state_thread(void *data)
        complete_and_exit(&tsk->completed, 0);
 }
 
-static void dhd_runtimepm(ulong data)
+static void dhd_runtimepm(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       ulong data
+#endif
+)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       dhd_info_t *dhd = from_timer(dhd, t, rpm_timer);
+#else
        dhd_info_t *dhd = (dhd_info_t *)data;
+#endif
 
        if (dhd->pub.dongle_reset) {
                return;
@@ -6842,6 +6597,7 @@ exit:
        return 0;
 }
 #endif /* DEBUG_CPU_FREQ */
+
 static int
 dhd_dpc_thread(void *data)
 {
@@ -8692,7 +8448,7 @@ dhd_open(struct net_device *net)
        uint32 slot_num = -1;
        wifi_adapter_info_t *adapter = NULL;
 #endif
-#if defined(WL_EXT_IAPSTA) && defined(IAPSTA_PREINIT)
+#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT)
        int bytes_written = 0;
        struct dhd_conf *conf;
 #endif
@@ -8705,14 +8461,7 @@ dhd_open(struct net_device *net)
        }
 
        printf("%s: Enter %p\n", __FUNCTION__, net);
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) {
-               DHD_ERROR(("%s : dhd_open: call dev open before insmod complete!\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif
-#endif /* MULTIPLE_SUPPLICANT */
+       DHD_MUTEX_LOCK();
        /* Init wakelock */
        if (!dhd_download_fw_on_driverload) {
                if (!(dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT)) {
@@ -8796,14 +8545,10 @@ dhd_open(struct net_device *net)
 
        if (ifidx == 0) {
                atomic_set(&dhd->pend_8021x_cnt, 0);
-#ifdef BCMDBUS
-               dhd_update_fw_nv_path(dhd); // terence 20140807: fix for op_mode issue
-               dhd_conf_read_config(&dhd->pub, dhd->pub.conf_path);
-#endif /* BCMDBUS */
                if (!dhd_download_fw_on_driverload) {
                        DHD_ERROR(("\n%s\n", dhd_version));
 #ifdef WL_EXT_IAPSTA
-                       wl_ext_iapsta_attach_netdev(net, ifidx);
+                       wl_ext_iapsta_attach_netdev(net, ifidx, dhd->iflist[ifidx]->bssidx);
 #endif
 #if defined(USE_INITIAL_SHORT_DWELL_TIME)
                        g_first_broadcast_scan = TRUE;
@@ -8820,12 +8565,12 @@ dhd_open(struct net_device *net)
                                ret = -1;
                                goto exit;
                        }
-#if defined(WL_EXT_IAPSTA) && defined(IAPSTA_PREINIT)
+#if defined(WL_EXT_IAPSTA) && defined(ISAM_PREINIT)
                        conf = dhd_get_conf(net);
                        if (conf) {
-                               wl_android_ext_priv_cmd(net, conf->iapsta_init, 0, &bytes_written);
-                               wl_android_ext_priv_cmd(net, conf->iapsta_config, 0, &bytes_written);
-                               wl_android_ext_priv_cmd(net, conf->iapsta_enable, 0, &bytes_written);
+                               wl_android_ext_priv_cmd(net, conf->isam_init, 0, &bytes_written);
+                               wl_android_ext_priv_cmd(net, conf->isam_config, 0, &bytes_written);
+                               wl_android_ext_priv_cmd(net, conf->isam_enable, 0, &bytes_written);
                        }
 #endif
                }
@@ -8847,32 +8592,39 @@ dhd_open(struct net_device *net)
 #endif
 
                if (dhd->pub.busstate != DHD_BUS_DATA) {
-
-#ifndef BCMDBUS
-                       /* try to bring up bus */
-                       DHD_PERIM_UNLOCK(&dhd->pub);
-                       ret = dhd_bus_start(&dhd->pub);
-                       DHD_PERIM_LOCK(&dhd->pub);
-                       if (ret) {
-                               DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
-                               ret = -1;
-                               goto exit;
-                       }
-#else
-                       if ((ret = dbus_up(dhd->pub.dbus)) != 0) {
+#ifdef BCMDBUS
+                       dhd_set_path(&dhd->pub);
+                       DHD_MUTEX_UNLOCK();
+                       wait_event_interruptible_timeout(dhd->adapter->status_event,
+                               wifi_get_adapter_status(dhd->adapter, WIFI_STATUS_FW_READY),
+                               msecs_to_jiffies(DHD_FW_READY_TIMEOUT));
+                       DHD_MUTEX_LOCK();
+                       if ((ret = dbus_up(dhd->pub.bus)) != 0) {
                                DHD_ERROR(("%s: failed to dbus_up with code %d\n", __FUNCTION__, ret));
                                goto exit;
                        } else {
                                dhd->pub.busstate = DHD_BUS_DATA;
                        }
-
                        if ((ret = dhd_sync_with_dongle(&dhd->pub)) < 0) {
                                DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
                                goto exit;
                        }
+#else
+                       /* try to bring up bus */
+                       DHD_PERIM_UNLOCK(&dhd->pub);
+                       ret = dhd_bus_start(&dhd->pub);
+                       DHD_PERIM_LOCK(&dhd->pub);
+                       if (ret) {
+                               DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret));
+                               ret = -1;
+                               goto exit;
+                       }
 #endif /* !BCMDBUS */
 
                }
+#ifdef WL_EXT_IAPSTA
+               wl_ext_iapsta_attach_name(net, ifidx);
+#endif
                if (dhd_download_fw_on_driverload) {
                        if (dhd->pub.conf->deepsleep)
                                dhd_deepsleep(dhd, 0);
@@ -9004,12 +8756,7 @@ exit:
 
        DHD_PERIM_UNLOCK(&dhd->pub);
        DHD_OS_WAKE_UNLOCK(&dhd->pub);
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-#endif
-#endif /* MULTIPLE_SUPPLICANT */
+       DHD_MUTEX_UNLOCK();
 
        printf("%s: Exit ret=%d\n", __FUNCTION__, ret);
        return ret;
@@ -9024,14 +8771,7 @@ int dhd_do_driver_init(struct net_device *net)
                return -EINVAL;
        }
 
-#ifdef MULTIPLE_SUPPLICANT
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && defined(BCMSDIO)
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) {
-               DHD_ERROR(("%s : dhdsdio_probe is already running!\n", __FUNCTION__));
-               return 0;
-       }
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* MULTIPLE_SUPPLICANT */
+       DHD_MUTEX_IS_LOCK_RETURN();
 
        /*  && defined(OEM_ANDROID) && defined(BCMSDIO) */
        dhd = DHD_DEV_INFO(net);
@@ -9631,20 +9371,64 @@ fail1:
 
 #endif /* SHOW_LOGTRACE */
 
+#ifdef BCMDBUS
+uint
+dhd_get_rxsz(dhd_pub_t *pub)
+{
+       struct net_device *net = NULL;
+       dhd_info_t *dhd = NULL;
+       uint rxsz;
+
+       /* Assign rxsz for dbus_attach */
+       dhd = pub->info;
+       net = dhd->iflist[0]->net;
+       net->hard_header_len = ETH_HLEN + pub->hdrlen;
+       rxsz = DBUS_RX_BUFFER_SIZE_DHD(net);
+
+       return rxsz;
+}
+
+void
+dhd_set_path(dhd_pub_t *pub)
+{
+       dhd_info_t *dhd = NULL;
+
+       dhd = pub->info;
+
+       /* try to download image and nvram to the dongle */
+       if      (dhd_update_fw_nv_path(dhd) && dhd->pub.bus) {
+               DHD_INFO(("%s: fw %s, nv %s, conf %s\n",
+                       __FUNCTION__, dhd->fw_path, dhd->nv_path, dhd->conf_path));
+               dhd_bus_update_fw_nv_path(dhd->pub.bus,
+                               dhd->fw_path, dhd->nv_path, dhd->clm_path, dhd->conf_path);
+       }
+}
+#endif
 
 dhd_pub_t *
-dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
+dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen
+#ifdef BCMDBUS
+       , void *data
+#endif
+)
 {
        dhd_info_t *dhd = NULL;
        struct net_device *net = NULL;
        char if_name[IFNAMSIZ] = {'\0'};
-       uint32 bus_type = -1;
-       uint32 bus_num = -1;
-       uint32 slot_num = -1;
 #ifdef SHOW_LOGTRACE
        int ret;
 #endif /* SHOW_LOGTRACE */
+#if defined(BCMSDIO) || defined(BCMPCIE)
+       uint32 bus_type = -1;
+       uint32 bus_num = -1;
+       uint32 slot_num = -1;
        wifi_adapter_info_t *adapter = NULL;
+#elif defined(BCMDBUS)
+       wifi_adapter_info_t *adapter = data;
+#endif
+#ifdef GET_CUSTOM_MAC_ENABLE
+       char hw_ether[62];
+#endif /* GET_CUSTOM_MAC_ENABLE */
 
        dhd_attach_states_t dhd_state = DHD_ATTACH_STATE_INIT;
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
@@ -9656,7 +9440,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 #if defined(BCMSDIO)
        dhd_bus_get_ids(bus, &bus_type, &bus_num, &slot_num);
 #endif 
+#if defined(BCMSDIO) || defined(BCMPCIE)
        adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
+#endif
 
        /* Allocate primary dhd_info */
        dhd = wifi_platform_prealloc(adapter, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t));
@@ -9677,6 +9463,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
        dll_init(&(dhd->pub.dump_iovlist_head));
 #endif /* DUMP_IOCTL_IOV_LIST */
        dhd->adapter = adapter;
+       dhd->pub.adapter = (void *)adapter;
 #ifdef DHD_DEBUG
        dll_init(&(dhd->pub.mw_list_head));
 #endif /* DHD_DEBUG */
@@ -9686,7 +9473,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 #endif /* BT_OVER_SDIO */
 
 #ifdef GET_CUSTOM_MAC_ENABLE
-       wifi_platform_get_mac_addr(dhd->adapter, dhd->pub.mac.octet);
+       wifi_platform_get_mac_addr(dhd->adapter, hw_ether);
+       bcopy(hw_ether, dhd->pub.mac.octet, sizeof(struct ether_addr));
 #endif /* GET_CUSTOM_MAC_ENABLE */
 #ifdef CUSTOM_FORCE_NODFS_FLAG
        dhd->pub.dhd_cflags |= WLAN_PLAT_NODFS_FLAG;
@@ -9715,7 +9503,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
        dhd->pub.bus = bus;
        dhd->pub.hdrlen = bus_hdrlen;
 
-#ifndef BCMDBUS
        /* dhd_conf must be attached after linking dhd to dhd->pub.info,
         * because dhd_detech will check .info is NULL or not.
        */
@@ -9723,6 +9510,7 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
                DHD_ERROR(("dhd_conf_attach failed\n"));
                goto fail;
        }
+#ifndef BCMDBUS
        dhd_conf_reset(&dhd->pub);
        dhd_conf_set_chiprev(&dhd->pub, dhd_bus_chip(bus), dhd_bus_chiprev(bus));
        dhd_conf_preinit(&dhd->pub);
@@ -9922,9 +9710,13 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 
 #ifndef BCMDBUS
        /* Set up the watchdog timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&dhd->timer, dhd_watchdog, 0);
+#else
        init_timer(&dhd->timer);
        dhd->timer.data = (ulong)dhd;
        dhd->timer.function = dhd_watchdog;
+#endif
        dhd->default_wd_interval = dhd_watchdog_ms;
 
        if (dhd_watchdog_prio >= 0) {
@@ -9940,9 +9732,13 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 
 #ifdef DHD_PCIE_RUNTIMEPM
        /* Setup up the runtime PM Idlecount timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&dhd->rpm_timer, dhd_runtimepm, 0);
+#else
        init_timer(&dhd->rpm_timer);
        dhd->rpm_timer.data = (ulong)dhd;
        dhd->rpm_timer.function = dhd_runtimepm;
+#endif
        dhd->rpm_timer_valid = FALSE;
 
        dhd->thr_rpm_ctl.thr_pid = DHD_PID_KT_INVALID;
@@ -9955,9 +9751,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
 #ifdef DEBUGGER
        debugger_init((void *) bus);
 #endif
-#ifdef SHOW_LOGTRACE
-       skb_queue_head_init(&dhd->evt_trace_queue);
-#endif /* SHOW_LOGTRACE */
 
        /* Set up the bottom half handler */
        if (dhd_dpc_prio >= 0) {
@@ -9981,6 +9774,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
                }
        }
 #endif /* !BCMDBUS */
+#ifdef SHOW_LOGTRACE
+       skb_queue_head_init(&dhd->evt_trace_queue);
+#endif /* SHOW_LOGTRACE */
 
        dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED;
 
@@ -10343,20 +10139,6 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
                return FALSE;
        }
 #endif /* BCMEMBEDIMAGE */
-#ifdef BCMDBUS
-       if (dhdinfo->conf_path[0] == '\0') {
-               dhd_conf_set_path(&dhdinfo->pub, "config.txt", dhdinfo->conf_path, dhdinfo->fw_path);
-       } else {
-               dhdinfo->pub.conf_path = dhdinfo->conf_path;
-               printf("%s: conf_path=%s\n", __FUNCTION__, dhdinfo->conf_path);
-       }
-       if (dhdinfo->clm_path[0] == '\0') {
-               dhd_conf_set_path(&dhdinfo->pub, "clm.blob", dhdinfo->clm_path, dhdinfo->fw_path);
-       } else {
-               dhdinfo->pub.clm_path= dhdinfo->clm_path;
-               printf("%s: clm_path=%s\n", __FUNCTION__, dhdinfo->clm_path);
-       }
-#endif /* BCMDBUS */
 
        return TRUE;
 }
@@ -12158,7 +11940,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        } else if (ret >= 1) {
                disable_proptx = 1;
                wlfc_enable = FALSE;
-               /* terence 20161229: we should set ampdu_hostreorder=0 when disalbe_proptx=1 */
+               /* terence 20161229: we should set ampdu_hostreorder=0 when disable_proptx=1 */
                hostreorder = 0;
        }
 
@@ -12887,16 +12669,14 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
                printf("%s\n", dhd_version);
 #ifdef WL_EXT_IAPSTA
        else
-               wl_ext_iapsta_attach_netdev(net, ifidx);
+               wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
 #endif
-#ifdef WLMESH
-       if (ifidx != 0 && dhdp->conf->fw_type == FW_TYPE_MESH) {
-               if (_dhd_set_mac_address(dhd, ifidx, temp_addr) == 0)
+       if (ifidx != 0) {
+               if (_dhd_set_mac_address(dhd, ifidx, net->dev_addr) == 0)
                        DHD_INFO(("%s: MACID is overwritten\n", __FUNCTION__));
                else
                        DHD_ERROR(("%s: _dhd_set_mac_address() failed\n", __FUNCTION__));
        }
-#endif
 
        if (need_rtnl_lock)
                err = register_netdev(net);
@@ -12909,7 +12689,7 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
        }
 #ifdef WL_EXT_IAPSTA
        if (ifidx == 0)
-               wl_ext_iapsta_attach_netdev(net, ifidx);
+               wl_ext_iapsta_attach_netdev(net, ifidx, ifp->bssidx);
        wl_ext_iapsta_attach_name(net, ifidx);
 #endif
 
@@ -12927,7 +12707,7 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
 #endif
 
 #if (defined(BCMPCIE) || (defined(BCMLXSDMMC) && (LINUX_VERSION_CODE >= \
-       KERNEL_VERSION(2, 6, 27))))
+       KERNEL_VERSION(2, 6, 27))) || defined(BCMDBUS))
        if (ifidx == 0) {
 #if defined(BCMLXSDMMC) && !defined(DHD_PRELOAD)
                up(&dhd_registration_sem);
@@ -12999,7 +12779,7 @@ dhd_bus_detach(dhd_pub_t *dhdp)
                                if (dhd_wl_ioctl_cmd(dhdp, WLC_TERMINATED, NULL, 0, TRUE, 0) < 0)
                                        DHD_ERROR(("%s Setting WLC_TERMINATED failed\n",
                                                __FUNCTION__));
-                               dbus_stop(dhd->pub.dbus);
+                               dbus_stop(dhd->pub.bus);
                                dhd->pub.busstate = DHD_BUS_DOWN;
 #else
                                dhd_bus_stop(dhd->pub.bus, TRUE);
@@ -13156,9 +12936,6 @@ void dhd_detach(dhd_pub_t *dhdp)
                ASSERT(ifp);
                ASSERT(ifp->net);
                if (ifp && ifp->net) {
-
-
-
 #ifdef WL_CFG80211
                        cfg = wl_get_cfg(ifp->net);
 #endif
@@ -13519,16 +13296,11 @@ dhd_module_cleanup(void)
 {
        printf("%s: Enter\n", __FUNCTION__);
 
-#ifdef BCMDBUS
-       dbus_deregister();
-#else
        dhd_bus_unregister();
-#endif /* BCMDBUS */
 
        wl_android_exit();
 
        dhd_wifi_platform_unregister_drv();
-
 #ifdef CUSTOMER_HW_AMLOGIC
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
        wifi_teardown_dt();
@@ -13620,163 +13392,6 @@ dhd_reboot_callback(struct notifier_block *this, unsigned long code, void *unuse
        return NOTIFY_DONE;
 }
 
-#ifdef BCMDBUS
-/*
- * hdrlen is space to reserve in pkt headroom for DBUS
- */
-void *
-dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, uint32 hdrlen)
-{
-       osl_t *osh = NULL;
-       int ret = 0;
-       dbus_attrib_t attrib;
-       dhd_pub_t *pub = NULL;
-
-       printf("%s: Enter\n", __FUNCTION__);
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
-               DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
-       }
-       else {
-               DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif 
-
-       /* Ask the OS interface part for an OSL handle */
-       if (!(osh = osl_attach(NULL, bustype, TRUE))) {
-               DHD_ERROR(("%s: OSL attach failed\n", __FUNCTION__));
-               ret = -ENOMEM;
-               goto fail;
-       }
-
-       /* Attach to the dhd/OS interface */
-       if (!(pub = dhd_attach(osh, NULL /* bus */, hdrlen))) {
-               DHD_ERROR(("%s: dhd_attach failed\n", __FUNCTION__));
-               ret = -ENXIO;
-               goto fail;
-       }
-
-       /* Ok, finish the attach to the OS network interface */
-       if (dhd_register_if(pub, 0, TRUE) != 0) {
-               DHD_ERROR(("%s: dhd_register_if failed\n", __FUNCTION__));
-               ret = -ENXIO;
-               goto fail;
-       }
-
-       pub->dbus = dbus_attach(pub->osh, pub->rxsz, DBUS_NRXQ, DBUS_NTXQ,
-               pub->info, &dhd_dbus_cbs, NULL, NULL);
-       if (pub->dbus) {
-               dbus_get_attrib(pub->dbus, &attrib);
-               DHD_ERROR(("DBUS: vid=0x%x pid=0x%x devid=0x%x bustype=0x%x mtu=%d rev=%d\n",
-                       attrib.vid, attrib.pid, attrib.devid, attrib.bustype, attrib.mtu, attrib.chiprev));
-       } else {
-               ret = -ENXIO;
-               goto fail;
-       }
-
-       /* dhd_conf must be attached after linking dhd to dhd->dbus,
-        * because dhd_detech will check .info is NULL or not.
-       */
-       if (dhd_conf_attach(pub) != 0) {
-               DHD_ERROR(("dhd_conf_attach failed\n"));
-               goto fail;
-       }
-       dhd_conf_reset(pub);
-       dhd_conf_set_chiprev(pub, attrib.devid, attrib.chiprev);
-       dhd_conf_preinit(pub);
-
-       /* Some DHD modules (e.g. cfg80211) configures operation mode based on firmware name.
-        * This is indeed a hack but we have to make it work properly before we have a better
-        * solution
-        */
-       dhd_update_fw_nv_path(pub->info);
-
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif 
-
-       printf("%s: Exit\n", __FUNCTION__);
-       /* This is passed to dhd_dbus_disconnect_cb */
-       return pub->info;
-fail:
-       /* Release resources in reverse order */
-       if (pub) {
-               if (pub->dbus) {
-                       dbus_detach(pub->dbus);
-                       pub->dbus = NULL;
-               }
-               dhd_detach(pub);
-               dhd_free(pub);
-       }
-       if (osh) {
-               osl_detach(osh);
-       }
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif 
-
-       BCM_REFERENCE(ret);
-       printf("%s: Exit\n", __FUNCTION__);
-       return NULL;
-}
-
-void
-dhd_dbus_disconnect_cb(void *arg)
-{
-       dhd_info_t *dhd = (dhd_info_t *)arg;
-       dhd_pub_t *pub;
-       osl_t *osh;
-
-       printf("%s: Enter\n", __FUNCTION__);
-       if (dhd == NULL)
-               return;
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
-               DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
-       }
-       else {
-               DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif 
-
-       pub = &dhd->pub;
-       osh = pub->osh;
-       dhd_detach(pub);
-       if (pub->dbus) {
-               dbus_detach(pub->dbus);
-               pub->dbus = NULL;
-       }
-       dhd_free(pub);
-
-       if (MALLOCED(osh)) {
-               DHD_ERROR(("%s: MEMORY LEAK %d bytes\n", __FUNCTION__, MALLOCED(osh)));
-       }
-       osl_detach(osh);
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* LINUX */
-       printf("%s: Exit\n", __FUNCTION__);
-}
-#endif /* BCMDBUS */
 
 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)
 #if defined(CONFIG_DEFERRED_INITCALLS) && !defined(EXYNOS_PCIE_MODULE_PATCH)
@@ -14265,13 +13880,13 @@ dhd_os_sdlock(dhd_pub_t *pub)
 
        dhd = (dhd_info_t *)(pub->info);
 
-#ifndef BCMDBUS
+#ifdef BCMDBUS
+       spin_lock_bh(&dhd->sdlock);
+#else
        if (dhd_dpc_prio >= 0)
                down(&dhd->sdsem);
        else
                spin_lock_bh(&dhd->sdlock);
-#else
-       spin_lock_bh(&dhd->sdlock);
 #endif /* !BCMDBUS */
 }
 
@@ -14282,13 +13897,13 @@ dhd_os_sdunlock(dhd_pub_t *pub)
 
        dhd = (dhd_info_t *)(pub->info);
 
-#ifndef BCMDBUS
+#ifdef BCMDBUS
+       spin_unlock_bh(&dhd->sdlock);
+#else
        if (dhd_dpc_prio >= 0)
                up(&dhd->sdsem);
        else
                spin_unlock_bh(&dhd->sdlock);
-#else
-       spin_unlock_bh(&dhd->sdlock);
 #endif /* !BCMDBUS */
 }
 
@@ -14585,7 +14200,7 @@ void dhd_wait_event_wakeup(dhd_pub_t *dhd)
        return;
 }
 
-#if defined(BCMSDIO) || defined(BCMPCIE)
+#if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS)
 int
 dhd_net_bus_devreset(struct net_device *dev, uint8 flag)
 {
@@ -14653,7 +14268,7 @@ dhd_net_bus_resume(struct net_device *dev, uint8 stage)
 }
 
 #endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMPCIE */
+#endif /* BCMSDIO || BCMPCIE || BCMDBUS */
 
 int net_os_set_suspend_disable(struct net_device *dev, int val)
 {
@@ -19868,8 +19483,9 @@ static void dhd_sysfs_exit(dhd_info_t *dhd)
                DHD_ERROR(("%s(): dhd is NULL \r\n", __FUNCTION__));
                return;
        }
+
        /* Releae the kobject */
-       if (dhd->dhd_kobj.state_initialized)
+       if (dhd->dhd_kobj.state_initialized)
                kobject_put(&dhd->dhd_kobj);
 }
 
index 4651dc51f69a8315fb7badde6e892f07e9785d40..248f5271da0b26ba0d472f9a85bc9875e6c618c6 100644 (file)
 #include <linux/earlysuspend.h>
 #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */
 
+/* dongle status */
+enum wifi_adapter_status {
+       WIFI_STATUS_POWER_ON = 0,
+       WIFI_STATUS_ATTACH,
+       WIFI_STATUS_FW_READY,
+       WIFI_STATUS_DETTACH
+};
+#define wifi_chk_adapter_status(adapter, stat) (test_bit(stat, &(adapter)->status))
+#define wifi_get_adapter_status(adapter, stat) (test_bit(stat, &(adapter)->status))
+#define wifi_set_adapter_status(adapter, stat) (set_bit(stat, &(adapter)->status))
+#define wifi_clr_adapter_status(adapter, stat) (clear_bit(stat, &(adapter)->status))
+#define wifi_chg_adapter_status(adapter, stat) (change_bit(stat, &(adapter)->status))
+
 #define DHD_REGISTRATION_TIMEOUT  12000  /* msec : allowed time to finished dhd registration */
+#define DHD_FW_READY_TIMEOUT  5000  /* msec : allowed time to finished fw download */
 
 typedef struct wifi_adapter_info {
        const char      *name;
@@ -65,6 +79,8 @@ typedef struct wifi_adapter_info {
        uint            bus_type;
        uint            bus_num;
        uint            slot_num;
+       wait_queue_head_t status_event;
+       unsigned long status;
 #if defined(BT_OVER_SDIO)
        const char      *btfw_path;
 #endif /* defined (BT_OVER_SDIO) */
@@ -120,6 +136,8 @@ typedef dhd_sta_t dhd_sta_pool_t;
 
 int dhd_wifi_platform_register_drv(void);
 void dhd_wifi_platform_unregister_drv(void);
+wifi_adapter_info_t* dhd_wifi_platform_attach_adapter(uint32 bus_type,
+       uint32 bus_num, uint32 slot_num, unsigned long status);
 wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num,
        uint32 slot_num);
 int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long msec);
index 957789543bd27aaa2326937b5742e0334f18eb0b..9fd726078d13ab653d32ea480dd3129e282e22c6 100644 (file)
@@ -42,9 +42,6 @@
 #if defined(CONFIG_WIFI_CONTROL_FUNC)
 #include <linux/wlan_plat.h>
 #endif
-#ifdef BCMDBUS
-#include <dbus.h>
-#endif /* BCMDBUS */
 #ifdef CONFIG_DTS
 #include<linux/regulator/consumer.h>
 #include<linux/of_gpio.h>
@@ -97,6 +94,30 @@ extern void bcm_bt_unlock(int cookie);
 static int lock_cookie_wifi = 'W' | 'i'<<8 | 'F'<<16 | 'i'<<24;        /* cookie is "WiFi" */
 #endif /* ENABLE_4335BT_WAR */
 
+wifi_adapter_info_t* dhd_wifi_platform_attach_adapter(uint32 bus_type,
+       uint32 bus_num, uint32 slot_num, unsigned long status)
+{
+       int i;
+
+       if (dhd_wifi_platdata == NULL)
+               return NULL;
+
+       for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+               wifi_adapter_info_t *adapter = &dhd_wifi_platdata->adapters[i];
+               if ((adapter->bus_type == -1 || adapter->bus_type == bus_type) &&
+                       (adapter->bus_num == -1 || adapter->bus_num == bus_num) &&
+                       (adapter->slot_num == -1 || adapter->slot_num == slot_num)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD)
+                       && (wifi_chk_adapter_status(adapter, status))
+#endif
+               ) {
+                       DHD_ERROR(("attach adapter info '%s'\n", adapter->name));
+                       return adapter;
+               }
+       }
+       return NULL;
+}
+
 wifi_adapter_info_t* dhd_wifi_platform_get_adapter(uint32 bus_type, uint32 bus_num, uint32 slot_num)
 {
        int i;
@@ -169,6 +190,11 @@ int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long
                return -EINVAL;
        }
 #endif /* BT_OVER_SDIO */
+       if (on) {
+               wifi_set_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+       } else {
+               wifi_clr_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+       }
 #ifdef CONFIG_DTS
        if (on) {
                printf("======== PULL WL_REG_ON HIGH! ========\n");
@@ -180,11 +206,15 @@ int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long
                err = regulator_disable(wifi_regulator);
                is_power_on = FALSE;
        }
-       if (err < 0)
+       if (err < 0) {
                DHD_ERROR(("%s: regulator enable/disable failed", __FUNCTION__));
+               goto fail;
+       }
 #else
-       if (!adapter || !adapter->wifi_plat_data)
-               return -EINVAL;
+       if (!adapter || !adapter->wifi_plat_data) {
+               err = -EINVAL;
+               goto fail;
+       }
        plat_data = adapter->wifi_plat_data;
 
        DHD_ERROR(("%s = %d\n", __FUNCTION__, on));
@@ -219,6 +249,13 @@ int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long
 
 #endif /* CONFIG_DTS */
 
+       return err;
+fail:
+       if (on) {
+               wifi_clr_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+       } else {
+               wifi_set_adapter_status(adapter, WIFI_STATUS_POWER_ON);
+       }
        return err;
 }
 
@@ -478,6 +515,7 @@ static int wifi_ctrlfunc_register_drv(void)
        dhd_wifi_platdata = kzalloc(sizeof(bcmdhd_wifi_platdata_t), GFP_KERNEL);
        dhd_wifi_platdata->num_adapters = 1;
        dhd_wifi_platdata->adapters = adapter;
+       init_waitqueue_head(&adapter->status_event);
 
 #ifndef CUSTOMER_HW
        if (dev1) {
@@ -741,7 +779,7 @@ void dhd_wifi_platform_unregister_drv(void)
 extern int dhd_watchdog_prio;
 extern int dhd_dpc_prio;
 extern uint dhd_deferred_tx;
-#if defined(BCMLXSDMMC)
+#if defined(BCMLXSDMMC) || defined(BCMDBUS)
 extern struct semaphore dhd_registration_sem;
 #endif 
 
@@ -877,33 +915,57 @@ static int dhd_wifi_platform_load_sdio(void)
 #endif /* BCMSDIO */
 
 #ifdef BCMDBUS
-/* User-specified vid/pid */
-int dhd_vid = 0xa5c;
-int dhd_pid = 0x48f;
-module_param(dhd_vid, int, 0);
-module_param(dhd_pid, int, 0);
-void *dhd_dbus_probe_cb(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
-void dhd_dbus_disconnect_cb(void *arg);
-
 static int dhd_wifi_platform_load_usb(void)
 {
+       wifi_adapter_info_t *adapter;
+       s32 timeout = -1;
+       int i;
        int err = 0;
+       enum wifi_adapter_status wait_status;
 
-       if (dhd_vid < 0 || dhd_vid > 0xffff) {
-               DHD_ERROR(("%s: invalid dhd_vid 0x%x\n", __FUNCTION__, dhd_vid));
-               return -EINVAL;
+       err = dhd_bus_register();
+       if (err) {
+               DHD_ERROR(("%s: usb_register failed\n", __FUNCTION__));
+               goto exit;
        }
-       if (dhd_pid < 0 || dhd_pid > 0xffff) {
-               DHD_ERROR(("%s: invalid dhd_pid 0x%x\n", __FUNCTION__, dhd_pid));
-               return -EINVAL;
+
+       /* power up all adapters */
+       for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+               adapter = &dhd_wifi_platdata->adapters[i];
+               DHD_ERROR(("Power-up adapter '%s'\n", adapter->name));
+               DHD_INFO((" - irq %d [flags %d], firmware: %s, nvram: %s\n",
+                       adapter->irq_num, adapter->intr_flags, adapter->fw_path, adapter->nv_path));
+               DHD_INFO((" - bus type %d, bus num %d, slot num %d\n\n",
+                       adapter->bus_type, adapter->bus_num, adapter->slot_num));
+               err = wifi_platform_set_power(adapter, TRUE, WIFI_TURNON_DELAY);
+               if (err) {
+                       DHD_ERROR(("failed to wifi_platform_set_power on %s\n", adapter->name));
+                       goto fail;
+               }
+               if (dhd_download_fw_on_driverload)
+                       wait_status = WIFI_STATUS_ATTACH;
+               else
+                       wait_status = WIFI_STATUS_DETTACH;
+               timeout = wait_event_interruptible_timeout(adapter->status_event,
+                       wifi_get_adapter_status(adapter, wait_status),
+                       msecs_to_jiffies(DHD_REGISTRATION_TIMEOUT));
+               if (timeout <= 0) {
+                       err = -1;
+                       DHD_ERROR(("%s: usb_register_driver timeout\n", __FUNCTION__));
+                       goto fail;
+               }
        }
 
-       err = dbus_register(dhd_vid, dhd_pid, dhd_dbus_probe_cb, dhd_dbus_disconnect_cb,
-               NULL, NULL, NULL);
+exit:
+       return err;
 
-       /* Device not detected */
-       if (err == DBUS_ERR_NODEVICE)
-               err = DBUS_OK;
+fail:
+       dhd_bus_unregister();
+       /* power down all adapters */
+       for (i = 0; i < dhd_wifi_platdata->num_adapters; i++) {
+               adapter = &dhd_wifi_platdata->adapters[i];
+               wifi_platform_set_power(adapter, FALSE, WIFI_TURNOFF_DELAY);
+       }
 
        return err;
 }
index 577b3937ad89c1542bf170ad670317ceed0b52e9..ecaed3e935586f8f6fa4a5a9ae6832c0d49634f2 100644 (file)
@@ -884,9 +884,7 @@ dhdpcie_bus_unregister(void)
 int __devinit
 dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
-#ifdef BUS_POWER_RESTORE
-       wifi_adapter_info_t *adapter = NULL;
-#endif
+       DHD_MUTEX_LOCK();
 
        if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) {
                DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__));
@@ -906,15 +904,8 @@ dhdpcie_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        device_disable_async_suspend(&pdev->dev);
 #endif /* BCMPCIE_DISABLE_ASYNC_SUSPEND */
 
-#ifdef BUS_POWER_RESTORE
-       adapter = dhd_wifi_platform_get_adapter(PCI_BUS, pdev->bus->number,
-                                               PCI_SLOT(pdev->devfn));
-
-       if (adapter != NULL)
-               adapter->pci_dev = pdev;
-#endif
-
        DHD_TRACE(("%s: PCIe Enumeration done!!\n", __FUNCTION__));
+       DHD_MUTEX_UNLOCK();
        return 0;
 }
 
@@ -942,17 +933,7 @@ dhdpcie_pci_remove(struct pci_dev *pdev)
 
        DHD_TRACE(("%s Enter\n", __FUNCTION__));
 
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
-               DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
-       }
-       else {
-               DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif 
+       DHD_MUTEX_LOCK();
 
        pch = pci_get_drvdata(pdev);
        bus = pch->bus;
@@ -1000,12 +981,7 @@ dhdpcie_pci_remove(struct pci_dev *pdev)
 
        dhdpcie_init_succeeded = FALSE;
 
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* LINUX */
+       DHD_MUTEX_UNLOCK();
 
        DHD_TRACE(("%s Exit\n", __FUNCTION__));
 
@@ -1232,10 +1208,6 @@ void dhdpcie_linkdown_cb(struct_pcie_notify *noti)
        */
 #endif /* SUPPORT_LINKDOWN_RECOVERY */
 
-#if defined(MULTIPLE_SUPPLICANT)
-extern void wl_android_post_init(void); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#endif
-
 int dhdpcie_init(struct pci_dev *pdev)
 {
 
@@ -1250,18 +1222,6 @@ int dhdpcie_init(struct pci_dev *pdev)
        dhdpcie_smmu_info_t     *dhdpcie_smmu_info = NULL;
 #endif /* USE_SMMU_ARCH_MSM */
 
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
-               DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
-       }
-       else {
-               DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif
-
        do {
                /* osl attach */
                if (!(osh = osl_attach(pdev, PCI_BUS, FALSE))) {
@@ -1272,9 +1232,12 @@ int dhdpcie_init(struct pci_dev *pdev)
                /* initialize static buffer */
                adapter = dhd_wifi_platform_get_adapter(PCI_BUS, pdev->bus->number,
                        PCI_SLOT(pdev->devfn));
-               if (adapter != NULL)
+               if (adapter != NULL) {
                        DHD_ERROR(("%s: found adapter info '%s'\n", __FUNCTION__, adapter->name));
-               else
+#ifdef BUS_POWER_RESTORE
+                       adapter->pci_dev = pdev;
+#endif
+               } else
                        DHD_ERROR(("%s: can't find adapter info for this chip\n", __FUNCTION__));
                osl_static_mem_init(osh, adapter);
 
@@ -1444,11 +1407,7 @@ int dhdpcie_init(struct pci_dev *pdev)
 
 #if defined(MULTIPLE_SUPPLICANT)
                wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-               mutex_unlock(&_dhd_sdio_mutex_lock_);
-               DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif 
+#endif /* MULTIPLE_SUPPLICANT */
 
                DHD_TRACE(("%s:Exit - SUCCESS \n", __FUNCTION__));
                return 0;  /* return  SUCCESS  */
@@ -1479,12 +1438,6 @@ int dhdpcie_init(struct pci_dev *pdev)
                osl_detach(osh);
 
        dhdpcie_init_succeeded = FALSE;
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif 
 
        DHD_TRACE(("%s:Exit - FAILURE \n", __FUNCTION__));
 
@@ -2305,6 +2258,7 @@ bool dhdpcie_is_resume_done(dhd_pub_t *dhdp)
        return bus->runtime_resume_done;
 }
 #endif /* DHD_PCIE_RUNTIMEPM */
+
 struct device * dhd_bus_to_dev(dhd_bus_t *bus)
 {
        struct pci_dev *pdev;
@@ -2315,6 +2269,7 @@ struct device * dhd_bus_to_dev(dhd_bus_t *bus)
        else
                return NULL;
 }
+
 #ifdef HOFFLOAD_MODULES
 void
 dhd_free_module_memory(struct dhd_bus *bus, struct module_metadata *hmem)
index c22288f07f6c08d80460b6f32b8509de0ab178a7..ea32a6b89ea286efec965ceca048317884458ee3 100644 (file)
@@ -5841,8 +5841,7 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished)
                        dhdsdio_sendpendctl(bus);
                } else if (bus->dotxinrx && (bus->clkstate == CLK_AVAIL) &&
                        !bus->fcstate && DATAOK(bus) &&
-                       (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres) &&
-                       bus->dhd->conf->tx_in_rx) {
+                       (pktq_mlen(&bus->txq, ~bus->flowcontrol) > bus->txinrx_thres)) {
                        dhdsdio_sendfromq(bus, dhd_txbound);
 #ifdef DHDTCPACK_SUPPRESS
                        /* In TCPACK_SUP_DELAYTX mode, do txinrx only if
@@ -7661,10 +7660,6 @@ dhdsdio_chipmatch(uint16 chipid)
        return FALSE;
 }
 
-#if defined(MULTIPLE_SUPPLICANT)
-extern void wl_android_post_init(void); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#endif
-
 static void *
 dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
        uint16 func, uint bustype, void *regsva, osl_t * osh, void *sdh)
@@ -7675,17 +7670,7 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
        struct ether_addr ea_addr;
 #endif
 
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
-               DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
-       }
-       else {
-               DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif 
+       DHD_MUTEX_LOCK();
 
        /* Init global variables at run-time, not as part of the declaration.
         * This is required to support init/de-init of the driver. Initialization
@@ -7866,11 +7851,8 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot,
 
 #if defined(MULTIPLE_SUPPLICANT)
        wl_android_post_init(); // terence 20120530: fix critical section in dhd_open and dhdsdio_probe
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif 
+#endif /* MULTIPLE_SUPPLICANT */
+       DHD_MUTEX_UNLOCK();
 
        return bus;
 
@@ -7878,12 +7860,7 @@ fail:
        dhdsdio_release(bus, osh);
 
 forcereturn:
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */
-#endif 
+       DHD_MUTEX_UNLOCK();
 
        return NULL;
 }
@@ -8511,33 +8488,14 @@ dhdsdio_disconnect(void *ptr)
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       if (mutex_is_locked(&_dhd_sdio_mutex_lock_) == 0) {
-               DHD_ERROR(("%s : no mutex held. set lock\n", __FUNCTION__));
-       }
-       else {
-               DHD_ERROR(("%s : mutex is locked!. wait for unlocking\n", __FUNCTION__));
-       }
-       mutex_lock(&_dhd_sdio_mutex_lock_);
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif 
-
-
+       DHD_MUTEX_LOCK();
        if (bus) {
                ASSERT(bus->dhd);
                /* Advertise bus remove during rmmod */
                dhdsdio_advertise_bus_remove(bus->dhd);
                dhdsdio_release(bus, bus->dhd->osh);
        }
-
-#if defined(MULTIPLE_SUPPLICANT)
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25))
-       mutex_unlock(&_dhd_sdio_mutex_lock_);
-       DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__));
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */
-#endif /* LINUX */
-
+       DHD_MUTEX_UNLOCK();
 
        DHD_TRACE(("%s: Disconnected\n", __FUNCTION__));
 }
index 33997cd8b78435a31f2aadf97cfdc0370ad916fc..2bf784c8ae936b877491ef7bc90ea6b797219c2a 100644 (file)
@@ -27,7 +27,7 @@
 #include <linux/wlan_plat.h>\r
 #include <linux/amlogic/dhd_buf.h>\r
 \r
-#define        DHD_STATIC_VERSION_STR          "1.579.77.41.1"\r
+#define        DHD_STATIC_VERSION_STR          "1.579.77.41.9"\r
 \r
 #define BCMDHD_SDIO\r
 #define BCMDHD_PCIE\r
@@ -72,7 +72,7 @@ enum dhd_prealloc_index {
 #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     (30 * 1024)\r
+#define DHD_PREALLOC_DHD_INFO_SIZE     (32 * 1024)\r
 #define DHD_PREALLOC_MEMDUMP_RAM_SIZE  (810 * 1024)\r
 #define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE      (73 * 1024)\r
 #define DHD_PREALLOC_WL_ESCAN_INFO_SIZE        (66 * 1024)\r
@@ -273,6 +273,8 @@ int bcmdhd_init_wlan_mem(void)
        int i;\r
        int j;\r
 \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
@@ -347,10 +349,12 @@ int bcmdhd_init_wlan_mem(void)
        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
+       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
@@ -367,31 +371,29 @@ int bcmdhd_init_wlan_mem(void)
        pr_err("%s: sectoin %d, size=%d\n", __func__,\r
                DHD_PREALLOC_WL_ESCAN_INFO, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
 \r
-       wlan_static_fw_verbose_ring_buf = kmalloc(\r
-                                               DHD_PREALLOC_WIPHY_ESCAN0_SIZE,\r
-                                               GFP_KERNEL);\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, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+               DHD_PREALLOC_FW_VERBOSE_RING, FW_VERBOSE_RING_SIZE);\r
 \r
-       wlan_static_fw_event_ring_buf = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\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, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+               DHD_PREALLOC_FW_EVENT_RING, FW_EVENT_RING_SIZE);\r
 \r
-       wlan_static_dhd_event_ring_buf = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\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_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+               DHD_PREALLOC_DHD_EVENT_RING, DHD_EVENT_RING_SIZE);\r
 \r
-       wlan_static_nan_event_ring_buf = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\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, DHD_PREALLOC_WL_ESCAN_INFO_SIZE);\r
+               DHD_PREALLOC_NAN_EVENT_RING, NAN_EVENT_RING_SIZE);\r
 \r
        return 0;\r
 \r
index 1a0d1bb1223ea2b4712aa9ff612a69fdcef73e72..442af325a67794c81f18b77bcf29edb19463b68a 100644 (file)
 #include <dngl_stats.h>
 #include <dhd.h>
 
-#ifdef BCMDBUS /* an abstraction layer that hides details of the underlying bus, eg \
-       Linux USB */
-#include <dbus.h>
-#else
 #include <dhd_bus.h>
-#endif /* BCMDBUS */
 
 #include <dhd_dbg.h>
 #include <dhd_config.h>
@@ -72,9 +67,6 @@
 #define WLFC_THREAD_RETRY_WAIT_MS          10000   /* 10 sec */
 #endif /* defined (DHD_WLFC_THREAD) */
 
-#if defined(BCMDBUS)
-extern int dhd_dbus_txdata(dhd_pub_t *dhdp, void *pktbuf);
-#endif
 
 #ifdef PROP_TXSTATUS
 
@@ -1005,8 +997,6 @@ _dhd_wlfc_send_signalonly_packet(athost_wl_status_info_t* ctx, wlfc_mac_descript
 
 #if defined(BCMPCIE)
                rc = dhd_bus_txdata(dhdp->bus, p, ctx->host_ifidx);
-#elif defined(BCMDBUS)
-               rc = dhd_dbus_txdata(dhdp, p);
 #else
                rc = dhd_bus_txdata(dhdp->bus, p);
 #endif
index 54357b8ea54c44cd3b076bad6ace6859585c9b58..f4dec0d9ef369f96600d0665ca016d11873d869b 100644 (file)
@@ -32,6 +32,7 @@
 #define __DBUS_H__
 
 #include "typedefs.h"
+#include <dhd_linux.h>
 
 extern uint dbus_msglevel;
 #define DBUS_ERROR_VAL 0x0001
@@ -191,7 +192,8 @@ typedef struct dbus_extdl {
 struct dbus_callbacks;
 struct exec_parms;
 
-typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype, uint32 hdrlen);
+typedef void *(*probe_cb_t)(void *arg, const char *desc, uint32 bustype,
+       uint16 bus_no, uint16 slot, uint32 hdrlen);
 typedef void (*disconnect_cb_t)(void *arg);
 typedef void *(*exec_cb_t)(struct exec_parms *args);
 
@@ -247,7 +249,7 @@ typedef struct {
        int  (*get_config)(void *bus, dbus_config_t *config);
 
        bool (*device_exists)(void *bus);
-       bool (*dlneeded)(void *bus);
+       int (*dlneeded)(void *bus);
        int  (*dlstart)(void *bus, uint8 *fw, int len);
        int  (*dlrun)(void *bus);
        bool (*recv_needed)(void *bus);
@@ -309,26 +311,21 @@ extern int dbus_register(int vid, int pid, probe_cb_t prcb, disconnect_cb_t disc
        void *param1, void *param2);
 extern int dbus_deregister(void);
 
-extern dbus_pub_t *dbus_attach(struct osl_info *osh, int rxsize, int nrxq, int ntxq,
-       void *cbarg, dbus_callbacks_t *cbs, dbus_extdl_t *extdl, struct shared_info *sh);
-extern void dbus_detach(dbus_pub_t *pub);
-
-extern int dbus_download_firmware(dbus_pub_t *pub);
-extern int dbus_up(dbus_pub_t *pub);
+//extern int dbus_download_firmware(dbus_pub_t *pub);
+//extern int dbus_up(struct dhd_bus *pub);
 extern int dbus_down(dbus_pub_t *pub);
-extern int dbus_stop(dbus_pub_t *pub);
+//extern int dbus_stop(struct dhd_bus *pub);
 extern int dbus_shutdown(dbus_pub_t *pub);
 extern void dbus_flowctrl_rx(dbus_pub_t *pub, bool on);
 
 extern int dbus_send_txdata(dbus_pub_t *dbus, void *pktbuf);
 extern int dbus_send_buf(dbus_pub_t *pub, uint8 *buf, int len, void *info);
 extern int dbus_send_pkt(dbus_pub_t *pub, void *pkt, void *info);
-extern int dbus_send_ctl(dbus_pub_t *pub, uint8 *buf, int len);
-extern int dbus_recv_ctl(dbus_pub_t *pub, uint8 *buf, int len);
+//extern int dbus_send_ctl(struct dhd_bus *pub, uint8 *buf, int len);
+//extern int dbus_recv_ctl(struct dhd_bus *pub, uint8 *buf, int len);
 extern int dbus_recv_bulk(dbus_pub_t *pub, uint32 ep_idx);
 extern int dbus_poll_intr(dbus_pub_t *pub);
 extern int dbus_get_stats(dbus_pub_t *pub, dbus_stats_t *stats);
-extern int dbus_get_attrib(dbus_pub_t *pub, dbus_attrib_t *attrib);
 extern int dbus_get_device_speed(dbus_pub_t *pub);
 extern int dbus_set_config(dbus_pub_t *pub, dbus_config_t *config);
 extern int dbus_get_config(dbus_pub_t *pub, dbus_config_t *config);
@@ -342,8 +339,8 @@ extern int dbus_pnp_sleep(dbus_pub_t *pub);
 extern int dbus_pnp_resume(dbus_pub_t *pub, int *fw_reload);
 extern int dbus_pnp_disconnect(dbus_pub_t *pub);
 
-extern int dbus_iovar_op(dbus_pub_t *pub, const char *name,
-       void *params, int plen, void *arg, int len, bool set);
+//extern int dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name,
+//     void *params, int plen, void *arg, int len, bool set);
 
 extern void *dhd_dbus_txq(const dbus_pub_t *pub);
 extern uint dhd_dbus_hdrlen(const dbus_pub_t *pub);
index f50d98fbbabf42659504feccef927ff63e5258f8..f3fe5e9f4629f3eaa646c7d3f1dfe321e2629282 100644 (file)
@@ -46,6 +46,6 @@
 #define EPI_VERSION_DEV                1.579.77.41
 
 /* Driver Version String, ASCII, 32 chars max */
-#define        EPI_VERSION_STR         "1.579.77.41.5 (r)"
+#define        EPI_VERSION_STR         "1.579.77.41.10 (r)"
 
 #endif /* _epivers_h_ */
index 3dd51bc372e59db6c7d8f0bb28f3b56f7e5ebe90..b40ec111c08b69b99d4c14234715adb43f2c0977 100644 (file)
@@ -1145,6 +1145,7 @@ typedef struct sk_buff_head PKT_LIST;
 #define PKTLIST_UNLINK(x, y)   skb_unlink((struct sk_buff *)(y), (struct sk_buff_head *)(x))
 #define PKTLIST_FINI(x)                skb_queue_purge((struct sk_buff_head *)(x))
 
+#ifdef REPORT_FATAL_TIMEOUTS
 typedef struct osl_timer {
        struct timer_list *timer;
        bool   set;
@@ -1156,5 +1157,6 @@ extern osl_timer_t * osl_timer_init(osl_t *osh, const char *name, void (*fn)(voi
 extern void osl_timer_add(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic);
 extern void osl_timer_update(osl_t *osh, osl_timer_t *t, uint32 ms, bool periodic);
 extern bool osl_timer_del(osl_t *osh, osl_timer_t *t);
+#endif
 
 #endif /* _linux_osl_h_ */
index b0d8798f5ea37166210b791a8613af674fc6147a..908119e23d1116bcab9b46887b338fe6c7e7b632 100644 (file)
@@ -2696,6 +2696,7 @@ osl_pkt_orphan_partial(struct sk_buff *skb, int tsq)
 /* timer apis */
 /* Note: All timer api's are thread unsafe and should be protected with locks by caller */
 
+#ifdef REPORT_FATAL_TIMEOUTS
 osl_timer_t *
 osl_timer_init(osl_t *osh, const char *name, void (*fn)(void *arg), void *arg)
 {
@@ -2780,3 +2781,4 @@ osl_timer_del(osl_t *osh, osl_timer_t *t)
        }
        return (TRUE);
 }
+#endif
index 71bfe6618c91dbe0da1b4bd203956c7e16e47a3a..74cdcfafb32c3af13aa8f89bdb958712c10807f8 100644 (file)
@@ -635,7 +635,7 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, volatile void *regs,
        sih->chiprev = (w & CID_REV_MASK) >> CID_REV_SHIFT;
        sih->chippkg = (w & CID_PKG_MASK) >> CID_PKG_SHIFT;
 
-#if defined(HW_OOB) || defined(FORCE_WOWLAN)
+#if defined(BCMSDIO) && (defined(HW_OOB) || defined(FORCE_WOWLAN))
        dhd_conf_set_hw_oob_intr(sdh, sih->chip);
 #endif
 
index 7154ac505ab4ca0bd6e9d64a4c90b1d88dc6a91d..a73c28df22b91807a935fc21438e525c95e7b8f4 100644 (file)
@@ -1072,7 +1072,7 @@ wl_cfg80211_get_sta_info(struct net_device *dev, char* command, int total_len)
 error:
        return bytes_written;
 }
-#endif /* CUSTOMER_HW4_PRIVATE_CMD */
+#endif
 
 #ifdef WBTEXT
 static int wl_android_wbtext(struct net_device *dev, char *command, int total_len)
@@ -1592,21 +1592,22 @@ int wl_android_wifi_on(struct net_device *dev)
                        ANDROID_ERROR(("\nfailed to power up wifi chip, max retry reached **\n\n"));
                        goto exit;
                }
-#ifdef BCMSDIO
+#if defined(BCMSDIO) || defined(BCMDBUS)
                ret = dhd_net_bus_devreset(dev, FALSE);
                if (ret)
                        goto err;
+#ifdef BCMSDIO
                dhd_net_bus_resume(dev, 1);
 #endif /* BCMSDIO */
-
-#ifndef BCMPCIE
+#endif /* BCMSDIO || BCMDBUS */
+#if defined(BCMSDIO) || defined(BCMDBUS)
                if (!ret) {
                        if (dhd_dev_init_ioctl(dev) < 0) {
                                ret = -EFAULT;
                                goto err;
                        }
                }
-#endif /* !BCMPCIE */
+#endif /* BCMSDIO || BCMDBUS */
                g_wifi_on = TRUE;
        }
 
@@ -1615,17 +1616,17 @@ exit:
        dhd_net_if_unlock(dev);
        return ret;
 
-#ifndef BCMPCIE
+#if defined(BCMSDIO) || defined(BCMDBUS)
 err:
-#ifdef BCMSDIO
        dhd_net_bus_devreset(dev, TRUE);
+#ifdef BCMSDIO
        dhd_net_bus_suspend(dev);
+#endif /* BCMSDIO */
        dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
-#endif
        printf("%s: Failed\n", __FUNCTION__);
        dhd_net_if_unlock(dev);
        return ret;
-#endif
+#endif /* BCMSDIO || BCMDBUS */
 }
 
 int wl_android_wifi_off(struct net_device *dev, bool on_failure)
@@ -1648,12 +1649,12 @@ int wl_android_wifi_off(struct net_device *dev, bool on_failure)
        dhd_net_if_lock(dev);
        printf("%s in 2: g_wifi_on=%d, on_failure=%d\n", __FUNCTION__, g_wifi_on, on_failure);
        if (g_wifi_on || on_failure) {
-#if defined(BCMSDIO) || defined(BCMPCIE)
+#if defined(BCMSDIO) || defined(BCMPCIE) || defined(BCMDBUS)
                ret = dhd_net_bus_devreset(dev, TRUE);
 #if  defined(BCMSDIO)
                dhd_net_bus_suspend(dev);
 #endif /* BCMSDIO */
-#endif /* BCMSDIO || BCMPCIE */
+#endif /* BCMSDIO || BCMPCIE || BCMDBUS */
                dhd_net_wifi_platform_set_power(dev, FALSE, WIFI_TURNOFF_DELAY);
                g_wifi_on = FALSE;
        }
@@ -2493,6 +2494,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
        uint32 band = WLC_BAND_2G;
        uint32 buf_size;
        char *pos = command;
+       int band_new, band_cur;
 
        if (cmd_str) {
                ANDROID_INFO(("Command: %s len:%d \n", cmd_str, (int)strlen(cmd_str)));
@@ -2512,20 +2514,22 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
                                (channel == APCS_BAND_2G_LEGACY2)) {
                                band = WLC_BAND_2G;
                        } else {
-                               ANDROID_ERROR(("Invalid argument\n"));
+                               ANDROID_ERROR(("%s: Invalid argument\n", __FUNCTION__));
                                return -EINVAL;
                        }
                }
        } else {
                /* If no argument is provided, default to 2G */
-               ANDROID_ERROR(("No argument given default to 2.4G scan\n"));
+               ANDROID_ERROR(("%s: No argument given default to 2.4G scan\n", __FUNCTION__));
                band = WLC_BAND_2G;
        }
-       ANDROID_INFO(("HAPD_AUTO_CHANNEL = %d, band=%d \n", channel, band));
+       ANDROID_INFO(("%s : HAPD_AUTO_CHANNEL = %d, band=%d \n", __FUNCTION__, channel, band));
+
+       ret = wldev_ioctl_set(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur));
 
        if ((ret =
             wldev_ioctl_get(dev, WLC_GET_SPECT_MANAGMENT, &spect, sizeof(spect))) < 0) {
-               ANDROID_ERROR(("ACS: error getting the spect\n"));
+               ANDROID_ERROR(("%s: ACS: error getting the spect\n", __FUNCTION__));
                goto done;
        }
 
@@ -2547,15 +2551,19 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
 
        reqbuf = kzalloc(CHANSPEC_BUF_SIZE, GFP_KERNEL);
        if (reqbuf == NULL) {
-               ANDROID_ERROR(("failed to allocate chanspec buffer\n"));
+               ANDROID_ERROR(("%s: failed to allocate chanspec buffer\n", __FUNCTION__));
                return -ENOMEM;
        }
 
        if (band == WLC_BAND_AUTO) {
-               ANDROID_INFO(("ACS full channel scan \n"));
+               ANDROID_INFO(("%s: ACS full channel scan \n", __func__));
                reqbuf[0] = htod32(0);
        } else if (band == WLC_BAND_5G) {
-               ANDROID_INFO(("ACS 5G band scan \n"));
+               band_new = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
+               ret = wldev_ioctl_set(dev, WLC_SET_BAND, &band_new, sizeof(band_new));
+               if (ret < 0)
+                       WL_ERR(("WLC_SET_BAND error %d\n", ret));
+               ANDROID_INFO(("%s: ACS 5G band scan \n", __func__));
                if ((ret = wl_cfg80211_get_chanspecs_5g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
                        ANDROID_ERROR(("ACS 5g chanspec retreival failed! \n"));
                        goto done;
@@ -2565,7 +2573,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
                 * If channel argument is not provided/ argument 20 is provided,
                 * Restrict channel to 2GHz, 20MHz BW, No SB
                 */
-               ANDROID_INFO(("ACS 2G band scan \n"));
+               ANDROID_INFO(("%s: ACS 2G band scan \n", __func__));
                if ((ret = wl_cfg80211_get_chanspecs_2g(dev, reqbuf, CHANSPEC_BUF_SIZE)) < 0) {
                        ANDROID_ERROR(("ACS 2g chanspec retreival failed! \n"));
                        goto done;
@@ -2575,11 +2583,12 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
                goto done2;
        }
 
-       buf_size = (band == WLC_BAND_AUTO) ? sizeof(int) : CHANSPEC_BUF_SIZE;
+       buf_size = CHANSPEC_BUF_SIZE;
        ret = wldev_ioctl_set(dev, WLC_START_CHANNEL_SEL, (void *)reqbuf,
                buf_size);
        if (ret < 0) {
-               ANDROID_ERROR(("can't start auto channel scan, err = %d\n", ret));
+               ANDROID_ERROR(("%s: can't start auto channel scan, err = %d\n",
+                       __FUNCTION__, ret));
                channel = 0;
                goto done;
        }
@@ -2605,6 +2614,18 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
                        chosen = dtoh32(chosen);
                }
 
+               if ((ret == 0) && (dtoh32(chosen) != 0)) {
+                       uint chip;
+                       chip = dhd_conf_get_chip(dhd_get_pub(dev));
+                       if (chip != BCM43143_CHIP_ID) {
+                               u32 chanspec = 0;
+                               chanspec = wl_chspec_driver_to_host(chosen);
+                               ANDROID_INFO(("%s: selected chanspec = 0x%x\n", __FUNCTION__, chanspec));
+                               chosen = wf_chspec_ctlchan(chanspec);
+                               ANDROID_INFO(("%s: selected chosen = 0x%x\n", __FUNCTION__, chosen));
+                       }
+               }
+
                if (chosen) {
                        int chosen_band;
                        int apcs_band;
@@ -2619,12 +2640,15 @@ wl_android_set_auto_channel(struct net_device *dev, const char* cmd_str,
 #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) {
+                       if (band == WLC_BAND_AUTO) {
+                               printf("%s: selected channel = %d\n", __FUNCTION__, channel);
+                               break;
+                       } else if (apcs_band == chosen_band) {
                                printf("%s: selected channel = %d\n", __FUNCTION__, channel);
                                break;
                        }
                }
-               ANDROID_INFO(("%d tried, ret = %d, chosen = 0x%x\n",
+               ANDROID_INFO(("%s: %d tried, ret = %d, chosen = 0x%x\n", __FUNCTION__,
                        (APCS_MAX_RETRY - retry), ret, chosen));
                OSL_SLEEP(250);
        }
@@ -2637,12 +2661,16 @@ done:
                } else {
                        channel = APCS_DEFAULT_2G_CH;
                }
-               ANDROID_ERROR(("ACS failed. Fall back to default channel (%d) \n", channel));
+               ANDROID_ERROR(("%s: ACS failed."
+                       " Fall back to default channel (%d) \n", __FUNCTION__, channel));
        }
 done2:
+       ret = wldev_ioctl_set(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur));
+       if (ret < 0)
+               WL_ERR(("WLC_SET_BAND error %d\n", ret));
        if (spect > 0) {
                if ((ret = wl_cfg80211_set_spect(dev, spect) < 0)) {
-                       ANDROID_ERROR(("ACS: error while setting spect\n"));
+                       ANDROID_ERROR(("%s: ACS: error while setting spect\n", __FUNCTION__));
                }
        }
 
@@ -2656,7 +2684,7 @@ done2:
                else
                        pos += snprintf(pos, total_len, "5g=");
                pos += snprintf(pos, total_len, "%d", channel);
-               ANDROID_INFO(("command result is %s \n", command));
+               ANDROID_INFO(("%s: command result is %s \n", __FUNCTION__, command));
                return strlen(command);
        } else {
                return ret;
@@ -3750,8 +3778,7 @@ wl_cfg80211_p2plo_offload(struct net_device *dev, char *cmd, char* buf, int len)
 }
 #endif /* P2P_LISTEN_OFFLOADING */
 
-#ifdef WL_CFG80211
-#ifdef BCM4359_CHIP
+#if defined(BCM4359_CHIP) && defined(WL_CFG80211)
 int
 wl_android_murx_bfe_cap(struct net_device *dev, int val)
 {
@@ -3793,7 +3820,6 @@ wl_android_murx_bfe_cap(struct net_device *dev, int val)
        return err;
 }
 #endif /* BCM4359_CHIP */
-#endif
 
 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
 int
@@ -4199,6 +4225,7 @@ wl_android_make_hang_with_reason(struct net_device *dev, const char *string_num)
 }
 #endif /* DHD_HANG_SEND_UP_TEST */
 
+#ifdef WL_CFG80211
 #ifdef WLMESH
 static int
 wl_android_set_rsdb_mode(struct net_device *dev, char *command, int total_len)
@@ -4230,6 +4257,7 @@ wl_android_set_rsdb_mode(struct net_device *dev, char *command, int total_len)
        return ret;
 }
 #endif /* WLMESH */
+#endif /* WL_CFG80211 */
 
 #ifdef SUPPORT_LQCM
 static int
@@ -4852,6 +4880,14 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
                bytes_written = wl_android_get_band(net, command, priv_cmd.total_len);
        }
 #ifdef WL_CFG80211
+       else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
+               bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
+       } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
+               bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
+       } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
+               bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
+       }
+#endif /* WL_CFG80211 */
        /* CUSTOMER_SET_COUNTRY feature is define for only GGSM model */
        else if (strnicmp(command, CMD_COUNTRY, strlen(CMD_COUNTRY)) == 0) {
                /*
@@ -4886,14 +4922,6 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
 #endif /* FCC_PWR_LIMIT_2G */
 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
        }
-       else if (strnicmp(command, CMD_SET_CSA, strlen(CMD_SET_CSA)) == 0) {
-               bytes_written = wl_android_set_csa(net, command, priv_cmd.total_len);
-       } else if (strnicmp(command, CMD_80211_MODE, strlen(CMD_80211_MODE)) == 0) {
-               bytes_written = wl_android_get_80211_mode(net, command, priv_cmd.total_len);
-       } else if (strnicmp(command, CMD_CHANSPEC, strlen(CMD_CHANSPEC)) == 0) {
-               bytes_written = wl_android_get_chanspec(net, command, priv_cmd.total_len);
-       }
-#endif /* WL_CFG80211 */
        else if (strnicmp(command, CMD_DATARATE, strlen(CMD_DATARATE)) == 0) {
                bytes_written = wl_android_get_datarate(net, command, priv_cmd.total_len);
        } else if (strnicmp(command, CMD_ASSOC_CLIENTS, strlen(CMD_ASSOC_CLIENTS)) == 0) {
@@ -4928,6 +4956,7 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
        else if (strnicmp(command, CMD_P2P_DEV_ADDR, strlen(CMD_P2P_DEV_ADDR)) == 0) {
                bytes_written = wl_android_get_p2p_dev_addr(net, command, priv_cmd.total_len);
        }
+#ifdef WL_CFG80211
 #ifdef WLMESH
        else if (strnicmp(command, CMD_SAE_SET_PASSWORD, strlen(CMD_SAE_SET_PASSWORD)) == 0) {
                int skip = strlen(CMD_SAE_SET_PASSWORD) + 1;
@@ -4938,6 +4967,7 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
                bytes_written = wl_android_set_rsdb_mode(net, command, priv_cmd.total_len);
        }
 #endif
+#endif /* WL_CFG80211 */
        else if (strnicmp(command, CMD_P2P_SET_NOA, strlen(CMD_P2P_SET_NOA)) == 0) {
                int skip = strlen(CMD_P2P_SET_NOA) + 1;
                bytes_written = wl_cfg80211_set_p2p_noa(net, command + skip,
@@ -5203,17 +5233,15 @@ wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len)
                bytes_written = wl_cfg80211_get_sta_info(net, command, priv_cmd.total_len);
        }
 #endif /* CUSTOMER_HW4_PRIVATE_CMD */
-#ifdef WL_CFG80211
        else if (strnicmp(command, CMD_MURX_BFE_CAP,
                        strlen(CMD_MURX_BFE_CAP)) == 0) {
-#ifdef BCM4359_CHIP
+#if defined(BCM4359_CHIP) && defined(WL_CFG80211)
                uint val = *(command + strlen(CMD_MURX_BFE_CAP) + 1) - '0';
                bytes_written = wl_android_murx_bfe_cap(net, val);
 #else
                return BCME_UNSUPPORTED;
 #endif /* BCM4359_CHIP */
        }
-#endif
 #ifdef SUPPORT_AP_HIGHER_BEACONRATE
        else if (strnicmp(command, CMD_GET_AP_BASICRATE, strlen(CMD_GET_AP_BASICRATE)) == 0) {
                bytes_written = wl_android_get_ap_basicrate(net, command, priv_cmd.total_len);
index df25768fa2a210f522f9f1bd4b356af55cd7e386..bd02240525b3441ab359e866227d3d25f81921c7 100644 (file)
@@ -104,10 +104,10 @@ int wl_handle_private_cmd(struct net_device *net, char *command, u32 cmd_len);
 
 s32 wl_netlink_send_msg(int pid, int type, int seq, const void *data, size_t size);
 #ifdef WL_EXT_IAPSTA
-int wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx);
-int wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx);
+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(void);
-void wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel);
+u32 wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel);
 int wl_ext_iapsta_alive_preinit(struct net_device *dev);
 int wl_ext_iapsta_alive_postinit(struct net_device *dev);
 int wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data);
@@ -119,90 +119,6 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len
 #define strnicmp(str1, str2, len) strncasecmp((str1), (str2), (len))
 #endif
 
-typedef enum IF_STATE {
-       IF_STATE_INIT = 1,
-       IF_STATE_DISALBE,
-       IF_STATE_ENABLE
-} if_state_t;
-
-typedef enum APSTAMODE {
-       ISTAONLY_MODE = 1,
-       IAPONLY_MODE,
-       IAPSTA_MODE,
-       IDUALAP_MODE,
-       IMESHONLY_MODE,
-       IMESHSTA_MODE,
-       IMESHAP_MODE,
-       IMESHAPSTA_MODE,
-       IMESHAPAP_MODE,
-       IGOSTA_MODE
-} apstamode_t;
-
-typedef enum IFMODE {
-       ISTA_MODE = 1,
-       IAP_MODE,
-       IMESH_MODE
-} ifmode_t;
-
-typedef enum BGNMODE {
-       IEEE80211B = 1,
-       IEEE80211G,
-       IEEE80211BG,
-       IEEE80211BGN,
-       IEEE80211BGNAC
-} bgnmode_t;
-
-typedef enum AUTHMODE {
-       AUTH_OPEN,
-       AUTH_SHARED,
-       AUTH_WPAPSK,
-       AUTH_WPA2PSK,
-       AUTH_WPAWPA2PSK
-} authmode_t;
-
-typedef enum ENCMODE {
-       ENC_NONE,
-       ENC_WEP,
-       ENC_TKIP,
-       ENC_AES,
-       ENC_TKIPAES
-} encmode_t;
-
-enum wl_if_list {
-       IF_PIF,
-       IF_VIF,
-       IF_VIF2,
-       MAX_IF_NUM
-};
-
-/* i/f query */
-typedef struct wl_if_info {
-       struct net_device *dev;
-       if_state_t ifstate;
-       ifmode_t ifmode;
-       uint bssidx;
-       char ifname[IFNAMSIZ+1];
-       char ssid[DOT11_MAX_SSID_LEN];
-       struct ether_addr bssid;
-       bgnmode_t bgnmode;
-       int hidden;
-       int maxassoc;
-       uint16 channel;
-       authmode_t amode;
-       encmode_t emode;
-       char key[100];
-} wl_if_info_t;
-
-typedef struct wl_apsta_params {
-       struct wl_if_info if_info[MAX_IF_NUM]; // primary device
-       int ioctl_ver;
-       bool init;
-       bool vsdb;
-       apstamode_t apstamode;
-       bool netif_change;
-       wait_queue_head_t netif_change_event;
-} wl_apsta_params_t;
-
 /* hostap mac mode */
 #define MACLIST_MODE_DISABLED   0
 #define MACLIST_MODE_DENY       1
@@ -243,6 +159,10 @@ int wl_android_set_ap_mac_list(struct net_device *dev, int macmode, struct macli
 #define REPEATED_SCAN_RESULT_CNT       1
 #endif
 
+#if defined(RSSIAVG) || defined(RSSIOFFSET)
+extern int g_wifi_on;
+#endif
+
 #if defined(RSSIAVG)
 #define RSSIAVG_LEN (4*REPEATED_SCAN_RESULT_CNT)
 #define RSSICACHE_TIMEOUT 15
@@ -305,4 +225,12 @@ void wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
        wl_scan_results_t *ss_list);
 void wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl);
 #endif
+int wl_ext_get_best_channel(struct net_device *net,
+#if defined(BSSCACHE)
+       wl_bss_cache_ctrl_t *bss_cache_ctrl,
+#else
+       struct wl_scan_results *bss_list,
+#endif
+       int ioctl_ver, int *best_2g_ch, int *best_5g_ch
+);
 #endif /* _wl_android_ */
index 2d9e1997fa6ac9a77e219bbe778b7354cb0d5b06..bf901eab419dabd409e195833bc0d0eb34915a20 100644 (file)
@@ -1,5 +1,4 @@
 
-
 #include <linux/module.h>
 #include <linux/netdevice.h>
 #include <net/netlink.h>
@@ -15,7 +14,9 @@
 #include <linux/if_arp.h>
 #include <asm/uaccess.h>
 #include <linux/wireless.h>
+#if defined(WL_WIRELESS_EXT)
 #include <wl_iw.h>
+#endif
 #include <wldev_common.h>
 #include <wlioctl.h>
 #include <bcmutils.h>
@@ -27,6 +28,9 @@
 #ifdef WL_CFG80211
 #include <wl_cfg80211.h>
 #endif
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif
 
 #ifndef WL_CFG80211
 #define htod32(i) i
@@ -56,6 +60,7 @@
 #define CMD_SET_SUSPEND_BCN_LI_DTIM            "SET_SUSPEND_BCN_LI_DTIM"
 
 #ifdef WL_EXT_IAPSTA
+#include <net/rtnetlink.h>
 #define CMD_IAPSTA_INIT                        "IAPSTA_INIT"
 #define CMD_IAPSTA_CONFIG              "IAPSTA_CONFIG"
 #define CMD_IAPSTA_ENABLE              "IAPSTA_ENABLE"
@@ -64,6 +69,7 @@
 #define CMD_ISAM_CONFIG                        "ISAM_CONFIG"
 #define CMD_ISAM_ENABLE                        "ISAM_ENABLE"
 #define CMD_ISAM_DISABLE               "ISAM_DISABLE"
+#define CMD_ISAM_STATUS                        "ISAM_STATUS"
 #ifdef PROP_TXSTATUS
 #ifdef PROP_TXSTATUS_VSDB
 #include <dhd_wlfc.h>
@@ -75,6 +81,7 @@ extern int disable_proptx;
 #define CMD_DHCPC_ENABLE       "DHCPC_ENABLE"
 #define CMD_DHCPC_DUMP         "DHCPC_DUMP"
 #endif
+#define CMD_AUTOCHANNEL                "AUTOCHANNEL"
 #define CMD_WL         "WL"
 
 int wl_ext_ioctl(struct net_device *dev, u32 cmd, void *arg, u32 len, u32 set)
@@ -134,9 +141,109 @@ int wl_ext_iovar_setbuf(struct net_device *dev, s8 *iovar_name,
 }
 
 #ifdef WL_EXT_IAPSTA
-static int wl_ext_iapsta_enable(struct net_device *dev, char *command, int total_len);
+typedef enum IF_STATE {
+       IF_STATE_INIT = 1,
+       IF_STATE_DISALBE,
+       IF_STATE_ENABLE
+} if_state_t;
+
+typedef enum APSTAMODE {
+       ISTAONLY_MODE = 1,
+       IAPONLY_MODE,
+       IAPSTA_MODE,
+       IDUALAP_MODE,
+       ISTAAPAP_MODE,
+       IMESHONLY_MODE,
+       IMESHSTA_MODE,
+       IMESHAP_MODE,
+       IMESHAPSTA_MODE,
+       IMESHAPAP_MODE,
+       IGOSTA_MODE
+} apstamode_t;
+
+typedef enum IFMODE {
+       ISTA_MODE = 1,
+       IAP_MODE,
+       IMESH_MODE
+} ifmode_t;
+
+typedef enum BGNMODE {
+       IEEE80211B = 1,
+       IEEE80211G,
+       IEEE80211BG,
+       IEEE80211BGN,
+       IEEE80211BGNAC
+} bgnmode_t;
+
+typedef enum AUTHMODE {
+       AUTH_OPEN,
+       AUTH_SHARED,
+       AUTH_WPAPSK,
+       AUTH_WPA2PSK,
+       AUTH_WPAWPA2PSK,
+       AUTH_SAE
+} authmode_t;
+
+typedef enum ENCMODE {
+       ENC_NONE,
+       ENC_WEP,
+       ENC_TKIP,
+       ENC_AES,
+       ENC_TKIPAES
+} encmode_t;
+
+enum wl_if_list {
+       IF_PIF,
+       IF_VIF,
+       IF_VIF2,
+       MAX_IF_NUM
+};
+
+typedef enum WL_PRIO {
+       PRIO_AP,
+       PRIO_MESH,
+       PRIO_STA
+}wl_prio_t;
+
+typedef struct wl_if_info {
+       struct net_device *dev;
+       if_state_t ifstate;
+       ifmode_t ifmode;
+       char prefix;
+       wl_prio_t prio;
+       int ifidx;
+       uint8 bssidx;
+       char ifname[IFNAMSIZ+1];
+       char ssid[DOT11_MAX_SSID_LEN];
+       struct ether_addr bssid;
+       bgnmode_t bgnmode;
+       int hidden;
+       int maxassoc;
+       uint16 channel;
+       authmode_t amode;
+       encmode_t emode;
+       char key[100];
+} wl_if_info_t;
+
+#define CSA_FW_BIT             (1<<0)
+#define CSA_DRV_BIT            (1<<1)
+
+typedef struct wl_apsta_params {
+       struct wl_if_info if_info[MAX_IF_NUM];
+       int ioctl_ver;
+       bool init;
+       bool rsdb;
+       bool vsdb;
+       uint csa;
+       apstamode_t apstamode;
+       bool netif_change;
+       wait_queue_head_t netif_change_event;
+} wl_apsta_params_t;
+
+static int wl_ext_enable_iface(struct net_device *dev, char *ifname);
 int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
-       void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
+       void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx,
+       struct mutex* buf_sync)
 {
        int ret;
 
@@ -147,19 +254,6 @@ int wl_ext_iovar_setbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
 
        return ret;
 }
-
-int wl_ext_iovar_getbuf_bsscfg(struct net_device *dev, s8 *iovar_name,
-       void *param, s32 paramlen, void *buf, s32 buflen, s32 bsscfg_idx, struct mutex* buf_sync)
-{
-       int ret;
-
-       ret = wldev_iovar_getbuf_bsscfg(dev, iovar_name, param, paramlen,
-               buf, buflen, bsscfg_idx, buf_sync);
-       if (ret < 0)
-               ANDROID_ERROR(("%s: iovar_name=%s ret=%d\n", __FUNCTION__, iovar_name, ret));
-
-       return ret;
-}
 #endif
 
 /* Return a legacy chanspec given a new chanspec
@@ -228,6 +322,55 @@ wl_ext_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec)
        return chanspec;
 }
 
+#if defined(WL_EXT_IAPSTA) || defined(WL_CFG80211) || defined(WL_ESCAN)
+static chanspec_t
+wl_ext_chspec_from_legacy(chanspec_t legacy_chspec)
+{
+       chanspec_t chspec;
+
+       /* get the channel number */
+       chspec = LCHSPEC_CHANNEL(legacy_chspec);
+
+       /* convert the band */
+       if (LCHSPEC_IS2G(legacy_chspec)) {
+               chspec |= WL_CHANSPEC_BAND_2G;
+       } else {
+               chspec |= WL_CHANSPEC_BAND_5G;
+       }
+
+       /* convert the bw and sideband */
+       if (LCHSPEC_IS20(legacy_chspec)) {
+               chspec |= WL_CHANSPEC_BW_20;
+       } else {
+               chspec |= WL_CHANSPEC_BW_40;
+               if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
+                       chspec |= WL_CHANSPEC_CTL_SB_L;
+               } else {
+                       chspec |= WL_CHANSPEC_CTL_SB_U;
+               }
+       }
+
+       if (wf_chspec_malformed(chspec)) {
+               ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
+                       chspec));
+               return INVCHANSPEC;
+       }
+
+       return chspec;
+}
+
+static chanspec_t
+wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
+{
+       chanspec = dtohchanspec(chanspec);
+       if (ioctl_ver == 1) {
+               chanspec = wl_ext_chspec_from_legacy(chanspec);
+       }
+
+       return chanspec;
+}
+#endif
+
 static int
 wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
 {
@@ -252,7 +395,8 @@ wl_ext_get_ioctl_ver(struct net_device *dev, int *ioctl_ver)
 }
 
 static int
-wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chspec)
+wl_ext_set_chanspec(struct net_device *dev, int ioctl_ver,
+       uint16 channel, chanspec_t *ret_chspec)
 {
        s32 _chan = channel;
        chanspec_t chspec = 0;
@@ -266,13 +410,11 @@ wl_ext_set_chanspec(struct net_device *dev, uint16 channel, chanspec_t *ret_chsp
                u32 bw_cap;
        } param = {0, 0};
        uint band;
-       int ioctl_ver = 0;
 
        if (_chan <= CH_MAX_2G_CHANNEL)
                band = IEEE80211_BAND_2GHZ;
        else
                band = IEEE80211_BAND_5GHZ;
-       wl_ext_get_ioctl_ver(dev, &ioctl_ver);
 
        if (band == IEEE80211_BAND_5GHZ) {
                param.band = WLC_BAND_5G;
@@ -314,11 +456,14 @@ set_channel:
                                wl_ext_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), 1);
                                printf("%s: channel %d\n", __FUNCTION__, _chan);
                        } else if (err) {
-                               ANDROID_ERROR(("%s: failed to set chanspec error %d\n", __FUNCTION__, err));
+                               ANDROID_ERROR(("%s: failed to set chanspec error %d\n",
+                                       __FUNCTION__, err));
                        } else
-                               printf("%s: channel %d, 0x%x\n", __FUNCTION__, channel, chspec);
+                               printf("%s: %s channel %d, 0x%x\n", __FUNCTION__,
+                                       dev->name, channel, chspec);
                } else {
-                       ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n", __FUNCTION__));
+                       ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n",
+                               __FUNCTION__));
                        err = BCME_ERROR;
                }
        } else {
@@ -347,19 +492,23 @@ wl_ext_channel(struct net_device *dev, char* command, int total_len)
        channel_info_t ci;
        int bytes_written = 0;
        chanspec_t fw_chspec;
+       int ioctl_ver = 0;
 
        ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command));
 
        sscanf(command, "%*s %d", &channel);
 
        if (channel > 0) {
-               ret = wl_ext_set_chanspec(dev, channel, &fw_chspec);
+               wl_ext_get_ioctl_ver(dev, &ioctl_ver);
+               ret = wl_ext_set_chanspec(dev, ioctl_ver, channel, &fw_chspec);
        } else {
-               if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t), FALSE))) {
+               if (!(ret = wldev_ioctl(dev, WLC_GET_CHANNEL, &ci,
+                               sizeof(channel_info_t), FALSE))) {
                        ANDROID_TRACE(("hw_channel %d\n", ci.hw_channel));
                        ANDROID_TRACE(("target_channel %d\n", ci.target_channel));
                        ANDROID_TRACE(("scan_channel %d\n", ci.scan_channel));
-                       bytes_written = snprintf(command, sizeof(channel_info_t)+2, "channel %d", ci.hw_channel);
+                       bytes_written = snprintf(command, sizeof(channel_info_t)+2,
+                               "channel %d", ci.hw_channel);
                        ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
                        ret = bytes_written;
                }
@@ -381,13 +530,15 @@ wl_ext_channels(struct net_device *dev, char* command, int total_len)
        memset(valid_chan_list, 0, sizeof(valid_chan_list));
        list = (wl_uint32_list_t *)(void *) valid_chan_list;
        list->count = htod32(WL_NUMCHANNELS);
-       ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list, sizeof(valid_chan_list), 0);
+       ret = wldev_ioctl(dev, WLC_GET_VALID_CHANNELS, valid_chan_list,
+               sizeof(valid_chan_list), 0);
        if (ret<0) {
                ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret));
        } else {
                bytes_written = snprintf(command, total_len, "channels");
                for (i = 0; i < dtoh32(list->count); i++) {
-                       bytes_written += snprintf(command+bytes_written, total_len, " %d", dtoh32(list->element[i]));
+                       bytes_written += snprintf(command+bytes_written, total_len, " %d",
+                               dtoh32(list->element[i]));
                        printf("%d ", dtoh32(list->element[i]));
                }
                printf("\n");
@@ -409,23 +560,29 @@ wl_ext_roam_trigger(struct net_device *dev, char* command, int total_len)
 
        if (roam_trigger[0]) {
                roam_trigger[1] = WLC_BAND_ALL;
-               ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 1);
+               ret = wldev_ioctl(dev, WLC_SET_ROAM_TRIGGER, roam_trigger,
+                       sizeof(roam_trigger), 1);
                if (ret)
-                       ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+                       ANDROID_ERROR(("WLC_SET_ROAM_TRIGGER ERROR %d ret=%d\n",
+                               roam_trigger[0], ret));
        } else {
                roam_trigger[1] = WLC_BAND_2G;
-               ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
+               ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
+                       sizeof(roam_trigger), 0);
                if (!ret)
                        trigger[0] = roam_trigger[0];
                else
-                       ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+                       ANDROID_ERROR(("2G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n",
+                               roam_trigger[0], ret));
 
                roam_trigger[1] = WLC_BAND_5G;
-               ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), 0);
+               ret = wldev_ioctl(dev, WLC_GET_ROAM_TRIGGER, roam_trigger,
+                       sizeof(roam_trigger), 0);
                if (!ret)
                        trigger[1] = roam_trigger[0];
                else
-                       ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n", roam_trigger[0], ret));
+                       ANDROID_ERROR(("5G WLC_GET_ROAM_TRIGGER ERROR %d ret=%d\n",
+                               roam_trigger[0], ret));
 
                ANDROID_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1]));
                bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]);
@@ -491,7 +648,8 @@ wl_ext_keep_alive(struct net_device *dev, char *command, int total_len)
        } else {
                if (id < 0)
                        id = 0;
-               ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf, sizeof(buf), NULL);
+               ret = wl_ext_iovar_getbuf(dev, "mkeep_alive", &id, sizeof(id), buf,
+                       sizeof(buf), NULL);
                if (ret) {
                        goto exit;
                } else {
@@ -508,10 +666,12 @@ wl_ext_keep_alive(struct net_device *dev, char *command, int total_len)
                        }
                        printf("\n");
                }
-               bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ", dtoh32(mkeep_alive_pktp->period_msec));
+               bytes_written = snprintf(command, total_len, "mkeep_alive_period_msec %d ",
+                       dtoh32(mkeep_alive_pktp->period_msec));
                bytes_written += snprintf(command+bytes_written, total_len, "0x");
                for (i=0; i<mkeep_alive_pktp->len_bytes; i++) {
-                       bytes_written += snprintf(command+bytes_written, total_len, "%x", mkeep_alive_pktp->data[i]);
+                       bytes_written += snprintf(command+bytes_written, total_len, "%x",
+                               mkeep_alive_pktp->data[i]);
                }
                ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
                ret = bytes_written;
@@ -695,33 +855,98 @@ wl_ext_set_bgnmode(struct wl_if_info *cur_if)
        return 0;
 }
 
+static void
+wl_ext_get_amode(struct wl_if_info *cur_if, char *amode)
+{
+       struct net_device *dev = cur_if->dev;
+       int auth=-1, wpa_auth=-1;
+
+       wl_ext_iovar_getint(dev, "auth", &auth);
+       wl_ext_iovar_getint(dev, "wpa_auth", &wpa_auth);
+
+       if (cur_if->ifmode == IMESH_MODE) {
+               if (auth == 0 && wpa_auth == 0) {
+                       strcpy(amode, "open");
+               } else if (auth == 0 && wpa_auth == 128) {
+                       strcpy(amode, "sae");
+               }
+       } else if (auth == 0 && wpa_auth == 0) {
+               strcpy(amode, "open");
+       } else if (auth == 1 && wpa_auth == 0) {
+               strcpy(amode, "shared");
+       } else if (auth == 0 && wpa_auth == 4) {
+               strcpy(amode, "wpapsk");
+       } else if (auth == 0 && wpa_auth == 128) {
+               strcpy(amode, "wpa2psk");
+       } else if (auth == 0 && wpa_auth == 132) {
+               strcpy(amode, "wpawpa2psk");
+       }
+}
+
+static void
+wl_ext_get_emode(struct wl_if_info *cur_if, char *emode)
+{
+       struct net_device *dev = cur_if->dev;
+       int wsec=0;
+
+       wl_ext_iovar_getint(dev, "wsec", &wsec);
+
+       if (cur_if->ifmode == IMESH_MODE) {
+               if (wsec == 0) {
+                       strcpy(emode, "none");
+               } else {
+                       strcpy(emode, "sae");
+               }
+       } else if (wsec == 0) {
+               strcpy(emode, "none");
+       } else if (wsec == 1) {
+               strcpy(emode, "wep");
+       } else if (wsec == 2 || wsec == 10) {
+               strcpy(emode, "tkip");
+       } else if (wsec == 4 || wsec == 12) {
+               strcpy(emode, "aes");
+       } else if (wsec == 6 || wsec == 14) {
+               strcpy(emode, "tkipaes");
+       }
+}
+
 static int
-wl_ext_set_amode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params)
+wl_ext_set_amode(struct wl_if_info *cur_if)
 {
        struct net_device *dev = cur_if->dev;
        authmode_t amode = cur_if->amode;
        int auth=0, wpa_auth=0;
 
-       if (amode == AUTH_OPEN) {
+       if (cur_if->ifmode == IMESH_MODE) {
+               if (amode == AUTH_SAE) {
+                       auth = 0;
+                       wpa_auth = 128;
+                       ANDROID_INFO(("%s: Authentication: SAE\n", __FUNCTION__));
+               } else {
+                       auth = 0;
+                       wpa_auth = 0;
+                       ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__));
+               }
+       } else if (amode == AUTH_OPEN) {
                auth = 0;
                wpa_auth = 0;
-               ANDROID_TRACE(("%s: Authentication: Open System\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Authentication: Open System\n", __FUNCTION__));
        } else if (amode == AUTH_SHARED) {
                auth = 1;
                wpa_auth = 0;
-               ANDROID_TRACE(("%s: Authentication: Shared Key\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Authentication: Shared Key\n", __FUNCTION__));
        } else if (amode == AUTH_WPAPSK) {
                auth = 0;
                wpa_auth = 4;
-               ANDROID_TRACE(("%s: Authentication: WPA-PSK\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Authentication: WPA-PSK\n", __FUNCTION__));
        } else if (amode == AUTH_WPA2PSK) {
                auth = 0;
                wpa_auth = 128;
-               ANDROID_TRACE(("%s: Authentication: WPA2-PSK\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Authentication: WPA2-PSK\n", __FUNCTION__));
        } else if (amode == AUTH_WPAWPA2PSK) {
                auth = 0;
                wpa_auth = 132;
-               ANDROID_TRACE(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Authentication: WPA/WPA2-PSK\n", __FUNCTION__));
        }
        if (cur_if->ifmode == IMESH_MODE) {
                s32 val = WL_BSSTYPE_MESH;
@@ -748,44 +973,59 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params
        encmode_t emode = cur_if->emode;
        char *key = cur_if->key;
        s8 iovar_buf[WLC_IOCTL_SMLEN];
+       struct dhd_pub *dhd = dhd_get_pub(dev);
 
        memset(&wsec_key, 0, sizeof(wsec_key));
        memset(&psk, 0, sizeof(psk));
-       if (emode == ENC_NONE) {
+
+       if (cur_if->ifmode == IMESH_MODE) {
+               if (amode == AUTH_SAE) {
+                       wsec = 4;
+                       ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__));
+               } else {
+                       wsec = 0;
+                       ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__));
+               }
+       } else if (emode == ENC_NONE) {
                wsec = 0;
-               ANDROID_TRACE(("%s: Encryption: No securiy\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Encryption: No securiy\n", __FUNCTION__));
        } else if (emode == ENC_WEP) {
                wsec = 1;
                wl_ext_parse_wep(key, &wsec_key);
-               ANDROID_TRACE(("%s: Encryption: WEP\n", __FUNCTION__));
-               ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data));
+               ANDROID_INFO(("%s: Encryption: WEP\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, wsec_key.data));
        } else if (emode == ENC_TKIP) {
                wsec = 2;
                psk.key_len = strlen(key);
                psk.flags = WSEC_PASSPHRASE;
                memcpy(psk.key, key, strlen(key));
-               ANDROID_TRACE(("%s: Encryption: TKIP\n", __FUNCTION__));
-               ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
-       } else if (emode == ENC_AES) {
+               ANDROID_INFO(("%s: Encryption: TKIP\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+       } else if (emode == ENC_AES || amode == AUTH_SAE) {
                wsec = 4;
                psk.key_len = strlen(key);
                psk.flags = WSEC_PASSPHRASE;
                memcpy(psk.key, key, strlen(key));
-               ANDROID_TRACE(("%s: Encryption: AES\n", __FUNCTION__));
-               ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+               ANDROID_INFO(("%s: Encryption: AES\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
        } else if (emode == ENC_TKIPAES) {
                wsec = 6;
                psk.key_len = strlen(key);
                psk.flags = WSEC_PASSPHRASE;
                memcpy(psk.key, key, strlen(key));
-               ANDROID_TRACE(("%s: Encryption: TKIP/AES\n", __FUNCTION__));
-               ANDROID_TRACE(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+               ANDROID_INFO(("%s: Encryption: TKIP/AES\n", __FUNCTION__));
+               ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, psk.key));
+       }
+       if (dhd->conf->chip == BCM43430_CHIP_ID && cur_if->ifidx > 0 && wsec >= 2 &&
+                       apsta_params->apstamode == IAPSTA_MODE) {
+               wsec |= 0x8; // terence 20180628: fix me, this is a workaround
        }
 
        wl_ext_iovar_setint(dev, "wsec", wsec);
 
        if (cur_if->ifmode == IMESH_MODE) {
-               if (amode == AUTH_WPA2PSK && emode == ENC_AES) {
+               if (amode == AUTH_SAE) {
+                       ANDROID_INFO(("%s: Key: \"%s\"\n", __FUNCTION__, 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),
@@ -809,6 +1049,105 @@ wl_ext_set_emode(struct wl_if_info *cur_if, struct wl_apsta_params *apsta_params
        return 0;
 }
 
+static uint16
+wl_ext_get_chan(struct net_device *dev)
+{
+       struct wl_apsta_params *apsta_params = &g_apsta_params;
+       int ret = 0;
+       uint16 chan = 0, ctl_chan;
+       struct ether_addr bssid;
+       u32 chanspec = 0;
+       
+       ret = wldev_ioctl(dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
+       if (ret != BCME_NOTASSOCIATED && memcmp(&ether_null, &bssid, ETHER_ADDR_LEN)) {
+               if (wldev_iovar_getint(dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
+                       chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
+                       ctl_chan = wf_chspec_ctlchan(chanspec);
+                       chan = (u16)(ctl_chan & 0x00FF);
+                       ANDROID_INFO(("%s: cur_chan=%d(0x%x)\n", __FUNCTION__,
+                               chan, chanspec));
+                       return chan;
+               }
+       }
+
+       return 0;
+}
+
+static chanspec_t
+wl_ext_get_chanspec(struct wl_apsta_params *apsta_params,
+       struct net_device *dev, uint16 channel)
+{
+       s32 _chan = channel;
+       chanspec_t chspec = 0;
+       chanspec_t fw_chspec = 0;
+       u32 bw = WL_CHANSPEC_BW_20;
+       s32 err = BCME_OK;
+       s32 bw_cap = 0;
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+       struct {
+               u32 band;
+               u32 bw_cap;
+       } param = {0, 0};
+       uint band;
+
+       if (_chan <= CH_MAX_2G_CHANNEL)
+               band = IEEE80211_BAND_2GHZ;
+       else
+               band = IEEE80211_BAND_5GHZ;
+
+       if (band == IEEE80211_BAND_5GHZ) {
+               param.band = WLC_BAND_5G;
+               err = wldev_iovar_getbuf(dev, "bw_cap", &param, sizeof(param),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               if (err) {
+                       if (err != BCME_UNSUPPORTED) {
+                               ANDROID_ERROR(("bw_cap failed, %d\n", err));
+                               return err;
+                       } else {
+                               err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap);
+                               if (err) {
+                                       ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err));
+                               }
+                               if (bw_cap != WLC_N_BW_20ALL)
+                                       bw = WL_CHANSPEC_BW_40;
+                       }
+               } else {
+                       if (WL_BW_CAP_80MHZ(iovar_buf[0]))
+                               bw = WL_CHANSPEC_BW_80;
+                       else if (WL_BW_CAP_40MHZ(iovar_buf[0]))
+                               bw = WL_CHANSPEC_BW_40;
+                       else
+                               bw = WL_CHANSPEC_BW_20;
+               }
+       }
+       else if (band == IEEE80211_BAND_2GHZ)
+               bw = WL_CHANSPEC_BW_20;
+
+set_channel:
+       chspec = wf_channel2chspec(_chan, bw);
+       if (wf_chspec_valid(chspec)) {
+               fw_chspec = wl_ext_chspec_host_to_driver(apsta_params->ioctl_ver, chspec);
+               if (fw_chspec == INVCHANSPEC) {
+                       ANDROID_ERROR(("%s: failed to convert host chanspec to fw chanspec\n",
+                               __FUNCTION__));
+                       fw_chspec = 0;
+               }
+       } else {
+               if (bw == WL_CHANSPEC_BW_80)
+                       bw = WL_CHANSPEC_BW_40;
+               else if (bw == WL_CHANSPEC_BW_40)
+                       bw = WL_CHANSPEC_BW_20;
+               else
+                       bw = 0;
+               if (bw)
+                       goto set_channel;
+               ANDROID_ERROR(("%s: Invalid chanspec 0x%x\n", __FUNCTION__, chspec));
+               err = BCME_ERROR;
+       }
+
+       return fw_chspec;
+}
+
 static void
 wl_ext_ch_to_chanspec(int ch, struct wl_join_params *join_params,
         size_t *join_params_size)
@@ -845,53 +1184,6 @@ wl_ext_ch_to_chanspec(int ch, struct wl_join_params *join_params,
        }
 }
 
-static chanspec_t
-wl_ext_chspec_from_legacy(chanspec_t legacy_chspec)
-{
-       chanspec_t chspec;
-
-       /* get the channel number */
-       chspec = LCHSPEC_CHANNEL(legacy_chspec);
-
-       /* convert the band */
-       if (LCHSPEC_IS2G(legacy_chspec)) {
-               chspec |= WL_CHANSPEC_BAND_2G;
-       } else {
-               chspec |= WL_CHANSPEC_BAND_5G;
-       }
-
-       /* convert the bw and sideband */
-       if (LCHSPEC_IS20(legacy_chspec)) {
-               chspec |= WL_CHANSPEC_BW_20;
-       } else {
-               chspec |= WL_CHANSPEC_BW_40;
-               if (LCHSPEC_CTL_SB(legacy_chspec) == WL_LCHANSPEC_CTL_SB_LOWER) {
-                       chspec |= WL_CHANSPEC_CTL_SB_L;
-               } else {
-                       chspec |= WL_CHANSPEC_CTL_SB_U;
-               }
-       }
-
-       if (wf_chspec_malformed(chspec)) {
-               ANDROID_ERROR(("wl_ext_chspec_from_legacy: output chanspec (0x%04X) malformed\n",
-                       chspec));
-               return INVCHANSPEC;
-       }
-
-       return chspec;
-}
-
-static chanspec_t
-wl_ext_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
-{
-       chanspec = dtohchanspec(chanspec);
-       if (ioctl_ver == 1) {
-               chanspec = wl_ext_chspec_from_legacy(chanspec);
-       }
-
-       return chanspec;
-}
-
 static s32
 wl_ext_connect(struct wl_if_info *cur_if)
 {
@@ -918,7 +1210,8 @@ wl_ext_connect(struct wl_if_info *cur_if)
                err = -ENOMEM;
                goto exit;
        }
-       ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), strlen(cur_if->ssid));
+       ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID),
+               strlen(cur_if->ssid));
        memcpy(&ext_join_params->ssid.SSID, cur_if->ssid, ext_join_params->ssid.SSID_len);
        ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len);
        /* increate dwell time to receive probe response or detect Beacon
@@ -958,8 +1251,8 @@ wl_ext_connect(struct wl_if_info *cur_if)
                        ext_join_params->ssid.SSID_len));
        }
 
-       err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params, join_params_size,
-               iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
+       err = wl_ext_iovar_setbuf_bsscfg(cur_if->dev, "join", ext_join_params,
+               join_params_size, iovar_buf, WLC_IOCTL_SMLEN, cur_if->bssidx, NULL);
 
        printf("Connecting with " MACDBG " channel (%d) ssid \"%s\", len (%d)\n\n",
                MAC2STRDBG((u8*)(&ext_join_params->assoc.bssid)), cur_if->channel,
@@ -1006,10 +1299,23 @@ exit:
 
 }
 
+static void
+wl_ext_wait_netif_change(struct wl_apsta_params *apsta_params,
+       bool need_rtnl_unlock)
+{
+       if (need_rtnl_unlock)
+               rtnl_unlock();
+       wait_event_interruptible_timeout(apsta_params->netif_change_event,
+               apsta_params->netif_change, msecs_to_jiffies(1500));
+       if (need_rtnl_unlock)
+               rtnl_lock();
+}
+
 static void
 wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_params)
 {
        struct dhd_pub *dhd;
+       apstamode_t apstamode = apsta_params->apstamode;
        wl_interface_create_t iface;
        struct wl_if_info *cur_if;
        wlc_ssid_t ssid = { 0, {0} };
@@ -1017,50 +1323,81 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
        wl_country_t cspec = {{0}, 0, {0}};
        wl_p2p_if_t ifreq;
        s32 val = 0;
-       int i, dfs = 1;
+       int i, dfs = 1, pm = 0;
 
        dhd = dhd_get_pub(dev);
 
-       if (!strlen(apsta_params->if_info[IF_VIF].ifname))
-               strcpy(apsta_params->if_info[IF_VIF].ifname, "wlan1");
-       if (!strlen(apsta_params->if_info[IF_VIF2].ifname))
-               strcpy(apsta_params->if_info[IF_VIF2].ifname, "wlan2");
-
        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;
                        cur_if->ifstate = IF_STATE_INIT;
-                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_sta", i);
+                       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;
                        cur_if->ifstate = IF_STATE_INIT;
-                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_ap", i);
+                       cur_if->prio = PRIO_AP;
+                       cur_if->prefix = 'A';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
                        dfs = 0;
                } else if (cur_if->ifmode == IMESH_MODE) {
                        cur_if->channel = 1;
                        cur_if->maxassoc = -1;
                        cur_if->ifstate = IF_STATE_INIT;
-                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt%d_mesh", i);
+                       cur_if->prio = PRIO_MESH;
+                       cur_if->prefix = 'M';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
                        dfs = 0;
                }
        }
-       if (dfs == 0) {
+
+       if (!dfs && !apsta_params->vsdb) {
                dhd_conf_get_country(dhd, &cspec);
-               if (!dhd_conf_map_country_list(dhd, &cspec, 1)) {
+               if (!dhd_conf_map_country_list(dhd, &cspec)) {
                        dhd_conf_set_country(dhd, &cspec);
                        dhd_bus_country_set(dev, &cspec, TRUE);
                }
+               wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+               wl_ext_iovar_setint(dev, "dfs_chan_disable", 1);
+               wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+       }
+
+       if (FW_SUPPORTED(dhd, rsdb)) {
+               if (apstamode == IDUALAP_MODE)
+                       apsta_params->rsdb = TRUE;
+               else if (apstamode == ISTAAPAP_MODE)
+                       apsta_params->rsdb = FALSE;
+               if (apstamode == IDUALAP_MODE || apstamode == ISTAAPAP_MODE ||
+                       apstamode == IMESHONLY_MODE || apstamode == IMESHSTA_MODE ||
+                       apstamode == IMESHAP_MODE || apstamode == IMESHAPSTA_MODE ||
+                       apstamode == IMESHAPAP_MODE) {
+                       wl_config_t rsdb_mode_cfg = {0, 0};
+                       if (apsta_params->rsdb)
+                               rsdb_mode_cfg.config = 1;
+                       printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
+                       wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+                       wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
+                               sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL);
+                       wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+               }
+       } else {
+               apsta_params->rsdb = FALSE;
        }
 
-       if (apsta_params->apstamode == ISTAONLY_MODE) {
+       if (apstamode == ISTAONLY_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
                // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
                wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
-       } else if (apsta_params->apstamode == IAPONLY_MODE) {
+       } else if (apstamode == IAPONLY_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
 #ifdef ARP_OFFLOAD_SUPPORT
                /* IF SoftAP is enabled, disable arpoe */
@@ -1084,26 +1421,25 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
 #endif
 #endif /* PROP_TXSTATUS_VSDB */
        }
-       else if (apsta_params->apstamode == IAPSTA_MODE) {
+       else if (apstamode == IAPSTA_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "mpc", 0);
                wl_ext_iovar_setint(dev, "apsta", 1);
                wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+               apsta_params->netif_change = FALSE;
                if (FW_SUPPORTED(dhd, rsdb)) {
                        bzero(&iface, sizeof(wl_interface_create_t));
                        iface.ver = WL_INTERFACE_CREATE_VER;
                        iface.flags = WL_INTERFACE_CREATE_AP;
-                       wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                               iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
+                       wl_ext_iovar_getbuf(dev, "interface_create", &iface,
+                               sizeof(iface), iovar_buf, WLC_IOCTL_SMLEN, NULL);
                } else {
-                       wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid), iovar_buf,
-                               WLC_IOCTL_SMLEN, 1, NULL);
+                       wl_ext_iovar_setbuf_bsscfg(dev, "ssid", &ssid, sizeof(ssid),
+                               iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
                }
-               apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_wait_netif_change(apsta_params, TRUE);
        }
-       else if (apsta_params->apstamode == IDUALAP_MODE) {
+       else if (apstamode == IDUALAP_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                /* IF SoftAP is enabled, disable arpoe or wlan1 will ping fail */
 #ifdef ARP_OFFLOAD_SUPPORT
@@ -1112,6 +1448,7 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                dhd_arp_offload_enable(dhd, FALSE);
 #endif /* ARP_OFFLOAD_SUPPORT */
                wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "mbcn", 1);
                wl_ext_iovar_setint(dev, "apsta", 0);
                wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                val = 1;
@@ -1119,106 +1456,140 @@ wl_ext_iapsta_preinit(struct net_device *dev, struct wl_apsta_params *apsta_para
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
                iface.flags = WL_INTERFACE_CREATE_AP;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 1, NULL);
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
        }
-       else if (apsta_params->apstamode == IMESHONLY_MODE) {
+       else if (apstamode == ISTAAPAP_MODE) {
+               u8 rand_bytes[2] = {0, };
+               get_random_bytes(&rand_bytes, sizeof(rand_bytes));
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "mbss", 1);
                wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
-               // don't set WLC_SET_AP to 0, some parameters will be reset, such as bcn_timeout and roam_off
-       }
-       else if (apsta_params->apstamode == IMESHSTA_MODE) {
-               wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
-               wl_ext_iovar_setint(dev, "mpc", 0);
-               wl_ext_iovar_setint(dev, "apsta", 1);
                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
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
-               iface.flags = WL_INTERFACE_CREATE_STA;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
+               iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE;
+               memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+               iface.mac_addr.octet[0] |= 0x02;
+               iface.mac_addr.octet[5] += 0x01;
+               memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
-       }
-       else if (apsta_params->apstamode == IMESHAP_MODE) {
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
+               bzero(&iface, sizeof(wl_interface_create_t));
+               iface.ver = WL_INTERFACE_CREATE_VER;
+               iface.flags = WL_INTERFACE_CREATE_AP | WL_INTERFACE_MAC_USE;
+               memcpy(&iface.mac_addr, dev->dev_addr, ETHER_ADDR_LEN);
+               iface.mac_addr.octet[0] |= 0x02;
+               iface.mac_addr.octet[5] += 0x02;
+               memcpy(&iface.mac_addr.octet[3], rand_bytes, sizeof(rand_bytes));
+               apsta_params->netif_change = FALSE;
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
+       }
+       else if (apstamode == IMESHONLY_MODE) {
+               wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+               wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+               wl_ext_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), 1);
+               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
+       }
+       else if (apstamode == IMESHSTA_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "mbcn", 1);
+               wl_ext_iovar_setint(dev, "apsta", 1);
+               wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
+               bzero(&iface, sizeof(wl_interface_create_t));
+               iface.ver = WL_INTERFACE_CREATE_VER;
+               iface.flags = WL_INTERFACE_CREATE_STA;
+               apsta_params->netif_change = FALSE;
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
+       }
+       else if (apstamode == IMESHAP_MODE) {
+               wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
+               wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "mbcn", 1);
                wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+               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
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
                iface.flags = WL_INTERFACE_CREATE_AP;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
        }
-       else if (apsta_params->apstamode == IMESHAPSTA_MODE) {
+       else if (apstamode == IMESHAPSTA_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "mbcn", 1);
                wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+               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
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
                iface.flags = WL_INTERFACE_CREATE_AP;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
                iface.flags = WL_INTERFACE_CREATE_STA;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
        }
-       else if (apsta_params->apstamode == IMESHAPAP_MODE) {
+       else if (apstamode == IMESHAPAP_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "mpc", 0);
+               wl_ext_iovar_setint(dev, "mbcn", 1);
                wl_ext_iovar_setint(dev, "apsta", 1); // keep 1 as we set in dhd_preinit_ioctls
+               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
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
                iface.flags = WL_INTERFACE_CREATE_AP;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
                bzero(&iface, sizeof(wl_interface_create_t));
                iface.ver = WL_INTERFACE_CREATE_VER;
                iface.flags = WL_INTERFACE_CREATE_AP;
-               wl_ext_iovar_getbuf_bsscfg(dev, "interface_create", &iface, sizeof(iface),
-                       iovar_buf, WLC_IOCTL_SMLEN, 0, NULL);
                apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_iovar_getbuf(dev, "interface_create", &iface, sizeof(iface),
+                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+               wl_ext_wait_netif_change(apsta_params, TRUE);
        }
-       else if (apsta_params->apstamode == IGOSTA_MODE) {
+       else if (apstamode == IGOSTA_MODE) {
                wl_ext_ioctl(dev, WLC_DOWN, NULL, 0, 1);
                wl_ext_iovar_setint(dev, "apsta", 1);
                wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                bzero(&ifreq, sizeof(wl_p2p_if_t));
                ifreq.type = htod32(WL_P2P_IF_GO);
+               apsta_params->netif_change = FALSE;
                wl_ext_iovar_setbuf(dev, "p2p_ifadd", &ifreq, sizeof(ifreq),
                        iovar_buf, WLC_IOCTL_SMLEN, NULL);
-               apsta_params->netif_change = FALSE;
-               wait_event_interruptible_timeout(apsta_params->netif_change_event,
-                       apsta_params->netif_change, msecs_to_jiffies(1500));
+               wl_ext_wait_netif_change(apsta_params, TRUE);
        }
 
        wl_ext_get_ioctl_ver(dev, &apsta_params->ioctl_ver);
        apsta_params->init = TRUE;
-       printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
+
+       printf("%s: apstamode=%d\n", __FUNCTION__, apstamode);
 }
 
 static int
@@ -1254,15 +1625,22 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len)
                                        apsta_params->apstamode = IAPSTA_MODE;
                                } 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, "mesh")) {
                                        apsta_params->apstamode = IMESHONLY_MODE;
-                               } else if (!strcmp(pick_tmp2, "mesh-sta")) {
+                               } else if (!strcmp(pick_tmp2, "mesh-sta") ||
+                                               !strcmp(pick_tmp2, "sta-mesh")) {
                                        apsta_params->apstamode = IMESHSTA_MODE;
-                               } else if (!strcmp(pick_tmp2, "mesh-ap")) {
+                               } else if (!strcmp(pick_tmp2, "mesh-ap") ||
+                                               !strcmp(pick_tmp2, "ap-mesh")) {
                                        apsta_params->apstamode = IMESHAP_MODE;
-                               } else if (!strcmp(pick_tmp2, "mesh-ap-sta")) {
+                               } else if (!strcmp(pick_tmp2, "mesh-ap-sta") ||
+                                               !strcmp(pick_tmp2, "sta-ap-mesh") ||
+                                               !strcmp(pick_tmp2, "sta-mesh-ap")) {
                                        apsta_params->apstamode = IMESHAPSTA_MODE;
-                               } else if (!strcmp(pick_tmp2, "mesh-ap-ap")) {
+                               } else if (!strcmp(pick_tmp2, "mesh-ap-ap") ||
+                                               !strcmp(pick_tmp2, "ap-ap-mesh")) {
                                        apsta_params->apstamode = IMESHAPAP_MODE;
                                } else if (!strcmp(pick_tmp2, "apsta")) {
                                        apsta_params->apstamode = IAPSTA_MODE;
@@ -1289,11 +1667,29 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len)
                                                apsta_params->if_info[i].ifmode = ISTA_MODE;
                                        else if (!strcmp(pch, "ap"))
                                                apsta_params->if_info[i].ifmode = IAP_MODE;
-                                       else if (!strcmp(pch, "mesh"))
+                                       else if (!strcmp(pch, "mesh")) {
+                                               if (dhd->conf->fw_type != FW_TYPE_MESH) {
+                                                       ANDROID_ERROR(("%s: wrong fw type\n", __FUNCTION__));
+                                                       return -1;
+                                               }
                                                apsta_params->if_info[i].ifmode = IMESH_MODE;
+                                       }
                                        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 {
+                                       ANDROID_ERROR(("%s: rsdb [y|n]\n", __FUNCTION__));
+                                       return -1;
+                               }
+                       }
                } else if (!strcmp(param, "vsdb")) {
                        pch = bcmstrtok(&pick_tmp, " ", 0);
                        if (pch) {
@@ -1306,6 +1702,11 @@ wl_ext_isam_init(struct net_device *dev, char *command, int total_len)
                                        return -1;
                                }
                        }
+               } else if (!strcmp(param, "csa")) {
+                       pch = bcmstrtok(&pick_tmp, " ", 0);
+                       if (pch) {
+                               apsta_params->csa = (int)simple_strtol(pch, NULL, 0);
+                       }
                } else if (!strcmp(param, "ifname")) {
                        pch = NULL;
                        pick_tmp2 = bcmstrtok(&pick_tmp, " ", 0);
@@ -1342,7 +1743,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
 {
        char *pch, *pick_tmp;
        char name[20], data[100];
-       int i, j;
+       int i, j, len;
        char *ifname_head = NULL;
 
        typedef struct config_map_t {
@@ -1350,7 +1751,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
                char *head;
                char *tail;
        } config_map_t;
-       
+
        config_map_t config_map [] = {
                {" ifname ",    NULL, NULL},
                {" ssid ",              NULL, NULL},
@@ -1368,14 +1769,14 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
        pick_tmp = command;
 
        // reset head and tail
-       for (i = 0;  i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+       for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
                row = &config_map[i];
                row->head = NULL;
                row->tail = pick_tmp + strlen(pick_tmp);
        }
 
        // pick head
-       for (i = 0;  i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+       for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
                row = &config_map[i];
                pch = strstr(pick_tmp, row->name);
                if (pch) {
@@ -1384,9 +1785,9 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
        }
 
        // sort by head
-       for (i = 0;  i < sizeof(config_map)/sizeof(config_map[0]) - 1;  i++) {
+       for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
                row_prev = &config_map[i];
-               for (j = i+1;  j < sizeof(config_map)/sizeof(config_map[0]);  j++) {
+               for (j = i+1; j < sizeof(config_map)/sizeof(config_map[0]); j++) {
                        row = &config_map[j];
                        if (row->head < row_prev->head) {
                                strcpy(name, row_prev->name);
@@ -1400,7 +1801,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
        }
 
        // pick tail
-       for (i = 0;  i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
+       for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]) - 1; i++) {
                row_prev = &config_map[i];
                row = &config_map[i+1];
                if (row_prev->head) {
@@ -1409,7 +1810,7 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
        }
 
        // remove name from head
-       for (i = 0;  i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+       for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
                row = &config_map[i];
                if (row->head) {
                        if (!strcmp(row->name, " ifname ")) {
@@ -1420,11 +1821,11 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
                }
        }
 
-       for (i = 0;  i < sizeof(config_map)/sizeof(config_map[0]); i++) {
+       for (i = 0; i < sizeof(config_map)/sizeof(config_map[0]); i++) {
                row = &config_map[i];
                if (row->head) {
                        memset(data, 0, sizeof(data));
-                       if (row->tail) {
+                       if (row->tail && row->tail > row->head) {
                                strncpy(data, row->head, row->tail-row->head);
                        } else {
                                strcpy(data, row->head);
@@ -1434,7 +1835,12 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
                        if (!strcmp(row->name, " ifname ")) {
                                break;
                        } else if (!strcmp(row->name, " ssid ")) {
-                               strcpy(cur_if->ssid, pick_tmp);
+                               len = strlen(pick_tmp);
+                               memset(cur_if->ssid, 0, sizeof(cur_if->ssid));
+                               if (pick_tmp[0] == '"' && pick_tmp[len-1] == '"')
+                                       strncpy(cur_if->ssid, &pick_tmp[1], len-2);
+                               else
+                                       strcpy(cur_if->ssid, pick_tmp);
                        } else if (!strcmp(row->name, " bssid ")) {
                                pch = bcmstrtok(&pick_tmp, ": ", 0);
                                for (j=0; j<6 && pch; j++) {
@@ -1480,6 +1886,8 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
                                        cur_if->amode = AUTH_WPA2PSK;
                                else if (!strcmp(pick_tmp, "wpawpa2psk"))
                                        cur_if->amode = AUTH_WPAWPA2PSK;
+                               else if (!strcmp(pick_tmp, "sae"))
+                                       cur_if->amode = AUTH_SAE;
                                else {
                                        ANDROID_ERROR(("%s: amode [open|shared|wpapsk|wpa2psk|wpawpa2psk]\n",
                                                __FUNCTION__));
@@ -1502,7 +1910,12 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
                                        return -1;
                                }
                        } else if (!strcmp(row->name, " key ")) {
-                               strcpy(cur_if->key, pick_tmp);
+                               len = strlen(pick_tmp);
+                               memset(cur_if->key, 0, sizeof(cur_if->key));
+                               if (pick_tmp[0] == '"' && pick_tmp[len-1] == '"')
+                                       strncpy(cur_if->key, &pick_tmp[1], len-2);
+                               else
+                                       strcpy(cur_if->key, pick_tmp);
                        }
                }
        }
@@ -1514,11 +1927,11 @@ wl_ext_parse_config(struct wl_if_info *cur_if, char *command, char **pick_next)
 static int
 wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len)
 {
-       int ret=0;
+       int ret=0, i;
        char *pch, *pch2, *pick_tmp, *pick_next=NULL, *param;
        struct wl_apsta_params *apsta_params = &g_apsta_params;
        char ifname[IFNAMSIZ+1];
-       struct wl_if_info *cur_if = &apsta_params->if_info[IF_PIF];
+       struct wl_if_info *cur_if = NULL;
 
        if (!apsta_params->init) {
                ANDROID_ERROR(("%s: please init first\n", __FUNCTION__));
@@ -1541,15 +1954,16 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len)
                                ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__));
                                return -1;
                        }
-                       if (!strcmp(apsta_params->if_info[IF_PIF].dev->name, ifname)) {
-                               cur_if = &apsta_params->if_info[IF_PIF];
-                       } else if (!strcmp(apsta_params->if_info[IF_VIF].ifname, ifname)) {
-                               cur_if = &apsta_params->if_info[IF_VIF];
-                       } else if (!strcmp(apsta_params->if_info[IF_VIF2].ifname, ifname)) {
-                               cur_if = &apsta_params->if_info[IF_VIF2];
-                       } else {
-                               ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n", __FUNCTION__,
-                                       ifname, apsta_params->apstamode));
+                       for (i=0; i<MAX_IF_NUM; i++) {
+                               if (apsta_params->if_info[i].dev &&
+                                               !strcmp(apsta_params->if_info[i].dev->name, ifname)) {
+                                       cur_if = &apsta_params->if_info[i];
+                                       break;
+                               }
+                       }
+                       if (!cur_if) {
+                               ANDROID_ERROR(("%s: wrong ifname=%s in apstamode=%d\n",
+                                       __FUNCTION__, ifname, apsta_params->apstamode));
                                return -1;
                        }
                        ret = wl_ext_parse_config(cur_if, pick_tmp, &pick_next);
@@ -1566,6 +1980,131 @@ wl_ext_iapsta_config(struct net_device *dev, char *command, int total_len)
        return 0;
 }
 
+static int
+wl_ext_isam_status(struct net_device *dev)
+{
+       struct wl_apsta_params *apsta_params = &g_apsta_params;
+       int i;
+       bool now_if;
+       struct wl_if_info *tmp_if;
+       uint16 chan = 0;
+       wlc_ssid_t ssid = { 0, {0} };
+       char amode[16], emode[16];
+
+       if (apsta_params->init == FALSE) {
+               return 0;
+       }
+
+       printf("****************************\n");
+       printf("%s: apstamode=%d\n", __FUNCTION__, apsta_params->apstamode);
+       for (i=0; i<MAX_IF_NUM; i++) {
+               now_if = FALSE;
+               memset(&ssid, 0, sizeof(ssid));
+               memset(amode, 0, sizeof(amode));
+               memset(emode, 0, sizeof(emode));
+               tmp_if = &apsta_params->if_info[i];
+               if (dev == tmp_if->dev)
+                       now_if = TRUE;
+               if (tmp_if->dev) {
+                       chan = wl_ext_get_chan(tmp_if->dev);
+                       if (chan) {
+                               wl_ext_ioctl(tmp_if->dev, WLC_GET_SSID, &ssid, sizeof(ssid), 0);
+                               wl_ext_get_amode(tmp_if, amode);
+                               wl_ext_get_emode(tmp_if, emode);
+                       }
+                       if (chan) {
+                               printf("%s[%c-%c%s]: chan %3d, amode %s, emode %s, SSID \"%s\"\n",
+                                       tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
+                                       now_if?"*":" ", chan, amode, emode, ssid.SSID);
+                       } else {
+                               printf("%s[%c-%c%s]:\n",
+                                       tmp_if->ifname, tmp_if->prefix, chan?'E':'D',
+                                       now_if?"*":" ");
+                       }
+               }
+       }
+       printf("****************************\n");
+
+       return 0;
+}
+
+static int
+wl_ext_if_down(struct wl_if_info *cur_if)
+{
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+       scb_val_t scbval;
+       struct {
+               s32 cfg;
+               s32 val;
+       } bss_setbuf;
+       apstamode_t apstamode = g_apsta_params.apstamode;
+
+       printf("%s: %s[%c] Turning off\n", __FUNCTION__, cur_if->ifname, cur_if->prefix);
+
+       if (cur_if->ifmode == ISTA_MODE) {
+               wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
+       } 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);
+               wl_ext_ioctl(cur_if->dev, WLC_SCB_DEAUTHENTICATE, &scbval.ea, ETHER_ADDR_LEN, 1);
+       }
+
+       if (apstamode == IAPONLY_MODE || apstamode == IMESHONLY_MODE) {
+               wl_ext_ioctl(cur_if->dev, WLC_DOWN, NULL, 0, 1);
+       } else {
+               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);
+       }
+
+       return 0;
+}
+
+static int
+wl_ext_if_up(struct wl_if_info *cur_if)
+{
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+       struct {
+               s32 cfg;
+               s32 val;
+       } bss_setbuf;
+       struct wl_apsta_params *apsta_params = &g_apsta_params;
+       apstamode_t apstamode = apsta_params->apstamode;
+       chanspec_t fw_chspec;
+
+       if (cur_if->ifmode != IAP_MODE) {
+               ANDROID_ERROR(("%s: Wrong ifmode on %s[%c]\n", __FUNCTION__,
+                       cur_if->ifname, cur_if->prefix));
+               return 0;
+       }
+
+       if (cur_if->channel >= 52 && cur_if->channel <= 148) {
+               printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+                       cur_if->ifname, cur_if->prefix, cur_if->channel);
+               return 0;
+       }
+
+       printf("%s: %s[%c] Turning on\n", __FUNCTION__, cur_if->ifname, cur_if->prefix);
+       wl_ext_isam_status(cur_if->dev);
+
+       wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
+               &fw_chspec);
+
+       if (apstamode == IAPONLY_MODE) {
+               wl_ext_ioctl(cur_if->dev, WLC_UP, NULL, 0, 1);
+       } else {
+               bss_setbuf.cfg = 0xffffffff;    
+               bss_setbuf.val = htod32(1);
+               wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf,
+                       sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL);
+       }
+
+       OSL_SLEEP(500);
+
+       return 0;
+}
+
 static int
 wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
 {
@@ -1574,7 +2113,6 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
        wlc_ssid_t ssid = { 0, {0} };
        scb_val_t scbval;
        struct {
-               s32 tmp;
                s32 cfg;
                s32 val;
        } bss_setbuf;
@@ -1621,6 +2159,8 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
                return -1;
        }
 
+       printf("%s: %s[%c] Disabling\n", __FUNCTION__, ifname, cur_if->prefix);
+
        if (cur_if->ifmode == ISTA_MODE) {
                wl_ext_ioctl(cur_if->dev, WLC_DISASSOC, NULL, 0, 1);
        } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
@@ -1635,9 +2175,7 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
                wl_ext_iovar_setint(dev, "mpc", 1);
        } else if ((apstamode==IAPSTA_MODE || apstamode==IGOSTA_MODE) &&
                        cur_if->ifmode == IAP_MODE) {
-               // if_info[IF_VIF] is AP mode
-               bss_setbuf.tmp = 0xffffffff;
-               bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+               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);
@@ -1658,16 +2196,16 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
                }
 #endif 
 #endif /* PROP_TXSTATUS_VSDB */
-       } else if (apstamode == IDUALAP_MODE) {
-               bss_setbuf.tmp = 0xffffffff;
-               bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+       }
+       else if (apstamode == IDUALAP_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);
        } else if (apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
-                       apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) {
-               bss_setbuf.tmp = 0xffffffff;
-               bss_setbuf.cfg = 0; // must be 0, or wlan1 can not be down
+                       apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_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);
@@ -1675,153 +2213,176 @@ wl_ext_iapsta_disable(struct net_device *dev, char *command, int total_len)
 
        cur_if->ifstate = IF_STATE_DISALBE;
 
-       printf("%s: ifname=%s, mode=%d\n", __FUNCTION__, ifname, cur_if->ifmode);
+       printf("%s: %s[%c] disabled\n", __FUNCTION__, ifname, cur_if->prefix);
 
        return 0;
 }
 
-static bool
-wl_ext_iapsta_diff_band(uint16 channel1, uint16 channel2)
-{
-       ANDROID_TRACE(("%s: cur_chan=%d, channel=%d\n", __FUNCTION__, channel1, channel2));
-       if ((channel1 <= CH_MAX_2G_CHANNEL && channel2 > CH_MAX_2G_CHANNEL) ||
-               (channel1 > CH_MAX_2G_CHANNEL && channel2 <= CH_MAX_2G_CHANNEL)) {
-               return TRUE;
-       } else {
-               return FALSE;
-       }
-}
-
 static uint16
-wl_ext_iapsta_is_vsdb(struct net_device *dev,
-       struct wl_if_info *cur_if, struct wl_if_info *another_if)
+wl_ext_get_vsdb_chan(struct net_device *dev,
+       struct wl_if_info *cur_if, struct wl_if_info *target_if)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
-       int ret = 0, cur_chan = 0;
-       uint16 another_chan = 0, ctl_chan;
+       uint16 target_chan = 0, cur_chan = cur_if->channel;
        struct dhd_pub *dhd;
-       struct ether_addr bssid;
-       u32 chanspec = 0;
 
        dhd = dhd_get_pub(dev);
-       
-       ret = wldev_ioctl(another_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
-       if (ret != BCME_NOTASSOCIATED && memcmp(&ether_null, &bssid, ETHER_ADDR_LEN)) {
-               if (wldev_iovar_getint(another_if->dev, "chanspec", (s32 *)&chanspec) == BCME_OK) {
-                       ANDROID_TRACE(("%s: chanspec=0x%x\n", __FUNCTION__, chanspec));
-                       chanspec = wl_ext_chspec_driver_to_host(apsta_params->ioctl_ver, chanspec);
-                       ctl_chan = wf_chspec_ctlchan(chanspec);
-                       another_chan = (u16)(ctl_chan & 0x00FF);
-                       cur_chan = cur_if->channel;
-                       if (wl_ext_iapsta_diff_band(another_chan, cur_chan)) {
-                               // different band
-                               if (!FW_SUPPORTED(dhd, rsdb))
-                                       return another_chan;
-                       } else {
-                               // same band
-                               if (another_chan != cur_chan)
-                                       return another_chan;
-                       }
+
+       target_chan = wl_ext_get_chan(target_if->dev);
+       if (target_chan) {
+               ANDROID_INFO(("%s: cur_chan=%d, target_chan=%d\n", __FUNCTION__,
+                       cur_chan, target_chan));
+               if ((cur_chan <= CH_MAX_2G_CHANNEL && target_chan > CH_MAX_2G_CHANNEL) ||
+                               (cur_chan > CH_MAX_2G_CHANNEL && target_chan <= CH_MAX_2G_CHANNEL)) {
+                       // different band
+                       if (!FW_SUPPORTED(dhd, rsdb) || !apsta_params->rsdb)
+                               return target_chan;
+               } else {
+                       // same band
+                       if (target_chan != cur_chan)
+                               return target_chan;
                }
        }
 
        return 0;
 }
 
-static void
-wl_ext_iapsta_change_channel(struct wl_if_info *cur_if, uint16 chan)
+static int
+wl_ext_triger_csa(struct wl_if_info *cur_if)
 {
-       if (chan) {
-               char cmd[50] = "";
-               printf("%s: deauthenticate all STA and move to chan=%d on %s\n",
-                       __FUNCTION__, chan, cur_if->ifname);
-               snprintf(cmd, 50, "%s %s", "isam_disable ifname", cur_if->ifname);
-               wl_ext_iapsta_disable(cur_if->dev, cmd, strlen(cmd));
-               cur_if->channel = chan;
-               snprintf(cmd, 50, "%s %s", "isam_enable ifname", cur_if->ifname);
-               wl_ext_iapsta_enable(cur_if->dev, cmd, strlen(cmd));
+       struct wl_apsta_params *apsta_params = &g_apsta_params;
+       s8 iovar_buf[WLC_IOCTL_SMLEN];
+
+       if (apsta_params->csa & CSA_DRV_BIT &&
+                       (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE)) {
+               if (!cur_if->channel) {
+                       printf("%s: %s[%c] skip channel %d\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix, cur_if->channel);
+               } else if (cur_if->channel >= 52 && cur_if->channel <= 148) {
+                       printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix, cur_if->channel);
+                       wl_ext_if_down(cur_if);
+               } else {
+                       wl_chan_switch_t csa_arg;
+                       memset(&csa_arg, 0, sizeof(csa_arg));
+                       csa_arg.mode = 1;
+                       csa_arg.count = 3;
+                       csa_arg.chspec = wl_ext_get_chanspec(apsta_params, cur_if->dev,
+                               cur_if->channel);
+                       if (csa_arg.chspec) {
+                               printf("%s: Trigger CSA to channel %d(0x%x)\n", __FUNCTION__,
+                                       cur_if->channel, csa_arg.chspec);
+                               wl_ext_iovar_setbuf(cur_if->dev, "csa", &csa_arg, sizeof(csa_arg),
+                                       iovar_buf, sizeof(iovar_buf), NULL);
+                               OSL_SLEEP(500);
+                               wl_ext_isam_status(cur_if->dev);
+                       } else {
+                               printf("%s: fail to get chanspec\n", __FUNCTION__);
+                       }
+               }
        }
+
+       return 0;
 }
 
-static void
-wl_ext_iapsta_change_cur_iface_channel(struct net_device *dev,
+static uint16
+wl_ext_move_cur_channel(struct net_device *dev,
        struct wl_if_info *cur_if)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
-       struct wl_if_info *another_if, *final_if = NULL;
-       uint16 new_chan = 0;
+       struct wl_if_info *tmp_if, *target_if = NULL;
+       uint16 tmp_chan, target_chan = 0;
+       wl_prio_t max_prio;
        int i;
 
-       if (cur_if->ifmode == IAP_MODE) {
-               for (i=MAX_IF_NUM-1; i>=0; i--) {
-                       another_if = &apsta_params->if_info[i];
-                       if (another_if->ifmode == ISTA_MODE) {
-                               new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
-                               if (new_chan) {
-                                       final_if = another_if;
-                                       break;
-                               }
-                       }
-               }
-       } else if (cur_if->ifmode == IMESH_MODE) {
-               for (i=MAX_IF_NUM-1; i>=0; i--) {
-                       another_if = &apsta_params->if_info[i];
-                       if (another_if->ifmode == ISTA_MODE || another_if->ifmode == IAP_MODE) {
-                               new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
-                               if (new_chan) {
-                                       final_if = another_if;
-                                       break;
-                               }
+       if (apsta_params->vsdb) {
+               target_chan = cur_if->channel;
+               goto exit;
+       }
+
+       // 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 (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if &&
+                               tmp_if->prio > max_prio) {
+                       tmp_chan = wl_ext_get_vsdb_chan(dev, cur_if, tmp_if);
+                       if (tmp_chan) {
+                               target_if = tmp_if;
+                               target_chan = tmp_chan;
+                               max_prio = tmp_if->prio;
                        }
                }
        }
-       if (new_chan && !apsta_params->vsdb) {
-               cur_if->channel = new_chan;
-               printf("%s: %s ifmode=%d, %s ifmode=%d, channel=%d\n", __FUNCTION__,
-                       cur_if->ifname, cur_if->ifmode, final_if->ifname, final_if->ifmode,
-                       cur_if->channel);
+
+       if (target_chan) {
+               printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__,
+                       cur_if->ifname, cur_if->channel, target_if->ifname, target_chan);
+               cur_if->channel = target_chan;
+       }
+exit:
+       if ((cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) &&
+                       (cur_if->channel >= 52 && cur_if->channel <= 148)) {
+               printf("%s: %s[%c] skip DFS channel %d\n", __FUNCTION__,
+                       cur_if->ifname, cur_if->prefix, cur_if->channel);
+               cur_if->channel = 0;
        }
 
+       return cur_if->channel;
 }
 
 static void
-wl_ext_iapsta_change_other_iface_channel(struct net_device *dev,
+wl_ext_move_other_channel(struct net_device *dev,
        struct wl_if_info *cur_if)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
-       struct wl_if_info *another_if;
-       uint16 new_chan = 0;
+       struct wl_if_info *tmp_if, *target_if=NULL;
+       uint16 tmp_chan, target_chan = 0;
+       wl_prio_t max_prio = 0, cur_prio;
        int i;
 
-       if (cur_if->ifmode == ISTA_MODE) {
-               for (i=MAX_IF_NUM-1; i>=0; i--) {
-                       another_if = &apsta_params->if_info[i];
-                       if (another_if->ifmode == IAP_MODE || another_if->ifmode == IMESH_MODE) {
-                               new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
-                               if (new_chan && !apsta_params->vsdb) {
-                                       wl_ext_iapsta_change_channel(another_if, cur_if->channel);
-                               }
+       if (apsta_params->vsdb || !cur_if->channel) {
+               return;
+       }
+
+       // find the max prio, but lower than cur_if
+       cur_prio = cur_if->prio;
+       for (i=0; i<MAX_IF_NUM; i++) {
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->ifstate >= IF_STATE_INIT && cur_if != tmp_if &&
+                               tmp_if->prio >= max_prio && tmp_if->prio <= cur_prio) {
+                       tmp_chan = wl_ext_get_vsdb_chan(dev, cur_if, tmp_if);
+                       if (tmp_chan) {
+                               target_if = tmp_if;
+                               target_chan = tmp_chan;
+                               max_prio = tmp_if->prio;
                        }
                }
-       } else if (cur_if->ifmode == IAP_MODE) {
-               for (i=0; i<MAX_IF_NUM; i++) {
-                       another_if = &apsta_params->if_info[i];
-                       if (another_if->ifmode == IMESH_MODE) {
-                               new_chan = wl_ext_iapsta_is_vsdb(dev, cur_if, another_if);
-                               if (new_chan && !apsta_params->vsdb) {
-                                       wl_ext_iapsta_change_channel(another_if, cur_if->channel);
-                               }
+       }
+
+       if (target_if) {
+               printf("%s: %s channel=%d => %s channel=%d\n", __FUNCTION__,
+                       target_if->ifname, target_chan, cur_if->ifname, cur_if->channel);
+               target_if->channel = cur_if->channel;
+               if (apsta_params->csa == 0) {
+                       wl_ext_if_down(target_if);
+                       wl_ext_move_other_channel(dev, target_if);
+                       if (target_if->ifmode == ISTA_MODE || target_if->ifmode == IMESH_MODE) {
+                               wl_ext_enable_iface(target_if->dev, target_if->ifname);
+                       } else if (target_if->ifmode == IAP_MODE) {
+                               wl_ext_if_up(target_if);
                        }
+               } else {
+                       wl_ext_triger_csa(target_if);
                }
        }
 
 }
 
 static int
-wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
+wl_ext_enable_iface(struct net_device *dev, char *ifname)
 {
-       int ret = 0, i;
-       char *pick_tmp, *param;
+       int i;
        s8 iovar_buf[WLC_IOCTL_SMLEN];
        wlc_ssid_t ssid = { 0, {0} };
        chanspec_t fw_chspec;
@@ -1834,9 +2395,7 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
        struct wl_apsta_params *apsta_params = &g_apsta_params;
        apstamode_t apstamode = apsta_params->apstamode;
        struct wl_if_info *cur_if = NULL;
-       char cmd[128];
        struct dhd_pub *dhd;
-       struct ether_addr bssid;
        uint16 cur_chan;
 
        dhd = dhd_get_pub(dev);
@@ -1853,38 +2412,34 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
                return -1;
        }
 
-       wl_ext_iapsta_change_cur_iface_channel(dev, cur_if);
+       printf("%s: %s[%c] Enabling\n", __FUNCTION__, ifname, cur_if->prefix);
 
-       if ((apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
-                       apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) &&
-                       cur_if == &apsta_params->if_info[IF_PIF] &&
-                       cur_if->ifstate == IF_STATE_INIT &&
-                       FW_SUPPORTED(dhd, rsdb)) {
-               wl_config_t rsdb_mode_cfg = {1, 0};
-               // mesh-ap must set rsdb_mode=1 in same channel or AP mode not easy to be found
-               printf("%s: set rsdb_mode %d\n", __FUNCTION__, rsdb_mode_cfg.config);
-               wl_ext_iovar_setbuf(dev, "rsdb_mode", &rsdb_mode_cfg,
-                       sizeof(rsdb_mode_cfg), iovar_buf, sizeof(iovar_buf), NULL);
-       }
+       wl_ext_isam_status(cur_if->dev);
 
-       ret = wldev_ioctl(cur_if->dev, WLC_GET_BSSID, &bssid, sizeof(bssid), 0);
-       if (ret != BCME_NOTASSOCIATED && memcmp(&ether_null, &bssid, ETHER_ADDR_LEN)) {
-               ANDROID_INFO(("%s: Associated! ret %d\n", __FUNCTION__, ret));
+       wl_ext_move_cur_channel(dev, cur_if);
+       if (!cur_if->channel && cur_if->ifmode != ISTA_MODE) {
                return 0;
        }
 
-       ssid.SSID_len = strlen(cur_if->ssid);
-       memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len);
-       ANDROID_TRACE(("%s: apstamode=%d, bssidx=%d\n", __FUNCTION__, apstamode, cur_if->bssidx));
+       cur_chan = wl_ext_get_chan(cur_if->dev);
+       if (cur_chan) {
+               ANDROID_INFO(("%s: Associated!\n", __FUNCTION__));
+               if (cur_chan != cur_if->channel) {
+                       wl_ext_triger_csa(cur_if);
+               }
+               return 0;
+       }
 
-       wl_ext_iapsta_change_other_iface_channel(dev, cur_if);
+       wl_ext_move_other_channel(dev, cur_if);
 
-       if (cur_if == &apsta_params->if_info[IF_VIF] || cur_if == &apsta_params->if_info[IF_VIF2]) {
+       if (cur_if->ifidx > 0) {
                wl_ext_iovar_setbuf(cur_if->dev, "cur_etheraddr", (u8 *)cur_if->dev->dev_addr,
                        ETHER_ADDR_LEN, iovar_buf, WLC_IOCTL_SMLEN, NULL);
        }
 
        // set ssid for AP
+       ssid.SSID_len = strlen(cur_if->ssid);
+       memcpy(ssid.SSID, cur_if->ssid, ssid.SSID_len);
        if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
                wl_ext_iovar_setint(dev, "mpc", 0);
                if (apstamode == IAPONLY_MODE) {
@@ -1897,10 +2452,12 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
 
        if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
                wl_ext_set_bgnmode(cur_if);
-               cur_chan = cur_if->channel;
-               if (!cur_chan) {
-                       cur_chan = 1;
+               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;
@@ -1913,12 +2470,16 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
                                }
                                param = bcmstrtok(&pick_tmp, " ", 0);
                        }
+                       cur_if->channel = cur_chan;
+#else
+                       cur_if->channel = 1;
 #endif
                }
-               wl_ext_set_chanspec(cur_if->dev, cur_chan, &fw_chspec);
+               wl_ext_set_chanspec(cur_if->dev, apsta_params->ioctl_ver, cur_if->channel,
+                       &fw_chspec);
        }
 
-       wl_ext_set_amode(cur_if, apsta_params);
+       wl_ext_set_amode(cur_if);
        wl_ext_set_emode(cur_if, apsta_params);
 
        if (cur_if->ifmode == IAP_MODE) {
@@ -1926,8 +2487,10 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
                        wl_ext_iovar_setint(dev, "maxassoc", cur_if->maxassoc);
                // terence: fix me, hidden does not work in dualAP mode
                if (cur_if->hidden > 0) {
-                       wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden, sizeof(cur_if->hidden), 1);
-                       printf("%s: Broadcast SSID: %s\n", __FUNCTION__, cur_if->hidden ? "OFF":"ON");
+                       wl_ext_ioctl(cur_if->dev, WLC_SET_CLOSED, &cur_if->hidden,
+                               sizeof(cur_if->hidden), 1);
+                       printf("%s: Broadcast SSID: %s\n", __FUNCTION__,
+                               cur_if->hidden ? "OFF":"ON");
                }
        }
 
@@ -1945,8 +2508,8 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
                        } else {
                                bss_setbuf.cfg = htod32(cur_if->bssidx);
                                bss_setbuf.val = htod32(1);
-                               wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf, sizeof(bss_setbuf),
-                                       iovar_buf, WLC_IOCTL_SMLEN, NULL);
+                               wl_ext_iovar_setbuf(cur_if->dev, "bss", &bss_setbuf,
+                                       sizeof(bss_setbuf), iovar_buf, WLC_IOCTL_SMLEN, NULL);
                        }
 #ifdef ARP_OFFLOAD_SUPPORT
                        /* IF SoftAP is enabled, disable arpoe */
@@ -1969,6 +2532,14 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
        }
        else if (apstamode == IDUALAP_MODE) {
                wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
+       } else if (apstamode == ISTAAPAP_MODE) {
+               if (cur_if->ifmode == ISTA_MODE) {
+                       wl_ext_connect(cur_if);
+               } else if (cur_if->ifmode == IAP_MODE) {
+                       wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
+               } else {
+                       printf("%s: wrong ifmode %d\n", __FUNCTION__, cur_if->ifmode);
+               }
        } else if (apstamode == IMESHONLY_MODE ||
                        apstamode == IMESHSTA_MODE || apstamode == IMESHAP_MODE ||
                        apstamode == IMESHAPSTA_MODE || apstamode == IMESHAPAP_MODE) {
@@ -1978,10 +2549,9 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
                        wl_ext_ioctl(cur_if->dev, WLC_SET_SSID, &ssid, sizeof(ssid), 1);
                } else if (cur_if->ifmode == IMESH_MODE) {
                        // need to up before setting ssid
-                       wl_ext_ioctl(dev, WLC_UP, NULL, 0, 1);
                        memset(&join_params, 0, sizeof(join_params));
                        join_params.ssid.SSID_len = strlen(cur_if->ssid);
-                       memcpy((void *)join_params.ssid.SSID, cur_if->ssid, ssid.SSID_len);
+                       memcpy((void *)join_params.ssid.SSID, cur_if->ssid, strlen(cur_if->ssid));
                        join_params.params.chanspec_list[0] = fw_chspec;
                        join_params.params.chanspec_num = 1;
                        join_params_size = sizeof(join_params);
@@ -1991,8 +2561,10 @@ wl_ext_iapsta_enable_iface(struct net_device *dev, char *ifname)
                }
        }
 
-       printf("%s: ifname=%s, mode=%d, SSID: \"%s\"\n", __FUNCTION__,
-               ifname, cur_if->ifmode, cur_if->ssid);
+       OSL_SLEEP(500);
+       printf("%s: %s[%c] enabled with SSID: \"%s\"\n", __FUNCTION__,
+               ifname, cur_if->prefix, cur_if->ssid);
+       wl_ext_isam_status(cur_if->dev);
 
        cur_if->ifstate = IF_STATE_ENABLE;
 
@@ -2022,11 +2594,9 @@ 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_iapsta_enable_iface(dev, ifname);
+                               ret = wl_ext_enable_iface(dev, ifname);
                                if (ret)
                                        return ret;
-                               else
-                                       OSL_SLEEP(1000);
                        } else {
                                ANDROID_ERROR(("%s: ifname [wlanX]\n", __FUNCTION__));
                                return -1;
@@ -2042,6 +2612,8 @@ int
 wl_ext_iapsta_alive_preinit(struct net_device *dev)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
+       struct wl_if_info *cur_if;
+       int i;
 
        if (apsta_params->init == TRUE) {
                ANDROID_ERROR(("%s: don't init twice\n", __FUNCTION__));
@@ -2050,21 +2622,35 @@ wl_ext_iapsta_alive_preinit(struct net_device *dev)
 
        ANDROID_TRACE(("%s: Enter\n", __FUNCTION__));
 
-       strcpy(apsta_params->if_info[IF_PIF].ssid, "tttp");
-       apsta_params->if_info[IF_PIF].maxassoc = -1;
-       apsta_params->if_info[IF_PIF].channel = 1;
-
-       if (!strlen(apsta_params->if_info[IF_VIF].ifname))
-               strcpy(apsta_params->if_info[IF_VIF].ifname, "wlan1");
-       strcpy(apsta_params->if_info[IF_VIF].ssid, "tttv");
-       apsta_params->if_info[IF_VIF].maxassoc = -1;
-       apsta_params->if_info[IF_VIF].channel = 1;
-
-       if (!strlen(apsta_params->if_info[IF_VIF2].ifname))
-               strcpy(apsta_params->if_info[IF_VIF2].ifname, "wlan2");
-       strcpy(apsta_params->if_info[IF_VIF2].ssid, "tttv2");
-       apsta_params->if_info[IF_VIF2].maxassoc = -1;
-       apsta_params->if_info[IF_VIF2].channel = 161;
+       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;
+                       cur_if->ifstate = IF_STATE_INIT;
+                       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;
+                       cur_if->ifstate = IF_STATE_INIT;
+                       cur_if->prio = PRIO_AP;
+                       cur_if->prefix = 'A';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_ap");
+               } else if (cur_if->ifmode == IMESH_MODE) {
+                       cur_if->channel = 1;
+                       cur_if->maxassoc = -1;
+                       cur_if->ifstate = IF_STATE_INIT;
+                       cur_if->prio = PRIO_MESH;
+                       cur_if->prefix = 'M';
+                       snprintf(cur_if->ssid, DOT11_MAX_SSID_LEN, "ttt_mesh");
+               }
+       }
 
        apsta_params->init = TRUE;
 
@@ -2095,6 +2681,7 @@ wl_ext_iapsta_alive_postinit(struct net_device *dev)
        return op_mode;
 }
 
+#if defined(WL_WIRELESS_EXT)
 static bool
 wl_ext_conn_status_str(uint32 event_type,
        uint32 status, uint32 reason, char* stringBuf, uint buflen)
@@ -2136,17 +2723,17 @@ wl_ext_conn_status_str(uint32 event_type,
 
        return FALSE;
 }
+#endif /* WL_WIRELESS_EXT */
 
 int
 wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
        struct wl_if_info *cur_if = NULL;
-       char extra[IW_CUSTOM_MAX + 1];
        int i;
 #if defined(WL_WIRELESS_EXT)
+       char extra[IW_CUSTOM_MAX + 1];
        union iwreq_data wrqu;
-       int cmd = 0;
 #endif
        uint32 event_type = ntoh32(e->event_type);
        uint32 status =  ntoh32(e->status);
@@ -2159,7 +2746,7 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data)
        }
 
        for (i=0; i<MAX_IF_NUM; i++) {
-               if (apsta_params->if_info[i].bssidx == e->ifidx) {
+               if (apsta_params->if_info[i].ifidx == e->ifidx) {
                        cur_if = &apsta_params->if_info[i];
                        break;
                }
@@ -2170,138 +2757,166 @@ wl_ext_iapsta_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                return -1;
        }
 
-       memset(extra, 0, sizeof(extra));
-#if defined(WL_WIRELESS_EXT)
-       memset(&wrqu, 0, sizeof(wrqu));
-       memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
-       wrqu.addr.sa_family = ARPHRD_ETHER;
-#endif
-
        if (cur_if->ifmode == ISTA_MODE) {
-               switch (event_type) {
-                       case WLC_E_LINK:
-                               if (!(flags & WLC_EVENT_MSG_LINK)) {
-                                       printf("%s: %s Link Down with BSSID="MACSTR"\n", __FUNCTION__,
-                                               cur_if->ifname, MAC2STR((u8 *)&e->addr));
-                               } else {
-                                       printf("%s: %s Link UP with BSSID="MACSTR"\n", __FUNCTION__,
-                                               cur_if->ifname, MAC2STR((u8 *)&e->addr));
-                               }
-                               break;
-                       default:
-                               /* Cannot translate event */
-                               break;
+               if (event_type == WLC_E_LINK) {
+                       if (!(flags & WLC_EVENT_MSG_LINK)) {
+                               printf("%s: %s[%c] Link Down with %pM\n", __FUNCTION__,
+                                       cur_if->ifname, cur_if->prefix, &e->addr);
+                       } else {
+                               printf("%s: %s[%c] Link UP with %pM\n", __FUNCTION__,
+                                       cur_if->ifname, cur_if->prefix, &e->addr);
+                       }
                }
-       } else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
-               if (((event_type == WLC_E_ASSOC_IND) || (event_type == WLC_E_REASSOC_IND)) &&
-                       reason == DOT11_SC_SUCCESS) {
-                       printf("%s: %s connected device "MACDBG"\n", __FUNCTION__,
-                               cur_if->ifname, MAC2STRDBG(e->addr.octet));
+       }
+       else if (cur_if->ifmode == IAP_MODE || cur_if->ifmode == IMESH_MODE) {
+               if ((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)) {
+                       printf("%s: %s[%c] Link up\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix);
+               } 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)) {
+                       printf("%s: %s[%c] Link down\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix);
+               }
+               else if ((event_type == WLC_E_ASSOC_IND || event_type == WLC_E_REASSOC_IND) &&
+                               reason == DOT11_SC_SUCCESS) {
+                       printf("%s: %s[%c] connected device %pM\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix, &e->addr);
                } else if (event_type == WLC_E_DISASSOC_IND) {
-                       printf("%s: %s disassociated device "MACDBG"\n", __FUNCTION__,
-                               cur_if->ifname, MAC2STRDBG(e->addr.octet));
-               } else if ((event_type == WLC_E_DEAUTH_IND) ||
-                       ((event_type == WLC_E_DEAUTH) && (reason != DOT11_RC_RESERVED))) {
-                       printf("%s: %s deauthenticated device "MACDBG"\n", __FUNCTION__,
-                               cur_if->ifname, MAC2STRDBG(e->addr.octet));
-               } else {
-                       ANDROID_TRACE(("%s: %s event %d "MACDBG"\n", __FUNCTION__,
-                               cur_if->ifname, event_type, MAC2STRDBG(e->addr.octet)));
+                       printf("%s: %s[%c] disassociated device %pM\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix, &e->addr);
+               } else if (event_type == WLC_E_DEAUTH_IND ||
+                               (event_type == WLC_E_DEAUTH && reason != DOT11_RC_RESERVED)) {
+                       printf("%s: %s[%c] deauthenticated device %pM\n", __FUNCTION__,
+                               cur_if->ifname, cur_if->prefix, &e->addr);
                }
        }
 
-       if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) {
 #if defined(WL_WIRELESS_EXT)
-               cmd = IWEVCUSTOM;
+       memset(extra, 0, sizeof(extra));
+       memset(&wrqu, 0, sizeof(wrqu));
+       memcpy(wrqu.addr.sa_data, &e->addr, ETHER_ADDR_LEN);
+       wrqu.addr.sa_family = ARPHRD_ETHER;
+       if (wl_ext_conn_status_str(event_type, status, reason, extra, sizeof(extra))) {
                wrqu.data.length = strlen(extra);
-               wireless_send_event(cur_if->dev, cmd, &wrqu, extra);
+               wireless_send_event(cur_if->dev, IWEVCUSTOM, &wrqu, extra);
+               ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d sent up\n",
+                       __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status,
+                       reason, flags));
+       } else
 #endif /* WL_WIRELESS_EXT */
-               ANDROID_TRACE(("%s: %s event=%d, status=%d, reason=%d sent up\n", __FUNCTION__,
-                       cur_if->ifname, event_type, status, reason));
-       } else {
-               ANDROID_TRACE(("%s: %s event=%d, status=%d, reason=%d\n", __FUNCTION__,
-                       cur_if->ifname, event_type, status, reason));
+       {
+               ANDROID_INFO(("%s: %s[%c] event=%d, status=%d, reason=%d, flags=%d\n",
+                       __FUNCTION__, cur_if->ifname, cur_if->prefix, event_type, status,
+                       reason, flags));
        }
 
        return 0;
 }
 
-void
-wl_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel)
+u32
+wl_ext_iapsta_update_channel(struct net_device *dev, u32 channel)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
-       struct wl_if_info *cur_if = NULL;
+       struct wl_if_info *cur_if = NULL, *tmp_if = NULL;
        int i;
 
        for (i=0; i<MAX_IF_NUM; i++) {
-               if (apsta_params->if_info[i].dev == dev) {
-                       cur_if = &apsta_params->if_info[i];
-                       cur_if->channel = channel;
-                       wl_ext_iapsta_change_other_iface_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+               tmp_if = &apsta_params->if_info[i];
+               if (tmp_if->dev && tmp_if->dev == dev) {
+                       cur_if = tmp_if;
+                       break;
                }
        }
 
+       if (cur_if) {
+               wl_ext_isam_status(cur_if->dev);
+               cur_if->channel = channel;
+               channel = wl_ext_move_cur_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+               if (channel)
+                       wl_ext_move_other_channel(apsta_params->if_info[IF_PIF].dev, cur_if);
+       }
+
+       return channel;
 }
 
 int
-wl_ext_iapsta_attach_name(struct net_device *net, uint8 bssidx)
+wl_ext_iapsta_attach_name(struct net_device *net, int ifidx)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
+       struct dhd_pub *dhd;
+       struct wl_if_info *cur_if = NULL;
 
-       ANDROID_TRACE(("%s: bssidx=%d, %s\n", __FUNCTION__, bssidx, net->name));
-       if (bssidx == 1 && apsta_params->if_info[IF_VIF].ifstate == IF_STATE_INIT) {
-               strcpy(apsta_params->if_info[IF_VIF].ifname, net->name);
-       } else if (bssidx == 2 && apsta_params->if_info[IF_VIF2].ifstate == IF_STATE_INIT) {
-               strcpy(apsta_params->if_info[IF_VIF2].ifname, net->name);
+       dhd = dhd_get_pub(net);
+
+       ANDROID_TRACE(("%s: ifidx=%d, %s\n", __FUNCTION__, ifidx, net->name));
+       if (ifidx < MAX_IF_NUM) {
+               cur_if = &apsta_params->if_info[ifidx];
+       }
+       if (ifidx == 0) {
+               if (dhd->conf->fw_type == FW_TYPE_MESH) {
+                       apsta_params->rsdb = TRUE;
+                       apsta_params->csa = CSA_FW_BIT | CSA_DRV_BIT;
+               }
+               strcpy(cur_if->ifname, net->name);
+       } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) {
+               strcpy(cur_if->ifname, net->name);
+               apsta_params->netif_change = TRUE;
+               wake_up_interruptible(&apsta_params->netif_change_event);
        }
 
        return 0;
 }
 
 int
-wl_ext_iapsta_attach_netdev(struct net_device *net, uint8 bssidx)
+wl_ext_iapsta_attach_netdev(struct net_device *net, int ifidx, uint8 bssidx)
 {
        struct wl_apsta_params *apsta_params = &g_apsta_params;
+       struct dhd_pub *dhd;
+       struct wl_if_info *cur_if = NULL, *primary_if;
 
-       printf("%s: bssidx=%d\n", __FUNCTION__, bssidx);
-       if (bssidx == 0) {
+       dhd = dhd_get_pub(net);
+
+       printf("%s: ifidx=%d, bssidx=%d\n", __FUNCTION__, ifidx, bssidx);
+       if (ifidx < MAX_IF_NUM) {
+               cur_if = &apsta_params->if_info[ifidx];
+       }
+       if (ifidx == 0) {
                memset(apsta_params, 0, sizeof(struct wl_apsta_params));
                apsta_params->vsdb = FALSE;
-               apsta_params->if_info[IF_PIF].dev = net;
-               apsta_params->if_info[IF_PIF].bssidx = bssidx;
-               strcpy(apsta_params->if_info[IF_PIF].ifname, net->name);
+               cur_if->dev = net;
+               cur_if->ifidx = ifidx;
+               cur_if->bssidx = bssidx;
+               strcpy(cur_if->ifname, net->name);
                init_waitqueue_head(&apsta_params->netif_change_event);
-       } else if (bssidx == 1 && apsta_params->if_info[IF_VIF].ifstate == IF_STATE_INIT) {
-               apsta_params->if_info[IF_VIF].dev = net;
-               apsta_params->if_info[IF_VIF].bssidx = bssidx;
-               if (strlen(apsta_params->if_info[IF_VIF].ifname)) {
+       } else if (cur_if && cur_if->ifstate == IF_STATE_INIT) {
+               primary_if = &apsta_params->if_info[IF_PIF];
+               cur_if->dev = net;
+               cur_if->ifidx = ifidx;
+               cur_if->bssidx = bssidx;
+               if (strlen(cur_if->ifname)) {
                        memset(net->name, 0, sizeof(IFNAMSIZ));
-                       strcpy(net->name, apsta_params->if_info[IF_VIF].ifname);
+                       strcpy(net->name, cur_if->ifname);
                        net->name[IFNAMSIZ-1] = '\0';
                }
-               if (apsta_params->if_info[IF_PIF].dev) {
-                       memcpy(net->dev_addr, apsta_params->if_info[IF_PIF].dev->dev_addr, ETHER_ADDR_LEN);
+               if (apsta_params->apstamode != ISTAAPAP_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);
+                       }
                }
-               apsta_params->netif_change = TRUE;
-               wake_up_interruptible(&apsta_params->netif_change_event);
-       } else if (bssidx == 2 && apsta_params->if_info[IF_VIF2].ifstate == IF_STATE_INIT) {
-               apsta_params->if_info[IF_VIF2].dev = net;
-               apsta_params->if_info[IF_VIF2].bssidx = bssidx;
-               if (strlen(apsta_params->if_info[IF_VIF2].ifname)) {
-                       memset(net->name, 0, sizeof(IFNAMSIZ));
-                       strcpy(net->name, apsta_params->if_info[IF_VIF2].ifname);
-                       net->name[IFNAMSIZ-1] = '\0';
-               }
-               if (apsta_params->if_info[IF_PIF].dev) {
-                       memcpy(net->dev_addr, apsta_params->if_info[IF_PIF].dev->dev_addr, ETHER_ADDR_LEN);
-                       net->dev_addr[0] |= 0x02;
-                       net->dev_addr[4] ^= 0x80;
-                       net->dev_addr[4] += bssidx;
-                       net->dev_addr[5] += bssidx;
+               if (cur_if->ifmode == ISTA_MODE) {
+                       wl_ext_iovar_setint(net, "roam_off", dhd->conf->roam_off);
+                       wl_ext_iovar_setint(net, "bcn_timeout", dhd->conf->bcn_timeout);
+               } else if (cur_if->ifmode == IMESH_MODE) {
+                       int pm = 0;
+                       wl_ext_ioctl(net, WLC_SET_PM, &pm, sizeof(pm), 1);
                }
-               apsta_params->netif_change = TRUE;
-               wake_up_interruptible(&apsta_params->netif_change_event);
        }
 
        return 0;
@@ -2367,7 +2982,6 @@ wl_ext_dhcpc_enable(struct net_device *dev, char *command, int total_len)
 int
 wl_ext_dhcpc_dump(struct net_device *dev, char *command, int total_len)
 {
-
        int ret = 0;
        int bytes_written = 0;
        uint32 ip_addr;
@@ -2469,8 +3083,8 @@ wl_ext_iovar(struct net_device *dev, char *command, int total_len)
        return ret;
 }
 
-int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
-               int *bytes_written)
+int wl_android_ext_priv_cmd(struct net_device *net, char *command,
+       int total_len, int *bytes_written)
 {
        int ret = 0;
 
@@ -2522,6 +3136,9 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len
        else if (strnicmp(command, CMD_ISAM_DISABLE, strlen(CMD_ISAM_DISABLE)) == 0) {
                *bytes_written = wl_ext_iapsta_disable(net, command, total_len);
        }
+       else if (strnicmp(command, CMD_ISAM_STATUS, strlen(CMD_ISAM_STATUS)) == 0) {
+               *bytes_written = wl_ext_isam_status(net);
+       }
 #endif
 #ifdef IDHCP
        else if (strnicmp(command, CMD_DHCPC_ENABLE, strlen(CMD_DHCPC_ENABLE)) == 0) {
@@ -2530,6 +3147,16 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len
        else if (strnicmp(command, CMD_DHCPC_DUMP, strlen(CMD_DHCPC_DUMP)) == 0) {
                *bytes_written = wl_ext_dhcpc_dump(net, command, total_len);
        }
+#endif
+#ifdef WL_CFG80211
+       else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
+               *bytes_written = wl_cfg80211_autochannel(net, command, total_len);
+       }
+#endif
+#ifdef WL_ESCAN
+       else if (strnicmp(command, CMD_AUTOCHANNEL, strlen(CMD_AUTOCHANNEL)) == 0) {
+               *bytes_written = wl_escan_autochannel(net, command, total_len);
+       }
 #endif
        else if (strnicmp(command, CMD_WL, strlen(CMD_WL)) == 0) {
                *bytes_written = wl_ext_iovar(net, command, total_len);
@@ -2540,6 +3167,198 @@ int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len
        return ret;
 }
 
+#if defined(WL_CFG80211) || defined(WL_ESCAN)
+int
+wl_ext_get_distance(struct net_device *net, u32 band)
+{
+       u32 bw = WL_CHANSPEC_BW_20;
+       s32 bw_cap = 0, distance = 0;
+       struct {
+               u32 band;
+               u32 bw_cap;
+       } param = {0, 0};
+       char buf[WLC_IOCTL_SMLEN]="\0";
+       s32 err = BCME_OK;
+
+       param.band = band;
+       err = wldev_iovar_getbuf(net, "bw_cap", &param, sizeof(param), buf,
+               sizeof(buf), NULL);
+       if (err) {
+               if (err != BCME_UNSUPPORTED) {
+                       ANDROID_ERROR(("bw_cap failed, %d\n", err));
+                       return err;
+               } else {
+                       err = wl_ext_iovar_getint(net, "mimo_bw_cap", &bw_cap);
+                       if (err) {
+                               ANDROID_ERROR(("error get mimo_bw_cap (%d)\n", err));
+                       }
+                       if (bw_cap != WLC_N_BW_20ALL)
+                               bw = WL_CHANSPEC_BW_40;
+               }
+       } else {
+               if (WL_BW_CAP_80MHZ(buf[0]))
+                       bw = WL_CHANSPEC_BW_80;
+               else if (WL_BW_CAP_40MHZ(buf[0]))
+                       bw = WL_CHANSPEC_BW_40;
+               else
+                       bw = WL_CHANSPEC_BW_20;
+       }
+
+       if (bw == WL_CHANSPEC_BW_20)
+               distance = 2;
+       else if (bw == WL_CHANSPEC_BW_40)
+               distance = 4;
+       else if (bw == WL_CHANSPEC_BW_80)
+               distance = 8;
+       else
+               distance = 16;
+       ANDROID_INFO(("%s: bw=0x%x, distance=%d\n", __FUNCTION__, bw, distance));
+
+       return distance;
+}
+
+int
+wl_ext_get_best_channel(struct net_device *net,
+#if defined(BSSCACHE)
+       wl_bss_cache_ctrl_t *bss_cache_ctrl,
+#else
+       struct wl_scan_results *bss_list,
+#endif
+       int ioctl_ver, int *best_2g_ch, int *best_5g_ch
+)
+{
+       struct wl_bss_info *bi = NULL;  /* must be initialized */
+       s32 i, j;
+#if defined(BSSCACHE)
+       wl_bss_cache_t *node;
+#endif
+       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;
+
+       memset(b_band, -1, sizeof(b_band));
+       memset(a_band1, -1, sizeof(a_band1));
+       memset(a_band4, -1, sizeof(a_band4));
+
+       memset(valid_chan_list, 0, sizeof(valid_chan_list));
+       list = (wl_uint32_list_t *)(void *) valid_chan_list;
+       list->count = htod32(WL_NUMCHANNELS);
+       ret = wldev_ioctl(net, WLC_GET_VALID_CHANNELS, valid_chan_list,
+               sizeof(valid_chan_list), 0);
+       if (ret<0) {
+               ANDROID_ERROR(("%s: get channels failed with %d\n", __FUNCTION__, ret));
+               return 0;
+       } else {
+               for (i = 0; i < dtoh32(list->count); i++) {
+                       ch = dtoh32(list->element[i]);
+                       if (ch < CH_MAX_2G_CHANNEL)
+                               b_band[ch-1] = 0;
+                       else if (ch <= 48)
+                               a_band1[(ch-36)/4] = 0;
+                       else if (ch >= 149 && ch <= 161)
+                               a_band4[(ch-149)/4] = 0;
+               }
+       }
+
+       distance_2g = wl_ext_get_distance(net, WLC_BAND_2G);
+       distance_5g = wl_ext_get_distance(net, WLC_BAND_5G);
+
+#if defined(BSSCACHE)
+       node = bss_cache_ctrl->m_cache_head;
+       for (i=0; node && i<256; i++)
+#else
+       for (i=0; i < bss_list->count; i++)
+#endif
+       {
+#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
+               chanspec = wl_ext_chspec_driver_to_host(ioctl_ver, bi->chanspec);
+               cen_ch = CHSPEC_CHANNEL(bi->chanspec);
+               distance = 0;
+               if (CHSPEC_IS20(chanspec))
+                       distance += 2;
+               else if (CHSPEC_IS40(chanspec))
+                       distance += 4;
+               else if (CHSPEC_IS80(chanspec))
+                       distance += 8;
+               else
+                       distance += 16;
+
+               if (CHSPEC_IS2G(chanspec)) {
+                       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;
+                       }
+               } else {
+                       distance += distance_5g;
+                       if (cen_ch <= 48) {
+                               for (j=0; j<ARRAYSIZE(a_band1); j++) {
+                                       if (a_band1[j] >= 0 && abs(cen_ch-(36+j*4)) <= distance)
+                                               a_band1[j] += 1;
+                               }
+                       } else if (cen_ch >= 149) {
+                               for (j=0; j<ARRAYSIZE(a_band4); j++) {
+                                       if (a_band4[j] >= 0 && abs(cen_ch-(149+j*4)) <= distance)
+                                               a_band4[j] += 1;
+                               }
+                       }
+               }
+#if defined(BSSCACHE)
+               node = node->next;
+#endif
+       }
+
+       *best_2g_ch = 0;
+       min_ap = 999;
+       for (i=0; i<CH_MAX_2G_CHANNEL; i++) {
+               if(b_band[i] < min_ap && b_band[i] >= 0) {
+                       min_ap = b_band[i];
+                       *best_2g_ch = i+1;
+               }
+       }
+       *best_5g_ch = 0;
+       min_ap = 999;
+       for (i=0; i<ARRAYSIZE(a_band1); i++) {
+               if(a_band1[i] < min_ap && a_band1[i] >= 0) {
+                       min_ap = a_band1[i];
+                       *best_5g_ch = i*4 + 36;
+               }
+       }
+       for (i=0; i<ARRAYSIZE(a_band4); i++) {
+               if(a_band4[i] < min_ap && a_band4[i] >= 0) {
+                       min_ap = a_band4[i];
+                       *best_5g_ch = i*4 + 149;
+               }
+       }
+
+       if (android_msg_level&ANDROID_INFO_LEVEL) {
+               printf("%s: b_band: ", __FUNCTION__);
+               for (j=0; j<ARRAYSIZE(b_band); j++)
+                       printf("%d, ", b_band[j]);
+               printf("\n");
+               printf("%s: a_band1: ", __FUNCTION__);
+               for (j=0; j<ARRAYSIZE(a_band1); j++)
+                       printf("%d, ", a_band1[j]);
+               printf("\n");
+               printf("%s: a_band4: ", __FUNCTION__);
+               for (j=0; j<ARRAYSIZE(a_band4); j++)
+                       printf("%d, ", a_band4[j]);
+               printf("\n");
+               printf("%s: best_2g_ch=%d, best_5g_ch=%d\n", __FUNCTION__,
+                       *best_2g_ch, *best_5g_ch);
+       }
+
+       return 0;
+}
+#endif
+
 #if defined(RSSIAVG)
 void
 wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
@@ -2600,7 +3419,8 @@ wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
 }
 
 void
-wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, u8 *bssid)
+wl_delete_disconnected_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+       u8 *bssid)
 {
        wl_rssi_cache_t *node, *prev, **rssi_head;
        int i = -1, tmp = 0;
@@ -2650,13 +3470,15 @@ wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
 }
 
 int
-wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
+wl_update_connected_rssi_cache(struct net_device *net,
+       wl_rssi_cache_ctrl_t *rssi_cache_ctrl, int *rssi_avg)
 {
        wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
        int j, k=0;
        int rssi, error=0;
        struct ether_addr bssid;
        struct timeval now, timeout;
+       scb_val_t scbval;
 
        if (!g_wifi_on)
                return 0;
@@ -2669,11 +3491,12 @@ wl_update_connected_rssi_cache(struct net_device *net, wl_rssi_cache_ctrl_t *rss
        if (error) {
                ANDROID_ERROR(("Could not get bssid (%d)\n", error));
        }
-       error = wldev_get_rssi(net, &rssi);
+       error = wldev_get_rssi(net, &scbval);
        if (error) {
                ANDROID_ERROR(("Could not get rssi (%d)\n", error));
                return error;
        }
+       rssi = scbval.val;
 
        do_gettimeofday(&now);
        timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
@@ -2734,7 +3557,8 @@ exit:
 }
 
 void
-wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, wl_scan_results_t *ss_list)
+wl_update_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
+       wl_scan_results_t *ss_list)
 {
        wl_rssi_cache_t *node, *prev, *leaf, **rssi_head;
        wl_bss_info_t *bi = NULL;
@@ -2921,7 +3745,8 @@ wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
 }
 
 void
-wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl, u8 *bssid)
+wl_delete_disconnected_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
+       u8 *bssid)
 {
        wl_bss_cache_t *node, *prev, **bss_head;
        int i = -1, tmp = 0;
@@ -2987,7 +3812,8 @@ void dump_bss_cache(
                rssi = dtoh16(node->results.bss_info->RSSI);
 #endif
                ANDROID_TRACE(("%s: dump %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
-                       __FUNCTION__, k, &node->results.bss_info->BSSID, rssi, node->results.bss_info->SSID));
+                       __FUNCTION__, k, &node->results.bss_info->BSSID, rssi,
+                       node->results.bss_info->SSID));
                k++;
                node = node->next;
        }
@@ -3077,7 +3903,8 @@ wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
 #endif
                        for (;node;) {
 #if defined(RSSIAVG)
-                               rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
+                               rssi_node = wl_get_avg_rssi(rssi_cache_ctrl,
+                                       &node->results.bss_info->BSSID);
 #else
                                rssi_node = dtoh16(node->results.bss_info->RSSI);
 #endif
index d926602be66b03b6fd44e2df3280e69d2add16a2..eb4e338d138eab070ff7254970bcadd21f608787 100644 (file)
@@ -272,7 +272,7 @@ static const struct ieee80211_iface_limit common_if_limits[] = {
 #else
 #define NUM_DIFF_CHANNELS 2
 #endif
-static struct ieee80211_iface_combination
+static const struct ieee80211_iface_combination
 common_iface_combinations[] = {
        {
        .num_different_channels = NUM_DIFF_CHANNELS,
@@ -1813,7 +1813,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
                 * requests.
                 */
                if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
-                       WL_ERR(("Fw doesnot support  multiple Go"));
+                       WL_ERR(("Fw does not support multiple Go\n"));
                        err = -ENOTSUPP;
                        goto fail;
                }
@@ -1831,7 +1831,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
                cfg_type = wl_cfgp2p_get_conn_idx(cfg);
                if (cfg_type == BCME_ERROR) {
                        wl_clr_p2p_status(cfg, IF_ADDING);
-                       WL_ERR(("Failed to get connection idx for p2p interface"));
+                       WL_ERR(("Failed to get connection idx for p2p interface\n"));
                        err = -ENOTSUPP;
                        goto fail;
                }
@@ -2296,7 +2296,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev,
                         */
                        if ((cfg->p2p->p2p_go_count > 0) && (type == NL80211_IFTYPE_P2P_GO)) {
                                wl_set_mode_by_netdev(cfg, ndev, WL_MODE_BSS);
-                               WL_ERR(("Fw doesnot support  multiple GO "));
+                               WL_ERR(("Fw does not support multiple GO\n"));
                                err = BCME_ERROR;
                                goto error;
                        }
@@ -3323,6 +3323,53 @@ scan_out:
        return err;
 }
 
+void
+wl_cfg80211_4way_start(struct bcm_cfg80211 *cfg, struct net_device *dev)
+{
+       dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
+       struct wl_security *sec;
+       s32 bssidx = -1;
+
+       bssidx = wl_get_bssidx_by_wdev(cfg, dev->ieee80211_ptr);
+
+       sec = wl_read_prof(cfg, dev, WL_PROF_SEC);
+       if ((sec->wpa_versions & (NL80211_WPA_VERSION_1 | NL80211_WPA_VERSION_2)) &&
+                       bssidx == 0 && dhdp->conf->in4way) {
+               WL_DBG(("Enter in4way=0x%x\n", dhdp->conf->in4way));
+               cfg->handshaking = 1;
+               if (dhdp->conf->in4way & NO_BTC_IN4WAY)
+                       wldev_iovar_setint(dev, "btc_mode", 0);
+       }
+}
+
+void
+wl_cfg80211_4way_exit(struct bcm_cfg80211 *cfg, struct net_device *dev)
+{
+       dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
+
+       if (cfg->handshaking) {
+               WL_DBG(("Enter in4way=0x%x\n", dhdp->conf->in4way));
+               if (dhdp->conf->in4way & NO_BTC_IN4WAY)
+                       wldev_iovar_setint(dev, "btc_mode", 1);
+               cfg->handshaking = 0;
+       }
+}
+
+s32
+wl_cfg80211_4way_check(struct bcm_cfg80211 *cfg, uint mode)
+{
+       dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
+
+       if (cfg->handshaking && (dhdp->conf->in4way & mode)) {
+               if (mode & NO_SCAN_IN4WAY && cfg->handshaking <= 3) {
+                       WL_ERR(("%s: return -EBUSY cnt %d\n", __FUNCTION__, cfg->handshaking));
+                       cfg->handshaking++;
+                       return -EBUSY;
+               }
+       }
+       return 0;
+}
+
 static s32
 #if defined(WL_CFG80211_P2P_DEV_IF)
 wl_cfg80211_scan(struct wiphy *wiphy, struct cfg80211_scan_request *request)
@@ -3354,6 +3401,9 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                         return -ENODEV;
                }
        }
+       err = wl_cfg80211_4way_check(cfg, NO_SCAN_IN4WAY);
+       if (err)
+               return err;
 
        mutex_lock(&cfg->usr_sync);
        err = __wl_cfg80211_scan(wiphy, ndev, request, NULL);
@@ -3856,7 +3906,8 @@ wl_customer6_legacy_chip_check(struct bcm_cfg80211 *cfg,
                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 == BCM4345_CHIP_ID) || (chipnum == BCM43430_CHIP_ID) ||
+               (chipnum == BCM43362_CHIP_ID)) {
                /* WAR required */
                return true;
        }
@@ -3868,7 +3919,27 @@ void
 wl_bss_iovar_war(struct bcm_cfg80211 *cfg,
        struct net_device *ndev, s32 *val)
 {
-       if (wl_customer6_legacy_chip_check(cfg, ndev)) {
+       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.
                 */
@@ -4138,8 +4209,8 @@ wl_cfg80211_post_ifcreate(struct net_device *ndev,
                        addr, ETH_ALEN, cfg->ioctl_buf, WLC_IOCTL_MAXLEN,
                        event->bssidx, &cfg->ioctl_buf_sync);
                if (unlikely(ret)) {
-                               WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
-                               goto fail;
+                       WL_ERR(("set cur_etheraddr Error (%d)\n", ret));
+                       goto fail;
                }
                memcpy(new_ndev->dev_addr, addr, ETH_ALEN);
                WL_ERR(("Applying updated mac address to firmware\n"));
@@ -5633,7 +5704,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        DHD_DISABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
 #endif /* BCMDONGLEHOST && CUSTOMER_HW2 */
 #ifdef WL_EXT_IAPSTA
-       wl_ext_iapsta_disconnect_sta(dev, cfg->channel);
+       wl_ext_iapsta_update_channel(dev, cfg->channel);
 #endif
        err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size,
                cfg->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &cfg->ioctl_buf_sync);
@@ -5691,6 +5762,8 @@ exit:
                WL_ERR(("error (%d)\n", err));
                wl_clr_drv_status(cfg, CONNECTING, dev);
        }
+       if (!err)
+               wl_cfg80211_4way_start(cfg, dev);
 
 #ifdef WLTDLS
        /* disable TDLS if number of connected interfaces is >= 1 */
@@ -6025,7 +6098,6 @@ wl_cfg80211_interface_create(struct net_device *dev, char *name)
 {
        struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
        bcm_struct_cfgdev *new_cfgdev;
-#ifdef WLMESH
        char ifname[IFNAMSIZ];
        char iftype[IFNAMSIZ];
        enum nl80211_iftype iface_type = NL80211_IFTYPE_STATION;
@@ -6035,14 +6107,9 @@ wl_cfg80211_interface_create(struct net_device *dev, char *name)
        if (strnicmp(iftype, "AP", strlen("AP")) == 0) {
                iface_type = NL80211_IFTYPE_AP;
        }
-#endif
 
        new_cfgdev = wl_cfg80211_create_iface(cfg->wdev->wiphy,
-#ifdef WLMESH
                iface_type, NULL, ifname);
-#else
-               NL80211_IFTYPE_STATION, NULL, name);
-#endif
        if (!new_cfgdev) {
                return BCME_ERROR;
        }
@@ -6141,6 +6208,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
        s32 bssidx = 0;
        struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
        s32 mode = wl_get_mode_by_netdev(cfg, dev);
+
        WL_DBG(("key index (%d)\n", key_idx));
        RETURN_EIO_IF_NOT_UP(cfg);
 
@@ -6148,6 +6216,7 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev,
                WL_ERR(("Find p2p index from dev(%p) failed\n", dev->ieee80211_ptr));
                return BCME_ERROR;
        }
+       wl_cfg80211_4way_exit(cfg, dev);
 
        if (mac_addr &&
                ((params->cipher != WLAN_CIPHER_SUITE_WEP40) &&
@@ -6373,14 +6442,6 @@ wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy,
 #endif /* MFP */
 }
 
-#if defined(RSSIAVG)
-static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
-static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
-#endif
-#if defined(BSSCACHE)
-static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
-#endif
-
 static s32
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 16, 0))
 wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
@@ -6538,13 +6599,13 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev,
                }
                rssi = dtoh32(scb_val.val);
 #if defined(RSSIAVG)
-               err = wl_update_connected_rssi_cache(dev, &g_connected_rssi_cache_ctrl, &rssi);
+               err = wl_update_connected_rssi_cache(dev, &cfg->g_connected_rssi_cache_ctrl, &rssi);
                if (err) {
                        WL_ERR(("Could not get rssi (%d)\n", err));
                        goto get_station_err;
                }
-               wl_delete_dirty_rssi_cache(&g_connected_rssi_cache_ctrl);
-               wl_reset_rssi_cache(&g_connected_rssi_cache_ctrl);
+               wl_delete_dirty_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
+               wl_reset_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
 #endif
 #if defined(RSSIOFFSET)
                rssi = wl_update_rssi_offset(dev, rssi);
@@ -8045,6 +8106,9 @@ 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(dev, _chan);
+#endif
        printf("%s: netdev_ifidx(%d), chan_type(%d) target channel(%d) \n",
                __FUNCTION__, dev->ifindex, channel_type, _chan);
 
@@ -9235,7 +9299,7 @@ ssid_retry:
                /* create softap */
                if ((err = wldev_ioctl_set(dev, WLC_SET_SSID, &join_params,
                        join_params_size)) != 0) {
-                       WL_ERR(("SoftAP/GO set ssid failed! \n"));
+                       WL_ERR(("SoftAP/GO set ssid failed! %d\n", err));
                        goto exit;
                } else {
                        WL_DBG((" SoftAP SSID \"%s\" \n", join_params.ssid.SSID));
@@ -9545,7 +9609,9 @@ wl_cfg80211_del_station(
        } else {
 #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 19, 0)) */
 #endif /* CUSTOM_BLOCK_DEAUTH_AT_EAP_FAILURE */
-//     dhd_wait_pend8021x(dev);
+#ifndef BCMDBUS
+       dhd_wait_pend8021x(dev);
+#endif /* !BCMDBUS */
        scb_val.val = DOT11_RC_DEAUTH_LEAVING;
        err = wldev_ioctl_set(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val,
                sizeof(scb_val_t));
@@ -9936,6 +10002,10 @@ wl_cfg80211_stop_ap(
 #endif /* ARP_OFFLOAD_SUPPORT */
 
                if (is_rsdb_supported == 0) {
+                       if (dhd_download_fw_on_driverload && bssidx == 0) {
+                               wldev_ioctl_set(dev, WLC_DOWN, &ap, sizeof(s32));
+                               wldev_iovar_setint(dev, "apsta", 1);
+                       }
                        /* For non-rsdb chips, we use stand alone AP. Do wl down on stop AP */
                        err = wldev_ioctl_set(dev, WLC_UP, &ap, sizeof(s32));
                        if (unlikely(err)) {
@@ -10897,10 +10967,6 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0)) && \
        (defined(WL_IFACE_COMB_NUM_CHANNELS) || defined(WL_CFG80211_P2P_DEV_IF))
        WL_DBG(("Setting interface combinations for common mode\n"));
-#ifndef BCMDBUS
-       if (dhd->conf->num_different_channels >= 0)
-               common_iface_combinations[0].num_different_channels = dhd->conf->num_different_channels;
-#endif /* !BCMDBUS */
        wdev->wiphy->iface_combinations = common_iface_combinations;
        wdev->wiphy->n_iface_combinations =
                ARRAY_SIZE(common_iface_combinations);
@@ -11088,8 +11154,8 @@ static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
        struct wl_bss_info *bi = NULL;  /* must be initialized */
        s32 err = 0;
        s32 i;
-#if defined(RSSIAVG)
        struct net_device *ndev = bcmcfg_to_prmry_ndev(cfg);
+#if defined(RSSIAVG)
        int rssi;
 #endif
 #if defined(BSSCACHE)
@@ -11101,18 +11167,18 @@ static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
        /* Free cache in p2p scanning*/
        if (p2p_is_on(cfg) && p2p_scan(cfg)) {
 #if defined(RSSIAVG)
-               wl_free_rssi_cache(&g_rssi_cache_ctrl);
+               wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-               wl_free_bss_cache(&g_bss_cache_ctrl);
+               wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
 #endif
        }
 
        /* Delete disconnected cache */
 #if defined(BSSCACHE)
-       wl_delete_disconnected_bss_cache(&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(&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);
@@ -11120,43 +11186,46 @@ static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
 
        /* Update cache */
 #if defined(RSSIAVG)
-       wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
+       wl_update_rssi_cache(&cfg->g_rssi_cache_ctrl, bss_list);
        if (!in_atomic())
-               wl_update_connected_rssi_cache(ndev, &g_rssi_cache_ctrl, &rssi);
+               wl_update_connected_rssi_cache(ndev, &cfg->g_rssi_cache_ctrl, &rssi);
 #endif
 #if defined(BSSCACHE)
-       wl_update_bss_cache(&g_bss_cache_ctrl,
+       wl_update_bss_cache(&cfg->g_bss_cache_ctrl,
 #if defined(RSSIAVG)
-               &g_rssi_cache_ctrl,
+               &cfg->g_rssi_cache_ctrl,
 #endif
                bss_list);
 #endif
 
        /* delete dirty cache */
 #if defined(RSSIAVG)
-       wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
-       wl_reset_rssi_cache(&g_rssi_cache_ctrl);
+       wl_delete_dirty_rssi_cache(&cfg->g_rssi_cache_ctrl);
+       wl_reset_rssi_cache(&cfg->g_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-       wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
-       wl_reset_bss_cache(&g_bss_cache_ctrl);
+       wl_delete_dirty_bss_cache(&cfg->g_bss_cache_ctrl);
+       wl_reset_bss_cache(&cfg->g_bss_cache_ctrl);
 #endif
 
 #if defined(BSSCACHE)
        if (cfg->p2p_disconnected > 0) {
                // terence 20130703: Fix for wrong group_capab (timing issue)
-               wl_delete_disconnected_bss_cache(&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(&g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
+               wl_delete_disconnected_rssi_cache(&cfg->g_rssi_cache_ctrl, (u8*)&cfg->disconnected_bssid);
 #endif
        }
        WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
-       node = g_bss_cache_ctrl.m_cache_head;
+       node = cfg->g_bss_cache_ctrl.m_cache_head;
        for (i=0; node && i<WL_AP_MAX; i++) {
                bi = node->results.bss_info;
                err = wl_inform_single_bss(cfg, bi, false);
                node = node->next;
        }
+       if (cfg->autochannel)
+               wl_ext_get_best_channel(ndev, &cfg->g_bss_cache_ctrl, ioctl_version,
+                       &cfg->best_2g_ch, &cfg->best_5g_ch);
 #else
        WL_SCAN(("scanned AP count (%d)\n", bss_list->count));
        preempt_disable();
@@ -11167,6 +11236,9 @@ static s32 wl_inform_bss(struct bcm_cfg80211 *cfg)
                err = wl_inform_single_bss(cfg, bi, false);
        }
        preempt_enable();
+       if (cfg->autochannel)
+               wl_ext_get_best_channel(ndev, bss_list, ioctl_version,
+                       &cfg->best_2g_ch, &cfg->best_5g_ch);
 #endif
 
        if (cfg->p2p_disconnected > 0) {
@@ -11201,6 +11273,7 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi
        u32 freq;
        s32 err = 0;
        gfp_t aflags;
+       chanspec_t chanspec;
 
        if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) {
                WL_DBG(("Beacon is larger than buffer. Discarding\n"));
@@ -11214,8 +11287,8 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi
                return -ENOMEM;
        }
        mgmt = (struct ieee80211_mgmt *)notif_bss_info->frame_buf;
-       notif_bss_info->channel =
-               wf_chspec_ctlchan(wl_chspec_driver_to_host(bi->chanspec));
+       chanspec = wl_chspec_driver_to_host(bi->chanspec);
+       notif_bss_info->channel = wf_chspec_ctlchan(chanspec);
 
        if (notif_bss_info->channel <= CH_MAX_2G_CHANNEL)
                band = wiphy->bands[IEEE80211_BAND_2GHZ];
@@ -11228,7 +11301,7 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi
        }
        notif_bss_info->rssi = dtoh16(bi->RSSI);
 #if defined(RSSIAVG)
-       notif_bss_info->rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
+       notif_bss_info->rssi = wl_get_avg_rssi(&cfg->g_rssi_cache_ctrl, &bi->BSSID);
        if (notif_bss_info->rssi == RSSI_MINVAL)
                notif_bss_info->rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
 #endif
@@ -11270,8 +11343,12 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi
                return -EINVAL;
        }
        channel = ieee80211_get_channel(wiphy, freq);
-       WL_SCAN(("BSSID %pM, channel %2d, rssi %3d, capa 0x04%x, mgmt_type %d, "
-               "frame_len %d, SSID \"%s\"\n", &bi->BSSID, notif_bss_info->channel,
+       WL_SCAN(("BSSID %pM, channel %2d(%2d %sMHz), rssi %3d, capa 0x04%x, mgmt_type %d, "
+               "frame_len %d, SSID \"%s\"\n",
+               &bi->BSSID, notif_bss_info->channel, CHSPEC_CHANNEL(chanspec),
+               CHSPEC_IS20(chanspec)?"20":
+               CHSPEC_IS40(chanspec)?"40":
+               CHSPEC_IS80(chanspec)?"80":"160",
                notif_bss_info->rssi, mgmt->u.beacon.capab_info, mgmt_type,
                notif_bss_info->frame_len, bi->SSID));
        if (unlikely(!channel)) {
@@ -12290,6 +12367,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                        "event : %d, reason=%d from " MACDBG "\n",
                                        ndev->name, event, ntoh32(e->reason),
                                        MAC2STRDBG((const u8*)(&e->addr)));
+                               wl_cfg80211_4way_exit(cfg, ndev);
 
                                /* roam offload does not sync BSSID always, get it from dongle */
                                if (cfg->roam_offload) {
@@ -12396,6 +12474,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                        }
                        else if (wl_get_drv_status(cfg, CONNECTING, ndev)) {
                                printf("link down, during connecting\n");
+                               wl_cfg80211_4way_exit(cfg, ndev);
                                /* Issue WLC_DISASSOC to prevent FW roam attempts */
                                err = wldev_ioctl_set(ndev, WLC_DISASSOC, NULL, 0);
                                if (err < 0) {
@@ -12426,6 +12505,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                } else if (wl_is_nonetwork(cfg, e)) {
                        printf("connect failed event=%d e->status %d e->reason %d \n",
                                event, (int)ntoh32(e->status), (int)ntoh32(e->reason));
+                       wl_cfg80211_4way_exit(cfg, ndev);
 #if defined(DHD_ENABLE_BIGDATA_LOGGING)
                        if (event == WLC_E_SET_SSID) {
                                wl_get_connect_failed_status(cfg, e);
@@ -12450,8 +12530,10 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                }
                DHD_ENABLE_RUNTIME_PM((dhd_pub_t *)cfg->pub);
        }
-               else {
-               WL_ERR(("Invalid ndev status %d\n", wl_get_mode_by_netdev(cfg, ndev)));
+       else {
+               printf("wl_notify_connect_status : Invalid %s mode %d event %d status %d\n",
+                       ndev->name, wl_get_mode_by_netdev(cfg, ndev), ntoh32(e->event_type),
+                       ntoh32(e->status));
        }
        return err;
 }
@@ -13299,8 +13381,10 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                if (completed) {
                        WL_INFORM(("Report connect result - connection succeeded\n"));
                        dhd_conf_set_wme(cfg->pub, 0);
-               } else
+               } else {
                        WL_ERR(("Report connect result - connection failed\n"));
+                       wl_cfg80211_4way_exit(cfg, ndev);
+               }
        }
 #ifdef CONFIG_TCPACK_FASTTX
        if (wl_get_chan_isvht80(ndev, dhdp))
@@ -14447,10 +14531,20 @@ void wl_terminate_event_handler(struct net_device *dev)
        }
 }
 
-static void wl_scan_timeout(unsigned long data)
+static void wl_scan_timeout(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       unsigned long data
+#endif
+)
 {
        wl_event_msg_t msg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct bcm_cfg80211 *cfg = from_timer(cfg, t, scan_timeout);
+#else
        struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
+#endif
        struct wireless_dev *wdev = NULL;
        struct net_device *ndev = NULL;
        struct wl_scan_results *bss_list;
@@ -14541,9 +14635,19 @@ static void wl_del_roam_timeout(struct bcm_cfg80211 *cfg)
 
 }
 
-static void wl_roam_timeout(unsigned long data)
+static void wl_roam_timeout(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       unsigned long data
+#endif
+)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct bcm_cfg80211 *cfg = from_timer(cfg, t, roam_timeout);
+#else
        struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *)data;
+#endif
        dhd_pub_t *dhdp = (dhd_pub_t *)(cfg->pub);
 
        WL_ERR(("roam timer expired\n"));
@@ -15573,6 +15677,7 @@ static s32 wl_notifier_change_state(struct bcm_cfg80211 *cfg, struct net_info *_
        }
        return err;
 }
+
 static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
 {
        int err = 0;
@@ -15582,9 +15687,13 @@ static s32 wl_init_scan(struct bcm_cfg80211 *cfg)
        wl_escan_init_sync_id(cfg);
 
        /* Init scan_timeout timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&cfg->scan_timeout, wl_scan_timeout, 0);
+#else
        init_timer(&cfg->scan_timeout);
        cfg->scan_timeout.data = (unsigned long) cfg;
        cfg->scan_timeout.function = wl_scan_timeout;
+#endif
 
        return err;
 }
@@ -15595,9 +15704,13 @@ static s32 wl_init_roam_timeout(struct bcm_cfg80211 *cfg)
        int err = 0;
 
        /* Init roam timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&cfg->roam_timeout, wl_roam_timeout, 0);
+#else
        init_timer(&cfg->roam_timeout);
        cfg->roam_timeout.data = (unsigned long) cfg;
        cfg->roam_timeout.function = wl_roam_timeout;
+#endif
 
        return err;
 }
@@ -15949,14 +16062,14 @@ void wl_cfg80211_detach(struct bcm_cfg80211 *cfg)
        wl_cfg80211_clear_mgmt_vndr_ies(cfg);
        wl_deinit_priv(cfg);
        wl_cfg80211_clear_parent_dev();
-       wl_free_wdev(cfg);
 #if defined(RSSIAVG)
-       wl_free_rssi_cache(&g_rssi_cache_ctrl);
-       wl_free_rssi_cache(&g_connected_rssi_cache_ctrl);
+       wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
+       wl_free_rssi_cache(&cfg->g_connected_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-       wl_release_bss_cache_ctrl(&g_bss_cache_ctrl);
+       wl_release_bss_cache_ctrl(&cfg->g_bss_cache_ctrl);
 #endif
+       wl_free_wdev(cfg);
        /* PLEASE do NOT call any function after wl_free_wdev, the driver's private
         * structure "cfg", which is the private part of wiphy, has been freed in
         * wl_free_wdev !!!!!!!!!!!
@@ -16896,11 +17009,10 @@ _Pragma("GCC diagnostic pop")
        }
 
        wl_flush_eq(cfg);
-
        if (cfg->link_up) { //army fix wifi stop call trace issue
-               CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
-                wl_link_down(cfg);
-        }
+               CFG80211_DISCONNECTED(ndev, 0, NULL, 0, false, GFP_KERNEL);
+               wl_link_down(cfg);
+       }
        if (cfg->p2p_supported) {
                if (timer_pending(&cfg->p2p->listen_timer))
                        del_timer_sync(&cfg->p2p->listen_timer);
@@ -16971,6 +17083,7 @@ s32 wl_cfg80211_up(struct net_device *net)
                return BCME_VERSION;
        }
        ioctl_version = val;
+       wl_cfg80211_4way_exit(cfg, net);
        WL_TRACE(("WLC_GET_VERSION=%d\n", ioctl_version));
 
        mutex_lock(&cfg->usr_sync);
@@ -17061,10 +17174,10 @@ int wl_cfg80211_hang(struct net_device *dev, u16 reason)
                CFG80211_DISCONNECTED(dev, reason, NULL, 0, false, GFP_KERNEL);
        }
 #if defined(RSSIAVG)
-       wl_free_rssi_cache(&g_rssi_cache_ctrl);
+       wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-       wl_free_bss_cache(&g_bss_cache_ctrl);
+       wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
 #endif
        if (cfg != NULL) {
                wl_link_down(cfg);
@@ -17082,10 +17195,10 @@ s32 wl_cfg80211_down(struct net_device *dev)
                return err;
        mutex_lock(&cfg->usr_sync);
 #if defined(RSSIAVG)
-       wl_free_rssi_cache(&g_rssi_cache_ctrl);
+       wl_free_rssi_cache(&cfg->g_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-       wl_free_bss_cache(&g_bss_cache_ctrl);
+       wl_free_bss_cache(&cfg->g_bss_cache_ctrl);
 #endif
        err = __wl_cfg80211_down(cfg);
        mutex_unlock(&cfg->usr_sync);
@@ -18001,8 +18114,10 @@ wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
                // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
                band = band_cur==WLC_BAND_2G ? band_cur : WLC_BAND_5G;
                ret = wldev_ioctl(dev, WLC_SET_BAND, &band, sizeof(band), true);
-               if (ret < 0)
+               if (ret < 0) {
                        WL_ERR(("WLC_SET_BAND error %d\n", ret));
+                       goto done;
+               }
 
                /* Best channel selection in 5GHz band. */
                ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
@@ -21637,3 +21752,24 @@ wl_set_rssi_logging(struct net_device *dev, void *param)
        return err;
 }
 #endif /* SUPPORT_RSSI_LOGGING */
+
+s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len)
+{
+       struct bcm_cfg80211 *cfg = wl_get_cfg(dev);
+       int ret = 0;
+       int bytes_written = -1;
+
+       sscanf(command, "%*s %d", &cfg->autochannel);
+
+       if (cfg->autochannel == 0) {
+               cfg->best_2g_ch = 0;
+               cfg->best_5g_ch = 0;
+       } else if (cfg->autochannel == 2) {
+               bytes_written = snprintf(command, total_len, "2g=%d 5g=%d",
+                       cfg->best_2g_ch, cfg->best_5g_ch);
+               ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
+               ret = bytes_written;
+       }
+
+       return ret;
+}
index 13c08cdf1df46ed482fd1cfaf27e6728901319eb..cf9b3fbd2752c8f6291240aa9053453bc7a53d3c 100644 (file)
@@ -45,6 +45,7 @@
 #include <dngl_stats.h>
 #include <dhd.h>
 #include <wl_cfgp2p.h>
+#include <wl_android.h>
 struct wl_conf;
 struct wl_iface;
 struct bcm_cfg80211;
@@ -858,8 +859,19 @@ struct bcm_cfg80211 {
        char sae_password[SAE_MAX_PASSWD_LEN];
        uint sae_password_len;
 #endif /* WLMESH */
+#if defined(RSSIAVG)
+       wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
+       wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
+#endif
+#if defined(BSSCACHE)
+       wl_bss_cache_ctrl_t g_bss_cache_ctrl;
+#endif
        int p2p_disconnected; // terence 20130703: Fix for wrong group_capab (timing issue)
        struct ether_addr disconnected_bssid;
+       int autochannel;
+       int best_2g_ch;
+       int best_5g_ch;
+       uint handshaking;
 };
 
 #if defined(STRICT_GCC_WARNINGS) && defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == \
@@ -1667,4 +1679,5 @@ int wl_cfg80211_iface_count(struct net_device *dev);
 struct net_device* wl_get_ap_netdev(struct bcm_cfg80211 *cfg, char *ifname);
 struct net_device* wl_get_netdev_by_name(struct bcm_cfg80211 *cfg, char *ifname);
 int wl_cfg80211_get_vndr_ouilist(struct bcm_cfg80211 *cfg, uint8 *buf, int max_cnt);
+s32 wl_cfg80211_autochannel(struct net_device *dev, char* command, int total_len);
 #endif /* _wl_cfg80211_h_ */
index 4fd40fd779fc992f1e097081668ff993c0bc7e96..6d62b3a40f0973ab0acd1198aba804ad150228d5 100644 (file)
@@ -294,9 +294,19 @@ wl_cfg80211_bt_setflag(struct net_device *dev, bool set)
 #endif
 }
 
-static void wl_cfg80211_bt_timerfunc(ulong data)
+static void wl_cfg80211_bt_timerfunc(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       unsigned long data
+#endif
+)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct btcoex_info *bt_local = from_timer(bt_local, t, timer);
+#else
        struct btcoex_info *bt_local = (struct btcoex_info *)data;
+#endif
        WL_TRACE(("Enter\n"));
        bt_local->timer_on = 0;
        schedule_work(&bt_local->work);
@@ -393,9 +403,13 @@ void* wl_cfg80211_btcoex_init(struct net_device *ndev)
        btco_inf->ts_dhcp_ok = 0;
        /* Set up timer for BT  */
        btco_inf->timer_ms = 10;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&btco_inf->timer, wl_cfg80211_bt_timerfunc, 0);
+#else
        init_timer(&btco_inf->timer);
        btco_inf->timer.data = (ulong)btco_inf;
        btco_inf->timer.function = wl_cfg80211_bt_timerfunc;
+#endif
 
        btco_inf->dev = ndev;
 
index 6d775f71636cbd1819a530c57a64e231783f3eea..69f7a050cd148fcd2fffff412172797873831103 100644 (file)
@@ -334,6 +334,9 @@ wl_cfgp2p_init_priv(struct bcm_cfg80211 *cfg)
                return -ENOMEM;
        }
 
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       cfg->p2p->cfg = cfg;
+#endif
        wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_PRIMARY) = bcmcfg_to_prmry_ndev(cfg);
        wl_to_p2p_bss_bssidx(cfg, P2PAPI_BSSCFG_PRIMARY) = 0;
        wl_to_p2p_bss_ndev(cfg, P2PAPI_BSSCFG_DEVICE) = NULL;
@@ -1386,10 +1389,21 @@ wl_cfgp2p_listen_complete(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
  *  so lets do it from thread context.
  */
 void
-wl_cfgp2p_listen_expired(unsigned long data)
+wl_cfgp2p_listen_expired(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       ulong data
+#endif
+)
 {
        wl_event_msg_t msg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct p2p_info *p2p = from_timer(p2p, t, listen_timer);
+       struct bcm_cfg80211 *cfg = p2p->cfg;
+#else
        struct bcm_cfg80211 *cfg = (struct bcm_cfg80211 *) data;
+#endif
        struct net_device *ndev;
        CFGP2P_DBG((" Enter\n"));
 
index dba6b4783fbad1c40f38ab45cf8e95bc1e66e391..ca930acc6553f7dddbe6b4d3a4221c918fae4d42 100644 (file)
@@ -71,6 +71,9 @@ struct p2p_bss {
 };
 
 struct p2p_info {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct bcm_cfg80211 *cfg;
+#endif
        bool on;    /**< p2p on/off switch */
        bool scan;
        int16 search_state;
@@ -183,6 +186,14 @@ enum wl_cfgp2p_status {
                        printk args;                                                    \
                }                                                                       \
        } while (0)
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+#define INIT_TIMER(timer, func, duration, extra_delay) \
+       do {                               \
+               timer_setup(timer, func, 0); \
+               timer->expires = jiffies + msecs_to_jiffies(duration + extra_delay); \
+               add_timer(timer); \
+       } while (0);
+#else
 #define INIT_TIMER(timer, func, duration, extra_delay) \
        do {                               \
                init_timer(timer); \
@@ -191,6 +202,7 @@ enum wl_cfgp2p_status {
                timer->data = (unsigned long) cfg; \
                add_timer(timer); \
        } while (0);
+#endif
 
 #if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 8))
 #ifdef WL_SUPPORT_BACKPORTED_KPATCHES
@@ -245,7 +257,13 @@ enum wl_cfgp2p_status {
 #define P2P_ECSA_CNT 50
 
 extern void
-wl_cfgp2p_listen_expired(unsigned long data);
+wl_cfgp2p_listen_expired(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       ulong data
+#endif
+);
 extern bool
 wl_cfgp2p_is_pub_action(void *frame, u32 frame_len);
 extern bool
index bd918e6583de28f08b88f854e985953f0e921310..c5b4b2b0562020f2a95363607061f4254f65ebd5 100644 (file)
@@ -2322,10 +2322,15 @@ static int wl_cfgvendor_lstats_get_info(struct wiphy *wiphy,
                        ((wl_cnt_info_t *)iovar_buf)->datalen,
                        WL_CNT_XTLV_CNTV_LE10_UCODE, NULL,
                        BCM_XTLV_OPTION_ALIGN32)) == NULL) {
-               macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
+               if ((macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
                                ((wl_cnt_info_t *)iovar_buf)->datalen,
                                WL_CNT_XTLV_GE40_UCODE_V1, NULL,
+                               BCM_XTLV_OPTION_ALIGN32)) == NULL) {
+                       macstat_cnt = bcm_get_data_from_xtlv_buf(((wl_cnt_info_t *)iovar_buf)->data,
+                               ((wl_cnt_info_t *)iovar_buf)->datalen,
+                               WL_CNT_XTLV_LT40_UCODE_V1, NULL,
                                BCM_XTLV_OPTION_ALIGN32);
+               }
        }
 
        if (macstat_cnt == NULL) {
index f9be06301ba64e850a48f5438b83b3cf33de13f2..03a09d1350b2f12920bd26c25fe232730ebe9615 100644 (file)
 #define ESCAN_ERROR(x) \
        do { \
                if (iw_msg_level & ESCAN_ERROR_LEVEL) { \
-                       printf(KERN_ERR "ESCAN-ERROR) ");       \
+                       printf(KERN_ERR "ESCAN-ERROR) %s : ", __func__);        \
                        printf x; \
                } \
        } while (0)
 #define ESCAN_SCAN(x) \
        do { \
                if (iw_msg_level & ESCAN_SCAN_LEVEL) { \
-                       printf(KERN_ERR "ESCAN-SCAN) ");        \
+                       printf(KERN_ERR "ESCAN-SCAN) %s : ", __func__); \
                        printf x; \
                } \
        } while (0)
 #define ESCAN_TRACE(x) \
        do { \
                if (iw_msg_level & ESCAN_TRACE_LEVEL) { \
-                       printf(KERN_ERR "ESCAN-TRACE) ");       \
+                       printf(KERN_ERR "ESCAN-TRACE) %s : ", __func__);        \
                        printf x; \
                } \
        } while (0)
@@ -72,15 +72,6 @@ typedef struct {
 #endif /* ESCAN_BUF_OVERFLOW_MGMT */
 
 struct wl_escan_info *g_escan = NULL;
-
-#if defined(RSSIAVG)
-static wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;
-static wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;
-#endif
-#if defined(BSSCACHE)
-static wl_bss_cache_ctrl_t g_bss_cache_ctrl;
-#endif
-
 /* Return a new chanspec given a legacy chanspec
  * Returns INVCHANSPEC on error
  */
@@ -188,9 +179,9 @@ wl_chspec_driver_to_host(int ioctl_ver, chanspec_t chanspec)
  * Returns INVCHANSPEC on error
  */
 static chanspec_t
-wl_chspec_host_to_driver(chanspec_t chanspec)
+wl_chspec_host_to_driver(int ioctl_ver, chanspec_t chanspec)
 {
-       if (1) {
+       if (ioctl_ver == 1) {
                chanspec = wl_chspec_to_legacy(chanspec);
                if (chanspec == INVCHANSPEC) {
                        return chanspec;
@@ -206,7 +197,7 @@ wl_chspec_host_to_driver(chanspec_t chanspec)
  * Returns INVCHANSPEC on error
  */
 static chanspec_t
-wl_ch_host_to_driver(s32 bssidx, u16 channel)
+wl_ch_host_to_driver(int ioctl_ver, s32 bssidx, u16 channel)
 {
        chanspec_t chanspec;
 
@@ -221,7 +212,7 @@ wl_ch_host_to_driver(s32 bssidx, u16 channel)
 
        chanspec |= WL_CHANSPEC_CTL_SB_NONE;
 
-       return wl_chspec_host_to_driver(chanspec);
+       return wl_chspec_host_to_driver(ioctl_ver, chanspec);
 }
 
 static inline struct wl_bss_info *next_bss(struct wl_scan_results *list, struct wl_bss_info *bss)
@@ -415,7 +406,7 @@ fail:
 }
 
 void
-wl_escan_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
+wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data)
 {
        u32 event_type = ntoh32(e->event_type);
        struct wl_escan_info *escan = g_escan;
@@ -442,7 +433,7 @@ wl_escan_event(struct net_device *ndev, const wl_event_msg_t * e, void *data)
        }
 
        DHD_EVENT_WAKE_LOCK(escan->pub);
-       if (likely(!wl_enq_event(escan, ndev, event_type, e, data))) {
+       if (likely(!wl_enq_event(escan, dev, event_type, e, data))) {
                wl_wakeup_event(escan);
        } else {
                DHD_EVENT_WAKE_UNLOCK(escan->pub);
@@ -461,34 +452,41 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan)
 
        /* Delete disconnected cache */
 #if defined(BSSCACHE)
-       wl_delete_disconnected_bss_cache(&g_bss_cache_ctrl, (u8*)&escan->disconnected_bssid);
+       wl_delete_disconnected_bss_cache(&escan->g_bss_cache_ctrl, (u8*)&escan->disconnected_bssid);
 #if defined(RSSIAVG)
-       wl_delete_disconnected_rssi_cache(&g_rssi_cache_ctrl, (u8*)&escan->disconnected_bssid);
+       wl_delete_disconnected_rssi_cache(&escan->g_rssi_cache_ctrl, (u8*)&escan->disconnected_bssid);
 #endif
 #endif
 
        /* Update cache */
 #if defined(RSSIAVG)
-       wl_update_rssi_cache(&g_rssi_cache_ctrl, bss_list);
+       wl_update_rssi_cache(&escan->g_rssi_cache_ctrl, bss_list);
        if (!in_atomic())
-               wl_update_connected_rssi_cache(escan->dev, &g_rssi_cache_ctrl, &rssi);
+               wl_update_connected_rssi_cache(escan->dev, &escan->g_rssi_cache_ctrl, &rssi);
 #endif
 #if defined(BSSCACHE)
-       wl_update_bss_cache(&g_bss_cache_ctrl,
+       wl_update_bss_cache(&escan->g_bss_cache_ctrl,
 #if defined(RSSIAVG)
-               &g_rssi_cache_ctrl,
+               &escan->g_rssi_cache_ctrl,
 #endif
                bss_list);
 #endif
 
        /* delete dirty cache */
 #if defined(RSSIAVG)
-       wl_delete_dirty_rssi_cache(&g_rssi_cache_ctrl);
-       wl_reset_rssi_cache(&g_rssi_cache_ctrl);
+       wl_delete_dirty_rssi_cache(&escan->g_rssi_cache_ctrl);
+       wl_reset_rssi_cache(&escan->g_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-       wl_delete_dirty_bss_cache(&g_bss_cache_ctrl);
-       wl_reset_bss_cache(&g_bss_cache_ctrl);
+       wl_delete_dirty_bss_cache(&escan->g_bss_cache_ctrl);
+       wl_reset_bss_cache(&escan->g_bss_cache_ctrl);
+       if (escan->autochannel)
+               wl_ext_get_best_channel(escan->dev, &escan->g_bss_cache_ctrl,
+                       escan->ioctl_ver &escan->best_2g_ch, &escan->best_5g_ch);
+#else
+       if (escan->autochannel)
+               wl_ext_get_best_channel(escan->dev, bss_list, escan->ioctl_ver,
+                       &escan->best_2g_ch, &escan->best_5g_ch);
 #endif
 
        ESCAN_TRACE(("scanned AP count (%d)\n", bss_list->count));
@@ -497,7 +495,8 @@ static s32 wl_escan_inform_bss(struct wl_escan_info *escan)
 }
 
 static wl_scan_params_t *
-wl_escan_alloc_params(int channel, int nprobes, int *out_params_size)
+wl_escan_alloc_params(struct wl_escan_info *escan, int channel,
+       int nprobes, int *out_params_size)
 {
        wl_scan_params_t *params;
        int params_size;
@@ -528,7 +527,7 @@ wl_escan_alloc_params(int channel, int nprobes, int *out_params_size)
        if (channel == -1)
                params->channel_list[0] = htodchanspec(channel);
        else
-               params->channel_list[0] = wl_ch_host_to_driver(bssidx, channel);
+               params->channel_list[0] = wl_ch_host_to_driver(escan->ioctl_ver, bssidx, channel);
 
        /* Our scan params have 1 channel and 0 ssids */
        params->channel_num = htod32((0 << WL_SCAN_PARAMS_NSSID_SHIFT) |
@@ -545,7 +544,7 @@ static void wl_escan_abort(struct wl_escan_info *escan)
        s32 err = BCME_OK;
        if (!in_atomic()) {
                /* Our scan params only need space for 1 channel and 0 ssids */
-               params = wl_escan_alloc_params(-1, 0, &params_size);
+               params = wl_escan_alloc_params(escan, -1, 0, &params_size);
                if (params == NULL) {
                        ESCAN_ERROR(("scan params allocation failed \n"));
                        err = -ENOMEM;
@@ -848,20 +847,21 @@ static s32 wl_escan_handler(struct wl_escan_info *escan,
        }
        else if (status == WLC_E_STATUS_SUCCESS) {
                escan->escan_state = ESCAN_STATE_IDLE;
-
-                       ESCAN_TRACE(("ESCAN COMPLETED\n"));
-                       escan->bss_list = wl_escan_get_buf(escan);
-                       ESCAN_TRACE(("SCAN COMPLETED: scanned AP count=%d\n",
-                               escan->bss_list->count));
-                       wl_escan_inform_bss(escan);
-                       wl_notify_escan_complete(escan, false);
-
+               ESCAN_TRACE(("ESCAN COMPLETED\n"));
+               escan->bss_list = wl_escan_get_buf(escan);
+               ESCAN_TRACE(("SCAN COMPLETED: scanned AP count=%d\n",
+                       escan->bss_list->count));
+               wl_escan_inform_bss(escan);
+               wl_notify_escan_complete(escan, false);
        } 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)) {
                /* Handle all cases of scan abort */
                escan->escan_state = ESCAN_STATE_IDLE;
                ESCAN_TRACE(("ESCAN ABORT reason: %d\n", status));
+               escan->bss_list = wl_escan_get_buf(escan);
+               ESCAN_TRACE(("SCAN ABORT: scanned AP count=%d\n",
+                       escan->bss_list->count));
                wl_escan_inform_bss(escan);
                wl_notify_escan_complete(escan, false);
        } else if (status == WLC_E_STATUS_TIMEOUT) {
@@ -870,6 +870,7 @@ static s32 wl_escan_handler(struct wl_escan_info *escan,
                if (e->reason == 0xFFFFFFFF) {
                        wl_notify_escan_complete(escan, true);
                }
+               escan->escan_state = ESCAN_STATE_IDLE;
        } else {
                ESCAN_ERROR(("unexpected Escan Event %d : abort\n", status));
                escan->escan_state = ESCAN_STATE_IDLE;
@@ -944,7 +945,8 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list,
                        params->channel_list[j] |= chanspec;
                        ESCAN_SCAN(("Chan : %d, Channel spec: %x \n",
                                channel, params->channel_list[j]));
-                       params->channel_list[j] = wl_chspec_host_to_driver(params->channel_list[j]);
+                       params->channel_list[j] = wl_chspec_host_to_driver(escan->ioctl_ver,
+                               params->channel_list[j]);
                        j++;
                }
        } else {
@@ -982,9 +984,8 @@ wl_escan_prep(struct wl_escan_info *escan, wl_uint32_list_t *list,
        return err;
 }
 
-static int wl_escan_reset(void) {
-       struct wl_escan_info *escan = g_escan;
-
+static int wl_escan_reset(struct wl_escan_info *escan)
+{
        if (timer_pending(&escan->scan_timeout))
                del_timer_sync(&escan->scan_timeout);
        escan->escan_state = ESCAN_STATE_IDLE;
@@ -992,10 +993,20 @@ static int wl_escan_reset(void) {
        return 0;
 }
 
-static void wl_escan_timeout(unsigned long data)
+static void wl_escan_timeout(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       unsigned long data
+#endif
+)
 {
        wl_event_msg_t msg;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct wl_escan_info *escan = from_timer(escan, t, scan_timeout);
+#else
        struct wl_escan_info *escan = (struct wl_escan_info *)data;
+#endif
        struct wl_scan_results *bss_list;
        struct wl_bss_info *bi = NULL;
        s32 i;
@@ -1046,7 +1057,7 @@ wl_escan_set_scan(
        wl_escan_params_t *params = NULL;
        scb_val_t scbval;
        static int cnt = 0;
-       struct wl_escan_info *escan = NULL;
+       struct wl_escan_info *escan = g_escan;
        wlc_ssid_t ssid;
        u32 n_channels = 0;
        wl_uint32_list_t *list;
@@ -1055,9 +1066,8 @@ wl_escan_set_scan(
 
        ESCAN_TRACE(("Enter \n"));
 
-       escan = g_escan;
        if (!escan) {
-               ESCAN_ERROR(("device is not ready\n"));           \
+               ESCAN_ERROR(("device is not ready\n"));
                return -EIO;
        }
        mutex_lock(&escan->usr_sync);
@@ -1144,7 +1154,7 @@ wl_escan_set_scan(
                        ESCAN_TRACE(("Escan not permitted at this time (%d)\n", err));
                else
                        ESCAN_ERROR(("Escan set error (%d)\n", err));
-               wl_escan_reset();
+               wl_escan_reset(escan);
        }
        kfree(params);
 
@@ -1205,10 +1215,15 @@ wl_escan_get_scan(
                err = -EAGAIN;
                goto exit;
        }
+       if (!escan->bss_list) {
+               ESCAN_ERROR(("%s: scan not ready\n", dev->name));
+               err = -EAGAIN;
+               goto exit;
+       }
 
 #if defined(BSSCACHE)
-       bss_list = &g_bss_cache_ctrl.m_cache_head->results;
-       node = g_bss_cache_ctrl.m_cache_head;
+       bss_list = &escan->g_bss_cache_ctrl.m_cache_head->results;
+       node = escan->g_bss_cache_ctrl.m_cache_head;
        for (i=0; node && i<IW_MAX_AP; i++)
 #else
        bss_list = escan->bss_list;
@@ -1227,7 +1242,7 @@ wl_escan_get_scan(
                }
 
 #if defined(RSSIAVG)
-               rssi = wl_get_avg_rssi(&g_rssi_cache_ctrl, &bi->BSSID);
+               rssi = wl_get_avg_rssi(&escan->g_rssi_cache_ctrl, &bi->BSSID);
                if (rssi == RSSI_MINVAL)
                        rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
 #else
@@ -1235,8 +1250,8 @@ wl_escan_get_scan(
                rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
 #endif
                channel = wf_chspec_ctlchan(wl_chspec_driver_to_host(escan->ioctl_ver, bi->chanspec));
-               ESCAN_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
-               __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
+               ESCAN_SCAN(("BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
+                       MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
 
                /* First entry must be the BSSID */
                iwe.cmd = SIOCGIWAP;
@@ -1322,6 +1337,27 @@ exit:
        return err;
 }
 
+s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len)
+{
+       struct wl_escan_info *escan = g_escan;
+       int ret = 0;
+       int bytes_written = -1;
+
+       sscanf(command, "%*s %d", &escan->autochannel);
+
+       if (escan->autochannel == 0) {
+               escan->best_2g_ch = 0;
+               escan->best_5g_ch = 0;
+       } else if (escan->autochannel == 2) {
+               bytes_written = snprintf(command, total_len, "2g=%d 5g=%d",
+                       escan->best_2g_ch, escan->best_5g_ch);
+               ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
+               ret = bytes_written;
+       }
+
+       return ret;
+}
+
 static s32 wl_create_event_handler(struct wl_escan_info *escan)
 {
        int ret = 0;
@@ -1342,42 +1378,44 @@ static void wl_destroy_event_handler(struct wl_escan_info *escan)
                PROC_STOP(&escan->event_tsk);
 }
 
-static void wl_escan_deinit(void)
+static void wl_escan_deinit(struct wl_escan_info *escan)
 {
-       struct wl_escan_info *escan = g_escan;
-
        printf("%s: Enter\n", __FUNCTION__);
        if (!escan) {
-               ESCAN_ERROR(("device is not ready\n"));           \
+               ESCAN_ERROR(("device is not ready\n"));
                return;
        }
        wl_destroy_event_handler(escan);
        wl_flush_eq(escan);
        del_timer_sync(&escan->scan_timeout);
+       escan->escan_state = ESCAN_STATE_IDLE;
 
 #if defined(RSSIAVG)
-       wl_free_rssi_cache(&g_rssi_cache_ctrl);
+       wl_free_rssi_cache(&escan->g_rssi_cache_ctrl);
 #endif
 #if defined(BSSCACHE)
-       wl_free_bss_cache(&g_bss_cache_ctrl);
+       wl_free_bss_cache(&escan->g_bss_cache_ctrl);
 #endif
 }
 
-static s32 wl_escan_init(void)
+static s32 wl_escan_init(struct wl_escan_info *escan)
 {
-       struct wl_escan_info *escan = g_escan;
        int err = 0;
 
        printf("%s: Enter\n", __FUNCTION__);
        if (!escan) {
-               ESCAN_ERROR(("device is not ready\n"));           \
+               ESCAN_ERROR(("device is not ready\n"));
                return -EIO;
        }
 
        /* Init scan_timeout timer */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&escan->scan_timeout, wl_escan_timeout, 0);
+#else
        init_timer(&escan->scan_timeout);
        escan->scan_timeout.data = (unsigned long) escan;
        escan->scan_timeout.function = wl_escan_timeout;
+#endif
 
        if (wl_create_event_handler(escan)) {
                err = -ENOMEM;
@@ -1392,7 +1430,7 @@ static s32 wl_escan_init(void)
 
        return 0;
 err:
-       wl_escan_deinit();
+       wl_escan_deinit(escan);
        return err;
 }
 
@@ -1403,11 +1441,11 @@ void wl_escan_detach(dhd_pub_t *dhdp)
        printf("%s: Enter\n", __FUNCTION__);
 
        if (!escan) {
-               ESCAN_ERROR(("device is not ready\n"));           \
+               ESCAN_ERROR(("device is not ready\n"));
                return;
        }
 
-       wl_escan_deinit();
+       wl_escan_deinit(escan);
 
        if (escan->escan_ioctl_buf) {
                kfree(escan->escan_ioctl_buf);
@@ -1429,10 +1467,10 @@ wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp)
        escan = (wl_escan_info_t *)DHD_OS_PREALLOC(dhdp, DHD_PREALLOC_WL_ESCAN_INFO, sizeof(struct wl_escan_info));
        if (!escan)
                return -ENOMEM;
+       g_escan = escan;
        memset(escan, 0, sizeof(struct wl_escan_info));
 
        /* we only care about main interface so save a global here */
-       g_escan = escan;
        escan->dev = dev;
        escan->pub = dhdp;
        escan->escan_state = ESCAN_STATE_IDLE;
@@ -1443,9 +1481,7 @@ wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp)
                goto err ;
        }
        wl_init_eq(escan);
-#ifdef WL_ESCAN
-       wl_escan_init();
-#endif
+       wl_escan_init(escan);
 
        return 0;
 err:
index 04255d4e2d04e7fdd69d064c820fa2829ffcd4c8..fdba0a672a202e0dad94daea48c0c1ea6699abee 100644 (file)
@@ -56,9 +56,19 @@ typedef struct wl_escan_info {
        tsk_ctl_t event_tsk;            /* task of main event handler thread */\r
        ESCAN_EVENT_HANDLER evt_handler[WLC_E_LAST];\r
        struct mutex usr_sync;  /* maily for up/down synchronization */\r
+       int autochannel;\r
+       int best_2g_ch;\r
+       int best_5g_ch;\r
+#if defined(RSSIAVG)\r
+       wl_rssi_cache_ctrl_t g_rssi_cache_ctrl;\r
+       wl_rssi_cache_ctrl_t g_connected_rssi_cache_ctrl;\r
+#endif\r
+#if defined(BSSCACHE)\r
+       wl_bss_cache_ctrl_t g_bss_cache_ctrl;\r
+#endif\r
 } wl_escan_info_t;\r
 \r
-void wl_escan_event(struct net_device *ndev, const wl_event_msg_t * e, void *data);\r
+void wl_escan_event(struct net_device *dev, const wl_event_msg_t * e, void *data);\r
 \r
 int wl_escan_set_scan(\r
        struct net_device *dev,\r
@@ -68,6 +78,7 @@ int wl_escan_set_scan(
 );\r
 int wl_escan_get_scan(struct net_device *dev,  struct iw_request_info *info,\r
        struct iw_point *dwrq, char *extra);\r
+s32 wl_escan_autochannel(struct net_device *dev, char* command, int total_len);\r
 int wl_escan_attach(struct net_device *dev, dhd_pub_t *dhdp);\r
 void wl_escan_detach(dhd_pub_t *dhdp);\r
 \r
index 5cae9f8ee448abc7aba6b4106fa2eb70157ddb00..4713882c27ae80f058f312379205bbe88193f4f4 100644 (file)
@@ -627,16 +627,18 @@ wl_iw_get_freq(
        char *extra
 )
 {
-       channel_info_t ci;
        int error;
+       u32 chanspec = 0;
+       int ctl_chan;
 
        WL_TRACE(("%s: SIOCGIWFREQ\n", dev->name));
 
-       if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(ci))))
+       if ((error = dev_wlc_intvar_get(dev, "chanspec", &chanspec)))
                return error;
+       ctl_chan = wf_chspec_ctlchan(chanspec);
 
        /* Return radio channel in channel form */
-       fwrq->m = dtoh32(ci.hw_channel);
+       fwrq->m = ctl_chan;
        fwrq->e = dtoh32(0);
        return 0;
 }
@@ -732,7 +734,7 @@ wl_iw_get_range(
 
        dwrq->length = sizeof(struct iw_range);
        memset(range, 0, sizeof(*range));
-       memset(channels, 0, sizeof(channels));
+
        /* We don't use nwids */
        range->min_nwid = range->max_nwid = 0;
 
@@ -3545,15 +3547,19 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
 #endif /* WIRELESS_EXT > 11 */
 
        phy_noise = 0;
-       if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise))))
+       if ((res = dev_wlc_ioctl(dev, WLC_GET_PHY_NOISE, &phy_noise, sizeof(phy_noise)))) {
+               WL_ERROR(("%s: WLC_GET_PHY_NOISE error=%d\n", __FUNCTION__, res));
                goto done;
+       }
 
        phy_noise = dtoh32(phy_noise);
        WL_TRACE(("wl_iw_get_wireless_stats phy noise=%d\n *****", phy_noise));
 
-       scb_val.val = 0;
-       if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t))))
+       memset(&scb_val, 0, sizeof(scb_val));
+       if ((res = dev_wlc_ioctl(dev, WLC_GET_RSSI, &scb_val, sizeof(scb_val_t)))) {
+               WL_ERROR(("%s: WLC_GET_RSSI error=%d\n", __FUNCTION__, res));
                goto done;
+       }
 
        rssi = dtoh32(scb_val.val);
        rssi = MIN(rssi, RSSI_MAXVAL);
@@ -3647,9 +3653,19 @@ done:
 
 #ifndef WL_ESCAN
 static void
-wl_iw_timerfunc(ulong data)
+wl_iw_timerfunc(
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       struct timer_list *t
+#else
+       unsigned long data
+#endif
+)
 {
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       iscan_info_t *iscan = from_timer(iscan, t, timer);
+#else
        iscan_info_t *iscan = (iscan_info_t *)data;
+#endif
        iscan->timer_on = 0;
        if (iscan->iscan_state != ISCAN_STATE_IDLE) {
                WL_TRACE(("timer trigger\n"));
@@ -3887,9 +3903,13 @@ wl_iw_attach(struct net_device *dev, void * dhdp)
 
        /* Set up the timer */
        iscan->timer_ms    = 2000;
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(4, 15, 0)
+       timer_setup(&iscan->timer, wl_iw_timerfunc, 0);
+#else
        init_timer(&iscan->timer);
        iscan->timer.data = (ulong)iscan;
        iscan->timer.function = wl_iw_timerfunc;
+#endif
 
        sema_init(&iscan->sysioc_sem, 0);
        init_completion(&iscan->sysioc_exited);
index ebe656ff35482ea2ac45b104cbd9bf107b00ba1c..38b7117463ac206dc081d00cd32e49b89d1d7820 100644 (file)
@@ -34,7 +34,9 @@
 
 #include <wldev_common.h>
 #include <bcmutils.h>
+#ifdef WL_CFG80211
 #include <wl_cfg80211.h>
+#endif
 #include <dhd_config.h>
 
 #define htod32(i) (i)
@@ -478,9 +480,11 @@ int wldev_set_country(
        wl_country_t cur_cspec = {{0}, 0, {0}}; /* current ccode */
        scb_val_t scbval;
        char smbuf[WLC_IOCTL_SMLEN];
+#ifdef WL_CFG80211
        struct wireless_dev *wdev = ndev_to_wdev(dev);
        struct wiphy *wiphy = wdev->wiphy;
        struct bcm_cfg80211 *cfg = wiphy_priv(wiphy);
+#endif
 
        if (!country_code)
                return error;
@@ -495,7 +499,7 @@ int wldev_set_country(
        cspec.rev = revinfo;
        memcpy(cspec.country_abbrev, country_code, WLC_CNTRY_BUF_SZ);
        memcpy(cspec.ccode, country_code, WLC_CNTRY_BUF_SZ);
-       error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec, 0);
+       error = dhd_conf_map_country_list(dhd_get_pub(dev), &cspec);
        if (error)
                dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);
 
@@ -506,7 +510,11 @@ int wldev_set_country(
                dhd_force_country_change(dev) ||
            (strncmp(cspec.ccode, cur_cspec.ccode, WLC_CNTRY_BUF_SZ) != 0)) {
 
-               if ((user_enforced) && (wl_get_drv_status(cfg, CONNECTED, dev))) {
+               if ((user_enforced)
+#ifdef WL_CFG80211
+                       && (wl_get_drv_status(cfg, CONNECTED, dev))
+#endif
+               ) {
                        bzero(&scbval, sizeof(scb_val_t));
                        error = wldev_ioctl_set(dev, WLC_DISASSOC,
                                                &scbval, sizeof(scb_val_t));