wifi: update ap6356 driver to 1.363.59.144.9 [1/2]
authorRongjun Chen <rongjun.chen@amlogic.com>
Wed, 2 Aug 2017 09:15:09 +0000 (17:15 +0800)
committerRongjun Chen <rongjun.chen@amlogic.com>
Wed, 2 Aug 2017 09:15:09 +0000 (17:15 +0800)
PD# 147497

fix ap6356 p2p connect fail issue

Change-Id: I6663fdcf4bd6248ac06bf5c68c75b0242721a2d9

35 files changed:
bcmdhd.1.363.59.144.x.cn/Makefile
bcmdhd.1.363.59.144.x.cn/bcmsdh_linux.c
bcmdhd.1.363.59.144.x.cn/bcmsdh_sdmmc.c
bcmdhd.1.363.59.144.x.cn/bcmsdh_sdmmc_linux.c
bcmdhd.1.363.59.144.x.cn/bcmutils.c
bcmdhd.1.363.59.144.x.cn/dhd.h
bcmdhd.1.363.59.144.x.cn/dhd_bus.h
bcmdhd.1.363.59.144.x.cn/dhd_common.c
bcmdhd.1.363.59.144.x.cn/dhd_config.c
bcmdhd.1.363.59.144.x.cn/dhd_config.h
bcmdhd.1.363.59.144.x.cn/dhd_gpio.c
bcmdhd.1.363.59.144.x.cn/dhd_linux.c
bcmdhd.1.363.59.144.x.cn/dhd_linux.h
bcmdhd.1.363.59.144.x.cn/dhd_linux_platdev.c
bcmdhd.1.363.59.144.x.cn/dhd_pcie.c
bcmdhd.1.363.59.144.x.cn/dhd_pcie_linux.c
bcmdhd.1.363.59.144.x.cn/dhd_sdio.c
bcmdhd.1.363.59.144.x.cn/dhd_static_buf.c
bcmdhd.1.363.59.144.x.cn/dhd_wlfc.c
bcmdhd.1.363.59.144.x.cn/include/bcmsdbus.h
bcmdhd.1.363.59.144.x.cn/include/bcmsdh_sdmmc.h
bcmdhd.1.363.59.144.x.cn/include/epivers.h
bcmdhd.1.363.59.144.x.cn/include/linux_osl.h
bcmdhd.1.363.59.144.x.cn/include/sbchipc.h
bcmdhd.1.363.59.144.x.cn/include/sbsocram.h
bcmdhd.1.363.59.144.x.cn/include/siutils.h
bcmdhd.1.363.59.144.x.cn/linux_osl.c
bcmdhd.1.363.59.144.x.cn/siutils.c
bcmdhd.1.363.59.144.x.cn/wl_android.c
bcmdhd.1.363.59.144.x.cn/wl_android.h
bcmdhd.1.363.59.144.x.cn/wl_cfg80211.c
bcmdhd.1.363.59.144.x.cn/wl_cfgp2p.h
bcmdhd.1.363.59.144.x.cn/wl_iw.c
bcmdhd.1.363.59.144.x.cn/wl_iw.h
bcmdhd.1.363.59.144.x.cn/wldev_common.c

index 043914e970fb8d1abea00c14922fca2ccba61c33..28d199baac1e4047f626c883a9e643956f127883 100644 (file)
@@ -4,6 +4,8 @@
 
 CONFIG_BCMDHD_SDIO := y
 #CONFIG_BCMDHD_PCIE := y
+CONFIG_BCMDHD_PROPTXSTATUS := y
+CONFIG_DHD_USE_STATIC_BUF :=y
 
 export CONFIG_BCMDHD = m
 export CONFIG_BCMDHD_OOB = y
@@ -14,30 +16,26 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DBCMDRIVER -DSDTEST       \
        -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          \
-       -DENABLE_INSMOD_NO_FW_LOAD -DGET_CUSTOM_MAC_ENABLE                     \
+       -DTSQ_MULTIPLIER                                                      \
+       -DBCMSDIOH_TXGLOM_EXT -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 \
-       hnd_pktq.o hnd_pktpool.o dhd_config.o
+       hnd_pktq.o hnd_pktpool.o dhd_config.o wl_android_ext.o
 
 ifneq ($(CONFIG_BCMDHD_SDIO),)
 DHDCFLAGS += \
-       -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR    \
-       -DBDC -DDHD_USE_IDLECOUNT -DBCMSDIOH_TXGLOM     \
-       -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=256 \
+       -DBCMSDIO -DMMC_SDIO_ABORT -DBCMLXSDMMC -DUSE_SDIOFIFO_IOVAR          \
+       -DBDC -DDHD_USE_IDLECOUNT -DBCMSDIOH_TXGLOM                           \
        -DCUSTOM_SDIO_F2_BLKSIZE=256
 
-DHDCFLAGS += -DPKT_STATICS
 DHDCFLAGS += -DDCUSTOM_DPC_PRIO_SETTING=-1
 DHDCFLAGS += -DCUSTOM_RXF_CPUCORE=2
-DHDCFLAGS += -DDHD_TXBOUND=64
-DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=36
-DHDCFLAGS += -DDHD_FIRSTREAD=256 -DMAX_HDR_READ=256 
-DHDCFLAGS += -DCUSTOM_TXINRX_THRES=128
-#DHDCFLAGS += -DPROP_TXSTATUS
+DHDCFLAGS += -DDHD_FIRSTREAD=256 -DMAX_HDR_READ=256
 
 DHDOFILES += bcmsdh.o bcmsdh_linux.o bcmsdh_sdmmc.o bcmsdh_sdmmc_linux.o \
        dhd_sdio.o dhd_cdc.o dhd_wlfc.o
@@ -52,6 +50,15 @@ DHDCFLAGS += -DSDIO_ISR_THREAD
 endif
 endif
 
+ifeq ($(CONFIG_BCMDHD_PROPTXSTATUS),y)
+ifneq ($(CONFIG_BCMDHD_SDIO),)
+DHDCFLAGS += -DPROP_TXSTATUS
+endif
+ifneq ($(CONFIG_CFG80211),)
+DHDCFLAGS += -DPROP_TXSTATUS_VSDB
+endif
+endif
+
 ifneq ($(CONFIG_BCMDHD_PCIE),)
 DHDCFLAGS += \
        -DPCIE_FULL_DONGLE -DBCMPCIE -DCUSTOM_DPC_PRIO_SETTING=-1
@@ -63,9 +70,10 @@ endif
 obj-$(CONFIG_BCMDHD) += dhd.o
 dhd-objs += $(DHDOFILES)
 
-#ifeq ($(CONFIG_MACH_ODROID_4210),y)
+#ifeq ($(CONFIG_MACH_PLATFORM),y)
 DHDOFILES += dhd_gpio.o
-DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT -DCUSTOMER_HW_AMLOGIC
+DHDCFLAGS += -DCUSTOMER_HW -DDHD_OF_SUPPORT
+DHDCFLAGS += -DCUSTOMER_HW_AMLOGIC
 #DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI
 #endif
 
@@ -81,11 +89,11 @@ DHDCFLAGS += -DSTATIC_WL_PRIV_STRUCT -DENHANCED_STATIC_BUF
 endif
 
 ifneq ($(CONFIG_WIRELESS_EXT),)
-DHDOFILES += wl_iw.o
-DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW
+DHDOFILES += wl_iw.o wl_escan.o
+DHDCFLAGS += -DSOFTAP -DWL_WIRELESS_EXT -DUSE_IW -DWL_ESCAN
 endif
 ifneq ($(CONFIG_CFG80211),)
-DHDOFILES += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o wl_cfg_btcoex.o
+DHDOFILES += wl_cfg80211.o wl_cfgp2p.o wl_linux_mon.o wl_cfg_btcoex.o wl_cfgvendor.o
 DHDOFILES += dhd_cfg80211.o dhd_cfg_vendor.o
 DHDCFLAGS += -DWL_CFG80211 -DWLP2P -DWL_CFG80211_STA_EVENT -DWL_ENABLE_P2P_IF
 DHDCFLAGS += -DWL_IFACE_COMB_NUM_CHANNELS
@@ -98,8 +106,6 @@ DHDCFLAGS += -DWL_SUPPORT_BACKPORTED_KPATCHES
 DHDCFLAGS += -DESCAN_RESULT_PATCH
 DHDCFLAGS += -DVSDB -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST
 DHDCFLAGS += -DWLTDLS -DMIRACAST_AMPDU_SIZE=8
-#DHDCFLAGS += -DPROP_TXSTATUS_VSDB
-
 endif
 EXTRA_CFLAGS = $(DHDCFLAGS)
 ifeq ($(CONFIG_BCMDHD),m)
index 1860c339a8ee5341b1fe04eee34621257d3d52ec..5087eb4eccf607b0f58824fe6a99d0f02c5686f9 100644 (file)
@@ -324,6 +324,7 @@ static irqreturn_t wlan_oob_irq(int irq, void *dev_id)
 {
        bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)dev_id;
        bcmsdh_os_info_t *bcmsdh_osinfo = bcmsdh->os_cxt;
+
        bcmsdh_oob_intr_set(bcmsdh, FALSE);
        bcmsdh_osinfo->oob_irq_handler(bcmsdh_osinfo->oob_irq_handler_context);
 
@@ -346,8 +347,8 @@ int bcmsdh_oob_intr_register(bcmsdh_info_t *bcmsdh, bcmsdh_cb_fn_t oob_irq_handl
 #else
        printf("%s: SW_OOB enabled\n", __FUNCTION__);
 #endif
-       printf("%s OOB irq=%d flags=0x%X\n", __FUNCTION__,
-               (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags);
+       SDLX_MSG(("%s OOB irq=%d flags=0x%X\n", __FUNCTION__,
+               (int)bcmsdh_osinfo->oob_irq_num, (int)bcmsdh_osinfo->oob_irq_flags));
        // anthony: test begin
        bcmsdh_osinfo->oob_irq_flags &= IRQF_TRIGGER_MASK;
        printf("%s change flags to 0x%X\n", __FUNCTION__, (int)bcmsdh_osinfo->oob_irq_flags);
index 5e798de9db15d56e299186536a4062a315c6d69d..9c576475f289f1b6d0b2b0516ea2caa3ee007430 100644 (file)
@@ -63,7 +63,7 @@ static void IRQHandler(struct sdio_func *func);
 static void IRQHandlerF2(struct sdio_func *func);
 #endif /* !defined(OOB_INTR_ONLY) */
 static int sdioh_sdmmc_get_cisaddr(sdioh_info_t *sd, uint32 regaddr);
-#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(CUSTOMER_HW_INTEL)
+#if defined(ENABLE_INSMOD_NO_FW_LOAD) && !defined(BUS_POWER_RESTORE)
 extern int sdio_reset_comm(struct mmc_card *card);
 #else
 int sdio_reset_comm(struct mmc_card *card)
@@ -546,7 +546,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
                /* Now set it */
                si->client_block_size[func] = blksize;
 
-#ifdef USE_DYNAMIC_F2_BLKSIZE
                if (si->func[func] == NULL) {
                        sd_err(("%s: SDIO Device not present\n", __FUNCTION__));
                        bcmerror = BCME_NORESOURCE;
@@ -558,7 +557,6 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name,
                        sd_err(("%s: Failed to set F%d blocksize to %d(%d)\n",
                                __FUNCTION__, func, blksize, bcmerror));
                sdio_release_host(si->func[func]);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
                break;
        }
 
@@ -722,7 +720,9 @@ exit:
 }
 
 #if (defined(OOB_INTR_ONLY) && defined(HW_OOB)) || defined(FORCE_WOWLAN)
+#ifdef CUSTOMER_HW_AMLOGIC
 extern int wifi_irq_trigger_level(void);
+#endif
 SDIOH_API_RC
 sdioh_enable_hw_oob_intr(sdioh_info_t *sd, bool enable)
 {
@@ -917,10 +917,11 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by
                }
        }
 
-       if (sd_msglevel & SDH_COST_VAL)
+       if (sd_msglevel & SDH_COST_VAL) {
                getnstimeofday(&now);
-//     sd_cost(("%s: rw=%d len=1 cost=%lds %luus\n", __FUNCTION__,
-//             rw, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000));
+               sd_cost(("%s: rw=%d len=1 cost=%lds %luus\n", __FUNCTION__,
+                       rw, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000));
+       }
 
        return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
 }
@@ -1393,10 +1394,11 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add
                }
        }
 
-       if (sd_msglevel & SDH_COST_VAL)
+       if (sd_msglevel & SDH_COST_VAL) {
                getnstimeofday(&now);
-//     sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__,
-//             rw, nbytes, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
+               sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__,
+                       rw, nbytes, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
+       }
 
        return (((err_ret == 0)&&(err_ret2 == 0)) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
 }
@@ -1473,7 +1475,7 @@ sdioh_request_packet_chain(sdioh_info_t *sd, uint fix_inc, uint write, uint func
                         * a restriction on max tx/glom count (based on host->max_segs).
                         */
                        if (sg_count >= ARRAYSIZE(sd->sg_list)) {
-//                             sd_err(("%s: sg list entries exceed limit, sg_count=%d(%lu)\n", __FUNCTION__, sg_count, ARRAYSIZE(sd->sg_list)));
+                               sd_err(("%s: sg list entries exceed limit %d\n", __FUNCTION__, sg_count));
                                return (SDIOH_API_RC_FAIL);
                        }
                        pdata += pkt_offset;
@@ -1609,10 +1611,11 @@ txglomfail:
                MFREE(sd->osh, localbuf, ttl_len);
 #endif /* BCMSDIOH_TXGLOM */
 
-       if (sd_msglevel & SDH_COST_VAL)
+       if (sd_msglevel & SDH_COST_VAL) {
                getnstimeofday(&now);
-//     sd_cost(("%s: rw=%d, cost=%lds %luus\n", __FUNCTION__,
-//             write, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000));
+               sd_cost(("%s: rw=%d, cost=%lds %luus\n", __FUNCTION__,
+                       write, now.tv_sec-before.tv_sec, now.tv_nsec/1000-before.tv_nsec/1000));
+       }
 
        sd_trace(("%s: Exit\n", __FUNCTION__));
        return SDIOH_API_RC_SUCCESS;
@@ -1663,10 +1666,12 @@ sdioh_buffer_tofrom_bus(sdioh_info_t *sd, uint fix_inc, uint write, uint func,
 
        sd_trace(("%s: Exit\n", __FUNCTION__));
 
-       if (sd_msglevel & SDH_COST_VAL)
+       if (sd_msglevel & SDH_COST_VAL) {
                getnstimeofday(&now);
-//     sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__,
-//             write, len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
+               sd_cost(("%s: rw=%d, len=%d cost=%lds %luus\n", __FUNCTION__,
+                       write, len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
+       }
+
        return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL);
 }
 
@@ -1738,10 +1743,11 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u
 
        PKTFREE_STATIC(sd->osh, tmppkt, write ? TRUE : FALSE);
 
-       if (sd_msglevel & SDH_COST_VAL)
+       if (sd_msglevel & SDH_COST_VAL) {
                getnstimeofday(&now);
-//     sd_cost(("%s: len=%d cost=%lds %luus\n", __FUNCTION__,
-//             buf_len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
+               sd_cost(("%s: len=%d cost=%lds %luus\n", __FUNCTION__,
+                       buf_len, now.tv_sec-before.tv_sec, now.tv_nsec/1000 - before.tv_nsec/1000));
+       }
 
        return status;
 }
index af321a68645a35f939493794cc023965f7151522..741c50892102be360df81cf0dcd63a042e87cfa8 100644 (file)
@@ -115,7 +115,7 @@ static int sdioh_probe(struct sdio_func *func)
        adapter = dhd_wifi_platform_get_adapter(SDIO_BUS, host_idx, rca);
        if (adapter != NULL) {
                sd_err(("found adapter info '%s'\n", adapter->name));
-#ifdef CUSTOMER_HW_INTEL
+#ifdef BUS_POWER_RESTORE
                adapter->sdio_func = func;
 #endif
        } else
index 74b03ddbfba4e776cce6eaf84138a7e3a4a75073..badb2237545223c8816b554b4def03b1c04bb3e4 100644 (file)
@@ -2309,7 +2309,7 @@ bcm_bprintf(struct bcmstrbuf *b, const char *fmt, ...)
 
        r = vsnprintf(b->buf, b->size, fmt, ap);
        if (bcm_bprintf_bypass == TRUE) {
-               printf(b->buf);
+               printf("%s", b->buf);
                goto exit;
        }
 
index 69cc464c5ee2f2758496651bc1e744aec3f5bc30..4cbbbb338fc0c93c18b5bd21aa81fc83dc35fe01 100644 (file)
@@ -128,7 +128,9 @@ enum dhd_bus_state {
 /* Download Types */
 typedef enum download_type {
        FW,
-       NVRAM
+       NVRAM,
+       CLM_BLOB,
+       CLMINFO
 } download_type_t;
 
 
@@ -177,12 +179,20 @@ enum dhd_op_flags {
 #define POWERUP_WAIT_MS                2000 /* ms: time out in waiting wifi to come up */
 #endif
 #define MAX_NVRAMBUF_SIZE      (16 * 1024) /* max nvram buf size */
+#define MAX_CLMINFO_BUF_SIZE    (4 * 1024) /* max clminfo buf size */
+#define MAX_CLM_BUF_SIZE       (48 * 1024) /* max clm blob size */
 #ifdef DHD_DEBUG
 #define DHD_JOIN_MAX_TIME_DEFAULT 10000 /* ms: Max time out for joining AP */
 #define DHD_SCAN_DEF_TIMEOUT 10000 /* ms: Max time out for scan in progress */
 #endif
 
+#ifndef CONFIG_BCMDHD_CLM_PATH
+#define CONFIG_BCMDHD_CLM_PATH "/system/etc/wifi/bcmdhd_clm.blob"
+#endif /* CONFIG_BCMDHD_CLM_PATH */
+#define WL_CCODE_NULL_COUNTRY  "#n"
+
 #define FW_VER_STR_LEN 128
+#define CLM_VER_STR_LEN 128
 
 enum dhd_bus_wake_state {
        WAKE_LOCK_OFF,
@@ -633,6 +643,7 @@ typedef struct dhd_pub {
        struct dhd_log_dump_buf dld_buf;
        unsigned int dld_enable;
 #endif /* DHD_LOG_DUMP */
+       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 */
 } dhd_pub_t;
@@ -969,6 +980,7 @@ extern int dhd_wakeup_ioctl_event(dhd_pub_t *pub, dhd_ioctl_recieved_status_t re
 
 
 extern int dhd_os_get_image_block(char * buf, int len, void * image);
+extern int dhd_os_get_image_size(void * image);
 extern void * dhd_os_open_image(char * filename);
 extern void dhd_os_close_image(void * image);
 extern void dhd_os_wd_timer(void *bus, uint wdtick);
@@ -1038,6 +1050,7 @@ extern int        dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val);
 extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd);
 extern int net_os_enable_packet_filter(struct net_device *dev, int val);
 extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num);
+extern int net_os_set_suspend_bcn_li_dtim(struct net_device *dev, int val);
 #endif /* PKT_FILTER_SUPPORT */
 
 extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd);
@@ -1176,23 +1189,6 @@ extern int wl_iw_send_priv_event(struct net_device *dev, char *flag);
 extern uint dhd_watchdog_ms;
 extern bool dhd_os_wd_timer_enabled(void *bus);
 
-#ifdef PKT_STATICS
-typedef struct pkt_statics {
-       uint16  event_count;
-       uint32  event_size;
-       uint16  ctrl_count;
-       uint32  ctrl_size;
-       uint32  data_count;
-       uint32  data_size;
-       uint32  glom_cnt[CUSTOM_MAX_TXGLOM_SIZE];
-       uint16  glom_max;
-       uint16  glom_count;
-       uint32  glom_size;
-       uint16  test_count;
-       uint32  test_size;
-} pkt_statics_t;
-#endif
-
 #ifdef DHD_PCIE_RUNTIMEPM
 extern uint dhd_runtimepm_ms;
 #endif /* DHD_PCIE_RUNTIMEPM */
@@ -1318,7 +1314,11 @@ extern uint dhd_force_tx_queueing;
 #define WIFI_TURNON_DELAY              DEFAULT_WIFI_TURNON_DELAY
 #endif /* WIFI_TURNON_DELAY */
 
+#ifdef BCMSDIO
 #define DEFAULT_DHD_WATCHDOG_INTERVAL_MS       10 /* msec */
+#else
+#define DEFAULT_DHD_WATCHDOG_INTERVAL_MS       0 /* msec */
+#endif
 #ifndef CUSTOM_DHD_WATCHDOG_MS
 #define CUSTOM_DHD_WATCHDOG_MS                 DEFAULT_DHD_WATCHDOG_INTERVAL_MS
 #endif /* DEFAULT_DHD_WATCHDOG_INTERVAL_MS */
@@ -1408,7 +1408,8 @@ int dhd_ndo_remove_ip(dhd_pub_t *dhd, int idx);
 /* ioctl processing for nl80211 */
 int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc, void *data_buf);
 
-void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path);
+void dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path,
+                                                                                       char *pclm_path, char *pconf_path);
 void dhd_set_bus_state(void *bus, uint32 state);
 
 /* Remove proper pkts(either one no-frag pkt or whole fragmented pkts) */
@@ -1541,6 +1542,9 @@ int dhd_get_download_buffer(dhd_pub_t     *dhd, char *file_path, download_type_t com
 
 void dhd_free_download_buffer(dhd_pub_t        *dhd, void *buffer, int length);
 
+int dhd_download_clm_blob(dhd_pub_t *dhd, unsigned char *image, uint32 len);
+
+int dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path);
 #define dhd_is_device_removed(x) FALSE
 #define dhd_os_ind_firmware_stall(x)
 
index be17a6bdf3a33cbdeafccbfe36cbedbb8a2d04b7..3517d800cb0e89a7ab2348d7a9b90e6d0274efdf 100644 (file)
@@ -43,7 +43,7 @@ extern void dhd_bus_unregister(void);
 
 /* Download firmware image and nvram image */
 extern int dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
-       char *fw_path, char *nv_path, char *conf_path);
+       char *fw_path, char *nv_path, char *clm_path, char *conf_path);
 
 /* Stop bus module: clear pending frames, disable data flow */
 extern void dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex);
index 1a724b246a248481b5a91d9ff74392c2a04fda8b..631cb4fb2372d21a07f133da5bf1aeb95993a86b 100644 (file)
@@ -50,6 +50,7 @@
 #include <dhd_bus.h>
 #include <dhd_proto.h>
 #include <dhd_config.h>
+#include <bcmsdbus.h>
 #include <dhd_dbg.h>
 #include <msgtrace.h>
 
@@ -129,6 +130,8 @@ extern int dhd_get_concurrent_capabilites(dhd_pub_t *dhd);
 
 extern int dhd_socram_dump(struct dhd_bus *bus);
 
+#define MAX_CHUNK_LEN 1408 /* 8 * 8 * 22 */
+
 bool ap_cfg_running = FALSE;
 bool ap_fw_loaded = FALSE;
 
@@ -140,12 +143,15 @@ bool ap_fw_loaded = FALSE;
 #define DHD_COMPILED "\nCompiled in " SRCBASE
 #endif /* DHD_DEBUG */
 
+#define CHIPID_MISMATCH        8
+
 #if defined(DHD_DEBUG)
 const char dhd_version[] = "Dongle Host Driver, version " EPI_VERSION_STR;
 #else
 const char dhd_version[] = "\nDongle Host Driver, version " EPI_VERSION_STR "\nCompiled from ";
 #endif 
 char fw_version[FW_VER_STR_LEN] = "\0";
+char clm_version[CLM_VER_STR_LEN] = "\0";
 
 void dhd_set_timer(void *bus, uint wdtick);
 
@@ -672,9 +678,6 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
                int_val = (int32)wl_dbg_level;
                bcopy(&int_val, arg, val_size);
                printf("cfg_msg_level=0x%x\n", wl_dbg_level);
-#endif
-#ifdef PKT_STATICS
-               dhdsdio_txpktstatics();
 #endif
                break;
 
@@ -703,7 +706,6 @@ dhd_doiovar(dhd_pub_t *dhd_pub, const bcm_iovar_t *vi, uint32 actionid, const ch
        case IOV_GVAL(IOV_MSGLEVEL):
                int_val = (int32)dhd_msg_level;
                bcopy(&int_val, arg, val_size);
-
 #ifdef PKT_STATICS
                dhdsdio_txpktstatics();
 #endif
@@ -3130,6 +3132,7 @@ dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd)
        if (bcn_li_dtim == 0) {
                bcn_li_dtim = 1;
        }
+       bcn_li_dtim = MAX(dhd->suspend_bcn_li_dtim, bcn_li_dtim);
 #else /* ENABLE_MAX_DTIM_IN_SUSPEND */
        /* attemp to use platform defined dtim skip interval */
        bcn_li_dtim = dhd->suspend_bcn_li_dtim;
@@ -3495,6 +3498,12 @@ int dhd_get_download_buffer(dhd_pub_t    *dhd, char *file_path, download_type_t com
                        len = dhd->cached_nvram_length;
                        buf = dhd->cached_nvram;
                }
+       }
+       else if (component == CLM_BLOB) {
+               if (dhd->cached_clm_length) {
+                       len = dhd->cached_clm_length;
+                       buf = dhd->cached_clm;
+               }
        } else {
                return ret;
        }
@@ -3544,6 +3553,12 @@ int dhd_get_download_buffer(dhd_pub_t    *dhd, char *file_path, download_type_t com
                        dhd->cached_nvram_length = len;
                }
        }
+       else if (component == CLM_BLOB) {
+               if (!dhd->cached_clm_length) {
+                        dhd->cached_clm = buf;
+                        dhd->cached_clm_length = len;
+               }
+       }
 #endif
 
 err:
@@ -3553,6 +3568,187 @@ err:
        return ret;
 }
 
+int
+dhd_download_2_dongle(dhd_pub_t        *dhd, char *iovar, uint16 flag, uint16 dload_type,
+       unsigned char *dload_buf, int len)
+{
+       struct wl_dload_data *dload_ptr = (struct wl_dload_data *)dload_buf;
+       int err = 0;
+       int dload_data_offset;
+       static char iovar_buf[WLC_IOCTL_MEDLEN];
+       int iovar_len;
+
+       memset(iovar_buf, 0, sizeof(iovar_buf));
+
+       dload_data_offset = OFFSETOF(wl_dload_data_t, data);
+       dload_ptr->flag = (DLOAD_HANDLER_VER << DLOAD_FLAG_VER_SHIFT) | flag;
+       dload_ptr->dload_type = dload_type;
+       dload_ptr->len = htod32(len - dload_data_offset);
+       dload_ptr->crc = 0;
+       len = len + 8 - (len%8);
+
+       iovar_len = bcm_mkiovar(iovar, dload_buf,
+               (uint)len, iovar_buf, sizeof(iovar_buf));
+       if (iovar_len == 0) {
+               DHD_ERROR(("%s: insufficient buffer space passed to bcm_mkiovar for '%s' \n",
+                          __FUNCTION__, iovar));
+               return BCME_BUFTOOSHORT;
+       }
+
+       err = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovar_buf,
+                       iovar_len, IOV_SET, 0);
+
+       return err;
+}
+
+int
+dhd_download_clm_blob(dhd_pub_t        *dhd, unsigned char *image, uint32 len)
+{
+       int chunk_len;
+       int size2alloc;
+       unsigned char *new_buf;
+       int err = 0, data_offset;
+       uint16 dl_flag = DL_BEGIN;
+
+       data_offset = OFFSETOF(wl_dload_data_t, data);
+       size2alloc = data_offset + MAX_CHUNK_LEN;
+
+       if ((new_buf = (unsigned char *)MALLOCZ(dhd->osh, size2alloc)) != NULL) {
+               do {
+                       chunk_len = dhd_os_get_image_block((char *)(new_buf + data_offset),
+                               MAX_CHUNK_LEN, image);
+                       if (chunk_len < 0) {
+                               DHD_ERROR(("%s: dhd_os_get_image_block failed (%d)\n",
+                                       __FUNCTION__, chunk_len));
+                               err = BCME_ERROR;
+                               goto exit;
+                       }
+
+                       if (len - chunk_len == 0)
+                               dl_flag |= DL_END;
+
+                       err = dhd_download_2_dongle(dhd, "clmload", dl_flag, DL_TYPE_CLM,
+                               new_buf, data_offset + chunk_len);
+
+                       dl_flag &= ~DL_BEGIN;
+
+                       len = len - chunk_len;
+               } while ((len > 0) && (err == 0));
+       } else {
+               err = BCME_NOMEM;
+       }
+exit:
+       if (new_buf) {
+               MFREE(dhd->osh, new_buf, size2alloc);
+       }
+
+       return err;
+}
+
+int
+dhd_apply_default_clm(dhd_pub_t *dhd, char *clm_path)
+{
+       char *clm_blob_path;
+       int len;
+       unsigned char *imgbuf = NULL;
+       int err = BCME_OK;
+       char iovbuf[WLC_IOCTL_SMLEN];
+       wl_country_t *cspec;
+
+       if (clm_path[0] != '\0') {
+               if (strlen(clm_path) > MOD_PARAM_PATHLEN) {
+                       DHD_ERROR(("clm path exceeds max len\n"));
+                       return BCME_ERROR;
+               }
+               clm_blob_path = clm_path;
+               DHD_TRACE(("clm path from module param:%s\n", clm_path));
+       } else {
+               clm_blob_path = CONFIG_BCMDHD_CLM_PATH;
+       }
+
+       /* If CLM blob file is found on the filesystem, download the file.
+        * After CLM file download or If the blob file is not present,
+        * validate the country code before proceeding with the initialization.
+        * If country code is not valid, fail the initialization.
+        */
+
+       imgbuf = dhd_os_open_image((char *)clm_blob_path);
+       if (imgbuf == NULL) {
+               printf("%s: Ignore clm file %s\n", __FUNCTION__, clm_path);
+               goto exit;
+       }
+
+       len = dhd_os_get_image_size(imgbuf);
+
+       if ((len > 0) && (len < MAX_CLM_BUF_SIZE) && imgbuf) {
+               bcm_mkiovar("country", NULL, 0, iovbuf, sizeof(iovbuf));
+               err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+               if (err) {
+                       DHD_ERROR(("%s: country code get failed\n", __FUNCTION__));
+                       goto exit;
+               }
+
+               cspec = (wl_country_t *)iovbuf;
+               if ((strncmp(cspec->ccode, WL_CCODE_NULL_COUNTRY, WLC_CNTRY_BUF_SZ)) != 0) {
+                       DHD_ERROR(("%s: CLM already exist in F/W, "
+                               "new CLM data will be added to the end of existing CLM data!\n",
+                               __FUNCTION__));
+               }
+
+               /* Found blob file. Download the file */
+               DHD_ERROR(("clm file download from %s \n", clm_blob_path));
+               err = dhd_download_clm_blob(dhd, imgbuf, len);
+               if (err) {
+                       DHD_ERROR(("%s: CLM download failed err=%d\n", __FUNCTION__, err));
+                       /* Retrieve clmload_status and print */
+                       bcm_mkiovar("clmload_status", NULL, 0, iovbuf, sizeof(iovbuf));
+                       err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+                       if (err) {
+                               DHD_ERROR(("%s: clmload_status get failed err=%d \n",
+                                       __FUNCTION__, err));
+                       } else {
+                               DHD_ERROR(("%s: clmload_status: %d \n",
+                                       __FUNCTION__, *((int *)iovbuf)));
+                               if (*((int *)iovbuf) == CHIPID_MISMATCH) {
+                                       DHD_ERROR(("Chip ID mismatch error \n"));
+                               }
+                       }
+                       err = BCME_ERROR;
+                       goto exit;
+               } else {
+                       DHD_INFO(("%s: CLM download succeeded \n", __FUNCTION__));
+               }
+       } else {
+               DHD_INFO(("Skipping the clm download. len:%d memblk:%p \n", len, imgbuf));
+#ifdef DHD_USE_CLMINFO_PARSER
+               err = BCME_ERROR;
+               goto exit;
+#endif /* DHD_USE_CLMINFO_PARSER */
+       }
+
+       /* Verify country code */
+       bcm_mkiovar("country", NULL, 0, iovbuf, sizeof(iovbuf));
+       err = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0);
+       if (err) {
+               DHD_ERROR(("%s: country code get failed\n", __FUNCTION__));
+               goto exit;
+       }
+
+       cspec = (wl_country_t *)iovbuf;
+       if ((strncmp(cspec->ccode, WL_CCODE_NULL_COUNTRY, WLC_CNTRY_BUF_SZ)) == 0) {
+               /* Country code not initialized or CLM download not proper */
+               DHD_ERROR(("country code not initialized\n"));
+               err = BCME_ERROR;
+       }
+exit:
+
+       if (imgbuf) {
+               dhd_os_close_image(imgbuf);
+       }
+
+       return err;
+}
+
 void dhd_free_download_buffer(dhd_pub_t        *dhd, void *buffer, int length)
 {
 #ifdef CACHE_FW_IMAGES
index 81535a16e087393f58293f18e974eeb755ebc828..b416610becace55e36a033431fe9ab3195df3c98 100644 (file)
@@ -49,154 +49,53 @@ uint config_msg_level = CONFIG_ERROR_LEVEL;
 \r
 #ifdef CONFIG_PATH_AUTO_SELECT\r
 #ifdef BCMSDIO\r
-#define BCM4330B2_CONF_NAME "config_40183b2.txt"\r
-#define BCM43362A0_CONF_NAME "config_40181a0.txt"\r
-#define BCM43362A2_CONF_NAME "config_40181a2.txt"\r
-#define BCM43438A0_CONF_NAME "config_43438a0.txt"\r
-#define BCM43438A1_CONF_NAME "config_43438a1.txt"\r
-#define BCM4334B1_CONF_NAME "config_4334b1.txt"\r
-#define BCM43341B0_CONF_NAME "config_43341b0.txt"\r
-#define BCM43241B4_CONF_NAME "config_43241b4.txt"\r
-#define BCM4339A0_CONF_NAME "config_4339a0.txt"\r
-#define BCM43455C0_CONF_NAME "config_43455c0.txt"\r
-#define BCM4354A1_CONF_NAME "config_4354a1.txt"\r
+#define CONFIG_BCM4330B2 "config_40183b2.txt"\r
+#define CONFIG_BCM43362A0 "config_40181a0.txt"\r
+#define CONFIG_BCM43362A2 "config_40181a2.txt"\r
+#define CONFIG_BCM43438A0 "config_43438a0.txt"\r
+#define CONFIG_BCM43438A1 "config_43438a1.txt"\r
+#define CONFIG_BCM43436B0 "config_43436b0.txt"\r
+#define CONFIG_BCM4334B1 "config_4334b1.txt"\r
+#define CONFIG_BCM43341B0 "config_43341b0.txt"\r
+#define CONFIG_BCM43241B4 "config_43241b4.txt"\r
+#define CONFIG_BCM4339A0 "config_4339a0.txt"\r
+#define CONFIG_BCM43455C0 "config_43455c0.txt"\r
+#define CONFIG_BCM43456C5 "config_43456c5.txt"\r
+#define CONFIG_BCM4354A1 "config_4354a1.txt"\r
 #endif\r
-#define BCM4356A2_CONF_NAME "config_4356a2.txt"\r
-#define BCM4359B1_CONF_NAME "config_4359b1.txt"\r
-#define BCM4359C0_CONF_NAME "config_4359c0.txt"\r
+#define CONFIG_BCM4356A2 "config_4356a2.txt"\r
+#define CONFIG_BCM4358A3 "config_4358a3.txt"\r
+#define CONFIG_BCM4359B1 "config_4359b1.txt"\r
+#define CONFIG_BCM4359C0 "config_4359c0.txt"\r
 #endif\r
 \r
 #ifdef BCMSDIO\r
 #define SBSDIO_CIS_SIZE_LIMIT          0x200           /* maximum bytes in one CIS */\r
 \r
-const static char *bcm4330b2_fw_name[] = {\r
-       "fw_bcm40183b2.bin",\r
-       "fw_bcm40183b2_apsta.bin",\r
-       "fw_bcm40183b2_p2p.bin",\r
-       "fw_bcm40183b2_es.bin",\r
-       "fw_bcm40183b2_mfg.bin"\r
-};\r
-\r
-const static char *bcm4330b2_ag_fw_name[] = {\r
-       "fw_bcm40183b2_ag.bin",\r
-       "fw_bcm40183b2_ag_apsta.bin",\r
-       "fw_bcm40183b2_ag_p2p.bin",\r
-       "fw_bcm40183b2_ag_es.bin",\r
-       "fw_bcm40183b2_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm43362a0_fw_name[] = {\r
-       "fw_bcm40181a0.bin",\r
-       "fw_bcm40181a0_apsta.bin",\r
-       "fw_bcm40181a0_p2p.bin",\r
-       "fw_bcm40181a0_es.bin",\r
-       "fw_bcm40181a0_mfg.bin"\r
-};\r
-\r
-const static char *bcm43362a2_fw_name[] = {\r
-       "fw_bcm40181a2.bin",\r
-       "fw_bcm40181a2_apsta.bin",\r
-       "fw_bcm40181a2_p2p.bin",\r
-       "fw_bcm40181a2_es.bin",\r
-       "fw_bcm40181a2_mfg.bin"\r
-};\r
-\r
-const static char *bcm4334b1_ag_fw_name[] = {\r
-       "fw_bcm4334b1_ag.bin",\r
-       "fw_bcm4334b1_ag_apsta.bin",\r
-       "fw_bcm4334b1_ag_p2p.bin",\r
-       "fw_bcm4334b1_ag_es.bin",\r
-       "fw_bcm4334b1_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm43438a0_fw_name[] = {\r
-       "fw_bcm43438a0.bin",\r
-       "fw_bcm43438a0_apsta.bin",\r
-       "fw_bcm43438a0_p2p.bin",\r
-       "fw_bcm43438a0_es.bin",\r
-       "fw_bcm43438a0_mfg.bin"\r
-};\r
-\r
-const static char *bcm43438a1_fw_name[] = {\r
-       "fw_bcm43438a1.bin",\r
-       "fw_bcm43438a1_apsta.bin",\r
-       "fw_bcm43438a1_p2p.bin",\r
-       "fw_bcm43438a1_es.bin",\r
-       "fw_bcm43438a1_mfg.bin"\r
-};\r
-\r
-const static char *bcm43341b0_ag_fw_name[] = {\r
-       "fw_bcm43341b0_ag.bin",\r
-       "fw_bcm43341b0_ag_apsta.bin",\r
-       "fw_bcm43341b0_ag_p2p.bin",\r
-       "fw_bcm43341b0_ag_es.bin",\r
-       "fw_bcm43341b0_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm43241b4_ag_fw_name[] = {\r
-       "fw_bcm43241b4_ag.bin",\r
-       "fw_bcm43241b4_ag_apsta.bin",\r
-       "fw_bcm43241b4_ag_p2p.bin",\r
-       "fw_bcm43241b4_ag_es.bin",\r
-       "fw_bcm43241b4_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm4339a0_ag_fw_name[] = {\r
-       "fw_bcm4339a0_ag.bin",\r
-       "fw_bcm4339a0_ag_apsta.bin",\r
-       "fw_bcm4339a0_ag_p2p.bin",\r
-       "fw_bcm4339a0_ag_es.bin",\r
-       "fw_bcm4339a0_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm43455c0_ag_fw_name[] = {\r
-       "fw_bcm43455c0_ag.bin",\r
-       "fw_bcm43455c0_ag_apsta.bin",\r
-       "fw_bcm43455c0_ag_p2p.bin",\r
-       "fw_bcm43455c0_ag_es.bin",\r
-       "fw_bcm43455c0_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm4354a1_ag_fw_name[] = {\r
-       "fw_bcm4354a1_ag.bin",\r
-       "fw_bcm4354a1_ag_apsta.bin",\r
-       "fw_bcm4354a1_ag_p2p.bin",\r
-       "fw_bcm4354a1_ag_es.bin",\r
-       "fw_bcm4354a1_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm4356a2_ag_fw_name[] = {\r
-       "fw_bcm4356a2_ag.bin",\r
-       "fw_bcm4356a2_ag_apsta.bin",\r
-       "fw_bcm4356a2_ag_p2p.bin",\r
-       "fw_bcm4356a2_ag_es.bin",\r
-       "fw_bcm4356a2_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm4359b1_ag_fw_name[] = {\r
-       "fw_bcm4359b1_ag.bin",\r
-       "fw_bcm4359b1_ag_apsta.bin",\r
-       "fw_bcm4359b1_ag_p2p.bin",\r
-       "fw_bcm4359b1_ag_es.bin",\r
-       "fw_bcm4359b1_ag_mfg.bin"\r
-};\r
-\r
-const static char *bcm4359c0_ag_fw_name[] = {\r
-       "fw_bcm4359c0_ag.bin",\r
-       "fw_bcm4359c0_ag_apsta.bin",\r
-       "fw_bcm4359c0_ag_p2p.bin",\r
-       "fw_bcm4359c0_ag_es.bin",\r
-       "fw_bcm4359c0_ag_mfg.bin"\r
-};\r
+#define FW_BCM4330B2 "fw_bcm40183b2"\r
+#define FW_BCM4330B2_AG "fw_bcm40183b2_ag"\r
+#define FW_BCM43362A0 "fw_bcm40181a0"\r
+#define FW_BCM43362A2 "fw_bcm40181a2"\r
+#define FW_BCM4334B1 "fw_bcm4334b1_ag"\r
+#define FW_BCM43438A0 "fw_bcm43438a0"\r
+#define FW_BCM43438A1 "fw_bcm43438a1"\r
+#define FW_BCM43436B0 "fw_bcm43436b0"\r
+#define FW_BCM43012B0 "fw_bcm43012b0"\r
+#define FW_BCM43341B1 "fw_bcm43341b0_ag"\r
+#define FW_BCM43241B4 "fw_bcm43241b4_ag"\r
+#define FW_BCM4339A0 "fw_bcm4339a0_ag"\r
+#define FW_BCM43455C0 "fw_bcm43455c0_ag"\r
+#define FW_BCM43456C5 "fw_bcm43456c5_ag"\r
+#define FW_BCM4354A1 "fw_bcm4354a1_ag"\r
+#define FW_BCM4356A2 "fw_bcm4356a2_ag"\r
+#define FW_BCM4358A3 "fw_bcm4358a3_ag"\r
+#define FW_BCM4359B1 "fw_bcm4359b1_ag"\r
+#define FW_BCM4359C0 "fw_bcm4359c0_ag"\r
+\r
+#define CLM_BCM43012B0 "clm_bcm43012b0"\r
 #endif\r
 #ifdef BCMPCIE\r
-const static char *bcm4356a2_pcie_ag_fw_name[] = {\r
-       "fw_bcm4356a2_pcie_ag.bin",\r
-       "fw_bcm4356a2_pcie_ag_apsta.bin",\r
-       "fw_bcm4356a2_pcie_ag_p2p.bin",\r
-       "fw_bcm4356a2_pcie_ag_es.bin",\r
-       "fw_bcm4356a2_pcie_ag_mfg.bin"\r
-};\r
+#define FW_BCM4356A2 "fw_bcm4356a2_pcie_ag"\r
 #endif\r
 \r
 #define htod32(i) i
@@ -454,6 +353,7 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
        int fw_type, ag_type;\r
        uint chip, chiprev;\r
        int i;\r
+       char fw_tail[20];\r
 \r
        chip = dhd->conf->chip;\r
        chiprev = dhd->conf->chiprev;\r
@@ -489,83 +389,147 @@ dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path)
                (strstr(&fw_path[i], "_es") ? FW_TYPE_ES :\r
                FW_TYPE_STA))));\r
 \r
+       if (fw_type == FW_TYPE_STA)\r
+               strcpy(fw_tail, ".bin");\r
+       else if (fw_type == FW_TYPE_APSTA)\r
+               strcpy(fw_tail, "_apsta.bin");\r
+       else if (fw_type == FW_TYPE_P2P)\r
+               strcpy(fw_tail, "_p2p.bin");\r
+       else if (fw_type == FW_TYPE_ES)\r
+               strcpy(fw_tail, "_es.bin");\r
+       else if (fw_type == FW_TYPE_MFG)\r
+               strcpy(fw_tail, "_mfg.bin");\r
+\r
        switch (chip) {\r
 #ifdef BCMSDIO\r
                case BCM4330_CHIP_ID:\r
                        if (ag_type == FW_TYPE_G) {\r
                                if (chiprev == BCM4330B2_CHIP_REV)\r
-                                       strcpy(&fw_path[i+1], bcm4330b2_fw_name[fw_type]);\r
-                               break;\r
+                                       strcpy(&fw_path[i+1], FW_BCM4330B2);\r
                        } else {\r
                                if (chiprev == BCM4330B2_CHIP_REV)\r
-                                       strcpy(&fw_path[i+1], bcm4330b2_ag_fw_name[fw_type]);\r
-                               break;\r
+                                       strcpy(&fw_path[i+1], FW_BCM4330B2_AG);\r
                        }\r
+                       break;\r
                case BCM43362_CHIP_ID:\r
                        if (chiprev == BCM43362A0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm43362a0_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43362A0);\r
                        else\r
-                               strcpy(&fw_path[i+1], bcm43362a2_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43362A2);\r
                        break;\r
                case BCM43430_CHIP_ID:\r
                        if (chiprev == BCM43430A0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm43438a0_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43438A0);\r
                        else if (chiprev == BCM43430A1_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm43438a1_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43438A1);\r
+                       else if (chiprev == BCM43430A2_CHIP_REV)\r
+                               strcpy(&fw_path[i+1], FW_BCM43436B0);\r
                        break;\r
+               case BCM43012_CHIP_ID:\r
+                       if (chiprev == BCM43012B0_CHIP_REV)\r
+                               strcpy(&fw_path[i+1], FW_BCM43012B0);\r
                case BCM4334_CHIP_ID:\r
                        if (chiprev == BCM4334B1_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4334b1_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4334B1);\r
                        break;\r
                case BCM43340_CHIP_ID:\r
                case BCM43341_CHIP_ID:\r
                        if (chiprev == BCM43341B0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm43341b0_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43341B1);\r
                        break;\r
                case BCM4324_CHIP_ID:\r
                        if (chiprev == BCM43241B4_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm43241b4_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43241B4);\r
                        break;\r
                case BCM4335_CHIP_ID:\r
                        if (chiprev == BCM4335A0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4339a0_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4339A0);\r
+                       break;\r
+               case BCM4339_CHIP_ID:\r
+                       if (chiprev == BCM4339A0_CHIP_REV)\r
+                               strcpy(&fw_path[i+1], FW_BCM4339A0);\r
                        break;\r
                case BCM4345_CHIP_ID:\r
                case BCM43454_CHIP_ID:\r
                        if (chiprev == BCM43455C0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm43455c0_ag_fw_name[fw_type]);\r
-                       break;\r
-               case BCM4339_CHIP_ID:\r
-                       if (chiprev == BCM4339A0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4339a0_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM43455C0);\r
+                       else if (chiprev == BCM43455C5_CHIP_REV)\r
+                               strcpy(&fw_path[i+1], FW_BCM43456C5);\r
                        break;\r
                case BCM4354_CHIP_ID:\r
                        if (chiprev == BCM4354A1_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4354a1_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4354A1);\r
                        else if (chiprev == BCM4356A2_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4356a2_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4356A2);\r
                        break;\r
                case BCM4356_CHIP_ID:\r
                case BCM4371_CHIP_ID:\r
                        if (chiprev == BCM4356A2_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4356a2_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4356A2);\r
+                       break;\r
+               case BCM43569_CHIP_ID:\r
+                       if (chiprev == BCM4358A3_CHIP_REV)\r
+                               strcpy(&fw_path[i+1], FW_BCM4358A3);\r
                        break;\r
                case BCM4359_CHIP_ID:\r
                        if (chiprev == BCM4359B1_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4359b1_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4359B1);\r
                        else if (chiprev == BCM4359C0_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4359c0_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4359C0);\r
                        break;\r
 #endif\r
 #ifdef BCMPCIE\r
+               case BCM4354_CHIP_ID:\r
                case BCM4356_CHIP_ID:\r
                        if (chiprev == BCM4356A2_CHIP_REV)\r
-                               strcpy(&fw_path[i+1], bcm4356a2_pcie_ag_fw_name[fw_type]);\r
+                               strcpy(&fw_path[i+1], FW_BCM4356A2);\r
+                       break;\r
+#endif\r
+               default:\r
+                       strcpy(&fw_path[i+1], "fw_bcmdhd");\r
+       }\r
+       strcat(fw_path, fw_tail);\r
+\r
+       CONFIG_TRACE(("%s: firmware_path=%s\n", __FUNCTION__, fw_path));\r
+}\r
+\r
+void\r
+dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path)\r
+{\r
+       uint chip, chiprev;\r
+       int i;\r
+       char fw_tail[20];\r
+\r
+       chip = dhd->conf->chip;\r
+       chiprev = dhd->conf->chiprev;\r
+\r
+       if (clm_path[0] == '\0') {\r
+               printf("clm path is null\n");\r
+               return;\r
+       }\r
+\r
+       /* find out the last '/' */\r
+       i = strlen(clm_path);\r
+       while (i > 0) {\r
+               if (clm_path[i] == '/') break;\r
+               i--;\r
+       }\r
+\r
+       strcpy(fw_tail, ".blob");\r
+\r
+       switch (chip) {\r
+#ifdef BCMSDIO\r
+               case BCM43012_CHIP_ID:\r
+                       if (chiprev == BCM43012B0_CHIP_REV)\r
+                               strcpy(&clm_path[i+1], CLM_BCM43012B0);\r
                        break;\r
 #endif\r
+               default:\r
+                       strcpy(&clm_path[i+1], "clm_bcmdhd");\r
        }\r
+       strcat(clm_path, fw_tail);\r
 \r
-       printf("%s: firmware_path=%s\n", __FUNCTION__, fw_path);\r
+       CONFIG_TRACE(("%s: clm_path=%s\n", __FUNCTION__, clm_path));\r
 }\r
 \r
 void\r
@@ -608,35 +572,29 @@ dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path)
 \r
        strcpy(&nv_path[i+1], dhd->conf->nv_by_chip.m_chip_nv_path_head[matched].name);\r
 \r
-       printf("%s: nvram_path=%s\n", __FUNCTION__, nv_path);\r
+       CONFIG_TRACE(("%s: nvram_path=%s\n", __FUNCTION__, nv_path));\r
 }\r
 \r
 void\r
-dhd_conf_set_conf_path_by_nv_path(dhd_pub_t *dhd, char *conf_path, char *nv_path)\r
+dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path)\r
 {\r
        int i;\r
 \r
-       if (nv_path[0] == '\0') {\r
-#ifdef CONFIG_BCMDHD_NVRAM_PATH\r
-               bcm_strncpy_s(conf_path, MOD_PARAM_PATHLEN-1, CONFIG_BCMDHD_NVRAM_PATH, MOD_PARAM_PATHLEN-1);\r
-               if (nv_path[0] == '\0')\r
-#endif\r
-               {\r
-                       printf("nvram path is null\n");\r
-                       return;\r
-               }\r
+       if (src_path[0] == '\0') {\r
+               printf("src_path is null\n");\r
+               return;\r
        } else\r
-               strcpy(conf_path, nv_path);\r
+               strcpy(dst_path, src_path);\r
 \r
        /* find out the last '/' */\r
-       i = strlen(conf_path);\r
+       i = strlen(dst_path);\r
        while (i > 0) {
-               if (conf_path[i] == '/') break;\r
+               if (dst_path[i] == '/') break;\r
                i--;\r
        }\r
-       strcpy(&conf_path[i+1], "config.txt");\r
+       strcpy(&dst_path[i+1], dst_name);\r
 \r
-       printf("%s: config_path=%s\n", __FUNCTION__, conf_path);\r
+       CONFIG_TRACE(("%s: dst_path=%s\n", __FUNCTION__, dst_path));\r
 }\r
 \r
 #ifdef CONFIG_PATH_AUTO_SELECT\r
@@ -665,146 +623,160 @@ dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path)
 #ifdef BCMSDIO\r
                case BCM4330_CHIP_ID:\r
                        if (chiprev == BCM4330B2_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4330B2_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4330B2);\r
                        break;\r
                case BCM43362_CHIP_ID:\r
                        if (chiprev == BCM43362A0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM43362A0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43362A0);\r
                        else\r
-                               strcpy(&conf_path[i+1], BCM43362A2_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43362A2);\r
                        break;\r
                case BCM43430_CHIP_ID:\r
                        if (chiprev == BCM43430A0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM43438A0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43438A0);\r
                        else if (chiprev == BCM43430A1_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM43438A1_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43438A1);\r
+                       else if (chiprev == BCM43430A2_CHIP_REV)\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43436B0);\r
                        break;\r
                case BCM4334_CHIP_ID:\r
                        if (chiprev == BCM4334B1_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4334B1_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4334B1);\r
                        break;\r
                case BCM43340_CHIP_ID:\r
                case BCM43341_CHIP_ID:\r
                        if (chiprev == BCM43341B0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM43341B0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43341B0);\r
                        break;\r
                case BCM4324_CHIP_ID:\r
                        if (chiprev == BCM43241B4_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM43241B4_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43241B4);\r
                        break;\r
                case BCM4335_CHIP_ID:\r
                        if (chiprev == BCM4335A0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4339A0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4339A0);\r
                        break;\r
                case BCM4345_CHIP_ID:\r
                case BCM43454_CHIP_ID:\r
                        if (chiprev == BCM43455C0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM43455C0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43455C0);\r
+                       else if (chiprev == BCM43455C5_CHIP_REV)\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM43456C5);\r
                        break;\r
                case BCM4339_CHIP_ID:\r
                        if (chiprev == BCM4339A0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4339A0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4339A0);\r
                        break;\r
                case BCM4354_CHIP_ID:\r
                        if (chiprev == BCM4354A1_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4354A1_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4354A1);\r
                        else if (chiprev == BCM4356A2_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4356A2_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4356A2);\r
                        break;\r
                case BCM4356_CHIP_ID:\r
                case BCM4371_CHIP_ID:\r
                        if (chiprev == BCM4356A2_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4356A2_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4356A2);\r
+                       break;\r
+               case BCM43569_CHIP_ID:\r
+                       if (chiprev == BCM4358A3_CHIP_REV)\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4358A3);\r
                        break;\r
                case BCM4359_CHIP_ID:\r
                        if (chiprev == BCM4359B1_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4359B1_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4359B1);\r
                        else if (chiprev == BCM4359C0_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4359C0_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4359C0);\r
                        break;\r
 #endif\r
 #ifdef BCMPCIE\r
+               case BCM4354_CHIP_ID:\r
                case BCM4356_CHIP_ID:\r
                        if (chiprev == BCM4356A2_CHIP_REV)\r
-                               strcpy(&conf_path[i+1], BCM4356A2_CONF_NAME);\r
+                               strcpy(&conf_path[i+1], CONFIG_BCM4356A2);\r
                        break;\r
 #endif\r
        }\r
 \r
-       printf("%s: config_path=%s\n", __FUNCTION__, conf_path);\r
+       CONFIG_TRACE(("%s: config_path=%s\n", __FUNCTION__, conf_path));\r
 }\r
 #endif\r
 \r
 int\r
-dhd_conf_set_fw_int_cmd(dhd_pub_t *dhd, char *name, uint cmd, int val,\r
+dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val,\r
        int def, bool down)\r
 {\r
-       int bcmerror = -1;\r
+       int ret = -1;\r
+       char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */\r
 \r
        if (val >= def) {\r
                if (down) {\r
-                       if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
-                               CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
+                       if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
+                               CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, ret));\r
+               }\r
+               if (cmd == WLC_SET_VAR) {\r
+                       printf("%s: set %s %d\n", __FUNCTION__, name, val);\r
+                       bcm_mkiovar(name, (char *)&val, sizeof(val), iovbuf, sizeof(iovbuf));\r
+                       if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
+                               CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));\r
+               } else {\r
+                       printf("%s: set %s %d %d\n", __FUNCTION__, name, cmd, val);\r
+                       if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, 0)) < 0)\r
+                               CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));\r
                }\r
-               printf("%s: set %s %d %d\n", __FUNCTION__, name, cmd, val);\r
-               if ((bcmerror = dhd_wl_ioctl_cmd(dhd, cmd, &val, sizeof(val), TRUE, 0)) < 0)\r
-                       CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, bcmerror));\r
        }\r
-       return bcmerror;\r
+\r
+       return ret;\r
 }\r
 \r
 int\r
-dhd_conf_set_fw_int_struct_cmd(dhd_pub_t *dhd, char *name, uint cmd,\r
-       int *val, int len, bool down)\r
+dhd_conf_set_bufiovar(dhd_pub_t *dhd, uint cmd, char *name, char *buf,\r
+       int len, bool down)\r
 {\r
-       int bcmerror = -1;\r
+       char iovbuf[WLC_IOCTL_SMLEN];\r
+       int ret = -1;\r
 \r
        if (down) {\r
-               if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
-                       CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
+               if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
+                       CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, ret));\r
        }\r
-       if ((bcmerror = dhd_wl_ioctl_cmd(dhd, cmd, val, len, TRUE, 0)) < 0)\r
-               CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, bcmerror));\r
-\r
-       return bcmerror;\r
-}\r
-\r
-int\r
-dhd_conf_set_fw_string_cmd(dhd_pub_t *dhd, char *cmd, int val, int def,\r
-       bool down)\r
-{\r
-       int bcmerror = -1;\r
-       char iovbuf[WL_EVENTING_MASK_LEN + 12]; /*  Room for "event_msgs" + '\0' + bitvec  */\r
 \r
-       if (val >= def) {\r
-               if (down) {\r
-                       if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
-                               CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
-               }\r
-               printf("%s: set %s %d\n", __FUNCTION__, cmd, val);\r
-               bcm_mkiovar(cmd, (char *)&val, 4, iovbuf, sizeof(iovbuf));\r
-               if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
-                       CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, cmd, bcmerror));\r
+       if (cmd == WLC_SET_VAR) {\r
+               bcm_mkiovar(name, buf, len, iovbuf, sizeof(iovbuf));\r
+               if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
+                       CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));\r
+       } else {\r
+               if ((ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, TRUE, 0)) < 0)\r
+                       CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, name, ret));\r
        }\r
-       return bcmerror;\r
+\r
+       return ret;\r
 }\r
 \r
 int\r
-dhd_conf_set_fw_string_struct_cmd(dhd_pub_t *dhd, char *cmd, char *val,\r
-       int len, bool down)\r
+dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int ifidx)\r
 {\r
-       int bcmerror = -1;\r
        char iovbuf[WLC_IOCTL_SMLEN];\r
-       \r
-       if (down) {\r
-               if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_DOWN, NULL, 0, TRUE, 0)) < 0)\r
-                       CONFIG_ERROR(("%s: WLC_DOWN setting failed %d\n", __FUNCTION__, bcmerror));\r
+       int ret = -1;\r
+\r
+       if (cmd == WLC_GET_VAR) {\r
+               if (bcm_mkiovar(name, NULL, 0, iovbuf, sizeof(iovbuf))) {\r
+                       ret = dhd_wl_ioctl_cmd(dhd, cmd, iovbuf, sizeof(iovbuf), FALSE, ifidx);\r
+                       if (!ret) {\r
+                               memcpy(buf, iovbuf, len);\r
+                       } else {\r
+                               CONFIG_ERROR(("%s: get iovar %s failed %d\n", __FUNCTION__, name, ret));\r
+                       }\r
+               } else {\r
+                       CONFIG_ERROR(("%s: mkiovar %s failed\n", __FUNCTION__, name));\r
+               }\r
+       } else {\r
+               ret = dhd_wl_ioctl_cmd(dhd, cmd, buf, len, FALSE, 0);\r
+               if (ret < 0)\r
+                       CONFIG_ERROR(("%s: get iovar %s failed %d\n", __FUNCTION__, name, ret));\r
        }\r
-       bcm_mkiovar(cmd, val, len, iovbuf, sizeof(iovbuf));\r
-       if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0)\r
-               CONFIG_ERROR(("%s: %s setting failed %d\n", __FUNCTION__, cmd, bcmerror));\r
 \r
-       return bcmerror;\r
+       return ret;\r
 }\r
 \r
 uint\r
@@ -828,7 +800,7 @@ dhd_conf_set_country(dhd_pub_t *dhd)
        memset(&dhd->dhd_cspec, 0, sizeof(wl_country_t));\r
        printf("%s: set country %s, revision %d\n", __FUNCTION__,\r
                dhd->conf->cspec.ccode, dhd->conf->cspec.rev);\r
-       dhd_conf_set_fw_string_struct_cmd(dhd, "country", (char *)&dhd->conf->cspec, sizeof(wl_country_t), FALSE);\r
+       dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "country", (char *)&dhd->conf->cspec, sizeof(wl_country_t), FALSE);\r
 \r
        return bcmerror;\r
 }\r
@@ -855,7 +827,7 @@ dhd_conf_get_country_from_config(dhd_pub_t *dhd, wl_country_t *cspec)
        struct dhd_conf *conf = dhd->conf;\r
 \r
        for (i = 0; i < conf->country_list.count; i++) {\r
-               if (strcmp(cspec->country_abbrev, conf->country_list.cspec[i].country_abbrev) == 0) {\r
+               if (!strncmp(cspec->country_abbrev, conf->country_list.cspec[i].country_abbrev, 2)) {\r
                        memcpy(cspec->ccode,\r
                                conf->country_list.cspec[i].ccode, WLC_CNTRY_BUF_SZ);\r
                        cspec->rev = conf->country_list.cspec[i].rev;\r
@@ -931,22 +903,22 @@ dhd_conf_set_roam(dhd_pub_t *dhd)
        struct dhd_conf *conf = dhd->conf;\r
 \r
        dhd_roam_disable = conf->roam_off;\r
-       dhd_conf_set_fw_string_cmd(dhd, "roam_off", dhd->conf->roam_off, 0, FALSE);\r
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "roam_off", dhd->conf->roam_off, 0, FALSE);\r
 \r
        if (!conf->roam_off || !conf->roam_off_suspend) {\r
                printf("%s: set roam_trigger %d\n", __FUNCTION__, conf->roam_trigger[0]);\r
-               dhd_conf_set_fw_int_struct_cmd(dhd, "WLC_SET_ROAM_TRIGGER", WLC_SET_ROAM_TRIGGER,\r
-                               conf->roam_trigger, sizeof(conf->roam_trigger), FALSE);\r
+               dhd_conf_set_bufiovar(dhd, WLC_SET_ROAM_TRIGGER, "WLC_SET_ROAM_TRIGGER",\r
+                               (char *)conf->roam_trigger, sizeof(conf->roam_trigger), FALSE);\r
 \r
                printf("%s: set roam_scan_period %d\n", __FUNCTION__, conf->roam_scan_period[0]);\r
-               dhd_conf_set_fw_int_struct_cmd(dhd, "WLC_SET_ROAM_SCAN_PERIOD", WLC_SET_ROAM_SCAN_PERIOD,\r
-                               conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE);\r
+               dhd_conf_set_bufiovar(dhd, WLC_SET_ROAM_SCAN_PERIOD, "WLC_SET_ROAM_SCAN_PERIOD",\r
+                               (char *)conf->roam_scan_period, sizeof(conf->roam_scan_period), FALSE);\r
 \r
                printf("%s: set roam_delta %d\n", __FUNCTION__, conf->roam_delta[0]);\r
-               dhd_conf_set_fw_int_struct_cmd(dhd, "WLC_SET_ROAM_DELTA", WLC_SET_ROAM_DELTA,\r
-                               conf->roam_delta, sizeof(conf->roam_delta), FALSE);\r
-               \r
-               dhd_conf_set_fw_string_cmd(dhd, "fullroamperiod", dhd->conf->fullroamperiod, 1, FALSE);\r
+               dhd_conf_set_bufiovar(dhd, WLC_SET_ROAM_DELTA, "WLC_SET_ROAM_DELTA",\r
+                               (char *)conf->roam_delta, sizeof(conf->roam_delta), FALSE);\r
+\r
+               dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "fullroamperiod", dhd->conf->fullroamperiod, 1, FALSE);\r
        }\r
 \r
        return bcmerror;\r
@@ -964,19 +936,19 @@ dhd_conf_set_bw_cap(dhd_pub_t *dhd)
                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
-               dhd_conf_set_fw_string_struct_cmd(dhd, "bw_cap", (char *)&param, sizeof(param), TRUE);\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
                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
-               dhd_conf_set_fw_string_struct_cmd(dhd, "bw_cap", (char *)&param, sizeof(param), TRUE);\r
+               dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "bw_cap", (char *)&param, sizeof(param), TRUE);\r
        }\r
 }\r
 \r
 void\r
-dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp)\r
+dhd_conf_get_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acp)\r
 {\r
        int bcmerror = -1;\r
        char iovbuf[WLC_IOCTL_SMLEN];\r
@@ -988,7 +960,10 @@ dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp)
         * Get current acparams, using buf as an input buffer.\r
         * Return data is array of 4 ACs of wme params.\r
         */\r
-       bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf));\r
+       if (mode == 0)\r
+               bcm_mkiovar("wme_ac_sta", NULL, 0, iovbuf, sizeof(iovbuf));\r
+       else\r
+               bcm_mkiovar("wme_ac_ap", NULL, 0, iovbuf, sizeof(iovbuf));\r
        if ((bcmerror = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0)) < 0) {\r
                CONFIG_ERROR(("%s: wme_ac_sta getting failed %d\n", __FUNCTION__, bcmerror));\r
                return;\r
@@ -1024,11 +999,17 @@ dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp)
 }\r
 \r
 void\r
-dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)\r
+dhd_conf_update_wme(dhd_pub_t *dhd, int mode, edcf_acparam_t *acparam_cur, int aci)\r
 {\r
        int aifsn, ecwmin, ecwmax, txop;\r
        edcf_acparam_t *acp;\r
        struct dhd_conf *conf = dhd->conf;\r
+       wme_param_t *wme;\r
+\r
+       if (mode == 0)\r
+               wme = &conf->wme_sta;\r
+       else\r
+               wme = &conf->wme_ap;\r
 \r
        /* Default value */\r
        aifsn = acparam_cur->ACI&EDCF_AIFSN_MASK;\r
@@ -1037,17 +1018,17 @@ dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)
        txop = acparam_cur->TXOP;\r
 \r
        /* Modified value */\r
-       if (conf->wme.aifsn[aci] > 0)\r
-               aifsn = conf->wme.aifsn[aci];\r
-       if (conf->wme.ecwmin[aci] > 0)\r
-               ecwmin = conf->wme.ecwmin[aci];\r
-       if (conf->wme.ecwmax[aci] > 0)\r
-               ecwmax = conf->wme.ecwmax[aci];\r
-       if (conf->wme.txop[aci] > 0)\r
-               txop = conf->wme.txop[aci];\r
-\r
-       if (!(conf->wme.aifsn[aci] || conf->wme.ecwmin[aci] ||\r
-                       conf->wme.ecwmax[aci] || conf->wme.txop[aci]))\r
+       if (wme->aifsn[aci] > 0)\r
+               aifsn = wme->aifsn[aci];\r
+       if (wme->ecwmin[aci] > 0)\r
+               ecwmin = wme->ecwmin[aci];\r
+       if (wme->ecwmax[aci] > 0)\r
+               ecwmax = wme->ecwmax[aci];\r
+       if (wme->txop[aci] > 0)\r
+               txop = wme->txop[aci];\r
+\r
+       if (!(wme->aifsn[aci] || wme->ecwmin[aci] ||\r
+                       wme->ecwmax[aci] || wme->txop[aci]))\r
                return;\r
 \r
        /* Update */\r
@@ -1057,8 +1038,8 @@ dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)
        acp->ECW = ((acp->ECW & EDCF_ECWMAX_MASK) | (ecwmin & EDCF_ECWMIN_MASK));\r
        acp->TXOP = txop;\r
 \r
-       printf("%s: mod aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",\r
-               __FUNCTION__,\r
+       printf("%s: wme_ac %s aci %d aifsn %d ecwmin %d ecwmax %d txop 0x%x\n",\r
+               __FUNCTION__, mode?"ap":"sta",\r
                acp->ACI, acp->ACI&EDCF_AIFSN_MASK,\r
                acp->ECW&EDCF_ECWMIN_MASK, (acp->ECW&EDCF_ECWMAX_MASK)>>EDCF_ECWMAX_SHIFT,\r
                acp->TXOP);\r
@@ -1068,12 +1049,15 @@ dhd_conf_update_wme(dhd_pub_t *dhd, edcf_acparam_t *acparam_cur, int aci)
        * Put WME acparams after "wme_ac\0" in buf.\r
        * NOTE: only one of the four ACs can be set at a time.\r
        */\r
-       dhd_conf_set_fw_string_struct_cmd(dhd, "wme_ac_sta", (char *)acp, sizeof(edcf_acparam_t), FALSE);\r
+       if (mode == 0)\r
+               dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "wme_ac_sta", (char *)acp, sizeof(edcf_acparam_t), FALSE);\r
+       else\r
+               dhd_conf_set_bufiovar(dhd, WLC_SET_VAR, "wme_ac_ap", (char *)acp, sizeof(edcf_acparam_t), FALSE);\r
 \r
 }\r
 \r
 void\r
-dhd_conf_set_wme(dhd_pub_t *dhd)\r
+dhd_conf_set_wme(dhd_pub_t *dhd, int mode)\r
 {\r
        edcf_acparam_t acparam_cur[AC_COUNT];\r
 \r
@@ -1085,15 +1069,15 @@ dhd_conf_set_wme(dhd_pub_t *dhd)
                }\r
 \r
                CONFIG_TRACE(("%s: Before change:\n", __FUNCTION__));\r
-               dhd_conf_get_wme(dhd, acparam_cur);\r
+               dhd_conf_get_wme(dhd, mode, acparam_cur);\r
 \r
-               dhd_conf_update_wme(dhd, &acparam_cur[AC_BK], AC_BK);\r
-               dhd_conf_update_wme(dhd, &acparam_cur[AC_BE], AC_BE);\r
-               dhd_conf_update_wme(dhd, &acparam_cur[AC_VI], AC_VI);\r
-               dhd_conf_update_wme(dhd, &acparam_cur[AC_VO], AC_VO);\r
+               dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_BK], AC_BK);\r
+               dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_BE], AC_BE);\r
+               dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_VI], AC_VI);\r
+               dhd_conf_update_wme(dhd, mode, &acparam_cur[AC_VO], AC_VO);\r
 \r
                CONFIG_TRACE(("%s: After change:\n", __FUNCTION__));\r
-               dhd_conf_get_wme(dhd, acparam_cur);\r
+               dhd_conf_get_wme(dhd, mode, acparam_cur);\r
        } else {\r
                CONFIG_ERROR(("%s: dhd or conf is NULL\n", __FUNCTION__));\r
        }\r
@@ -1105,13 +1089,21 @@ dhd_conf_set_wme(dhd_pub_t *dhd)
 void\r
 dhd_conf_add_pkt_filter(dhd_pub_t *dhd)\r
 {\r
-       int i;\r
+       int i, j;\r
        char str[12];\r
 #define MACS "%02x%02x%02x%02x%02x%02x"\r
 \r
        /*\r
-        * All pkt: pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000\r
-        * Netbios pkt: 120 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089\r
+        * 1. Filter out all pkt: actually not to enable this since 4-way handshake will be filter out as well.\r
+        *   1) dhd_master_mode=0\r
+        *   2) pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000\r
+        * 2. Filter in less pkt: ARP(0x0806, ID is 105), BRCM(0x886C), 802.1X(0x888E)\r
+        *   1) dhd_master_mode=1\r
+        *   2) pkt_filter_del=100, 102, 103, 104, 105\r
+        *   3) pkt_filter_add=131 0 0 12 0xFFFF 0x886C, 132 0 0 12 0xFFFF 0x888E\r
+        * 3. magic pkt: magic_pkt_filter_add=141 0 1 12\r
+        * 4. Filter out netbios pkt:\r
+        *   Netbios: 121 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089\r
         */\r
        for(i=0; i<dhd->conf->pkt_filter_add.count; i++) {\r
                dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[i];\r
@@ -1119,15 +1111,17 @@ dhd_conf_add_pkt_filter(dhd_pub_t *dhd)
        }\r
        dhd->pktfilter_count += i;\r
 \r
-       if (dhd->conf->pkt_filter_magic) {\r
-               strcpy(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], "256 0 1 0 0x");\r
-               for (i=0; i<16; i++)\r
-                       strcat(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], "FFFFFFFFFFFF");\r
-               strcat(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], " 0x");\r
+       for(i=0; i<dhd->conf->magic_pkt_filter_add.count; i++) {\r
+               strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], " 0x");\r
+               strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], "FFFFFFFFFFFF");\r
+               for (j=0; j<16; j++)\r
+                       strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], "FFFFFFFFFFFF");\r
+               strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], " 0x");\r
+               strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], "FFFFFFFFFFFF");\r
                sprintf(str, MACS, MAC2STRDBG(dhd->mac.octet));\r
-               for (i=0; i<16; i++)\r
-                       strcat(&dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count][0], str);\r
-               dhd->pktfilter[dhd->pktfilter_count] = dhd->conf->pkt_filter_add.filter[dhd->conf->pkt_filter_add.count];\r
+               for (j=0; j<16; j++)\r
+                       strcat(&dhd->conf->magic_pkt_filter_add.filter[i][0], str);\r
+               dhd->pktfilter[i+dhd->pktfilter_count] = dhd->conf->magic_pkt_filter_add.filter[i];\r
                dhd->pktfilter_count += 1;\r
        }\r
 }\r
@@ -1171,19 +1165,12 @@ dhd_conf_discard_pkt_filter(dhd_pub_t *dhd)
        dhd->pktfilter[dhd->pktfilter_count] = "112 0 0 12 0xFFFF000000000000000000000000000000000000000000000000FF 0x86DD000000000000000000000000000000000000000000000000FF";\r
        dhd->pktfilter_count++;\r
        /* discard Netbios pkt */\r
-       dhd->pktfilter[dhd->pktfilter_count] = "120 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089";\r
+       dhd->pktfilter[dhd->pktfilter_count] = "121 0 0 12 0xFFFF000000000000000000FF000000000000000000000000FFFF 0x0800000000000000000000110000000000000000000000000089";\r
        dhd->pktfilter_count++;\r
 \r
 }\r
 #endif /* PKT_FILTER_SUPPORT */\r
 \r
-void\r
-dhd_conf_set_disable_proptx(dhd_pub_t *dhd)\r
-{\r
-       printf("%s: set disable_proptx %d\n", __FUNCTION__, dhd->conf->disable_proptx);\r
-       disable_proptx = dhd->conf->disable_proptx;\r
-}\r
-\r
 int\r
 dhd_conf_get_pm(dhd_pub_t *dhd)\r
 {\r
@@ -1192,17 +1179,72 @@ dhd_conf_get_pm(dhd_pub_t *dhd)
        return -1;\r
 }\r
 \r
-unsigned int\r
-process_config_vars(char *varbuf, unsigned int len, char *pickbuf, char *param)\r
+#ifdef PROP_TXSTATUS\r
+int\r
+dhd_conf_get_disable_proptx(dhd_pub_t *dhd)\r
+{\r
+       struct dhd_conf *conf = dhd->conf;\r
+       int disable_proptx = -1;\r
+       int fw_proptx = 0;\r
+\r
+       /* check fw proptx priority:\r
+         * 1st: check fw support by wl cap\r
+         * 2nd: 4334/43340/43341/43241 support proptx but not show in wl cap, so enable it by default\r
+         *        if you would like to disable it, please set disable_proptx=1 in config.txt\r
+         * 3th: disable when proptxstatus not support in wl cap\r
+         */\r
+       if (FW_SUPPORTED(dhd, proptxstatus)) {\r
+               fw_proptx = 1;\r
+       } else if (conf->chip == BCM4334_CHIP_ID || conf->chip == BCM43340_CHIP_ID ||\r
+                       dhd->conf->chip == BCM43340_CHIP_ID || conf->chip == BCM4324_CHIP_ID) {\r
+               fw_proptx = 1;\r
+       } else {\r
+               fw_proptx = 0;\r
+       }\r
+\r
+       /* returned disable_proptx value:\r
+         * -1: disable in STA and enable in P2P(follow original dhd settings when PROP_TXSTATUS_VSDB enabled)\r
+         * 0: depend on fw support\r
+         * 1: always disable proptx\r
+         */\r
+       if (conf->disable_proptx == 0) {\r
+               // check fw support as well\r
+               if (fw_proptx)\r
+                       disable_proptx = 0;\r
+               else\r
+                       disable_proptx = 1;\r
+       } else if (conf->disable_proptx >= 1) {\r
+               disable_proptx = 1;\r
+       } else {\r
+               // check fw support as well\r
+               if (fw_proptx)\r
+                       disable_proptx = -1;\r
+               else\r
+                       disable_proptx = 1;\r
+       }\r
+\r
+       printf("%s: fw_proptx=%d, disable_proptx=%d\n", __FUNCTION__, fw_proptx, disable_proptx);\r
+\r
+       return disable_proptx;\r
+}\r
+#endif\r
+\r
+uint\r
+pick_config_vars(char *varbuf, uint len, uint start_pos, char *pickbuf)\r
 {\r
        bool findNewline, changenewline=FALSE, pick=FALSE;\r
        int column;\r
-       unsigned int n, pick_column=0;\r
+       uint n, pick_column=0;\r
 \r
        findNewline = FALSE;\r
        column = 0;\r
 \r
-       for (n = 0; n < len; n++) {\r
+       if (start_pos >= len) {\r
+               CONFIG_ERROR(("%s: wrong start pos\n", __FUNCTION__));\r
+               return 0;\r
+       }\r
+\r
+       for (n = start_pos; n < len; n++) {\r
                if (varbuf[n] == '\r')\r
                        continue;\r
                if ((findNewline || changenewline) && varbuf[n] != '\n')\r
@@ -1226,15 +1268,16 @@ process_config_vars(char *varbuf, unsigned int len, char *pickbuf, char *param)
                        changenewline = FALSE;\r
                        continue;\r
                }\r
-               if (!memcmp(&varbuf[n], param, strlen(param)) && column==0) {\r
+\r
+               if (column==0 && !pick) { // start to pick\r
                        pick = TRUE;\r
-                       column = strlen(param);\r
-                       n += column;\r
+                       column++;\r
                        pick_column = 0;\r
                } else {\r
-                       if (pick && column==0)\r
+                       if (pick && column==0) { // stop to pick\r
                                pick = FALSE;\r
-                       else\r
+                               break;\r
+                       } else\r
                                column++;\r
                }\r
                if (pick) {\r
@@ -1247,191 +1290,142 @@ process_config_vars(char *varbuf, unsigned int len, char *pickbuf, char *param)
                }\r
        }\r
 \r
-       return pick_column;\r
+       return n; // return current position\r
 }\r
 \r
-void\r
-dhd_conf_read_log_level(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_log_level(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
-       char *pick;\r
-\r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
+       char *data = full_param+len_param;\r
 \r
-       /* Process dhd_msglevel */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "msglevel=");\r
-       if (len_val) {\r
-               dhd_msg_level = (int)simple_strtol(pick, NULL, 0);\r
+       if (!strncmp("dhd_msg_level=", full_param, len_param)) {\r
+               dhd_msg_level = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: dhd_msg_level = 0x%X\n", __FUNCTION__, dhd_msg_level);\r
        }\r
 #ifdef BCMSDIO\r
-       /* Process sd_msglevel */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "sd_msglevel=");\r
-       if (len_val) {\r
-               sd_msglevel = (int)simple_strtol(pick, NULL, 0);\r
+       else if (!strncmp("sd_msglevel=", full_param, len_param)) {\r
+               sd_msglevel = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: sd_msglevel = 0x%X\n", __FUNCTION__, sd_msglevel);\r
        }\r
 #endif\r
-       /* Process android_msg_level */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "android_msg_level=");\r
-       if (len_val) {\r
-               android_msg_level = (int)simple_strtol(pick, NULL, 0);\r
+       else if (!strncmp("android_msg_level=", full_param, len_param)) {\r
+               android_msg_level = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: android_msg_level = 0x%X\n", __FUNCTION__, android_msg_level);\r
        }\r
-       /* Process config_msg_level */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "config_msg_level=");\r
-       if (len_val) {\r
-               config_msg_level = (int)simple_strtol(pick, NULL, 0);\r
+       else if (!strncmp("config_msg_level=", full_param, len_param)) {\r
+               config_msg_level = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: config_msg_level = 0x%X\n", __FUNCTION__, config_msg_level);\r
        }\r
 #ifdef WL_CFG80211\r
-       /* Process wl_dbg_level */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "wl_dbg_level=");\r
-       if (len_val) {\r
-               wl_dbg_level = (int)simple_strtol(pick, NULL, 0);\r
+       else if (!strncmp("wl_dbg_level=", full_param, len_param)) {\r
+               wl_dbg_level = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: wl_dbg_level = 0x%X\n", __FUNCTION__, wl_dbg_level);\r
        }\r
 #endif\r
 #if defined(WL_WIRELESS_EXT)\r
-       /* Process iw_msg_level */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "iw_msg_level=");\r
-       if (len_val) {\r
-               iw_msg_level = (int)simple_strtol(pick, NULL, 0);\r
+       else if (!strncmp("iw_msg_level=", full_param, len_param)) {\r
+               iw_msg_level = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: iw_msg_level = 0x%X\n", __FUNCTION__, iw_msg_level);\r
        }\r
 #endif\r
-\r
 #if defined(DHD_DEBUG)\r
-       /* Process dhd_console_ms */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "dhd_console_ms=");\r
-       if (len_val) {\r
-               dhd_console_ms = (int)simple_strtol(pick, NULL, 0);\r
+       else if (!strncmp("dhd_console_ms=", full_param, len_param)) {\r
+               dhd_console_ms = (int)simple_strtol(data, NULL, 0);\r
                printf("%s: dhd_console_ms = 0x%X\n", __FUNCTION__, dhd_console_ms);\r
        }\r
 #endif\r
+       else\r
+               return false;\r
 \r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
+       return true;\r
 }\r
 
 void\r
-dhd_conf_read_wme_ac_value(dhd_pub_t *dhd, char *pick, uint len, int ac_val)\r
+dhd_conf_read_wme_ac_value(wme_param_t *wme, char *pick, int ac_val)\r
 {\r
        char *pick_tmp, *pch;\r
-       struct dhd_conf *conf = dhd->conf;\r
 \r
        /* Process WMM parameters */\r
-       if (len) {\r
-               pick_tmp = pick;\r
-               pch = bcmstrstr(pick_tmp, "aifsn ");\r
-               if (pch) {\r
-                       conf->wme.aifsn[ac_val] = (int)simple_strtol(pch+strlen("aifsn "), NULL, 0);\r
-                       printf("%s: ac_val=%d, aifsn=%d\n", __FUNCTION__, ac_val, conf->wme.aifsn[ac_val]);\r
-               }\r
-               pick_tmp = pick;\r
-               pch = bcmstrstr(pick_tmp, "ecwmin ");\r
-               if (pch) {\r
-                       conf->wme.ecwmin[ac_val] = (int)simple_strtol(pch+strlen("ecwmin "), NULL, 0);\r
-                       printf("%s: ac_val=%d, ecwmin=%d\n", __FUNCTION__, ac_val, conf->wme.ecwmin[ac_val]);\r
-               }\r
-               pick_tmp = pick;\r
-               pch = bcmstrstr(pick_tmp, "ecwmax ");\r
-               if (pch) {\r
-                       conf->wme.ecwmax[ac_val] = (int)simple_strtol(pch+strlen("ecwmax "), NULL, 0);\r
-                       printf("%s: ac_val=%d, ecwmax=%d\n", __FUNCTION__, ac_val, conf->wme.ecwmax[ac_val]);\r
-               }\r
-               pick_tmp = pick;\r
-               pch = bcmstrstr(pick_tmp, "txop ");\r
-               if (pch) {\r
-                       conf->wme.txop[ac_val] = (int)simple_strtol(pch+strlen("txop "), NULL, 0);\r
-                       printf("%s: ac_val=%d, txop=0x%x\n", __FUNCTION__, ac_val, conf->wme.txop[ac_val]);\r
-               }\r
+       pick_tmp = pick;\r
+       pch = bcmstrstr(pick_tmp, "aifsn ");\r
+       if (pch) {\r
+               wme->aifsn[ac_val] = (int)simple_strtol(pch+strlen("aifsn "), NULL, 0);\r
+               printf("%s: ac_val=%d, aifsn=%d\n", __FUNCTION__, ac_val, wme->aifsn[ac_val]);\r
+       }\r
+       pick_tmp = pick;\r
+       pch = bcmstrstr(pick_tmp, "ecwmin ");\r
+       if (pch) {\r
+               wme->ecwmin[ac_val] = (int)simple_strtol(pch+strlen("ecwmin "), NULL, 0);\r
+               printf("%s: ac_val=%d, ecwmin=%d\n", __FUNCTION__, ac_val, wme->ecwmin[ac_val]);\r
+       }\r
+       pick_tmp = pick;\r
+       pch = bcmstrstr(pick_tmp, "ecwmax ");\r
+       if (pch) {\r
+               wme->ecwmax[ac_val] = (int)simple_strtol(pch+strlen("ecwmax "), NULL, 0);\r
+               printf("%s: ac_val=%d, ecwmax=%d\n", __FUNCTION__, ac_val, wme->ecwmax[ac_val]);\r
+       }\r
+       pick_tmp = pick;\r
+       pch = bcmstrstr(pick_tmp, "txop ");\r
+       if (pch) {\r
+               wme->txop[ac_val] = (int)simple_strtol(pch+strlen("txop "), NULL, 0);\r
+               printf("%s: ac_val=%d, txop=0x%x\n", __FUNCTION__, ac_val, wme->txop[ac_val]);\r
        }\r
 \r
 }\r
 
-void\r
-dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_wme_ac_params(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
-       char *pick;\r
        struct dhd_conf *conf = dhd->conf;\r
+       char *data = full_param+len_param;\r
 \r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
-       // wme_ac_sta_be aifsn 1 ecwmin 2 ecwmax 3 txop 0x5e\r
-       // wme_ac_sta_vo aifsn 1 ecwmin 1 ecwmax 1 txop 0x5e\r
+       // wme_ac_sta_be=aifsn 1 ecwmin 2 ecwmax 3 txop 0x5e\r
+       // wme_ac_sta_vo=aifsn 1 ecwmin 1 ecwmax 1 txop 0x5e\r
 \r
        /* Process WMM parameters */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "force_wme_ac=");\r
-       if (len_val) {\r
-               conf->force_wme_ac = (int)simple_strtol(pick, NULL, 10);\r
+       if (!strncmp("force_wme_ac=", full_param, len_param)) {\r
+               conf->force_wme_ac = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: force_wme_ac = %d\n", __FUNCTION__, conf->force_wme_ac);\r
        }
-\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "wme_ac_sta_be=");\r
-       if (len_val) {\r
-               dhd_conf_read_wme_ac_value(dhd, pick, len, AC_BE);\r
+       else if (!strncmp("wme_ac_sta_be=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BE);\r
        }\r
-\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "wme_ac_sta_bk=");\r
-       if (len_val) {\r
-               dhd_conf_read_wme_ac_value(dhd, pick, len, AC_BK);\r
+       else if (!strncmp("wme_ac_sta_bk=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_BK);\r
        }\r
-\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "wme_ac_sta_vi=");\r
-       if (len_val) {\r
-               dhd_conf_read_wme_ac_value(dhd, pick, len, AC_VI);\r
+       else if (!strncmp("wme_ac_sta_vi=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_VI);\r
        }\r
-\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "wme_ac_sta_vo=");\r
-       if (len_val) {\r
-               dhd_conf_read_wme_ac_value(dhd, pick, len, AC_VO);\r
+       else if (!strncmp("wme_ac_sta_vo=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_sta, data, AC_VO);\r
        }\r
+       else if (!strncmp("wme_ac_ap_be=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_BE);\r
+       }\r
+       else if (!strncmp("wme_ac_ap_bk=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_BK);\r
+       }\r
+       else if (!strncmp("wme_ac_ap_vi=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_VI);\r
+       }\r
+       else if (!strncmp("wme_ac_ap_vo=", full_param, len_param)) {\r
+               dhd_conf_read_wme_ac_value(&conf->wme_ap, data, AC_VO);\r
+       }\r
+       else\r
+               return false;\r
 \r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
-\r
+       return true;\r
 }\r
 \r
-void\r
-dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
        int i, j;\r
-       char *pick;\r
        char *pch, *pick_tmp;\r
        wl_mac_list_t *mac_list;\r
        wl_mac_range_t *mac_range;\r
        struct dhd_conf *conf = dhd->conf;\r
-\r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
+       char *data = full_param+len_param;\r
 \r
        /* Process fw_by_mac:\r
         * fw_by_mac=[fw_mac_num] \\r
@@ -1446,10 +1440,9 @@ dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *bufp, uint len)
         *  fw_bcmdhd2.bin 3 0x0022F4 0xE85408 0xE8549D 0x983B16 0x3557A9 0x35582A \\r
         *                           0x983B16 0x916157 0x916487\r
         */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "fw_by_mac=");\r
-       if (len_val) {\r
-               pick_tmp = pick;\r
+\r
+       if (!strncmp("fw_by_mac=", full_param, len_param)) {\r
+               pick_tmp = data;\r
                pch = bcmstrtok(&pick_tmp, " ", 0);\r
                conf->fw_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
                if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->fw_by_mac.count, GFP_KERNEL))) {\r
@@ -1484,36 +1477,27 @@ dhd_conf_read_fw_by_mac(dhd_pub_t *dhd, char *bufp, uint len)
                        }\r
                }\r
        }\r
+       else\r
+               return false;\r
 \r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
+       return true;\r
 }\r
 \r
-void\r
-dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
        int i, j;\r
-       char *pick;\r
        char *pch, *pick_tmp;\r
        wl_mac_list_t *mac_list;\r
        wl_mac_range_t *mac_range;\r
        struct dhd_conf *conf = dhd->conf;\r
-\r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
+       char *data = full_param+len_param;\r
 \r
        /* Process nv_by_mac:\r
         * [nv_by_mac]: The same format as fw_by_mac\r
         */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "nv_by_mac=");\r
-       if (len_val) {\r
-               pick_tmp = pick;\r
+       if (!strncmp("nv_by_mac=", full_param, len_param)) {\r
+               pick_tmp = data;\r
                pch = bcmstrtok(&pick_tmp, " ", 0);\r
                conf->nv_by_mac.count = (uint32)simple_strtol(pch, NULL, 0);\r
                if (!(mac_list = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_mac.count, GFP_KERNEL))) {\r
@@ -1548,27 +1532,20 @@ dhd_conf_read_nv_by_mac(dhd_pub_t *dhd, char *bufp, uint len)
                        }\r
                }\r
        }\r
+       else\r
+               return false;\r
 \r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
+       return true;\r
 }\r
 \r
-void\r
-dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
        int i;\r
-       char *pick;\r
        char *pch, *pick_tmp;\r
        wl_chip_nv_path_t *chip_nv_path;\r
        struct dhd_conf *conf = dhd->conf;\r
-\r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
+       char *data = full_param+len_param;\r
 \r
        /* Process nv_by_chip:\r
         * nv_by_chip=[nv_chip_num] \\r
@@ -1576,10 +1553,8 @@ dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *bufp, uint len)
         * Ex: nv_by_chip=2 \\r
         *  43430 0 nvram_ap6212.txt 43430 1 nvram_ap6212a.txt \\r
         */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "nv_by_chip=");\r
-       if (len_val) {\r
-               pick_tmp = pick;\r
+       if (!strncmp("nv_by_chip=", full_param, len_param)) {\r
+               pick_tmp = data;\r
                pch = bcmstrtok(&pick_tmp, " ", 0);\r
                conf->nv_by_chip.count = (uint32)simple_strtol(pch, NULL, 0);\r
                if (!(chip_nv_path = kmalloc(sizeof(wl_mac_list_t)*conf->nv_by_chip.count, GFP_KERNEL))) {\r
@@ -1599,105 +1574,71 @@ dhd_conf_read_nv_by_chip(dhd_pub_t *dhd, char *bufp, uint len)
                                chip_nv_path[i].chip, chip_nv_path[i].chiprev, chip_nv_path[i].name);\r
                }\r
        }\r
+       else\r
+               return false;\r
 \r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
+       return true;\r
 }\r
 \r
-void\r
-dhd_conf_read_roam_params(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_roam_params(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
-       char *pick;\r
        struct dhd_conf *conf = dhd->conf;\r
+       char *data = full_param+len_param;\r
 \r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
-\r
-       /* Process roam */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "roam_off=");\r
-       if (len_val) {\r
-               if (!strncmp(pick, "0", len_val))\r
+       if (!strncmp("roam_off=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
                        conf->roam_off = 0;\r
                else\r
                        conf->roam_off = 1;\r
                printf("%s: roam_off = %d\n", __FUNCTION__, conf->roam_off);\r
        }\r
-\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "roam_off_suspend=");\r
-       if (len_val) {\r
-               if (!strncmp(pick, "0", len_val))\r
+       else if (!strncmp("roam_off_suspend=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
                        conf->roam_off_suspend = 0;\r
                else\r
                        conf->roam_off_suspend = 1;\r
-               printf("%s: roam_off_suspend = %d\n", __FUNCTION__,\r
-                       conf->roam_off_suspend);\r
+               printf("%s: roam_off_suspend = %d\n", __FUNCTION__, conf->roam_off_suspend);\r
        }\r
-\r
-       if (!conf->roam_off || !conf->roam_off_suspend) {\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "roam_trigger=");\r
-               if (len_val)\r
-                       conf->roam_trigger[0] = (int)simple_strtol(pick, NULL, 10);\r
+       else if (!strncmp("roam_trigger=", full_param, len_param)) {\r
+               conf->roam_trigger[0] = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: roam_trigger = %d\n", __FUNCTION__,\r
                        conf->roam_trigger[0]);\r
-\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "roam_scan_period=");\r
-               if (len_val)\r
-                       conf->roam_scan_period[0] = (int)simple_strtol(pick, NULL, 10);\r
+       }\r
+       else if (!strncmp("roam_scan_period=", full_param, len_param)) {\r
+               conf->roam_scan_period[0] = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: roam_scan_period = %d\n", __FUNCTION__,\r
                        conf->roam_scan_period[0]);\r
-\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "roam_delta=");\r
-               if (len_val)\r
-                       conf->roam_delta[0] = (int)simple_strtol(pick, NULL, 10);\r
+       }\r
+       else if (!strncmp("roam_delta=", full_param, len_param)) {\r
+               conf->roam_delta[0] = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: roam_delta = %d\n", __FUNCTION__, conf->roam_delta[0]);\r
-\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "fullroamperiod=");\r
-               if (len_val)\r
-                       conf->fullroamperiod = (int)simple_strtol(pick, NULL, 10);\r
+       }\r
+       else if (!strncmp("fullroamperiod=", full_param, len_param)) {\r
+               conf->fullroamperiod = (int)simple_strtol(data, NULL, 10);\r
                printf("%s: fullroamperiod = %d\n", __FUNCTION__,\r
                        conf->fullroamperiod);\r
-       }\r
-\r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
+       } else\r
+               return false;\r
 \r
+       return true;\r
 }\r
 \r
-void\r
-dhd_conf_read_country_list(dhd_pub_t *dhd, char *bufp, uint len)\r
+bool\r
+dhd_conf_read_country_list(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       uint len_val;\r
        int i;\r
-       char *pick, *pch, *pick_tmp;\r
+       char *pch, *pick_tmp;\r
        struct dhd_conf *conf = dhd->conf;\r
-\r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               return;\r
-       }\r
+       char *data = full_param+len_param;\r
 \r
        /* Process country_list:\r
         * country_list=[country1]:[ccode1]/[regrev1],\r
         * [country2]:[ccode2]/[regrev2] \\r
         * Ex: country_list=US:US/0, TW:TW/1\r
         */\r
-       memset(pick, 0, MAXSZ_BUF);\r
-       len_val = process_config_vars(bufp, len, pick, "country_list=");\r
-       if (len_val) {\r
-               pick_tmp = pick;\r
+       if (!strncmp("country_list=", full_param, len_param)) {\r
+               pick_tmp = data;\r
                for (i=0; i<CONFIG_COUNTRY_LIST_SIZE; i++) {\r
                        /* Process country code */\r
                        pch = bcmstrtok(&pick_tmp, ":", 0);\r
@@ -1720,544 +1661,561 @@ dhd_conf_read_country_list(dhd_pub_t *dhd, char *bufp, uint len)
                }\r
                printf("%s: %d country in list\n", __FUNCTION__, conf->country_list.count);\r
        }\r
+       else\r
+               return false;\r
 \r
-       if (pick)\r
-               MFREE(dhd->osh, pick, MAXSZ_BUF);\r
+       return true;\r
 }\r
 \r
-int\r
-dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)\r
+#ifdef PKT_FILTER_SUPPORT\r
+bool\r
+dhd_conf_read_pkt_filter(dhd_pub_t *dhd, char *full_param, uint len_param)\r
 {\r
-       int bcmerror = -1, i;\r
-       uint len, len_val;\r
-       void * image = NULL;\r
-       char * memblock = NULL;\r
-       char *bufp, *pick = NULL, *pch, *pick_tmp;\r
-       bool conf_file_exists;\r
        struct dhd_conf *conf = dhd->conf;\r
+       char *data = full_param+len_param;\r
+       char *pch, *pick_tmp;\r
+       int i;\r
 \r
-       conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));\r
-       if (!conf_file_exists) {\r
-               printf("%s: config path %s\n", __FUNCTION__, conf_path);\r
-               return (0);\r
-       }\r
-\r
-       if (conf_file_exists) {\r
-               image = dhd_os_open_image(conf_path);\r
-               if (image == NULL) {\r
-                       printf("%s: Ignore config file %s\n", __FUNCTION__, conf_path);\r
-                       goto err;\r
+       /* Process pkt filter:\r
+        * 1) pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000\r
+        * 2) pkt_filter_del=100, 102, 103, 104, 105\r
+        * 3) magic_pkt_filter_add=141 0 1 12\r
+        */\r
+       if (!strncmp("dhd_master_mode=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       dhd_master_mode = FALSE;\r
+               else\r
+                       dhd_master_mode = TRUE;\r
+               printf("%s: dhd_master_mode = %d\n", __FUNCTION__, dhd_master_mode);\r
+       }\r
+       else if (!strncmp("pkt_filter_add=", full_param, len_param)) {\r
+               pick_tmp = data;\r
+               pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
+               i=0;\r
+               while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
+                       strcpy(&conf->pkt_filter_add.filter[i][0], pch);\r
+                       printf("%s: pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->pkt_filter_add.filter[i][0]);\r
+                       pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
+                       i++;\r
                }\r
+               conf->pkt_filter_add.count = i;\r
        }\r
-\r
-       memblock = MALLOC(dhd->osh, MAXSZ_CONFIG);\r
-       if (memblock == NULL) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_CONFIG));\r
-               goto err;\r
-       }\r
-\r
-       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
-       if (!pick) {\r
-               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
-                       __FUNCTION__, MAXSZ_BUF));\r
-               goto err;\r
-       }\r
-\r
-       /* Read variables */\r
-       if (conf_file_exists) {\r
-               len = dhd_os_get_image_block(memblock, MAXSZ_CONFIG, image);\r
-       }\r
-       if (len > 0 && len < MAXSZ_CONFIG) {\r
-               bufp = (char *)memblock;\r
-               bufp[len] = 0;\r
-\r
-               /* Process log_level */\r
-               dhd_conf_read_log_level(dhd, bufp, len);\r
-               dhd_conf_read_roam_params(dhd, bufp, len);\r
-               dhd_conf_read_wme_ac_params(dhd, bufp, len);
-               dhd_conf_read_fw_by_mac(dhd, bufp, len);\r
-               dhd_conf_read_nv_by_mac(dhd, bufp, len);\r
-               dhd_conf_read_nv_by_chip(dhd, bufp, len);\r
-               dhd_conf_read_country_list(dhd, bufp, len);\r
-\r
-               /* Process band:\r
-                * band=a for 5GHz only and band=b for 2.4GHz only\r
-                */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "band=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "b", len_val))\r
-                               conf->band = WLC_BAND_2G;\r
-                       else if (!strncmp(pick, "a", len_val))\r
-                               conf->band = WLC_BAND_5G;\r
-                       else\r
-                               conf->band = WLC_BAND_AUTO;\r
-                       printf("%s: band = %d\n", __FUNCTION__, conf->band);\r
-               }\r
-\r
-               /* Process mimo_bw_cap */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "mimo_bw_cap=");\r
-               if (len_val) {\r
-                       conf->mimo_bw_cap = (uint)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: mimo_bw_cap = %d\n", __FUNCTION__, conf->mimo_bw_cap);\r
-               }\r
-\r
-               /* Process bw_cap_2g */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "bw_cap_2g=");\r
-               if (len_val) {\r
-                       conf->bw_cap_2g = (uint)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: bw_cap_2g = %d\n", __FUNCTION__, conf->bw_cap_2g);\r
-               }\r
-\r
-               /* Process bw_cap_5g */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "bw_cap_5g=");\r
-               if (len_val) {\r
-                       conf->bw_cap_5g = (uint)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: bw_cap_5g = %d\n", __FUNCTION__, conf->bw_cap_5g);\r
-               }\r
-\r
-               /* Process country code */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "ccode=");\r
-               if (len_val) {\r
-                       memset(&conf->cspec, 0, sizeof(wl_country_t));\r
-                       memcpy(conf->cspec.country_abbrev, pick, len_val);\r
-                       memcpy(conf->cspec.ccode, pick, len_val);\r
-                       memset(pick, 0, MAXSZ_BUF);\r
-                       len_val = process_config_vars(bufp, len, pick, "regrev=");\r
-                       if (len_val)\r
-                               conf->cspec.rev = (int32)simple_strtol(pick, NULL, 10);\r
-               }\r
-\r
-               /* Process channels */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "channels=");\r
-               pick_tmp = pick;\r
-               if (len_val) {\r
+       else if (!strncmp("pkt_filter_del=", full_param, len_param)) {\r
+               pick_tmp = data;\r
+               pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+               i=0;\r
+               while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
+                       conf->pkt_filter_del.id[i] = (uint32)simple_strtol(pch, NULL, 10);\r
                        pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
-                       i=0;\r
-                       while (pch != NULL && i<WL_NUMCHANNELS) {\r
-                               conf->channels.channel[i] = (uint32)simple_strtol(pch, NULL, 10);\r
-                               pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
-                               i++;\r
-                       }\r
-                       conf->channels.count = i;\r
-                       printf("%s: channels = ", __FUNCTION__);\r
-                       for (i=0; i<conf->channels.count; i++)\r
-                               printf("%d ", conf->channels.channel[i]);\r
-                       printf("\n");\r
-               }\r
-\r
-               /* Process keep alive period */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "keep_alive_period=");\r
-               if (len_val) {\r
-                       conf->keep_alive_period = (uint)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: keep_alive_period = %d\n", __FUNCTION__,\r
-                               conf->keep_alive_period);\r
-               }\r
-\r
-               /* Process STBC parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "stbc=");\r
-               if (len_val) {\r
-                       conf->stbc = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: stbc = %d\n", __FUNCTION__, conf->stbc);\r
-               }\r
-\r
-               /* Process phy_oclscdenable parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "phy_oclscdenable=");\r
-               if (len_val) {\r
-                       conf->phy_oclscdenable = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: phy_oclscdenable = %d\n", __FUNCTION__, conf->phy_oclscdenable);\r
-               }\r
-\r
-#ifdef BCMSDIO\r
-               /* Process dhd_doflow parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "dhd_doflow=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "0", len_val))\r
-                               dhd_doflow = FALSE;\r
-                       else\r
-                               dhd_doflow = TRUE;\r
-                       printf("%s: dhd_doflow = %d\n", __FUNCTION__, dhd_doflow);\r
-               }\r
-\r
-               /* Process dhd_slpauto parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "dhd_slpauto=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "0", len_val))\r
-                               dhd_slpauto = FALSE;\r
-                       else\r
-                               dhd_slpauto = TRUE;\r
-                       printf("%s: dhd_slpauto = %d\n", __FUNCTION__, dhd_slpauto);\r
-               }\r
-#endif\r
-\r
-               /* Process dhd_master_mode parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "dhd_master_mode=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "0", len_val))\r
-                               dhd_master_mode = FALSE;\r
-                       else\r
-                               dhd_master_mode = TRUE;\r
-                       printf("%s: dhd_master_mode = %d\n", __FUNCTION__, dhd_master_mode);\r
-               }\r
-\r
-#ifdef PKT_FILTER_SUPPORT\r
-               /* Process pkt_filter_add:\r
-                * All pkt: pkt_filter_add=99 0 0 0 0x000000000000 0x000000000000\r
-                */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "pkt_filter_add=");\r
-               pick_tmp = pick;\r
-               if (len_val) {\r
+                       i++;\r
+               }\r
+               conf->pkt_filter_del.count = i;\r
+               printf("%s: pkt_filter_del id = ", __FUNCTION__);\r
+               for (i=0; i<conf->pkt_filter_del.count; i++)\r
+                       printf("%d ", conf->pkt_filter_del.id[i]);\r
+               printf("\n");\r
+       }\r
+       else if (!strncmp("magic_pkt_filter_add=", full_param, len_param)) {\r
+               pick_tmp = data;\r
+               pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
+               i=0;\r
+               while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
+                       strcpy(&conf->magic_pkt_filter_add.filter[i][0], pch);\r
+                       printf("%s: magic_pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->magic_pkt_filter_add.filter[i][0]);\r
                        pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
-                       i=0;\r
-                       while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
-                               strcpy(&conf->pkt_filter_add.filter[i][0], pch);\r
-                               printf("%s: pkt_filter_add[%d][] = %s\n", __FUNCTION__, i, &conf->pkt_filter_add.filter[i][0]);\r
-                               pch = bcmstrtok(&pick_tmp, ",.-", 0);\r
-                               i++;\r
-                       }\r
-                       conf->pkt_filter_add.count = i;\r
+                       i++;\r
                }\r
+               conf->magic_pkt_filter_add.count = i;\r
+       }\r
+       else\r
+               return false;\r
 \r
-               /* Process pkt_filter_del */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "pkt_filter_del=");\r
-               pick_tmp = pick;\r
-               if (len_val) {\r
-                       pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
-                       i=0;\r
-                       while (pch != NULL && i<DHD_CONF_FILTER_MAX) {\r
-                               conf->pkt_filter_del.id[i] = (uint32)simple_strtol(pch, NULL, 10);\r
-                               pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
-                               i++;\r
-                       }\r
-                       conf->pkt_filter_del.count = i;\r
-                       printf("%s: pkt_filter_del id = ", __FUNCTION__);\r
-                       for (i=0; i<conf->pkt_filter_del.count; i++)\r
-                               printf("%d ", conf->pkt_filter_del.id[i]);\r
-                       printf("\n");\r
-               }\r
+       return true;\r
+}\r
 #endif\r
 \r
-               /* Process srl parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "srl=");\r
-               if (len_val) {\r
-                       conf->srl = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: srl = %d\n", __FUNCTION__, conf->srl);\r
-               }\r
-\r
-               /* Process lrl parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "lrl=");\r
-               if (len_val) {\r
-                       conf->lrl = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: lrl = %d\n", __FUNCTION__, conf->lrl);\r
-               }\r
-\r
-               /* Process beacon timeout parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "bcn_timeout=");\r
-               if (len_val) {\r
-                       conf->bcn_timeout= (uint)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: bcn_timeout = %d\n", __FUNCTION__, conf->bcn_timeout);\r
-               }\r
+#ifdef IAPSTA_PREINIT\r
+/*\r
+ * iapsta_init=mode [sta|ap|apsta|dualap] vifname [wlan1]\r
+ * iapsta_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
+*/\r
+bool\r
+dhd_conf_read_iapsta(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
-               /* Process ampdu_ba_wsize parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "ampdu_ba_wsize=");\r
-               if (len_val) {\r
-                       conf->ampdu_ba_wsize = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: ampdu_ba_wsize = %d\n", __FUNCTION__, conf->ampdu_ba_wsize);\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
+       }\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
+       }\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
+       }\r
+       else\r
+               return false;\r
 \r
-               /* Process spect parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "spect=");\r
-               if (len_val) {\r
-                       conf->spect = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: spect = %d\n", __FUNCTION__, conf->spect);\r
-               }\r
+       return true;\r
+}\r
+#endif\r
 \r
-               /* Process txbf parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "txbf=");\r
-               if (len_val) {\r
-                       conf->txbf = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: txbf = %d\n", __FUNCTION__, conf->txbf);\r
-               }\r
+#ifdef IDHCPC\r
+bool\r
+dhd_conf_read_dhcp_params(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
-               /* Process frameburst parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "frameburst=");\r
-               if (len_val) {\r
-                       conf->frameburst = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: frameburst = %d\n", __FUNCTION__, conf->frameburst);\r
-               }\r
+       if (!strncmp("dhcpc_enable=", full_param, len_param)) {\r
+               conf->dhcpc_enable = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: dhcpc_enable = %d\n", __FUNCTION__, conf->dhcpc_enable);\r
+       }\r
+       else\r
+               return false;\r
 \r
-               /* Process lpc parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "lpc=");\r
-               if (len_val) {\r
-                       conf->lpc = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: lpc = %d\n", __FUNCTION__, conf->lpc);\r
-               }\r
+       return true;\r
+}\r
+#endif\r
 \r
 #ifdef BCMSDIO\r
-               /* Process kso_enable parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "kso_enable=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "0", len_val))\r
-                               conf->kso_enable = FALSE;\r
-                       else\r
-                               conf->kso_enable = TRUE;\r
-               }\r
-               conf->kso_enable = FALSE;
-               /* Process bus:txglom */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "bus:txglom=");\r
-               if (len_val) {\r
-                       conf->bus_txglom = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: bus:txglom = %d\n", __FUNCTION__, conf->bus_txglom);
-               }\r
+bool\r
+dhd_conf_read_sdio_params(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
-               /* Process use_rxchain parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "use_rxchain=");\r
-               if (len_val) {\r
-                       conf->use_rxchain = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: use_rxchain = %d\n", __FUNCTION__, conf->use_rxchain);\r
-               }\r
+       if (!strncmp("dhd_doflow=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       dhd_doflow = FALSE;\r
+               else\r
+                       dhd_doflow = TRUE;\r
+               printf("%s: dhd_doflow = %d\n", __FUNCTION__, dhd_doflow);\r
+       }\r
+       else if (!strncmp("dhd_slpauto=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       dhd_slpauto = FALSE;\r
+               else\r
+                       dhd_slpauto = TRUE;\r
+               printf("%s: dhd_slpauto = %d\n", __FUNCTION__, dhd_slpauto);\r
+       }\r
+       else if (!strncmp("kso_enable=", full_param, len_param)) {\r
+               if (!strncmp(data, "1", 1))\r
+                       dhd_slpauto = FALSE;\r
+               else\r
+                       dhd_slpauto = TRUE;\r
+               printf("%s: dhd_slpauto = %d\n", __FUNCTION__, dhd_slpauto);\r
+       }\r
+       else if (!strncmp("bus:txglom=", full_param, len_param)) {\r
+               conf->bus_txglom = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: bus:txglom = %d\n", __FUNCTION__, conf->bus_txglom);\r
+       }\r
+       else if (!strncmp("use_rxchain=", full_param, len_param)) {\r
+               conf->use_rxchain = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: use_rxchain = %d\n", __FUNCTION__, conf->use_rxchain);\r
+       }\r
+       else if (!strncmp("dhd_txminmax=", full_param, len_param)) {\r
+               conf->dhd_txminmax = (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: dhd_txminmax = %d\n", __FUNCTION__, conf->dhd_txminmax);\r
+       }\r
+       else if (!strncmp("txinrx_thres=", full_param, len_param)) {\r
+               conf->txinrx_thres = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: txinrx_thres = %d\n", __FUNCTION__, conf->txinrx_thres);\r
+       }\r
+       else if (!strncmp("sd_f2_blocksize=", full_param, len_param)) {\r
+               conf->sd_f2_blocksize = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: sd_f2_blocksize = %d\n", __FUNCTION__, conf->sd_f2_blocksize);\r
+       }\r
+       else if (!strncmp("oob_enabled_later=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->oob_enabled_later = FALSE;\r
+               else\r
+                       conf->oob_enabled_later = TRUE;\r
+               printf("%s: oob_enabled_later = %d\n", __FUNCTION__, conf->oob_enabled_later);\r
+       }\r
+#if defined(BCMSDIOH_TXGLOM)\r
+       else if (!strncmp("txglomsize=", full_param, len_param)) {\r
+               conf->txglomsize = (uint)simple_strtol(data, NULL, 10);\r
+               if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)\r
+                       conf->txglomsize = SDPCM_MAXGLOM_SIZE;\r
+               printf("%s: txglomsize = %d\n", __FUNCTION__, conf->txglomsize);\r
+       }\r
+       else if (!strncmp("swtxglom=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->swtxglom = FALSE;\r
+               else\r
+                       conf->swtxglom = TRUE;\r
+               printf("%s: swtxglom = %d\n", __FUNCTION__, conf->swtxglom);\r
+       }\r
+       else if (!strncmp("txglom_ext=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->txglom_ext = FALSE;\r
+               else\r
+                       conf->txglom_ext = TRUE;\r
+               printf("%s: txglom_ext = %d\n", __FUNCTION__, conf->txglom_ext);\r
+               if (conf->txglom_ext) {\r
+                       if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID))\r
+                               conf->txglom_bucket_size = 1680;\r
+                       else if (conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||\r
+                                       conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID)\r
+                               conf->txglom_bucket_size = 1684;\r
+               }\r
+               printf("%s: txglom_bucket_size = %d\n", __FUNCTION__, conf->txglom_bucket_size);\r
+       }\r
+       else if (!strncmp("bus:rxglom=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->bus_rxglom = FALSE;\r
+               else\r
+                       conf->bus_rxglom = TRUE;\r
+               printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom);\r
+       }\r
+       else if (!strncmp("dhd_poll=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->dhd_poll = 0;\r
+               else\r
+                       conf->dhd_poll = 1;\r
+               printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll);\r
+       }\r
+       else if (!strncmp("deferred_tx_len=", full_param, len_param)) {\r
+               conf->deferred_tx_len = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len);\r
+       }\r
+       else if (!strncmp("txctl_tmo_fix=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->txctl_tmo_fix = FALSE;\r
+               else\r
+                       conf->txctl_tmo_fix = TRUE;\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
+       }\r
+       else if (!strncmp("txglom_mode=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->txglom_mode = FALSE;\r
+               else\r
+                       conf->txglom_mode = TRUE;\r
+               printf("%s: txglom_mode = %d\n", __FUNCTION__, conf->txglom_mode);\r
+       }\r
+#endif\r
+       else\r
+               return false;\r
 \r
-#if defined(BCMSDIOH_TXGLOM)
-               /* Process txglomsize parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "txglomsize=");\r
-               if (len_val) {\r
-                       conf->txglomsize = (uint)simple_strtol(pick, NULL, 10);\r
-                       if (conf->txglomsize > SDPCM_MAXGLOM_SIZE)\r
-                               conf->txglomsize = SDPCM_MAXGLOM_SIZE;\r
-                       printf("%s: txglomsize = %d\n", __FUNCTION__, conf->txglomsize);\r
-               }\r
-
-               /* Process swtxglom parameters */\r
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "swtxglom=");\r
-               if (len_val) {
-                       if (!strncmp(pick, "0", len_val))
-                               conf->swtxglom = FALSE;\r
-                       else
-                               conf->swtxglom = TRUE;\r
-                       printf("%s: swtxglom = %d\n", __FUNCTION__, conf->swtxglom);\r
-               }\r
+       return true;\r
+}\r
+#endif\r
 \r
-               /* Process txglom_ext parameters */
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "txglom_ext=");
-               if (len_val) {
-                       if (!strncmp(pick, "0", len_val))
-                               conf->txglom_ext = FALSE;
-                       else
-                               conf->txglom_ext = TRUE;
-                       printf("%s: txglom_ext = %d\n", __FUNCTION__, conf->txglom_ext);
-                       if (conf->txglom_ext) {
-                               if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID))
-                                       conf->txglom_bucket_size = 1680;
-                               else if (conf->chip == BCM43340_CHIP_ID || conf->chip == BCM43341_CHIP_ID ||
-                                               conf->chip == BCM4334_CHIP_ID || conf->chip == BCM4324_CHIP_ID)\r
-                                       conf->txglom_bucket_size = 1684;
-                       }
-                       printf("%s: txglom_bucket_size = %d\n", __FUNCTION__, conf->txglom_bucket_size);
-               }
-\r
-               /* Process bus:rxglom parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "bus:rxglom=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "0", len_val))\r
-                               conf->bus_rxglom = FALSE;\r
-                       else\r
-                               conf->bus_rxglom = TRUE;\r
-                       printf("%s: bus:rxglom = %d\n", __FUNCTION__, conf->bus_rxglom);\r
-               }\r
+bool\r
+dhd_conf_read_pm_params(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
-               /* Process dhd_poll parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "dhd_poll=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "0", len_val))\r
-                               conf->dhd_poll = 0;\r
-                       else\r
-                               conf->dhd_poll = 1;\r
-                       printf("%s: dhd_poll = %d\n", __FUNCTION__, conf->dhd_poll);\r
-               }\r
+       if (!strncmp("lpc=", full_param, len_param)) {\r
+               conf->lpc = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: lpc = %d\n", __FUNCTION__, conf->lpc);\r
+       }\r
+       else if (!strncmp("deepsleep=", full_param, len_param)) {\r
+               if (!strncmp(data, "1", 1))\r
+                       conf->deepsleep = TRUE;\r
+               else\r
+                       conf->deepsleep = FALSE;\r
+               printf("%s: deepsleep = %d\n", __FUNCTION__, conf->deepsleep);\r
+       }\r
+       else if (!strncmp("PM=", full_param, len_param)) {\r
+               conf->pm = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: PM = %d\n", __FUNCTION__, conf->pm);\r
+       }\r
+       else if (!strncmp("pm_in_suspend=", full_param, len_param)) {\r
+               conf->pm_in_suspend = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: pm_in_suspend = %d\n", __FUNCTION__, conf->pm_in_suspend);\r
+       }\r
+       else if (!strncmp("pm2_sleep_ret=", full_param, len_param)) {\r
+               conf->pm2_sleep_ret = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: pm2_sleep_ret = %d\n", __FUNCTION__, conf->pm2_sleep_ret);\r
+       }\r
+       else if (!strncmp("xmit_in_suspend=", full_param, len_param)) {\r
+               if (!strncmp(data, "1", 1))\r
+                       conf->xmit_in_suspend = TRUE;\r
+               else\r
+                       conf->xmit_in_suspend = FALSE;\r
+               printf("%s: xmit_in_suspend = %d\n", __FUNCTION__, conf->xmit_in_suspend);\r
+       }\r
+       else\r
+               return false;\r
 \r
-               /* Process deferred_tx_len parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "deferred_tx_len=");\r
-               if (len_val) {\r
-                       conf->deferred_tx_len = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: deferred_tx_len = %d\n", __FUNCTION__, conf->deferred_tx_len);\r
-               }\r
-
-               /* Process txctl_tmo_fix parameters */
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "txctl_tmo_fix=");
-               if (len_val) {
-                       if (!strncmp(pick, "0", len_val))
-                               conf->txctl_tmo_fix = FALSE;
-                       else
-                               conf->txctl_tmo_fix = TRUE;
-                       printf("%s: txctl_tmo_fix = %d\n", __FUNCTION__, conf->txctl_tmo_fix);
-               }\r
+       return true;\r
+}\r
 \r
-               /* Process tx_in_rx parameters */
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "tx_in_rx=");
-               if (len_val) {
-                       if (!strncmp(pick, "0", len_val))
-                               conf->tx_in_rx = FALSE;
-                       else
-                               conf->tx_in_rx = TRUE;
-                       printf("%s: tx_in_rx = %d\n", __FUNCTION__, conf->tx_in_rx);
-               }\r
+bool\r
+dhd_conf_read_others(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
+       uint len_data = strlen(data);\r
+       char *pch, *pick_tmp;\r
+       int i;\r
 \r
-               /* Process tx_max_offset parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "tx_max_offset=");\r
-               if (len_val) {\r
-                       conf->tx_max_offset = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: tx_max_offset = %d\n", __FUNCTION__, conf->tx_max_offset);\r
-               }\r
-
-               /* Process txglom_mode parameters */\r
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "txglom_mode=");\r
-               if (len_val) {
-                       if (!strncmp(pick, "0", len_val))
-                               conf->txglom_mode = FALSE;\r
-                       else
-                               conf->txglom_mode = TRUE;\r
-                       printf("%s: txglom_mode = %d\n", __FUNCTION__, conf->txglom_mode);\r
+       if (!strncmp("band=", full_param, len_param)) {\r
+               /* Process band:\r
+                * band=a for 5GHz only and band=b for 2.4GHz only\r
+                */\r
+               if (!strcmp(data, "b"))\r
+                       conf->band = WLC_BAND_2G;\r
+               else if (!strcmp(data, "a"))\r
+                       conf->band = WLC_BAND_5G;\r
+               else\r
+                       conf->band = WLC_BAND_AUTO;\r
+               printf("%s: band = %d\n", __FUNCTION__, conf->band);\r
+       }\r
+       else if (!strncmp("mimo_bw_cap=", full_param, len_param)) {\r
+               conf->mimo_bw_cap = (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: mimo_bw_cap = %d\n", __FUNCTION__, conf->mimo_bw_cap);\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
+       }\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_2g = %d\n", __FUNCTION__, conf->bw_cap_5g);\r
+       }\r
+       else if (!strncmp("ccode=", full_param, len_param)) {\r
+               memset(&conf->cspec, 0, sizeof(wl_country_t));\r
+               memcpy(conf->cspec.country_abbrev, data, len_data);\r
+               memcpy(conf->cspec.ccode, data, len_data);\r
+               printf("%s: ccode = %s\n", __FUNCTION__, conf->cspec.ccode);\r
+       }\r
+       else if (!strncmp("regrev=", full_param, len_param)) {\r
+               conf->cspec.rev = (int32)simple_strtol(data, NULL, 10);\r
+               printf("%s: regrev = %d\n", __FUNCTION__, conf->cspec.rev);\r
+       }\r
+       else if (!strncmp("channels=", full_param, len_param)) {\r
+               pick_tmp = data;\r
+               pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+               i=0;\r
+               while (pch != NULL && i<WL_NUMCHANNELS) {\r
+                       conf->channels.channel[i] = (uint32)simple_strtol(pch, NULL, 10);\r
+                       pch = bcmstrtok(&pick_tmp, " ,.-", 0);\r
+                       i++;\r
                }\r
+               conf->channels.count = i;\r
+               printf("%s: channels = ", __FUNCTION__);\r
+               for (i=0; i<conf->channels.count; i++)\r
+                       printf("%d ", conf->channels.channel[i]);\r
+               printf("\n");\r
+       }\r
+       else if (!strncmp("keep_alive_period=", full_param, len_param)) {\r
+               conf->keep_alive_period = (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: keep_alive_period = %d\n", __FUNCTION__,\r
+                       conf->keep_alive_period);\r
+       }\r
+       else if (!strncmp("stbc=", full_param, len_param)) {\r
+               conf->stbc = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: stbc = %d\n", __FUNCTION__, conf->stbc);\r
+       }\r
+       else if (!strncmp("phy_oclscdenable=", full_param, len_param)) {\r
+               conf->phy_oclscdenable = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: phy_oclscdenable = %d\n", __FUNCTION__, conf->phy_oclscdenable);\r
+       }\r
+       else if (!strncmp("srl=", full_param, len_param)) {\r
+               conf->srl = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: srl = %d\n", __FUNCTION__, conf->srl);\r
+       }\r
+       else if (!strncmp("lrl=", full_param, len_param)) {\r
+               conf->lrl = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: lrl = %d\n", __FUNCTION__, conf->lrl);\r
+       }\r
+       else if (!strncmp("bcn_timeout=", full_param, len_param)) {\r
+               conf->bcn_timeout= (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: bcn_timeout = %d\n", __FUNCTION__, conf->bcn_timeout);\r
+       }\r
+       else if (!strncmp("ampdu_ba_wsize=", full_param, len_param)) {\r
+               conf->ampdu_ba_wsize = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: ampdu_ba_wsize = %d\n", __FUNCTION__, conf->ampdu_ba_wsize);\r
+       }\r
+       else if (!strncmp("ampdu_hostreorder=", full_param, len_param)) {\r
+               conf->ampdu_hostreorder = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: ampdu_hostreorder = %d\n", __FUNCTION__, conf->ampdu_hostreorder);\r
+       }\r
+       else if (!strncmp("spect=", full_param, len_param)) {\r
+               conf->spect = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: spect = %d\n", __FUNCTION__, conf->spect);\r
+       }\r
+       else if (!strncmp("txbf=", full_param, len_param)) {\r
+               conf->txbf = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: txbf = %d\n", __FUNCTION__, conf->txbf);\r
+       }\r
+       else if (!strncmp("frameburst=", full_param, len_param)) {\r
+               conf->frameburst = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: frameburst = %d\n", __FUNCTION__, conf->frameburst);\r
+       }\r
+       else if (!strncmp("disable_proptx=", full_param, len_param)) {\r
+               conf->disable_proptx = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: disable_proptx = %d\n", __FUNCTION__, conf->disable_proptx);\r
+       }\r
+#ifdef DHDTCPACK_SUPPRESS\r
+       else if (!strncmp("tcpack_sup_mode=", full_param, len_param)) {\r
+               conf->tcpack_sup_mode = (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: tcpack_sup_mode = %d\n", __FUNCTION__, conf->tcpack_sup_mode);\r
+       }\r
 #endif\r
-#endif\r
+       else if (!strncmp("pktprio8021x=", full_param, len_param)) {\r
+               conf->pktprio8021x = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: pktprio8021x = %d\n", __FUNCTION__, conf->pktprio8021x);\r
+       }\r
+       else if (!strncmp("dhd_txbound=", full_param, len_param)) {\r
+               dhd_txbound = (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: dhd_txbound = %d\n", __FUNCTION__, dhd_txbound);\r
+       }\r
+       else if (!strncmp("dhd_rxbound=", full_param, len_param)) {\r
+               dhd_rxbound = (uint)simple_strtol(data, NULL, 10);\r
+               printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound);\r
+       }\r
+       else if (!strncmp("rsdb_mode=", full_param, len_param)) {\r
+               conf->rsdb_mode = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: rsdb_mode = %d\n", __FUNCTION__, conf->rsdb_mode);\r
+       }\r
+       else if (!strncmp("vhtmode=", full_param, len_param)) {\r
+               if (!strncmp(data, "0", 1))\r
+                       conf->vhtmode = 0;\r
+               else\r
+                       conf->vhtmode = 1;\r
+               printf("%s: vhtmode = %d\n", __FUNCTION__, conf->vhtmode);\r
+       }\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("autocountry=", full_param, len_param)) {\r
+               conf->autocountry = (int)simple_strtol(data, NULL, 10);\r
+               printf("%s: autocountry = %d\n", __FUNCTION__, conf->autocountry);\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
+       }\r
+       else\r
+               return false;\r
 \r
-               /* Process disable_proptx parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "disable_proptx=");\r
-               if (len_val) {\r
-                       conf->disable_proptx = (int)simple_strtol(pick, NULL, 10);
-                       printf("%s: disable_proptx = %d\n", __FUNCTION__, conf->disable_proptx);
-               }\r
+       return true;\r
+}\r
 \r
-               /* Process dpc_cpucore parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "dpc_cpucore=");\r
-               if (len_val) {\r
-                       conf->dpc_cpucore = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: dpc_cpucore = %d\n", __FUNCTION__, conf->dpc_cpucore);\r
-               }\r
+int\r
+dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path)\r
+{\r
+       int bcmerror = -1;\r
+       uint len, start_pos=0;\r
+       void * image = NULL;\r
+       char * memblock = NULL;\r
+       char *bufp, *pick = NULL, *pch;\r
+       bool conf_file_exists;\r
+       uint len_param;\r
 \r
-               /* Process deepsleep parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "deepsleep=");\r
-               if (len_val) {\r
-                       if (!strncmp(pick, "1", len_val))\r
-                               conf->deepsleep = TRUE;\r
-                       else\r
-                               conf->deepsleep = FALSE;\r
-                       printf("%s: deepsleep = %d\n", __FUNCTION__, conf->deepsleep);\r
-               }\r
+       conf_file_exists = ((conf_path != NULL) && (conf_path[0] != '\0'));\r
+       if (!conf_file_exists) {\r
+               printf("%s: config path %s\n", __FUNCTION__, conf_path);\r
+               return (0);\r
+       }\r
 \r
-               /* Process PM parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "PM=");\r
-               if (len_val) {\r
-                       conf->pm = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: PM = %d\n", __FUNCTION__, conf->pm);\r
+       if (conf_file_exists) {\r
+               image = dhd_os_open_image(conf_path);\r
+               if (image == NULL) {\r
+                       printf("%s: Ignore config file %s\n", __FUNCTION__, conf_path);\r
+                       goto err;\r
                }\r
+       }\r
 \r
-               /* Process pm2_sleep_ret parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "pm2_sleep_ret=");\r
-               if (len_val) {\r
-                       conf->pm2_sleep_ret = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: pm2_sleep_ret = %d\n", __FUNCTION__, conf->pm2_sleep_ret);\r
-               }\r
+       memblock = MALLOC(dhd->osh, MAXSZ_CONFIG);\r
+       if (memblock == NULL) {\r
+               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
+                       __FUNCTION__, MAXSZ_CONFIG));\r
+               goto err;\r
+       }\r
 \r
-#ifdef DHDTCPACK_SUPPRESS\r
-               /* Process tcpack_sup_mode parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "tcpack_sup_mode=");\r
-               if (len_val) {\r
-                       conf->tcpack_sup_mode = (uint)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: tcpack_sup_mode = %d\n", __FUNCTION__, conf->tcpack_sup_mode);\r
-               }\r
-#endif\r
+       pick = MALLOC(dhd->osh, MAXSZ_BUF);\r
+       if (!pick) {\r
+               CONFIG_ERROR(("%s: Failed to allocate memory %d bytes\n",\r
+                       __FUNCTION__, MAXSZ_BUF));\r
+               goto err;\r
+       }\r
 \r
-               /* Process pktprio8021x parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "pktprio8021x=");\r
-               if (len_val) {\r
-                       conf->pktprio8021x = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: pktprio8021x = %d\n", __FUNCTION__, conf->pktprio8021x);\r
-               }
-
-               /* Process dhd_txbound parameters */
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "dhd_txbound=");
-               if (len_val) {
-                       dhd_txbound = (uint)simple_strtol(pick, NULL, 10);
-                       printf("%s: dhd_txbound = %d\n", __FUNCTION__, dhd_txbound);
-               }
-
-               /* Process dhd_rxbound parameters */
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "dhd_rxbound=");
-               if (len_val) {
-                       dhd_rxbound = (uint)simple_strtol(pick, NULL, 10);
-                       printf("%s: dhd_rxbound = %d\n", __FUNCTION__, dhd_rxbound);
-               }\r
+       /* Read variables */\r
+       if (conf_file_exists) {\r
+               len = dhd_os_get_image_block(memblock, MAXSZ_CONFIG, image);\r
+       }\r
+       if (len > 0 && len < MAXSZ_CONFIG) {\r
+               bufp = (char *)memblock;\r
+               bufp[len] = 0;\r
 \r
-               /* Process rsdb_mode parameters */\r
-               memset(pick, 0, MAXSZ_BUF);\r
-               len_val = process_config_vars(bufp, len, pick, "rsdb_mode=");\r
-               if (len_val) {\r
-                       conf->rsdb_mode = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: rsdb_mode = %d\n", __FUNCTION__, conf->rsdb_mode);\r
-               }\r
+               while (start_pos < len) {\r
+                       memset(pick, 0, MAXSZ_BUF);\r
+                       start_pos = pick_config_vars(bufp, len, start_pos, pick);\r
+                       pch = strchr(pick, '=');\r
+                       if (pch != NULL) {\r
+                               len_param = pch-pick+1;\r
+                               if (len_param == strlen(pick)) {\r
+                                       CONFIG_ERROR(("%s: not a right parameter %s\n", __FUNCTION__, pick));\r
+                                       continue;\r
+                               }\r
+                       } else {\r
+                               CONFIG_ERROR(("%s: not a right parameter %s\n", __FUNCTION__, pick));\r
+                               continue;\r
+                       }\r
 \r
-               /* Process vhtmode parameters */\r
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "vhtmode=");\r
-               if (len_val) {
-                       if (!strncmp(pick, "0", len_val))
-                               conf->vhtmode = 0;\r
+                       if (dhd_conf_read_log_level(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_roam_params(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_wme_ac_params(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_fw_by_mac(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_nv_by_mac(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_nv_by_chip(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_country_list(dhd, pick, len_param))\r
+                               continue;\r
+#ifdef PKT_FILTER_SUPPORT\r
+                       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
+                               continue;\r
+#endif /* IAPSTA_PREINIT */\r
+#ifdef IDHCPC\r
+                       else if (dhd_conf_read_dhcp_params(dhd, pick, len_param))\r
+                               continue;\r
+#endif /* IDHCPC */\r
+#ifdef BCMSDIO\r
+                       else if (dhd_conf_read_sdio_params(dhd, pick, len_param))\r
+                               continue;\r
+#endif /* BCMSDIO */\r
+                       else if (dhd_conf_read_pm_params(dhd, pick, len_param))\r
+                               continue;\r
+                       else if (dhd_conf_read_others(dhd, pick, len_param))\r
+                               continue;\r
                        else
-                               conf->vhtmode = 1;\r
-                       printf("%s: vhtmode = %d\n", __FUNCTION__, conf->vhtmode);\r
-               }\r
-\r
-               /* Process num_different_channels parameters */\r
-               memset(pick, 0, MAXSZ_BUF);
-               len_val = process_config_vars(bufp, len, pick, "num_different_channels=");\r
-               if (len_val) {\r
-                       conf->num_different_channels = (int)simple_strtol(pick, NULL, 10);\r
-                       printf("%s: num_different_channels = %d\n", __FUNCTION__, conf->num_different_channels);\r
+                               continue;\r
                }\r
 \r
                bcmerror = 0;\r
@@ -2341,13 +2299,14 @@ dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable)
                conf->txglomsize = 0;\r
                conf->deferred_tx_len = 0;\r
        }\r
-       printf("%s: swtxglom=%d, txglom_ext=%d\n", __FUNCTION__,\r
-               conf->swtxglom, conf->txglom_ext);\r
-       printf("%s: txglom_bucket_size=%d\n", __FUNCTION__, conf->txglom_bucket_size);\r
+       printf("%s: swtxglom=%d, txglom_ext=%d, txglom_bucket_size=%d\n", __FUNCTION__,\r
+               conf->swtxglom, conf->txglom_ext, conf->txglom_bucket_size);\r
        printf("%s: txglomsize=%d, deferred_tx_len=%d, bus_txglom=%d\n", __FUNCTION__,\r
                conf->txglomsize, conf->deferred_tx_len, conf->bus_txglom);\r
-       printf("%s: tx_in_rx=%d, tx_max_offset=%d\n", __FUNCTION__,\r
-               conf->tx_in_rx, conf->tx_max_offset);\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: tx_max_offset=%d, txctl_tmo_fix=%d\n", __FUNCTION__,\r
+               conf->tx_max_offset, conf->txctl_tmo_fix);\r
 \r
 }\r
 #endif\r
@@ -2376,7 +2335,7 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        } else if (conf->chip == BCM4335_CHIP_ID || conf->chip == BCM4339_CHIP_ID ||\r
                        conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
                        conf->chip == BCM4345_CHIP_ID || conf->chip == BCM4371_CHIP_ID ||\r
-                       conf->chip == BCM4359_CHIP_ID) {\r
+                       conf->chip == BCM43569_CHIP_ID || conf->chip == BCM4359_CHIP_ID) {\r
                strcpy(conf->cspec.country_abbrev, "CN");\r
                strcpy(conf->cspec.ccode, "CN");\r
                conf->cspec.rev = 38;\r
@@ -2413,12 +2372,14 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->keep_alive_period = 28000;\r
 #endif\r
        conf->force_wme_ac = 0;\r
+       memset(&conf->wme_sta, 0, sizeof(wme_param_t));\r
+       memset(&conf->wme_ap, 0, sizeof(wme_param_t));\r
        conf->stbc = -1;\r
        conf->phy_oclscdenable = -1;\r
 #ifdef PKT_FILTER_SUPPORT\r
        memset(&conf->pkt_filter_add, 0, sizeof(conf_pkt_filter_add_t));\r
        memset(&conf->pkt_filter_del, 0, sizeof(conf_pkt_filter_del_t));\r
-       conf->pkt_filter_magic = FALSE;\r
+       memset(&conf->magic_pkt_filter_add, 0, sizeof(conf_pkt_filter_del_t));\r
 #endif\r
        conf->srl = -1;\r
        conf->lrl = -1;\r
@@ -2426,9 +2387,8 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->spect = -1;\r
        conf->txbf = -1;\r
        conf->lpc = -1;\r
-       conf->disable_proptx = 0;\r
+       conf->disable_proptx = -1;\r
 #ifdef BCMSDIO\r
-       conf->kso_enable = TRUE;\r
        conf->bus_txglom = -1;\r
        conf->use_rxchain = 0;\r
        conf->bus_rxglom = TRUE;\r
@@ -2440,37 +2400,59 @@ dhd_conf_preinit(dhd_pub_t *dhd)
        conf->tx_in_rx = TRUE;\r
        conf->txglom_mode = SDPCM_TXGLOM_MDESC;\r
        conf->deferred_tx_len = 0;\r
+       conf->dhd_txminmax = 1;\r
+       conf->txinrx_thres = -1;\r
+       conf->sd_f2_blocksize = 0;\r
+       conf->oob_enabled_later = FALSE;\r
 #endif\r
        conf->ampdu_ba_wsize = 0;\r
+       conf->ampdu_hostreorder = -1;\r
        conf->dpc_cpucore = -1;\r
+       conf->rxf_cpucore = -1;\r
        conf->frameburst = -1;\r
        conf->deepsleep = FALSE;\r
        conf->pm = -1;\r
+       conf->pm_in_suspend = -1;\r
        conf->pm2_sleep_ret = -1;\r
        conf->num_different_channels = -1;\r
+       conf->xmit_in_suspend = TRUE;\r
+#ifdef IDHCPC\r
+       conf->dhcpc_enable = -1;\r
+#endif\r
+       conf->tsq = 0;\r
 #ifdef DHDTCPACK_SUPPRESS
        conf->tcpack_sup_mode = TCPACK_SUP_OFF;\r
 #endif\r
        conf->pktprio8021x = -1;\r
        conf->rsdb_mode = -2;\r
        conf->vhtmode = -1;\r
-       if ((conf->chip == BCM43362_CHIP_ID) || (conf->chip == BCM4330_CHIP_ID)) {\r
-               conf->disable_proptx = 1;\r
-       }\r
-       if (conf->chip == BCM43430_CHIP_ID) {\r
-               conf->txctl_tmo_fix = 1; // terence 20161011: fix credict issue in adaptivity testing\r
-       }\r
-       if (conf->chip == BCM4354_CHIP_ID) {\r
-               conf->txbf = 1;\r
-       }\r
-       if (conf->chip == BCM4356_CHIP_ID) {\r
-               conf->txbf = 1;\r
-       }\r
-       if (conf->chip == BCM4371_CHIP_ID) {\r
-               conf->txbf = 1;\r
+       conf->autocountry = -1;\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
+#endif\r
+#ifdef BCMSDIO\r
+       if (conf->chip == BCM43430_CHIP_ID || conf->chip == BCM4345_CHIP_ID) {\r
+               conf->txctl_tmo_fix = 1;\r
        }\r
-       if (conf->chip == BCM4359_CHIP_ID) {\r
+#endif\r
+       if (conf->chip == BCM4354_CHIP_ID || conf->chip == BCM4356_CHIP_ID ||\r
+                       conf->chip == BCM4371_CHIP_ID || conf->chip == BCM43569_CHIP_ID ||\r
+                       conf->chip == BCM4359_CHIP_ID) {\r
+#ifdef DHDTCPACK_SUPPRESS\r
+               conf->tcpack_sup_mode = TCPACK_SUP_REPLACE;\r
+#endif\r
+               dhd_rxbound = 64;\r
+               dhd_txbound = 64;\r
                conf->txbf = 1;\r
+               conf->frameburst = 1;\r
+#ifdef BCMSDIO\r
+               conf->dhd_txminmax = -1;\r
+               conf->txinrx_thres = 128;\r
+               conf->sd_f2_blocksize = 256;\r
+               conf->oob_enabled_later = TRUE;\r
+#endif\r
        }\r
 \r
 #ifdef BCMSDIO\r
index cc76e8b2aabcdf62bfb057b33e849cbaa13a8712..750a2830fb555dd3c055aadc2110ae04685a87b5 100644 (file)
@@ -11,7 +11,6 @@
 #define FW_PATH_AUTO_SELECT 1\r
 //#define CONFIG_PATH_AUTO_SELECT\r
 extern char firmware_path[MOD_PARAM_PATHLEN];\r
-extern int disable_proptx;\r
 extern uint dhd_rxbound;
 extern uint dhd_txbound;\r
 #ifdef BCMSDIO\r
@@ -23,6 +22,8 @@ extern uint dhd_slpauto;
 #define BCM43362A2_CHIP_REV     1\r
 #define BCM43430A0_CHIP_REV     0\r
 #define BCM43430A1_CHIP_REV     1\r
+#define BCM43430A2_CHIP_REV     2\r
+#define BCM43012B0_CHIP_REV     1\r
 #define BCM4330B2_CHIP_REV      4\r
 #define BCM4334B1_CHIP_REV      3\r
 #define BCM43341B0_CHIP_REV     2\r
@@ -30,11 +31,13 @@ extern uint dhd_slpauto;
 #define BCM4335A0_CHIP_REV      2\r
 #define BCM4339A0_CHIP_REV      1\r
 #define BCM43455C0_CHIP_REV     6\r
+#define BCM43455C5_CHIP_REV     9\r
 #define BCM4354A1_CHIP_REV      1\r
 #define BCM4359B1_CHIP_REV      5\r
 #define BCM4359C0_CHIP_REV      9\r
 #endif\r
 #define BCM4356A2_CHIP_REV      2\r
+#define BCM4358A3_CHIP_REV      3\r
 \r
 /* mac range */\r
 typedef struct wl_mac_range {\r
@@ -132,13 +135,14 @@ typedef struct dhd_conf {
        int fullroamperiod;                     /* Full Roaming period */\r
        uint keep_alive_period;         /* The perioid in ms to send keep alive packet */\r
        int force_wme_ac;\r
-       wme_param_t wme;        /* WME parameters */\r
+       wme_param_t wme_sta;    /* WME parameters */\r
+       wme_param_t wme_ap;     /* WME parameters */\r
        int stbc;                       /* STBC for Tx/Rx */\r
        int phy_oclscdenable;           /* phy_oclscdenable */\r
 #ifdef PKT_FILTER_SUPPORT\r
        conf_pkt_filter_add_t pkt_filter_add;           /* Packet filter add */\r
        conf_pkt_filter_del_t pkt_filter_del;           /* Packet filter add */\r
-       bool pkt_filter_magic;\r
+       conf_pkt_filter_add_t magic_pkt_filter_add;             /* Magic Packet filter add */\r
 #endif\r
        int srl;        /* short retry limit */\r
        int lrl;        /* long retry limit */\r
@@ -148,30 +152,44 @@ typedef struct dhd_conf {
        int lpc;\r
        int disable_proptx;\r
 #ifdef BCMSDIO\r
-       bool kso_enable;\r
        int bus_txglom; /* bus:txglom */\r
        int use_rxchain;\r
-       bool bus_rxglom;        /* bus:rxglom */\r
+       bool bus_rxglom; /* bus:rxglom */\r
        bool txglom_ext; /* Only for 43362/4330/43340/43341/43241 */
-       /*txglom_bucket_size:
-        * 43362/4330: 1680
-        * 43340/43341/43241: 1684
-        */\r
+       /* terence 20161011:\r
+           1) conf->tx_max_offset = 1 to fix credict issue in adaptivity testing\r
+           2) conf->tx_max_offset = 1 will cause to UDP Tx not work in rxglom supported,\r
+               but not happened in sw txglom\r
+       */\r
        int tx_max_offset;\r
        uint txglomsize;\r
        int dhd_poll;\r
+       /* terence 20161011: conf->txctl_tmo_fix = 1 to fix for "sched: RT throttling activated, "\r
+            this issue happened in tx tput. and tx cmd at the same time in inband interrupt mode\r
+       */\r
        bool txctl_tmo_fix;\r
        bool tx_in_rx; // Skip tx before rx, in order to get more glomed in tx\r
        bool txglom_mode;\r
        uint deferred_tx_len;\r
        bool swtxglom; /* SW TXGLOM */\r
+       /*txglom_bucket_size:
+        * 43362/4330: 1680
+        * 43340/43341/43241: 1684
+        */\r
        int txglom_bucket_size;\r
+       int txinrx_thres;\r
+       int dhd_txminmax; // -1=DATABUFCNT(bus)\r
+       uint sd_f2_blocksize;\r
+       bool oob_enabled_later;\r
 #endif\r
        int ampdu_ba_wsize;\r
+       int ampdu_hostreorder;\r
        int dpc_cpucore;\r
+       int rxf_cpucore;\r
        int frameburst;\r
        bool deepsleep;\r
        int pm;\r
+       int pm_in_suspend;\r
        int pm2_sleep_ret;\r
 #ifdef DHDTCPACK_SUPPRESS\r
        uint8 tcpack_sup_mode;\r
@@ -180,6 +198,17 @@ typedef struct dhd_conf {
        int rsdb_mode;\r
        int vhtmode;\r
        int num_different_channels;\r
+       int xmit_in_suspend;\r
+#ifdef IDHCPC\r
+       int dhcpc_enable;\r
+#endif\r
+#ifdef IAPSTA_PREINIT\r
+       char iapsta_init[50];\r
+       char iapsta_config[300];\r
+       char iapsta_enable[50];\r
+#endif\r
+       int autocountry;\r
+       int tsq;\r
 } dhd_conf_t;\r
 \r
 #ifdef BCMSDIO\r
@@ -192,13 +221,14 @@ void dhd_conf_set_hw_oob_intr(bcmsdh_info_t *sdh, uint chip);
 void dhd_conf_set_txglom_params(dhd_pub_t *dhd, bool enable);\r
 #endif\r
 void dhd_conf_set_fw_name_by_chip(dhd_pub_t *dhd, char *fw_path);\r
+void dhd_conf_set_clm_name_by_chip(dhd_pub_t *dhd, char *clm_path);\r
 void dhd_conf_set_nv_name_by_chip(dhd_pub_t *dhd, char *nv_path);\r
-void dhd_conf_set_conf_path_by_nv_path(dhd_pub_t *dhd, char *conf_path, char *nv_path);\r
+void dhd_conf_set_path(dhd_pub_t *dhd, char *dst_name, char *dst_path, char *src_path);\r
 #ifdef CONFIG_PATH_AUTO_SELECT\r
 void dhd_conf_set_conf_name_by_chip(dhd_pub_t *dhd, char *conf_path);\r
 #endif\r
-int dhd_conf_set_fw_int_cmd(dhd_pub_t *dhd, char *name, uint cmd, int val, int def, bool down);\r
-int dhd_conf_set_fw_string_cmd(dhd_pub_t *dhd, char *cmd, int val, int def, bool down);\r
+int dhd_conf_set_intiovar(dhd_pub_t *dhd, uint cmd, char *name, int val, int def, bool down);\r
+int dhd_conf_get_iovar(dhd_pub_t *dhd, int cmd, char *name, char *buf, int len, int ifidx);\r
 uint dhd_conf_get_band(dhd_pub_t *dhd);\r
 int dhd_conf_set_country(dhd_pub_t *dhd);\r
 int dhd_conf_get_country(dhd_pub_t *dhd, wl_country_t *cspec);\r
@@ -207,21 +237,22 @@ int dhd_conf_fix_country(dhd_pub_t *dhd);
 bool dhd_conf_match_channel(dhd_pub_t *dhd, uint32 channel);\r
 int dhd_conf_set_roam(dhd_pub_t *dhd);\r
 void dhd_conf_set_bw_cap(dhd_pub_t *dhd);\r
-void dhd_conf_get_wme(dhd_pub_t *dhd, edcf_acparam_t *acp);\r
-void dhd_conf_set_wme(dhd_pub_t *dhd);\r
+void dhd_conf_set_wme(dhd_pub_t *dhd, int mode);\r
 void dhd_conf_add_pkt_filter(dhd_pub_t *dhd);\r
 bool dhd_conf_del_pkt_filter(dhd_pub_t *dhd, uint32 id);\r
 void dhd_conf_discard_pkt_filter(dhd_pub_t *dhd);\r
-void dhd_conf_set_disable_proptx(dhd_pub_t *dhd);\r
 int dhd_conf_read_config(dhd_pub_t *dhd, char *conf_path);\r
 int dhd_conf_set_chiprev(dhd_pub_t *dhd, uint chip, uint chiprev);\r
 uint dhd_conf_get_chip(void *context);\r
 uint dhd_conf_get_chiprev(void *context);\r
 int dhd_conf_get_pm(dhd_pub_t *dhd);\r
+#ifdef PROP_TXSTATUS\r
+int dhd_conf_get_disable_proptx(dhd_pub_t *dhd);\r
+#endif\r
 int dhd_conf_preinit(dhd_pub_t *dhd);\r
 int dhd_conf_reset(dhd_pub_t *dhd);\r
 int dhd_conf_attach(dhd_pub_t *dhd);\r
 void dhd_conf_detach(dhd_pub_t *dhd);\r
 void *dhd_get_pub(struct net_device *dev);\r
-\r
+void *dhd_get_conf(struct net_device *dev);\r
 #endif /* _dhd_config_ */\r
index 89c194e1f520bde276c66873f4e0eb8d5f208f3c..b371ca810497ea97f25e4593356eb05dbc64b465 100644 (file)
@@ -1,23 +1,20 @@
 
 #include <osl.h>
 #include <dhd_linux.h>
+#include <linux/gpio.h>
 
-#ifdef CONFIG_MACH_ODROID_4210
-#include <mach/gpio.h>
-#include <mach/regs-gpio.h>
-#include <plat/gpio-cfg.h>
+#ifdef CUSTOMER_HW_PLATFORM
 #include <plat/sdhci.h>
-#include <plat/devs.h>
-#define        sdmmc_channel   s3c_device_hsmmc0
-#endif
+#define        sdmmc_channel   sdmmc_device_mmc0
+#endif /* CUSTOMER_HW_PLATFORM */
 
-#if defined(CUSTOMER_HW_INTEL) && defined(BCMSDIO)
+#if defined(BUS_POWER_RESTORE) && defined(BCMSDIO)
 #include <linux/mmc/core.h>
 #include <linux/mmc/card.h>
 #include <linux/mmc/host.h>
 #include <linux/mmc/sdio_func.h>
-#include <linux/gpio.h>
-#endif
+#endif /* defined(BUS_POWER_RESTORE) && defined(BCMSDIO) */
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
 #include <linux/amlogic/aml_gpio_consumer.h>
 extern int wifi_irq_trigger_level(void);
@@ -31,104 +28,32 @@ extern int wifi_irq_num(void);
 #endif
 
 extern u8 *wifi_get_mac(void);
-#ifndef CUSTOMER_HW_AMLOGIC
-#define WL_REG_ON 0 // WL_REG_ON is the input pin of WLAN module
-#define WL_HOST_WAKE 0 // WL_HOST_WAKE is output pin of WLAN module
-#endif
-
-struct wifi_platform_data dhd_wlan_control = {0};
+#ifdef CONFIG_DHD_USE_STATIC_BUF
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
 
+static int gpio_wl_reg_on = -1; // WL_REG_ON is input pin of WLAN module
 #ifdef CUSTOMER_OOB
-uint bcm_wlan_get_oob_irq(void)
-{
-#ifndef CUSTOMER_HW_AMLOGIC
-       int wl_host_wake = WL_HOST_WAKE;
-#endif
-       uint host_oob_irq = 0;
-
-#ifndef CUSTOMER_HW_AMLOGIC
-       printf("GPIO(WL_HOST_WAKE) = %d\n", wl_host_wake);
-       if (gpio_request(wl_host_wake, "bcmdhd") < 0) {
-               printf("%s: gpio_request failed\n", __FUNCTION__);
-       }
-       host_oob_irq = gpio_to_irq(wl_host_wake);
-       if (gpio_direction_input(wl_host_wake) < 0 ) {
-               printf("%s: gpio_direction_input failed\n", __FUNCTION__);
-       }
-#endif
-
-#ifdef CUSTOMER_HW_AMLOGIC
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
-       host_oob_irq = INT_GPIO_4;
-#else
-       host_oob_irq = wifi_irq_num();
-#endif
-#endif
-       printf("host_oob_irq: %d\n", host_oob_irq);
-
-       return host_oob_irq;
-}
-
-void bcm_wlan_free_oob_gpio(uint irq_num)
-{
-#ifndef CUSTOMER_HW_AMLOGIC
-       if (irq_num) {
-               printf("%s: gpio_free(%d)\n", __FUNCTION__, WL_HOST_WAKE);
-               gpio_free(WL_HOST_WAKE);
-       }
+static int gpio_wl_host_wake = -1; // WL_HOST_WAKE is output pin of WLAN module
 #endif
-}
 
-uint bcm_wlan_get_oob_irq_flags(void)
-{
-       uint host_oob_irq_flags = 0;
-
-#ifdef HW_OOB
-#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
-       if (wifi_irq_trigger_level() == GPIO_IRQ_LOW)
-               host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
-       else
-               host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
-#else
-#ifdef HW_OOB_LOW_LEVEL
-       host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
-#else
-       host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
-#endif
-#endif
-#else
-       host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE;
-#endif
-
-       printf("host_oob_irq_flags=0x%X\n", host_oob_irq_flags);
-
-       return host_oob_irq_flags;
-}
-#endif
-
-int
-bcm_wlan_set_power(bool on
-#ifdef CUSTOMER_HW_INTEL
+static int
+dhd_wlan_set_power(bool on
+#ifdef BUS_POWER_RESTORE
 , wifi_adapter_info_t *adapter
-#endif
+#endif /* BUS_POWER_RESTORE */
 )
 {
        int err = 0;
-#ifndef CUSTOMER_HW_AMLOGIC
-       uint wl_reg_on = WL_REG_ON;
-#endif
 
        if (on) {
-               printf("======== PULL WL_REG_ON HIGH! ========\n");
-#ifdef CONFIG_MACH_ODROID_4210
-               err = gpio_set_value(wl_reg_on, 1);
-#endif
-#if defined(CUSTOMER_HW_INTEL) & defined(BCMSDIO)
-               if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
-                       printf("======== mmc_power_restore_host! ========\n");
-                       mmc_power_restore_host(adapter->sdio_func->card->host);
+               printf("======== PULL WL_REG_ON(%d) HIGH! ========\n", gpio_wl_reg_on);
+               if (gpio_wl_reg_on >= 0) {
+                       err = gpio_direction_output(gpio_wl_reg_on, 1);
+                       if (err) {
+                               printf("%s: WL_REG_ON didn't output high\n", __FUNCTION__);
+                               return -EIO;
+                       }
                }
-#endif
 #ifdef CUSTOMER_HW_AMLOGIC
                extern_wifi_set_enable(0);
                mdelay(200);
@@ -136,19 +61,55 @@ bcm_wlan_set_power(bool on
                mdelay(200);
 //             sdio_reinit();
 #endif
+#if defined(BUS_POWER_RESTORE)
+#if defined(BCMSDIO)
+               if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
+                       printf("======== mmc_power_restore_host! ========\n");
+                       mmc_power_restore_host(adapter->sdio_func->card->host);
+               }
+#elif defined(BCMPCIE)
+               OSL_SLEEP(50); /* delay needed to be able to restore PCIe configuration registers */
+               if (adapter->pci_dev) {
+                       printf("======== pci_set_power_state PCI_D0! ========\n");
+                       pci_set_power_state(adapter->pci_dev, PCI_D0);
+                       if (adapter->pci_saved_state)
+                               pci_load_and_free_saved_state(adapter->pci_dev, &adapter->pci_saved_state);
+                       pci_restore_state(adapter->pci_dev);
+                       err = pci_enable_device(adapter->pci_dev);
+                       if (err < 0)
+                               printf("%s: PCI enable device failed", __FUNCTION__);
+                       pci_set_master(adapter->pci_dev);
+               }
+#endif /* BCMPCIE */
+#endif /* BUS_POWER_RESTORE */
                /* Lets customer power to get stable */
                mdelay(100);
        } else {
-#if defined(CUSTOMER_HW_INTEL) & defined(BCMSDIO)
+#if defined(BUS_POWER_RESTORE)
+#if defined(BCMSDIO)
                if (adapter->sdio_func && adapter->sdio_func->card && adapter->sdio_func->card->host) {
                        printf("======== mmc_power_save_host! ========\n");
                        mmc_power_save_host(adapter->sdio_func->card->host);
                }
-#endif
-               printf("======== PULL WL_REG_ON LOW! ========\n");
-#ifdef CONFIG_MACH_ODROID_4210
-               err = gpio_set_value(wl_reg_on, 0);
-#endif
+#elif defined(BCMPCIE)
+               if (adapter->pci_dev) {
+                       printf("======== pci_set_power_state PCI_D3hot! ========\n");
+                       pci_save_state(adapter->pci_dev);
+                       adapter->pci_saved_state = pci_store_saved_state(adapter->pci_dev);
+                       if (pci_is_enabled(adapter->pci_dev))
+                               pci_disable_device(adapter->pci_dev);
+                       pci_set_power_state(adapter->pci_dev, PCI_D3hot);
+               }
+#endif /* BCMPCIE */
+#endif /* BUS_POWER_RESTORE */
+               printf("======== PULL WL_REG_ON(%d) LOW! ========\n", gpio_wl_reg_on);
+               if (gpio_wl_reg_on >= 0) {
+                       err = gpio_direction_output(gpio_wl_reg_on, 0);
+                       if (err) {
+                               printf("%s: WL_REG_ON didn't output low\n", __FUNCTION__);
+                               return -EIO;
+                       }
+               }
 #ifdef CUSTOMER_HW_AMLOGIC
 //             extern_wifi_set_enable(0);
 //             mdelay(200);
@@ -158,33 +119,48 @@ bcm_wlan_set_power(bool on
        return err;
 }
 
-int bcm_wlan_set_carddetect(bool present)
+static int dhd_wlan_set_reset(int onoff)
+{
+       return 0;
+}
+
+static int dhd_wlan_set_carddetect(bool present)
 {
        int err = 0;
 
+#if !defined(BUS_POWER_RESTORE)
        if (present) {
+#if defined(BCMSDIO)
                printf("======== Card detection to detect SDIO card! ========\n");
-#ifdef CONFIG_MACH_ODROID_4210
-               err = sdhci_s3c_force_presence_change(&sdmmc_channel, 1);
-#endif
+#ifdef CUSTOMER_HW_PLATFORM
+               err = sdhci_force_presence_change(&sdmmc_channel, 1);
+#endif /* CUSTOMER_HW_PLATFORM */
 #ifdef CUSTOMER_HW_AMLOGIC
                sdio_reinit();
+#endif
+#elif defined(BCMPCIE)
+               printf("======== Card detection to detect PCIE card! ========\n");
 #endif
        } else {
+#if defined(BCMSDIO)
                printf("======== Card detection to remove SDIO card! ========\n");
-#ifdef CONFIG_MACH_ODROID_4210
-               err = sdhci_s3c_force_presence_change(&sdmmc_channel, 0);
-#endif
+#ifdef CUSTOMER_HW_PLATFORM
+               err = sdhci_force_presence_change(&sdmmc_channel, 0);
+#endif /* CUSTOMER_HW_PLATFORM */
 #ifdef CUSTOMER_HW_AMLOGIC
                extern_wifi_set_enable(0);
                mdelay(200);
+#endif
+#elif defined(BCMPCIE)
+               printf("======== Card detection to remove PCIE card! ========\n");
 #endif
        }
+#endif /* BUS_POWER_RESTORE */
 
        return err;
 }
 
-int bcm_wlan_get_mac_address(unsigned char *buf)
+static int dhd_wlan_get_mac_addr(unsigned char *buf)
 {
        int err = 0;
 
@@ -201,9 +177,9 @@ int bcm_wlan_get_mac_address(unsigned char *buf)
                printf("custom wifi mac is not set\n");
                err = -1;
        }
+
        return err;
 }
-
 #ifdef CONFIG_DHD_USE_STATIC_BUF
 extern void *bcmdhd_mem_prealloc(int section, unsigned long size);
 void* bcm_wlan_prealloc(int section, unsigned long size)
@@ -242,7 +218,7 @@ struct cntry_locales_custom brcm_wlan_translate_nodfs_table[] = {
 };
 #endif
 
-static void *bcm_wlan_get_country_code(char *ccode
+static void *dhd_wlan_get_country_code(char *ccode
 #ifdef CUSTOM_FORCE_NODFS_FLAG
        , u32 flags
 #endif
@@ -273,15 +249,136 @@ static void *bcm_wlan_get_country_code(char *ccode
        return NULL;
 }
 
-int bcm_wlan_set_plat_data(void) {
-       printf("======== %s ========\n", __FUNCTION__);
-       dhd_wlan_control.set_power = bcm_wlan_set_power;
-       dhd_wlan_control.set_carddetect = bcm_wlan_set_carddetect;
-       dhd_wlan_control.get_mac_addr = bcm_wlan_get_mac_address;
+struct resource dhd_wlan_resources[] = {
+       [0] = {
+               .name   = "bcmdhd_wlan_irq",
+               .start  = 0, /* Dummy */
+               .end    = 0, /* Dummy */
+               .flags  = IORESOURCE_IRQ | IORESOURCE_IRQ_SHAREABLE
+                       | IORESOURCE_IRQ_HIGHLEVEL, /* Dummy */
+       },
+};
+
+struct wifi_platform_data dhd_wlan_control = {
+       .set_power      = dhd_wlan_set_power,
+       .set_reset      = dhd_wlan_set_reset,
+       .set_carddetect = dhd_wlan_set_carddetect,
+       .get_mac_addr   = dhd_wlan_get_mac_addr,
 #ifdef CONFIG_DHD_USE_STATIC_BUF
-       dhd_wlan_control.mem_prealloc = bcm_wlan_prealloc;
+       .mem_prealloc   = bcm_wlan_prealloc,
+#endif /* CONFIG_DHD_USE_STATIC_BUF */
+       .get_country_code = dhd_wlan_get_country_code,
+};
+
+int dhd_wlan_init_gpio(void)
+{
+       int err = 0;
+#ifdef CUSTOMER_OOB
+       int host_oob_irq = -1;
+       uint host_oob_irq_flags = 0;
+#endif
+
+       /* Please check your schematic and fill right GPIO number which connected to
+       * WL_REG_ON and WL_HOST_WAKE.
+       */
+       gpio_wl_reg_on = -1;
+#ifdef CUSTOMER_OOB
+       gpio_wl_host_wake = -1;
+#endif
+
+       printf("%s: GPIO(WL_REG_ON) = %d\n", __FUNCTION__, gpio_wl_reg_on);
+       if (gpio_wl_reg_on >= 0) {
+               err = gpio_request(gpio_wl_reg_on, "WL_REG_ON");
+               if (err < 0) {
+                       printf("%s: Faiiled to request gpio %d for WL_REG_ON\n",
+                               __FUNCTION__, gpio_wl_reg_on);
+                       gpio_wl_reg_on = -1;
+               }
+       }
+
+#ifdef CUSTOMER_OOB
+       printf("%s: GPIO(WL_HOST_WAKE) = %d\n", __FUNCTION__, gpio_wl_host_wake);
+       if (gpio_wl_host_wake >= 0) {
+               err = gpio_request(gpio_wl_host_wake, "bcmdhd");
+               if (err < 0) {
+                       printf("%s: gpio_request failed\n", __FUNCTION__);
+                       return -1;
+               }
+               err = gpio_direction_input(gpio_wl_host_wake);
+               if (err < 0) {
+                       printf("%s: gpio_direction_input failed\n", __FUNCTION__);
+                       gpio_free(gpio_wl_host_wake);
+                       return -1;
+               }
+               host_oob_irq = gpio_to_irq(gpio_wl_host_wake);
+               if (host_oob_irq < 0) {
+                       printf("%s: gpio_to_irq failed\n", __FUNCTION__);
+                       gpio_free(gpio_wl_host_wake);
+                       return -1;
+               }
+       }
+#ifdef CUSTOMER_HW_AMLOGIC
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
+       host_oob_irq = INT_GPIO_4;
+#else
+       host_oob_irq = wifi_irq_num();
 #endif
-       dhd_wlan_control.get_country_code = bcm_wlan_get_country_code;
+#endif
+       printf("%s: host_oob_irq: %d\n", __FUNCTION__, host_oob_irq);
+
+#ifdef HW_OOB
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
+       if (wifi_irq_trigger_level() == GPIO_IRQ_LOW)
+               host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
+       else
+               host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
+#else
+#ifdef HW_OOB_LOW_LEVEL
+       host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_LOWLEVEL | IORESOURCE_IRQ_SHAREABLE;
+#else
+       host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHLEVEL | IORESOURCE_IRQ_SHAREABLE;
+#endif
+#endif
+#else
+       host_oob_irq_flags = IORESOURCE_IRQ | IORESOURCE_IRQ_HIGHEDGE | IORESOURCE_IRQ_SHAREABLE;
+#endif
+
+       dhd_wlan_resources[0].start = dhd_wlan_resources[0].end = host_oob_irq;
+       dhd_wlan_resources[0].flags = host_oob_irq_flags;
+       printf("%s: host_oob_irq_flags=0x%x\n", __FUNCTION__, host_oob_irq_flags);
+#endif /* CUSTOMER_OOB */
+
        return 0;
 }
 
+static void dhd_wlan_deinit_gpio(void)
+{
+       if (gpio_wl_reg_on >= 0) {
+               printf("%s: gpio_free(WL_REG_ON %d)\n", __FUNCTION__, gpio_wl_reg_on);
+               gpio_free(gpio_wl_reg_on);
+               gpio_wl_reg_on = -1;
+       }
+#ifdef CUSTOMER_OOB
+       if (gpio_wl_host_wake >= 0) {
+               printf("%s: gpio_free(WL_HOST_WAKE %d)\n", __FUNCTION__, gpio_wl_host_wake);
+               gpio_free(gpio_wl_host_wake);
+               gpio_wl_host_wake = -1;
+       }
+#endif /* CUSTOMER_OOB */
+}
+
+int dhd_wlan_init_plat_data(void)
+{
+       int err = 0;
+
+       printf("======== %s ========\n", __FUNCTION__);
+       err = dhd_wlan_init_gpio();
+       return err;
+}
+
+void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter)
+{
+       printf("======== %s ========\n", __FUNCTION__);
+       dhd_wlan_deinit_gpio();
+}
+
index c64f85111d846ccde686425f481b53e0144ac42c..1dff80656143c2e1cb65cdccf9c863365fd5d356 100644 (file)
@@ -81,6 +81,9 @@
 #include <dhd_bus.h>
 #include <dhd_proto.h>
 #include <dhd_config.h>
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif
 #include <dhd_dbg.h>
 #ifdef CONFIG_HAS_WAKELOCK
 #include <linux/wakelock.h>
@@ -225,13 +228,12 @@ static u32 vendor_oui = CONFIG_DHD_SET_RANDOM_MAC_VAL;
 
 #include <wl_android.h>
 
-#ifdef CUSTOMER_HW_AMLOGIC
-#include <linux/amlogic/wifi_dt.h>
-#endif
-
 /* Maximum STA per radio */
 #define DHD_MAX_STA     32
 
+#ifdef CUSTOMER_HW_AMLOGIC
+#include <linux/amlogic/wifi_dt.h>
+#endif
 
 
 const uint8 wme_fifo2ac[] = { 0, 1, 2, 3, 1, 1 };
@@ -296,10 +298,8 @@ extern bool dhd_wlfc_skip_fc(void);
 extern void dhd_wlfc_plat_init(void *dhd);
 extern void dhd_wlfc_plat_deinit(void *dhd);
 #endif /* PROP_TXSTATUS */
-#ifdef USE_DYNAMIC_F2_BLKSIZE
 extern uint sd_f2_blocksize;
 extern int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size);
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
 
 #if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 15)
 const char *
@@ -477,6 +477,7 @@ typedef struct dhd_info {
        void *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 */
        char conf_path[PATH_MAX];       /* path to config vars file */
 
        /* serialize dhd iovars */
@@ -705,6 +706,7 @@ uint dhd_driver_init_done = FALSE;
  */
 char firmware_path[MOD_PARAM_PATHLEN];
 char nvram_path[MOD_PARAM_PATHLEN];
+char clm_path[MOD_PARAM_PATHLEN];
 char config_path[MOD_PARAM_PATHLEN];
 
 /* backup buffer for firmware and nvram path */
@@ -772,6 +774,7 @@ module_param(disable_proptx, int, 0644);
 /* load firmware and/or nvram values from the filesystem */
 module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660);
 module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660);
+module_param_string(clm_path, clm_path, MOD_PARAM_PATHLEN, 0660);
 module_param_string(config_path, config_path, MOD_PARAM_PATHLEN, 0);
 
 /* Watchdog interval */
@@ -1358,6 +1361,7 @@ module_param(allow_delay_fwdl, int, 0);
 
 extern char dhd_version[];
 extern char fw_version[];
+extern char clm_version[];
 
 int dhd_net_bus_devreset(struct net_device *dev, uint8 flag);
 static void dhd_net_if_lock_local(dhd_info_t *dhd);
@@ -2554,9 +2558,7 @@ void dhd_enable_packet_filter(int value, dhd_pub_t *dhd)
 
 static int dhd_set_suspend(int value, dhd_pub_t *dhd)
 {
-#ifndef SUPPORT_PM2_ONLY
        int power_mode = PM_MAX;
-#endif /* SUPPORT_PM2_ONLY */
 #ifdef SUPPORT_SENSORHUB
        uint32 shub_msreq;
 #endif /* SUPPORT_SENSORHUB */
@@ -2608,10 +2610,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
        /* set specific cpucore */
        dhd_set_cpucore(dhd, TRUE);
 #endif /* CUSTOM_SET_CPUCORE */
-#ifndef SUPPORT_PM2_ONLY
+
        if (dhd->conf->pm >= 0)
                power_mode = dhd->conf->pm;
-#endif /* SUPPORT_PM2_ONLY */
+       else
+               power_mode = PM_FAST;
        if (dhd->up) {
                if (value && dhd->in_suspend) {
 #ifdef PKT_FILTER_SUPPORT
@@ -2633,10 +2636,10 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
                        }
 #endif /* SUPPORT_SENSORHUB */
 
-#ifndef SUPPORT_PM2_ONLY
+                       if (dhd->conf->pm_in_suspend >= 0)
+                               power_mode = dhd->conf->pm_in_suspend;
                        dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
                                sizeof(power_mode), TRUE, 0);
-#endif /* SUPPORT_PM2_ONLY */
 
 #ifdef PKT_FILTER_SUPPORT
                        /* Enable packet filter,
@@ -2747,11 +2750,8 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
                                DHD_ERROR(("failed to set intr_width (%d)\n", ret));
                        }
 #endif /* DYNAMIC_SWOOB_DURATION */
-#ifndef SUPPORT_PM2_ONLY
-                       power_mode = PM_FAST;
                        dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode,
                                sizeof(power_mode), TRUE, 0);
-#endif /* SUPPORT_PM2_ONLY */
 #ifdef PKT_FILTER_SUPPORT
                        /* disable pkt filter */
                        dhd_enable_packet_filter(0, dhd);
@@ -2807,6 +2807,11 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd)
                                                ret));
                        }
 #endif /* DHD_USE_EARLYSUSPEND */
+
+                       /* terence 2017029: Reject in early suspend */
+                       if (!dhd->conf->xmit_in_suspend) {
+                               dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF);
+                       }
                }
        }
        dhd_suspend_unlock(dhd);
@@ -3500,6 +3505,9 @@ dhd_os_wlfc_block(dhd_pub_t *pub)
 {
        dhd_info_t *di = (dhd_info_t *)(pub->info);
        ASSERT(di != NULL);
+       /* terence 20161229: don't do spin lock if proptx not enabled */
+       if (disable_proptx)
+               return 1;
        spin_lock_bh(&di->wlfc_spinlock);
        return 1;
 }
@@ -3510,6 +3518,9 @@ dhd_os_wlfc_unblock(dhd_pub_t *pub)
        dhd_info_t *di = (dhd_info_t *)(pub->info);
 
        ASSERT(di != NULL);
+       /* terence 20161229: don't do spin lock if proptx not enabled */
+       if (disable_proptx)
+               return 1;
        spin_unlock_bh(&di->wlfc_spinlock);
        return 1;
 }
@@ -3920,6 +3931,16 @@ dhd_start_xmit(struct sk_buff *skb, struct net_device *net)
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
 
+       /* terence 2017029: Reject in early suspend */
+       if (!dhd->pub.conf->xmit_in_suspend && dhd->pub.early_suspended) {
+               dhd_txflowcontrol(&dhd->pub, ALL_INTERFACES, ON);
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 20))
+               return -ENODEV;
+#else
+               return NETDEV_TX_BUSY;
+#endif
+       }
+
 
 #ifdef PCIE_FULL_DONGLE
        DHD_GENERAL_LOCK(&dhd->pub, flags);
@@ -4240,7 +4261,6 @@ dhd_txflowcontrol(dhd_pub_t *dhdp, int ifidx, bool state)
        int i;
 
        DHD_TRACE(("%s: Enter\n", __FUNCTION__));
-       //DHD_ERROR(("%s: Enter, state=%d\n", __FUNCTION__, state));
 
        ASSERT(dhd);
 
@@ -5008,7 +5028,13 @@ dhd_rxf_thread(void *data)
        /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below  */
 
 #ifdef CUSTOM_RXF_CPUCORE
+       /* change rxf thread to other cpu core */
        set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_RXF_CPUCORE));
+#else
+       if (dhd->pub.conf->rxf_cpucore >= 0) {
+               printf("%s: set rxf_cpucore %d from config.txt\n", __FUNCTION__, dhd->pub.conf->rxf_cpucore);
+               set_cpus_allowed_ptr(current, cpumask_of(dhd->pub.conf->rxf_cpucore));
+       }
 #endif
 
        /*  signal: thread has started */
@@ -6016,7 +6042,10 @@ dhd_stop(struct net_device *net)
 #endif /* CONFIG_IPV6 && IPV6_NDO_SUPPORT */
                                dhd_net_if_unlock_local(dhd);
                        }
+#if 0
+                       // terence 20161024: remove this to prevent dev_close() get stuck in dhd_hang_process
                        cancel_work_sync(dhd->dhd_deferred_wq);
+#endif
 #if defined(DHD_LB) && defined(DHD_LB_RXP)
                        __skb_queue_purge(&dhd->rx_pend_queue);
 #endif /* DHD_LB && DHD_LB_RXP */
@@ -6047,9 +6076,12 @@ dhd_stop(struct net_device *net)
 
        OLD_MOD_DEC_USE_COUNT;
 exit:
-       if (ifidx == 0 && !dhd_download_fw_on_driverload)
+       if (ifidx == 0 && !dhd_download_fw_on_driverload) {
                wl_android_wifi_off(net, TRUE);
-       else {
+#ifdef WL_EXT_IAPSTA
+               wl_android_ext_dettach_netdev();
+#endif
+       } else {
                if (dhd->pub.conf->deepsleep)
                        dhd_deepsleep(dhd, 1);
        }
@@ -6126,6 +6158,12 @@ dhd_open(struct net_device *net)
 #endif /* BCM_FD_AGGR */
        int ifidx;
        int32 ret = 0;
+#if defined(OOB_INTR_ONLY)
+       uint32 bus_type = -1;
+       uint32 bus_num = -1;
+       uint32 slot_num = -1;
+       wifi_adapter_info_t *adapter = NULL;
+#endif
 
        if (!dhd_download_fw_on_driverload && !dhd_driver_init_done) {
                DHD_ERROR(("%s: WLAN driver is not initialized\n", __FUNCTION__));
@@ -6223,6 +6261,16 @@ dhd_open(struct net_device *net)
                        dhd_fix_cpu_freq(dhd);
                }
 #endif /* FIX_CPU_MIN_CLOCK */
+#if defined(OOB_INTR_ONLY)
+               if (dhd->pub.conf->dpc_cpucore >= 0) {
+                       dhd_bus_get_ids(dhd->pub.bus, &bus_type, &bus_num, &slot_num);
+                       adapter = dhd_wifi_platform_get_adapter(bus_type, bus_num, slot_num);
+                       if (adapter) {
+                               printf("%s: set irq affinity hit %d\n", __FUNCTION__, dhd->pub.conf->dpc_cpucore);
+                               irq_set_affinity_hint(adapter->irq_num, cpumask_of(dhd->pub.conf->dpc_cpucore));
+                       }
+               }
+#endif
 
                if (dhd->pub.busstate != DHD_BUS_DATA) {
 
@@ -6638,7 +6686,7 @@ dhd_remove_if(dhd_pub_t *dhdpub, int ifidx, bool need_rtnl_lock)
                dhd_if_del_sta_list(ifp);
 
                MFREE(dhdinfo->pub.osh, ifp, sizeof(*ifp));
-
+               ifp = NULL;
        }
 
        return BCME_OK;
@@ -7125,9 +7173,6 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
         * solution
         */
        dhd_update_fw_nv_path(dhd);
-#ifndef BUILD_IN_KERNEL
-       dhd_conf_read_config(&dhd->pub, dhd->conf_path);
-#endif
 
        /* Set network interface name if it was provided as module parameter */
        if (iface_name[0]) {
@@ -7207,6 +7252,8 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
        DHD_OS_WAKE_LOCK_INIT(dhd);
        dhd->wakelock_wd_counter = 0;
 #ifdef CONFIG_HAS_WAKELOCK
+       // terence 20161023: can not destroy wl_wifi when wlan down, it will happen null pointer in dhd_ioctl_entry
+       wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
        wake_lock_init(&dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake");
 #endif /* CONFIG_HAS_WAKELOCK */
 
@@ -7245,6 +7292,9 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen)
                }
                dhd_state |= DHD_ATTACH_STATE_WL_ATTACH;
        }
+#ifdef WL_ESCAN
+       wl_escan_attach(net, (void *)&dhd->pub);
+#endif
 #endif /* defined(WL_WIRELESS_EXT) */
 
 #ifdef SHOW_LOGTRACE
@@ -7481,9 +7531,11 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
 {
        int fw_len;
        int nv_len;
+       int clm_len;
        int conf_len;
        const char *fw = NULL;
        const char *nv = NULL;
+       const char *clm = NULL;
        const char *conf = NULL;
        wifi_adapter_info_t *adapter = dhdinfo->adapter;
 
@@ -7518,6 +7570,10 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
                if (adapter && adapter->nv_path && adapter->nv_path[0] != '\0')
                        nv = adapter->nv_path;
        }
+       if (dhdinfo->clm_path[0] == '\0') {
+               if (adapter && adapter->clm_path && adapter->clm_path[0] != '\0')
+                       clm = adapter->clm_path;
+       }
        if (dhdinfo->conf_path[0] == '\0') {
                if (adapter && adapter->conf_path && adapter->conf_path[0] != '\0')
                        conf = adapter->conf_path;
@@ -7531,6 +7587,8 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
                fw = firmware_path;
        if (nvram_path[0] != '\0')
                nv = nvram_path;
+       if (clm_path[0] != '\0')
+               clm = clm_path;
        if (config_path[0] != '\0')
                conf = config_path;
 
@@ -7554,6 +7612,16 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
                if (dhdinfo->nv_path[nv_len-1] == '\n')
                       dhdinfo->nv_path[nv_len-1] = '\0';
        }
+       if (clm && clm[0] != '\0') {
+               clm_len = strlen(clm);
+               if (clm_len >= sizeof(dhdinfo->clm_path)) {
+                       DHD_ERROR(("clm path len exceeds max len of dhdinfo->clm_path\n"));
+                       return FALSE;
+               }
+               strncpy(dhdinfo->clm_path, clm, sizeof(dhdinfo->clm_path));
+               if (dhdinfo->clm_path[clm_len-1] == '\n')
+                      dhdinfo->clm_path[clm_len-1] = '\0';
+       }
        if (conf && conf[0] != '\0') {
                conf_len = strlen(conf);
                if (conf_len >= sizeof(dhdinfo->conf_path)) {
@@ -7570,6 +7638,7 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
        if (dhd_download_fw_on_driverload) {
                firmware_path[0] = '\0';
                nvram_path[0] = '\0';
+               clm_path[0] = '\0';
                config_path[0] = '\0';
        }
 #endif
@@ -7584,12 +7653,6 @@ bool dhd_update_fw_nv_path(dhd_info_t *dhdinfo)
                DHD_ERROR(("nvram path not found\n"));
                return FALSE;
        }
-       if (dhdinfo->conf_path[0] == '\0') {
-               dhd_conf_set_conf_path_by_nv_path(&dhdinfo->pub, dhdinfo->conf_path, dhdinfo->nv_path);
-       }
-#ifdef CONFIG_PATH_AUTO_SELECT
-       dhd_conf_set_conf_name_by_chip(&dhdinfo->pub, dhdinfo->conf_path);
-#endif
 #endif /* BCMEMBEDIMAGE */
 
        return TRUE;
@@ -7625,6 +7688,8 @@ bool dhd_validate_chipid(dhd_pub_t *dhdp)
        config_chipid = BCM43342_CHIP_ID;
 #elif defined(BCM43455_CHIP)
        config_chipid = BCM4345_CHIP_ID;
+#elif defined(BCM43012_CHIP_)
+       config_chipid = BCM43012_CHIP_ID;
 #else
        DHD_ERROR(("%s: Unknown chip id, if you use new chipset,"
                " please add CONFIG_BCMXXXX into the Kernel and"
@@ -7665,7 +7730,7 @@ dhd_bus_start(dhd_pub_t *dhdp)
                DHD_INFO(("%s download fw %s, nv %s, conf %s\n",
                        __FUNCTION__, dhd->fw_path, dhd->nv_path, dhd->conf_path));
                ret = dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh,
-                       dhd->fw_path, dhd->nv_path, dhd->conf_path);
+                       dhd->fw_path, dhd->nv_path, dhd->clm_path, dhd->conf_path);
                if (ret < 0) {
                        DHD_ERROR(("%s: failed to download firmware %s\n",
                                __FUNCTION__, dhd->fw_path));
@@ -8230,7 +8295,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM;
        DHD_TRACE(("Enter %s\n", __FUNCTION__));
 
-       dhd_conf_set_fw_int_cmd(dhd, "WLC_SET_BAND", WLC_SET_BAND, dhd->conf->band, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_BAND, "WLC_SET_BAND", dhd->conf->band, 0, FALSE);
 #ifdef DHDTCPACK_SUPPRESS
        printf("%s: Set tcpack_sup_mode %d\n", __FUNCTION__, dhd->conf->tcpack_sup_mode);
        dhd_tcpack_suppress_set(dhd, dhd->conf->tcpack_sup_mode);
@@ -8271,27 +8336,25 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                if (ret < 0) {
                        DHD_ERROR(("%s: can't set MAC address MAC="MACDBG", error=%d\n",
                                __FUNCTION__, MAC2STRDBG(ea_addr.octet), ret));
-                       ret = BCME_NOTUP;
-                       goto done;
                }
-               memcpy(dhd->mac.octet, ea_addr.octet, ETHER_ADDR_LEN);
-       } else {
+       }
 #endif /* GET_CUSTOM_MAC_ENABLE */
-               /* Get the default device MAC address directly from firmware */
-               memset(buf, 0, sizeof(buf));
-               bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf));
-               if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
-                       FALSE, 0)) < 0) {
-                       DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
-                       ret = BCME_NOTUP;
-                       goto done;
-               }
-               /* Update public MAC address after reading from Firmware */
-               memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
+       /* Get the default device MAC address directly from firmware */
+       memset(buf, 0, sizeof(buf));
+       bcm_mkiovar("cur_etheraddr", 0, 0, buf, sizeof(buf));
+       if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf),
+               FALSE, 0)) < 0) {
+               DHD_ERROR(("%s: can't get MAC address , error=%d\n", __FUNCTION__, ret));
+               ret = BCME_NOTUP;
+               goto done;
+       }
+       /* Update public MAC address after reading from Firmware */
+       memcpy(dhd->mac.octet, buf, ETHER_ADDR_LEN);
 
-#ifdef GET_CUSTOM_MAC_ENABLE
+       if ((ret = dhd_apply_default_clm(dhd, dhd->clm_path)) < 0) {
+               DHD_ERROR(("%s: CLM set failed. Abort initialization.\n", __FUNCTION__));
+               goto done;
        }
-#endif /* GET_CUSTOM_MAC_ENABLE */
 
        /* get a capabilities from firmware */
        {
@@ -8438,6 +8501,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                (void)concurrent_mode;
 #endif 
        }
+#ifdef BCMSDIO
+       if (dhd->conf->sd_f2_blocksize)
+               dhdsdio_func_blocksize(dhd, 2, dhd->conf->sd_f2_blocksize);
+#endif
 
 #ifdef RSDB_MODE_FROM_FILE
        (void)dhd_rsdb_mode_from_file(dhd);
@@ -8486,6 +8553,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                dhd_conf_set_country(dhd);
                dhd_conf_fix_country(dhd);
        }
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "autocountry", dhd->conf->autocountry, 0, FALSE);
        dhd_conf_get_country(dhd, &dhd->dhd_cspec);
 
 
@@ -8555,13 +8623,13 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                }
        }
 #endif /* DHD_ENABLE_LPC */
-       dhd_conf_set_fw_string_cmd(dhd, "lpc", dhd->conf->lpc, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "lpc", dhd->conf->lpc, 0, FALSE);
 
        /* Set PowerSave mode */
        if (dhd->conf->pm >= 0)
                power_mode = dhd->conf->pm;
        dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0);
-       dhd_conf_set_fw_string_cmd(dhd, "pm2_sleep_ret", dhd->conf->pm2_sleep_ret, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "pm2_sleep_ret", dhd->conf->pm2_sleep_ret, 0, FALSE);
 
 #if defined(BCMSDIO)
        /* Match Host and Dongle rx alignment */
@@ -8600,15 +8668,18 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
        dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0);
 #endif /* defined(AP) && !defined(WLP2P) */
        /*  0:HT20 in ALL, 1:HT40 in ALL, 2: HT20 in 2G HT40 in 5G */
-       dhd_conf_set_fw_string_cmd(dhd, "mimo_bw_cap", dhd->conf->mimo_bw_cap, 1, TRUE);
-       dhd_conf_set_fw_string_cmd(dhd, "force_wme_ac", dhd->conf->force_wme_ac, 1, FALSE);
-       dhd_conf_set_fw_string_cmd(dhd, "stbc_tx", dhd->conf->stbc, 0, FALSE);
-       dhd_conf_set_fw_string_cmd(dhd, "stbc_rx", dhd->conf->stbc, 0, FALSE);
-       dhd_conf_set_fw_int_cmd(dhd, "WLC_SET_SRL", WLC_SET_SRL, dhd->conf->srl, 0, TRUE);
-       dhd_conf_set_fw_int_cmd(dhd, "WLC_SET_LRL", WLC_SET_LRL, dhd->conf->lrl, 0, FALSE);
-       dhd_conf_set_fw_int_cmd(dhd, "WLC_SET_SPECT_MANAGMENT", WLC_SET_SPECT_MANAGMENT, dhd->conf->spect, 0, FALSE);
-       dhd_conf_set_fw_string_cmd(dhd, "rsdb_mode", dhd->conf->rsdb_mode, -1, TRUE);
-       dhd_conf_set_fw_string_cmd(dhd, "vhtmode", dhd->conf->vhtmode, 0, TRUE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "mimo_bw_cap", dhd->conf->mimo_bw_cap, 1, TRUE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "force_wme_ac", dhd->conf->force_wme_ac, 1, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "stbc_tx", dhd->conf->stbc, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "stbc_rx", dhd->conf->stbc, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_SRL, "WLC_SET_SRL", dhd->conf->srl, 0, TRUE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_LRL, "WLC_SET_LRL", dhd->conf->lrl, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_SPECT_MANAGMENT, "WLC_SET_SPECT_MANAGMENT", dhd->conf->spect, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "rsdb_mode", dhd->conf->rsdb_mode, -1, TRUE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "vhtmode", dhd->conf->vhtmode, 0, TRUE);
+#ifdef IDHCPC
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "dhcpc_enable", dhd->conf->dhcpc_enable, 0, FALSE);
+#endif
        dhd_conf_set_bw_cap(dhd);
 
 #ifdef MIMO_ANT_SETTING
@@ -8645,7 +8716,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                DHD_ERROR(("%s Set txbf returned (%d)\n", __FUNCTION__, ret));
        }
 #endif /* USE_WL_TXBF */
-       dhd_conf_set_fw_string_cmd(dhd, "txbf", dhd->conf->txbf, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "txbf", dhd->conf->txbf, 0, FALSE);
 
 #ifdef USE_WFA_CERT_CONF
 #ifdef USE_WL_FRAMEBURST
@@ -8668,7 +8739,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                sizeof(frameburst), TRUE, 0)) < 0) {
                DHD_INFO(("%s frameburst not supported  %d\n", __FUNCTION__, ret));
        }
-       dhd_conf_set_fw_int_cmd(dhd, "WLC_SET_FAKEFRAG", WLC_SET_FAKEFRAG, dhd->conf->frameburst, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_FAKEFRAG, "WLC_SET_FAKEFRAG", dhd->conf->frameburst, 0, FALSE);
 #if defined(CUSTOM_AMPDU_BA_WSIZE)
        /* Set ampdu ba wsize to 64 or 16 */
 #ifdef CUSTOM_AMPDU_BA_WSIZE
@@ -8683,7 +8754,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                }
        }
 #endif 
-       dhd_conf_set_fw_string_cmd(dhd, "ampdu_ba_wsize", dhd->conf->ampdu_ba_wsize, 1, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_ba_wsize", dhd->conf->ampdu_ba_wsize, 1, FALSE);
 
        iov_buf = (char*)kmalloc(WLC_IOCTL_SMLEN, GFP_KERNEL);
        if (iov_buf == NULL) {
@@ -8811,6 +8882,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #ifdef WLTDLS
        setbit(eventmask, WLC_E_TDLS_PEER_EVENT);
 #endif /* WLTDLS */
+#ifdef WL_ESCAN
+       setbit(eventmask, WLC_E_ESCAN_RESULT);
+#endif
 #ifdef WL_CFG80211
        setbit(eventmask, WLC_E_ESCAN_RESULT);
        setbit(eventmask, WLC_E_AP_STARTED);
@@ -8985,14 +9059,35 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                sec_save_wlinfo(buf, EPI_VERSION_STR, dhd->info->nv_path);
 #endif /* WRITE_WLANINFO */
        }
+       /* query for 'clmver' to get clm version info from firmware */
+       memset(buf, 0, sizeof(buf));
+       bcm_mkiovar("clmver", (char *)&buf, 4, buf, sizeof(buf));
+       if ((ret  = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, sizeof(buf), FALSE, 0)) < 0)
+               DHD_ERROR(("%s failed %d\n", __FUNCTION__, ret));
+       else {
+               char *clmver_temp_buf = NULL;
+
+               if ((clmver_temp_buf = bcmstrstr(buf, "Data:")) == NULL) {
+                       DHD_ERROR(("Couldn't find \"Data:\"\n"));
+               } else {
+                       ptr = (clmver_temp_buf + strlen("Data:"));
+                       if ((clmver_temp_buf = bcmstrtok(&ptr, "\n", 0)) == NULL) {
+                               DHD_ERROR(("Couldn't find New line character\n"));
+                       } else {
+                               memset(clm_version, 0, CLM_VER_STR_LEN);
+                               strncpy(clm_version, clmver_temp_buf,
+                                       MIN(strlen(clmver_temp_buf), CLM_VER_STR_LEN - 1));
+                               DHD_ERROR(("  clm = %s\n", clm_version));
+                       }
+               }
+       }
 
 #if defined(BCMSDIO)
        dhd_txglom_enable(dhd, dhd->conf->bus_rxglom);
        // terence 20151210: set bus:txglom after dhd_txglom_enable since it's possible changed in dhd_conf_set_txglom_params
-       dhd_conf_set_fw_string_cmd(dhd, "bus:txglom", dhd->conf->bus_txglom, 0, FALSE);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "bus:txglom", dhd->conf->bus_txglom, 0, FALSE);
 #endif /* defined(BCMSDIO) */
 
-       dhd_conf_set_disable_proptx(dhd);
 #if defined(BCMSDIO)
 #ifdef PROP_TXSTATUS
        if (disable_proptx ||
@@ -9004,6 +9099,16 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
                FALSE) {
                wlfc_enable = FALSE;
        }
+       ret = dhd_conf_get_disable_proptx(dhd);
+       if (ret == 0){
+               disable_proptx = 0;
+               wlfc_enable = TRUE;
+       } else if (ret >= 1) {
+               disable_proptx = 1;
+               wlfc_enable = FALSE;
+               /* terence 20161229: we should set ampdu_hostreorder=0 when disalbe_proptx=1 */
+               hostreorder = 0;
+       }
 
 #ifdef USE_WFA_CERT_CONF
        if (sec_get_param_wfa_cert(dhd, SET_PARAM_PROPTX, &proptx) == BCME_OK) {
@@ -9040,14 +9145,21 @@ dhd_preinit_ioctls(dhd_pub_t *dhd)
 #endif /* DISABLE_11N */
 
 
-       if (wlfc_enable)
+       if (wlfc_enable) {
                dhd_wlfc_init(dhd);
+               /* terence 20161229: enable ampdu_hostreorder if tlv enabled */
+               dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", 1, 0, TRUE);
+       }
 #ifndef DISABLE_11N
        else if (hostreorder)
                dhd_wlfc_hostreorder_init(dhd);
 #endif /* DISABLE_11N */
-
+#else
+       /* terence 20161229: disable ampdu_hostreorder if PROP_TXSTATUS not defined */
+       printf("%s: not define PROP_TXSTATUS\n", __FUNCTION__);
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", 0, 0, TRUE);
 #endif /* PROP_TXSTATUS */
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", dhd->conf->ampdu_hostreorder, 0, TRUE);
 #endif /* BCMSDIO || BCMBUS */
 #ifdef PCIE_FULL_DONGLE
        /* For FD we need all the packets at DHD to handle intra-BSS forwarding */
@@ -9495,6 +9607,11 @@ dhd_register_if(dhd_pub_t *dhdp, int ifidx, bool need_rtnl_lock)
 
        if (ifidx == 0)
                printf("%s\n", dhd_version);
+#ifdef WL_EXT_IAPSTA
+       else if (!strncmp(net->name, "wl0.", strlen("wl0."))) {
+               wl_android_ext_attach_netdev(net, ifidx);
+       }
+#endif
 
        if (need_rtnl_lock)
                err = register_netdev(net);
@@ -9682,6 +9799,9 @@ void dhd_detach(dhd_pub_t *dhdp)
                /* Detatch and unlink in the iw */
                wl_iw_detach();
        }
+#ifdef WL_ESCAN
+       wl_escan_detach();
+#endif
 #endif /* defined(WL_WIRELESS_EXT) */
 
        /* delete all interfaces, start with virtual  */
@@ -9827,6 +9947,8 @@ void dhd_detach(dhd_pub_t *dhdp)
 #ifdef CONFIG_HAS_WAKELOCK
                dhd->wakelock_wd_counter = 0;
                wake_lock_destroy(&dhd->wl_wdwake);
+               // terence 20161023: can not destroy wl_wifi when wlan down, it will happen null pointer in dhd_ioctl_entry
+               wake_lock_destroy(&dhd->wl_wifi);
 #endif /* CONFIG_HAS_WAKELOCK */
                DHD_OS_WAKE_LOCK_DESTROY(dhd);
        }
@@ -9955,6 +10077,7 @@ dhd_module_cleanup(void)
        wl_android_exit();
 
        dhd_wifi_platform_unregister_drv();
+
 #ifdef CUSTOMER_HW_AMLOGIC
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
        wifi_teardown_dt();
@@ -9977,7 +10100,7 @@ dhd_module_init(void)
        int err;
        int retry = POWERUP_MAX_RETRY;
 
-       printf("%s: in\n", __FUNCTION__);
+       printf("%s: in %s\n", __FUNCTION__, dhd_version);
 #ifdef CUSTOMER_HW_AMLOGIC
 #if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 14, 0))
        if (wifi_setup_dt()) {
@@ -10396,6 +10519,20 @@ dhd_os_get_image_block(char *buf, int len, void *image)
        return rdlen;
 }
 
+int
+dhd_os_get_image_size(void *image)
+{
+       struct file *fp = (struct file *)image;
+       int size;
+       if (!image) {
+               return 0;
+       }
+
+       size = i_size_read(file_inode(fp));
+
+       return size;
+}
+
 void
 dhd_os_close_image(void *image)
 {
@@ -10721,7 +10858,7 @@ dhd_net_bus_devreset(struct net_device *dev, uint8 flag)
                dhd_update_fw_nv_path(dhd);
                /* update firmware and nvram path to sdio bus */
                dhd_bus_update_fw_nv_path(dhd->pub.bus,
-                       dhd->fw_path, dhd->nv_path, dhd->conf_path);
+                       dhd->fw_path, dhd->nv_path, dhd->clm_path, dhd->conf_path);
        }
 #endif /* BCMSDIO */
 
@@ -11251,6 +11388,10 @@ static void dhd_hang_process(void *dhd_info, void *event_info, u8 event)
        dev = dhd->iflist[0]->net;
 
        if (dev) {
+               // terence 20161024: let wlan0 down when hang happened
+               rtnl_lock();
+               dev_close(dev);
+               rtnl_unlock();
 #if defined(WL_WIRELESS_EXT)
                wl_iw_send_priv_event(dev, "HANG");
 #endif
@@ -12337,7 +12478,7 @@ void dhd_os_wake_lock_init(struct dhd_info *dhd)
        dhd->wakelock_rx_timeout_enable = 0;
        dhd->wakelock_ctrl_timeout_enable = 0;
 #ifdef CONFIG_HAS_WAKELOCK
-       wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake");
+       // terence 20161023: can not destroy wl_wifi when wlan down, it will happen null pointer in dhd_ioctl_entry
        wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake");
        wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake");
        wake_lock_init(&dhd->wl_evtwake, WAKE_LOCK_SUSPEND, "wlan_evt_wake");
@@ -12361,7 +12502,7 @@ void dhd_os_wake_lock_destroy(struct dhd_info *dhd)
        dhd->wakelock_counter = 0;
        dhd->wakelock_rx_timeout_enable = 0;
        dhd->wakelock_ctrl_timeout_enable = 0;
-       wake_lock_destroy(&dhd->wl_wifi);
+       // terence 20161023: can not destroy wl_wifi when wlan down, it will happen null pointer in dhd_ioctl_entry
        wake_lock_destroy(&dhd->wl_rxwake);
        wake_lock_destroy(&dhd->wl_ctrlwake);
        wake_lock_destroy(&dhd->wl_evtwake);
@@ -13920,8 +14061,21 @@ void *dhd_get_pub(struct net_device *dev)
        dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
        if (dhdinfo)
                return (void *)&dhdinfo->pub;
-       else
+       else {
+               printf("%s: null dhdinfo\n", __FUNCTION__);
+               return NULL;
+       }
+}
+
+void *dhd_get_conf(struct net_device *dev)
+{
+       dhd_info_t *dhdinfo = *(dhd_info_t **)netdev_priv(dev);
+       if (dhdinfo)
+               return (void *)dhdinfo->pub.conf;
+       else {
+               printf("%s: null dhdinfo\n", __FUNCTION__);
                return NULL;
+       }
 }
 
 bool dhd_os_wd_timer_enabled(void *bus)
index 307de6b793607461d2c9f7afba40d414c91a323f..79290db34dd27160252e3a9c406f79bf056c041f 100644 (file)
@@ -59,27 +59,32 @@ typedef struct wifi_adapter_info {
        uint            intr_flags;
        const char      *fw_path;
        const char      *nv_path;
+       const char      *clm_path;
        const char      *conf_path;
        void            *wifi_plat_data;        /* wifi ctrl func, for backward compatibility */
        uint            bus_type;
        uint            bus_num;
        uint            slot_num;
-#ifdef CUSTOMER_HW_INTEL
+#ifdef BUS_POWER_RESTORE
 #if defined(BCMSDIO)
        struct sdio_func *sdio_func;
 #endif /* BCMSDIO */
+#if defined(BCMPCIE)
+       struct pci_dev *pci_dev;
+       struct pci_saved_state *pci_saved_state;
+#endif /* BCMPCIE */
 #endif
 } wifi_adapter_info_t;
 
-#if defined(CUSTOMER_HW)
 #define WLAN_PLAT_NODFS_FLAG    0x01
 #define WLAN_PLAT_AP_FLAG      0x02
 struct wifi_platform_data {
-#ifdef CUSTOMER_HW_INTEL
+#ifdef BUS_POWER_RESTORE
        int (*set_power)(bool val, wifi_adapter_info_t *adapter);
 #else
        int (*set_power)(bool val);
 #endif
+       int (*set_reset)(int val);
        int (*set_carddetect)(bool val);
        void *(*mem_prealloc)(int section, unsigned long size);
        int (*get_mac_addr)(unsigned char *buf);
@@ -89,7 +94,6 @@ struct wifi_platform_data {
        void *(*get_country_code)(char *ccode);
 #endif
 };
-#endif
 
 typedef struct bcmdhd_wifi_platdata {
        uint                            num_adapters;
index c1d90b6eb5de550f4902adfeca0a2975ba3f1be7..a154cb3c2e12e8cbe67dce2b45acf583c3c4f65d 100644 (file)
 #endif /* CONFIG_DTS */
 
 #if defined(CUSTOMER_HW)
-#if defined(CUSTOMER_OOB)
-extern uint bcm_wlan_get_oob_irq(void);
-extern void bcm_wlan_free_oob_gpio(uint irq_num);
-extern uint bcm_wlan_get_oob_irq_flags(void);
-#endif
-extern int bcm_wlan_set_plat_data(void);
+extern int dhd_wlan_init_plat_data(void);
+extern void dhd_wlan_deinit_plat_data(wifi_adapter_info_t *adapter);
 #endif /* CUSTOMER_HW */
 
 #define WIFI_PLAT_NAME         "bcmdhd_wlan"
@@ -71,13 +67,12 @@ static bool is_power_on = FALSE;
 #if !defined(CONFIG_DTS)
 #if defined(DHD_OF_SUPPORT)
 static bool dts_enabled = TRUE;
+extern struct resource dhd_wlan_resources;
 extern struct wifi_platform_data dhd_wlan_control;
 #else
 static bool dts_enabled = FALSE;
 struct resource dhd_wlan_resources = {0};
-#ifdef CUSTOMER_HW
-struct wifi_platform_data dhd_wlan_control = {0};
-#endif
+extern struct wifi_platform_data dhd_wlan_control;
 #endif /* !defind(DHD_OF_SUPPORT) */
 #endif /* !defind(CONFIG_DTS) */
 
@@ -188,7 +183,7 @@ int wifi_platform_set_power(wifi_adapter_info_t *adapter, bool on, unsigned long
                }
 #endif /* ENABLE_4335BT_WAR */
 
-#ifdef CUSTOMER_HW_INTEL
+#ifdef BUS_POWER_RESTORE
                err = plat_data->set_power(on, adapter);
 #else
                err = plat_data->set_power(on);
@@ -262,7 +257,7 @@ wifi_platform_get_country_code(wifi_adapter_info_t *adapter, char *ccode)
                return plat_data->get_country_code(ccode);
 #endif /* CUSTOM_COUNTRY_CODE */
        }
-#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 10, 58)) */
+#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 39)) */
 
        return NULL;
 }
@@ -439,7 +434,7 @@ static int wifi_ctrlfunc_register_drv(void)
        adapter = kzalloc(sizeof(wifi_adapter_info_t), GFP_KERNEL);
        if (adapter == NULL) {
                DHD_ERROR(("%s:adapter alloc failed", __FUNCTION__));
-               return ENOMEM;
+               return -ENOMEM;
        }
        adapter->name = "DHD generic adapter";
        adapter->bus_type = -1;
@@ -473,19 +468,16 @@ static int wifi_ctrlfunc_register_drv(void)
 
 #if !defined(CONFIG_DTS)
        if (dts_enabled) {
-#ifdef CUSTOMER_HW
-               adapter->wifi_plat_data = (void *)&dhd_wlan_control;
-               bcm_wlan_set_plat_data();
-#ifdef CUSTOMER_OOB
-               adapter->irq_num = bcm_wlan_get_oob_irq();
-               adapter->intr_flags = bcm_wlan_get_oob_irq_flags();
-#endif
-#else
                struct resource *resource;
+               adapter->wifi_plat_data = (void *)&dhd_wlan_control;
                resource = &dhd_wlan_resources;
+#ifdef CUSTOMER_HW
+               wifi_plat_dev_probe_ret = dhd_wlan_init_plat_data();
+               if (wifi_plat_dev_probe_ret)
+                       return wifi_plat_dev_probe_ret;
+#endif
                adapter->irq_num = resource->start;
                adapter->intr_flags = resource->flags & IRQF_TRIGGER_MASK;
-#endif
                wifi_plat_dev_probe_ret = dhd_wifi_platform_load();
        }
 #endif /* !defined(CONFIG_DTS) */
@@ -531,8 +523,8 @@ void wifi_ctrlfunc_unregister_drv(void)
        }
 #endif /* !defined(CONFIG_DTS) */
 
-#if defined(CUSTOMER_HW) && defined(CUSTOMER_OOB)
-       bcm_wlan_free_oob_gpio(adapter->irq_num);
+#if defined(CUSTOMER_HW)
+       dhd_wlan_deinit_plat_data(adapter);
 #endif
 
        kfree(dhd_wifi_platdata->adapters);
index 72f2ca3dc5f4e805faf88083c37c44feb9efa214..d6fc50de4d954102c7d35e2557572f48735ec5f7 100644 (file)
@@ -813,7 +813,8 @@ dhdpcie_bus_remove_prep(dhd_bus_t *bus)
        dhd_os_sdlock(bus->dhd);
 
        dhdpcie_bus_intr_disable(bus);
-       if (!bus->dhd->dongle_isolation) {
+       // terence 20150406: fix for null pointer handle when doing remove driver
+       if (!bus->dhd->dongle_isolation && bus->sih) {
                pcie_watchdog_reset(bus->osh, bus->sih, (sbpcieregs_t *)(bus->regs));
        }
 
@@ -1182,12 +1183,14 @@ err:
 /* Download firmware image and nvram image */
 int
 dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
-                          char *pfw_path, char *pnv_path, char *pconf_path)
+                          char *pfw_path, char *pnv_path,
+                          char *pclm_path, char *pconf_path)
 {
        int ret;
 
        bus->fw_path = pfw_path;
        bus->nv_path = pnv_path;
+       bus->dhd->clm_path = pclm_path;
        bus->dhd->conf_path = pconf_path;
 
        DHD_ERROR(("%s: firmware path=%s, nvram path=%s\n",
@@ -1200,6 +1203,36 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
        return ret;
 }
 
+void
+dhd_set_path_params(struct dhd_bus *bus)
+{
+       /* External conf takes precedence if specified */
+       dhd_conf_preinit(bus->dhd);
+
+       if (bus->dhd->clm_path[0] == '\0') {
+               dhd_conf_set_path(bus->dhd, "clm.blob", bus->dhd->clm_path, bus->fw_path);
+       }
+       dhd_conf_set_clm_name_by_chip(bus->dhd, bus->dhd->clm_path);
+       if (bus->dhd->conf_path[0] == '\0') {
+               dhd_conf_set_path(bus->dhd, "config.txt", bus->dhd->conf_path, bus->nv_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);
+
+}
+
 static int
 dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
 {
@@ -1240,15 +1273,7 @@ dhdpcie_download_firmware(struct dhd_bus *bus, osl_t *osh)
 
        DHD_OS_WAKE_LOCK(bus->dhd);
 
-       /* External conf takes precedence if specified */
-       dhd_conf_preinit(bus->dhd);
-       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);
-
-       printf("Final fw_path=%s\n", bus->fw_path);
-       printf("Final nv_path=%s\n", bus->nv_path);
-       printf("Final conf_path=%s\n", bus->dhd->conf_path);
+       dhd_set_path_params(bus);
 
        ret = _dhdpcie_download_firmware(bus);
 
@@ -2086,7 +2111,7 @@ dhdpcie_bus_membytes(dhd_bus_t *bus, bool write, ulong address, uint8 *data, uin
        dsize = sizeof(uint64);
 
        /* Do the transfer(s) */
-       DHD_INFO(("%s: %s %d bytes in window 0x%08x\n",
+       DHD_INFO(("%s: %s %d bytes in window 0x%08lx\n",
                  __FUNCTION__, (write ? "write" : "read"), size, address));
        if (write) {
                while (size) {
@@ -2180,7 +2205,7 @@ dhd_bus_schedule_queue(struct dhd_bus  *bus, uint16 flow_id, bool txs)
                }
 
                while ((txp = dhd_flow_queue_dequeue(bus->dhd, queue)) != NULL) {
-                       PKTORPHAN(txp);
+                       PKTORPHAN(txp, bus->dhd->conf->tsq);
 
                        /*
                         * Modifying the packet length caused P2P cert failures.
@@ -3732,6 +3757,7 @@ dhdpcie_bus_suspend(struct dhd_bus *bus, bool state)
        unsigned long flags;
        int rc = 0;
 
+       printf("%s: state=%d\n", __FUNCTION__, state);
        if (bus->dhd == NULL) {
                DHD_ERROR(("%s: bus not inited\n", __FUNCTION__));
                return BCME_ERROR;
index 053e784345b5402dafdf3df0b370b802c8f4fdd6..0fef810a3a7cad8ff0a678602d02d885e14da5fd 100644 (file)
@@ -493,6 +493,9 @@ 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
 
        if (dhdpcie_chipmatch (pdev->vendor, pdev->device)) {
                DHD_ERROR(("%s: chipmatch failed!!\n", __FUNCTION__));
@@ -512,6 +515,14 @@ 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__));
        return 0;
 }
@@ -1399,9 +1410,9 @@ int dhdpcie_oob_intr_register(dhd_bus_t *bus)
        }
 
        if (dhdpcie_osinfo->oob_irq_num > 0) {
-               DHD_INFO_HW4(("%s OOB irq=%d flags=%X \n", __FUNCTION__,
+               printf("%s OOB irq=%d flags=0x%X\n", __FUNCTION__,
                        (int)dhdpcie_osinfo->oob_irq_num,
-                       (int)dhdpcie_osinfo->oob_irq_flags));
+                       (int)dhdpcie_osinfo->oob_irq_flags);
                err = request_irq(dhdpcie_osinfo->oob_irq_num, wlan_oob_irq,
                        dhdpcie_osinfo->oob_irq_flags, "dhdpcie_host_wake",
                        bus);
@@ -1410,10 +1421,17 @@ int dhdpcie_oob_intr_register(dhd_bus_t *bus)
                                __FUNCTION__, err));
                        return err;
                }
+#if defined(DISABLE_WOWLAN)
+               printf("%s: disable_irq_wake\n", __FUNCTION__);
+               dhdpcie_osinfo->oob_irq_wake_enabled = FALSE;
+#else
+               printf("%s: enable_irq_wake\n", __FUNCTION__);
                err = enable_irq_wake(dhdpcie_osinfo->oob_irq_num);
                if (!err) {
                        dhdpcie_osinfo->oob_irq_wake_enabled = TRUE;
-               }
+               } else
+                       printf("%s: enable_irq_wake failed with %d\n", __FUNCTION__, err);
+#endif
                dhdpcie_osinfo->oob_irq_enabled = TRUE;
        }
 
index a71225ae4d651ec7742fc4dbcc0ce293ad267f2a..a5059f9bd21f89d21d50508ab7048efc848f2d5b 100644 (file)
@@ -92,11 +92,11 @@ extern bool  bcmsdh_fatal_error(void *sdh);
 #define TXRETRIES      2       /* # of retries for tx frames */
 #define READ_FRM_CNT_RETRIES   3
 #ifndef DHD_RXBOUND
-#define DHD_RXBOUND    64      /* Default for max rx frames in one scheduling */
+#define DHD_RXBOUND    50      /* Default for max rx frames in one scheduling */
 #endif
 
 #ifndef DHD_TXBOUND
-#define DHD_TXBOUND    64      /* Default for max tx frames in one scheduling */
+#define DHD_TXBOUND    20      /* Default for max tx frames in one scheduling */
 #endif
 
 #define DHD_TXMINMAX   1       /* Max tx frames if rx still pending */
@@ -777,11 +777,14 @@ dhdsdio_sr_cap(dhd_bus_t *bus)
                (bus->sih->chip == BCM43569_CHIP_ID) ||
                (bus->sih->chip == BCM4371_CHIP_ID) ||
                (BCM4349_CHIP(bus->sih->chip))          ||
-               (bus->sih->chip == BCM4350_CHIP_ID)) {
+               (bus->sih->chip == BCM4350_CHIP_ID) ||
+               (bus->sih->chip == BCM43012_CHIP_ID)) {
                core_capext = TRUE;
        } else {
-                       core_capext = bcmsdh_reg_read(bus->sdh, CORE_CAPEXT_ADDR, 4);
-                       core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
+               core_capext = bcmsdh_reg_read(bus->sdh,
+                       si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, core_cap_ext)),
+                       4);
+               core_capext = (core_capext & CORE_CAPEXT_SR_SUPPORTED_MASK);
        }
        if (!(core_capext))
                return FALSE;
@@ -820,7 +823,8 @@ dhdsdio_sr_cap(dhd_bus_t *bus)
                        cap = TRUE;
        } else {
                data = bcmsdh_reg_read(bus->sdh,
-                       SI_ENUM_BASE + OFFSETOF(chipcregs_t, retention_ctl), 4);
+                       si_get_pmu_reg_addr(bus->sih, OFFSETOF(chipcregs_t, retention_ctl)),
+                       4);
                if ((data & (RCTL_MACPHY_DISABLE_MASK | RCTL_LOGIC_DISABLE_MASK)) == 0)
                        cap = TRUE;
        }
@@ -850,11 +854,19 @@ dhdsdio_sr_init(dhd_bus_t *bus)
        if ((bus->sih->chip == BCM4334_CHIP_ID) && (bus->sih->chiprev == 2))
                dhdsdio_srwar_init(bus);
 
-       val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
-       val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
-       bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
-               1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
-       val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+       if (bus->sih->chip == BCM43012_CHIP_ID) {
+               val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+               val |= 1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT;
+               bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
+                       1 << SBSDIO_FUNC1_WCTRL_ALPWAIT_SHIFT, &err);
+               val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+       } else {
+               val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+               val |= 1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT;
+               bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL,
+                       1 << SBSDIO_FUNC1_WCTRL_HTWAIT_SHIFT, &err);
+               val = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_WAKEUPCTRL, NULL);
+       }
 
 #ifdef USE_CMD14
        /* Add CMD14 Support */
@@ -864,9 +876,13 @@ dhdsdio_sr_init(dhd_bus_t *bus)
 
        dhdsdio_devcap_set(bus, SDIOD_CCCR_BRCM_CARDCAP_CMD_NODEC);
 
-       bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
-               SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
-
+       if (bus->sih->chip == BCM43012_CHIP_ID) {
+               bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+                       SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_HT_AVAIL_REQ, &err);
+       } else {
+               bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1,
+                       SBSDIO_FUNC1_CHIPCLKCSR, SBSDIO_FORCE_HT, &err);
+       }
        bus->_slpauto = dhd_slpauto ? TRUE : FALSE;
 
        bus->_srenab = TRUE;
@@ -920,16 +936,22 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on)
        uint8 wr_val = 0, rd_val, cmp_val, bmask;
        int err = 0;
        int try_cnt = 0;
-
-       if (!bus->dhd->conf->kso_enable)
-               return 0;
-
+       return 0;
        KSO_DBG(("%s> op:%s\n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR")));
 
        wr_val |= (on << SBSDIO_FUNC1_SLEEPCSR_KSO_SHIFT);
 
        bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err);
 
+
+       /* In case of 43012 chip, the chip could go down immediately after KSO bit is cleared.
+        * So the further reads of KSO register could fail. Thereby just bailing out immediately
+        * after clearing KSO bit, to avoid polling of KSO bit.
+        */
+       if ((!on) && (bus->sih->chip == BCM43012_CHIP_ID)) {
+               return err;
+       }
+
        if (on) {
                cmp_val = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK |  SBSDIO_FUNC1_SLEEPCSR_DEVON_MASK;
                bmask = cmp_val;
@@ -1602,7 +1624,6 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep)
        return err;
 }
 
-#ifdef USE_DYNAMIC_F2_BLKSIZE
 int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
 {
        int func_blk_size = function_num;
@@ -1618,7 +1639,7 @@ int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
        }
 
        if (result != block_size) {
-               DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n",
+               DHD_ERROR(("%s: F%d Block size set from %d to %d\n",
                        __FUNCTION__, function_num, result, block_size));
                func_blk_size = function_num << 16 | block_size;
                bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL,
@@ -1631,7 +1652,6 @@ int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size)
 
        return BCME_OK;
 }
-#endif /* USE_DYNAMIC_F2_BLKSIZE */
 
 #if defined(OOB_INTR_ONLY) || defined(FORCE_WOWLAN)
 void
@@ -1695,8 +1715,8 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt)
        prec = PRIO2PREC((PKTPRIO(pkt) & PRIOMASK));
 
        /* move from dhdsdio_sendfromq(), try to orphan skb early */
-       PKTORPHAN(pkt);
-       
+       PKTORPHAN(pkt, bus->dhd->conf->tsq);
+
        /* Check for existing queue, current flow-control, pending event, or pending clock */
        if (dhd_deferred_tx || bus->fcstate || pktq_len(&bus->txq) || bus->dpc_sched ||
            (!DATAOK(bus)) || (bus->flowcontrol & NBITVAL(prec)) ||
@@ -2916,7 +2936,6 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
                        num_pkt = MIN(num_pkt, ARRAYSIZE(pkts));
                }
                num_pkt = MIN(num_pkt, pktq_mlen(&bus->txq, tx_prec_map));
-
                for (i = 0; i < num_pkt; i++) {
                        pkts[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out);
                        if (!pkts[i]) {
@@ -2926,7 +2945,7 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes)
                                break;
                        }
                        /* move orphan to dhd_bus_txdata() */
-                       /* PKTORPHAN(pkts[i]); */
+                       /* PKTORPHAN(pkts[i], bus->dhd->conf->tsq); */
                        datalen += PKTLEN(osh, pkts[i]);
                }
                dhd_os_sdunlock_txq(bus->dhd);
@@ -5281,8 +5300,13 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex)
        /* Force clocks on backplane to be sure F2 interrupt propagates */
        saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err);
        if (!err) {
-               bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
-                                (saveclk | SBSDIO_FORCE_HT), &err);
+               if (bus->sih->chip == BCM43012_CHIP_ID) {
+                       bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+                               (saveclk | SBSDIO_HT_AVAIL_REQ), &err);
+               } else {
+                       bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR,
+                               (saveclk | SBSDIO_FORCE_HT), &err);
+               }
        }
        if (err) {
                DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err));
@@ -6922,12 +6946,11 @@ dhdsdio_dpc(dhd_bus_t *bus)
        bus->intstatus = intstatus;
 
 clkwait:
-#if 0
        /* Re-enable interrupts to detect new device events (mailbox, rx frame)
         * or clock availability.  (Allows tx loop to check ipend if desired.)
         * (Unless register access seems hosed, as we may not be able to ACK...)
         */
-       if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
+       if (!bus->dhd->conf->oob_enabled_later && bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
                DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
                          __FUNCTION__, rxdone, framecnt));
                bus->intdis = FALSE;
@@ -6936,7 +6959,6 @@ clkwait:
 #endif /* defined(OOB_INTR_ONLY) */
                bcmsdh_intr_enable(sdh);
        }
-#endif
 
 #if defined(OOB_INTR_ONLY) && !defined(HW_OOB)
        /* In case of SW-OOB(using edge trigger),
@@ -6958,12 +6980,16 @@ clkwait:
        dhd_wlfc_commit_packets(bus->dhd, (f_commitpkt_t)dhd_bus_txdata, (void *)bus, NULL, FALSE);
 #endif
 
-       if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) {
+       if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL))
                dhdsdio_sendpendctl(bus);
-       } else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
+
+       /* Send queued frames (limit 1 if rx may still be pending) */
+       else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate &&
            pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) {
-               /* Send queued frames (limit 1 if rx may still be pending) */
-               framecnt = rxdone ? txlimit : MIN(txlimit, DATABUFCNT(bus));
+               if (bus->dhd->conf->dhd_txminmax < 0)
+                       framecnt = rxdone ? txlimit : MIN(txlimit, DATABUFCNT(bus));
+               else
+                       framecnt = rxdone ? txlimit : MIN(txlimit, bus->dhd->conf->dhd_txminmax);
 #if defined(SWTXGLOM)
                if (bus->dhd->conf->swtxglom)
                        framecnt = dhdsdio_sendfromq_swtxglom(bus, framecnt);
@@ -6972,26 +6998,6 @@ clkwait:
                framecnt = dhdsdio_sendfromq(bus, framecnt);
                txlimit -= framecnt;
        }
-#if 0 
-       else {
-               if (pktq_mlen(&bus->txq, ~bus->flowcontrol)) {
-                       DHD_ERROR(("%s: cannot do tx due to:\n", __FUNCTION__));
-                       DHD_ERROR(("%s: pkq_mlen = %d, bus->flowcontrol=%x\n", __FUNCTION__,
-                               pktq_mlen(&bus->txq, ~bus->flowcontrol), bus->flowcontrol));
-
-                       if (bus->clkstate != CLK_AVAIL)
-                               DHD_ERROR(("%s: bus->clkstate = %d\n", __FUNCTION__, bus->clkstate));
-                       if (bus->fcstate)
-                               DHD_ERROR(("%s: bus->fcstate = %d\n", __FUNCTION__, bus->fcstate));
-                       if (!txlimit)
-                               DHD_ERROR(("%s: txlimit = %d\n", __FUNCTION__, txlimit));
-                       if (!DATAOK(bus))
-                               DHD_ERROR(("%s: bus->tx_max = %d, bus->tx_seq = %d\n", __FUNCTION__,
-                                       bus->tx_max, bus->tx_seq));
-               }
-       }
-#endif
-
        /* Resched the DPC if ctrl cmd is pending on bus credit */
        if (bus->ctrl_frame_stat) {
                if (bus->dhd->conf->txctl_tmo_fix) {
@@ -7036,22 +7042,20 @@ clkwait:
 exit:
 
        if (!resched) {
-#if 1
                /* Re-enable interrupts to detect new device events (mailbox, rx frame)
-                * or clock availability.  (Allows tx loop to check ipend if desired.)
-                * (Unless register access seems hosed, as we may not be able to ACK...)
-                */
-               if (bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
+                * or clock availability.  (Allows tx loop to check ipend if desired.)
+                * (Unless register access seems hosed, as we may not be able to ACK...)
+                */
+               if (bus->dhd->conf->oob_enabled_later && bus->intr && bus->intdis && !bcmsdh_regfail(sdh)) {
                        DHD_INTR(("%s: enable SDIO interrupts, rxdone %d framecnt %d\n",
-                               __FUNCTION__, rxdone, framecnt));
+                                         __FUNCTION__, rxdone, framecnt));
                        bus->intdis = FALSE;
 #if defined(OOB_INTR_ONLY)
                        bcmsdh_oob_intr_set(bus->sdh, TRUE);
 #endif /* defined(OOB_INTR_ONLY) */
                        bcmsdh_intr_enable(sdh);
                }
-#endif
-               if(dhd_dpcpoll) {
+               if (dhd_dpcpoll) {
                        if (dhdsdio_readframes(bus, dhd_rxbound, &rxdone) != 0) {
                                resched = TRUE;
 #ifdef DEBUG_DPC_THREAD_WATCHDOG
@@ -7059,7 +7063,7 @@ exit:
 #endif /* DEBUG_DPC_THREAD_WATCHDOG */
                        }
                }
-       }       
+       }
 
        dhd_os_sdunlock(bus->dhd);
 #ifdef DEBUG_DPC_THREAD_WATCHDOG
@@ -7157,22 +7161,38 @@ void dhdsdio_txpktstatics(void)
 {
        uint i, total = 0;
 
-       printf("Randy: TYPE EVENT: %d pkts (size=%d) transfered\n", tx_statics.event_count, tx_statics.event_size);
-       printf("Randy: TYPE CTRL:  %d pkts (size=%d) transfered\n", tx_statics.ctrl_count, tx_statics.ctrl_size);
-       printf("Randy: TYPE DATA:  %d pkts (size=%d) transfered\n", tx_statics.data_count, tx_statics.data_size);
-       printf("Glom size distribution:\n");
-       for (i=0;i<CUSTOM_MAX_TXGLOM_SIZE;i++) {
-               printf("%d: %d", i+1, tx_statics.glom_cnt[i]);
-               if (i%8) 
+       printf("%s: TYPE EVENT: %d pkts (size=%d) transfered\n",
+               __FUNCTION__, tx_statics.event_count, tx_statics.event_size);
+       printf("%s: TYPE CTRL:  %d pkts (size=%d) transfered\n",
+               __FUNCTION__, tx_statics.ctrl_count, tx_statics.ctrl_size);
+       printf("%s: TYPE DATA:  %d pkts (size=%d) transfered\n",
+               __FUNCTION__, tx_statics.data_count, tx_statics.data_size);
+       printf("%s: Glom size distribution:\n", __FUNCTION__);
+       for (i=0;i<tx_statics.glom_max;i++) {
+               total += tx_statics.glom_cnt[i];
+       }
+       for (i=0;i<tx_statics.glom_max;i++) {
+               printf("%02d: %d", i+1, tx_statics.glom_cnt[i]);
+               if ((i+1)%8)
                        printf(", ");
                else
                        printf("\n");
-               total += tx_statics.glom_cnt[i];
        }
        printf("\n");
-       printf("Randy: data/glom=%d, glom_max=%d\n", tx_statics.data_count/total, tx_statics.glom_max);
-       printf("Randy: TYPE RX GLOM: %d pkts (size=%d) transfered\n", tx_statics.glom_count, tx_statics.glom_size);
-       printf("Randy: TYPE TEST: %d pkts (size=%d) transfered\n\n\n", tx_statics.test_count, tx_statics.test_size);
+       for (i=0;i<tx_statics.glom_max;i++) {
+               printf("%02d:%3d%%", i+1, (tx_statics.glom_cnt[i]*100)/total);
+               if ((i+1)%8)
+                       printf(", ");
+               else
+                       printf("\n");
+       }
+       printf("\n");
+       printf("%s: data/glom=%d, glom_max=%d\n",
+               __FUNCTION__, tx_statics.data_count/total, tx_statics.glom_max);
+       printf("%s: TYPE RX GLOM: %d pkts (size=%d) transfered\n",
+               __FUNCTION__, tx_statics.glom_count, tx_statics.glom_size);
+       printf("%s: TYPE TEST: %d pkts (size=%d) transfered\n\n\n",
+               __FUNCTION__, tx_statics.test_count, tx_statics.test_size);
 }
 #endif
 
@@ -7811,6 +7831,8 @@ dhdsdio_chipmatch(uint16 chipid)
                return TRUE;
        if (BCM4349_CHIP(chipid))
                return TRUE;
+       if (chipid == BCM43012_CHIP_ID)
+               return TRUE;
        return FALSE;
 }
 
@@ -8405,12 +8427,14 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh)
 
 int
 dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
-                          char *pfw_path, char *pnv_path, char *pconf_path)
+                          char *pfw_path, char *pnv_path,
+                          char *pclm_path, char *pconf_path)
 {
        int ret;
 
        bus->fw_path = pfw_path;
        bus->nv_path = pnv_path;
+       bus->dhd->clm_path = pclm_path;
        bus->dhd->conf_path = pconf_path;
 
        ret = dhdsdio_download_firmware(bus, osh, bus->sdh);
@@ -8419,44 +8443,76 @@ dhd_bus_download_firmware(struct dhd_bus *bus, osl_t *osh,
        return ret;
 }
 
-static int
-dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
+void
+dhd_set_path_params(struct dhd_bus *bus)
 {
-       int ret;
-
-
-       DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
-               __FUNCTION__, bus->fw_path, bus->nv_path));
-       DHD_OS_WAKE_LOCK(bus->dhd);
-
-       /* Download the firmware */
-       dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
-
        /* 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);
+
        dhd_conf_set_fw_name_by_mac(bus->dhd, bus->sdh, bus->fw_path);
        dhd_conf_set_nv_name_by_mac(bus->dhd, bus->sdh, bus->nv_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_set_bus_params(struct dhd_bus *bus)
+{
        if (bus->dhd->conf->dhd_poll >= 0) {
-               printf("%s: set polling mode %d\n", __FUNCTION__, bus->dhd->conf->dhd_poll);
                bus->poll = bus->dhd->conf->dhd_poll;
                if (!bus->pollrate)
                        bus->pollrate = 1;
+               printf("%s: set polling mode %d\n", __FUNCTION__, bus->dhd->conf->dhd_poll);
        }
        if (bus->dhd->conf->use_rxchain >= 0) {
-               printf("%s: set use_rxchain %d\n", __FUNCTION__, bus->dhd->conf->use_rxchain);
                bus->use_rxchain = (bool)bus->dhd->conf->use_rxchain;
+               printf("%s: set use_rxchain %d\n", __FUNCTION__, bus->dhd->conf->use_rxchain);
+       }
+       if (bus->dhd->conf->txinrx_thres >= 0) {
+               bus->txinrx_thres = bus->dhd->conf->txinrx_thres;
+               printf("%s: set txinrx_thres %d\n", __FUNCTION__, bus->txinrx_thres);
        }
        if (bus->dhd->conf->txglomsize >= 0) {
-               printf("%s: set txglomsize %d\n", __FUNCTION__, bus->dhd->conf->txglomsize);
                bus->txglomsize = bus->dhd->conf->txglomsize;
+               printf("%s: set txglomsize %d\n", __FUNCTION__, bus->dhd->conf->txglomsize);
        }
+}
 
-       printf("Final fw_path=%s\n", bus->fw_path);
-       printf("Final nv_path=%s\n", bus->nv_path);
-       printf("Final conf_path=%s\n", bus->dhd->conf_path);
+static int
+dhdsdio_download_firmware(struct dhd_bus *bus, osl_t *osh, void *sdh)
+{
+       int ret;
+
+
+       DHD_TRACE_HW4(("%s: firmware path=%s, nvram path=%s\n",
+               __FUNCTION__, bus->fw_path, bus->nv_path));
+       DHD_OS_WAKE_LOCK(bus->dhd);
+
+       /* Download the firmware */
+       dhdsdio_clkctl(bus, CLK_AVAIL, FALSE);
+
+       dhd_set_path_params(bus);
+       dhd_set_bus_params(bus);
 
        ret = _dhdsdio_download_firmware(bus);
 
@@ -9231,11 +9287,10 @@ dhd_bus_devreset(dhd_pub_t *dhdp, uint8 flag)
                                        }
                                        bcmerror = BCME_SDIO_ERROR;
                                }
-                       } else {
-
+                       } else
                                bcmerror = BCME_SDIO_ERROR;
-                       }
-                               dhd_os_sdunlock(dhdp);
+
+                       dhd_os_sdunlock(dhdp);
                } else {
                        bcmerror = BCME_SDIO_ERROR;
                        printf("%s called when dongle is not in reset\n",
@@ -9316,10 +9371,12 @@ dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint si
 
 
 void
-dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path, char *pconf_path)
+dhd_bus_update_fw_nv_path(struct dhd_bus *bus, char *pfw_path, char *pnv_path,
+                                                                       char *pclm_path, char *pconf_path)
 {
        bus->fw_path = pfw_path;
        bus->nv_path = pnv_path;
+       bus->dhd->clm_path = pclm_path;
        bus->dhd->conf_path = pconf_path;
 }
 
index 1ebd3ee93ae709aaad168acd39f67864d74a852f..36cca5b32551a36fe250d2c6a973f20c89dc32f2 100644 (file)
 #include <linux/delay.h>\r
 #include <linux/err.h>\r
 #include <linux/skbuff.h>\r
-#include <linux/wlan_plat.h>\r
 \r
-#define CONFIG_BROADCOM_WIFI_RESERVED_MEM\r
+enum dhd_prealloc_index {\r
+       DHD_PREALLOC_PROT = 0,\r
+       DHD_PREALLOC_RXBUF,\r
+       DHD_PREALLOC_DATABUF,\r
+       DHD_PREALLOC_OSL_BUF,\r
+       DHD_PREALLOC_SKB_BUF,\r
+       DHD_PREALLOC_WIPHY_ESCAN0 = 5,\r
+       DHD_PREALLOC_WIPHY_ESCAN1 = 6,\r
+       DHD_PREALLOC_DHD_INFO = 7,\r
+       DHD_PREALLOC_DHD_WLFC_INFO = 8,\r
+       DHD_PREALLOC_IF_FLOW_LKUP = 9,\r
+       DHD_PREALLOC_MEMDUMP_BUF = 10,\r
+       DHD_PREALLOC_MEMDUMP_RAM = 11,\r
+       DHD_PREALLOC_DHD_WLFC_HANGER = 12,\r
+       DHD_PREALLOC_MAX\r
+};\r
+\r
+#define STATIC_BUF_MAX_NUM     20\r
+#define STATIC_BUF_SIZE        (PAGE_SIZE*2)\r
 \r
-#ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM\r
+#define DHD_PREALLOC_PROT_SIZE         (16 * 1024)\r
+#define DHD_PREALLOC_RXBUF_SIZE        (24 * 1024)\r
+#define DHD_PREALLOC_DATABUF_SIZE      (64 * 1024)\r
+#define DHD_PREALLOC_OSL_BUF_SIZE      (STATIC_BUF_MAX_NUM * STATIC_BUF_SIZE)\r
+#define DHD_PREALLOC_WIPHY_ESCAN0_SIZE (64 * 1024)\r
+#define DHD_PREALLOC_DHD_INFO_SIZE             (24 * 1024)\r
+#define DHD_PREALLOC_DHD_WLFC_HANGER_SIZE      (64 * 1024)\r
+#ifdef CONFIG_64BIT\r
+#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024 * 2)\r
+#else\r
+#define DHD_PREALLOC_IF_FLOW_LKUP_SIZE (20 * 1024)\r
+#endif\r
 \r
-#define WLAN_STATIC_PKT_BUF                    4\r
-#define WLAN_STATIC_SCAN_BUF0          5\r
-#define WLAN_STATIC_SCAN_BUF1          6\r
-#define WLAN_STATIC_DHD_INFO           7\r
-#define WLAN_STATIC_DHD_WLFC_INFO              8\r
-#define PREALLOC_WLAN_SEC_NUM          6\r
-#define PREALLOC_WLAN_BUF_NUM          160\r
-#define PREALLOC_WLAN_SECTION_HEADER   24\r
+#if defined(CONFIG_64BIT)\r
+#define WLAN_DHD_INFO_BUF_SIZE         (24 * 1024)\r
+#define WLAN_DHD_WLFC_BUF_SIZE         (64 * 1024)\r
+#define WLAN_DHD_IF_FLOW_LKUP_SIZE     (64 * 1024)\r
+#else\r
+#define WLAN_DHD_INFO_BUF_SIZE         (16 * 1024)\r
+#define WLAN_DHD_WLFC_BUF_SIZE         (24 * 1024)\r
+#define WLAN_DHD_IF_FLOW_LKUP_SIZE     (20 * 1024)\r
+#endif /* CONFIG_64BIT */\r
+#define WLAN_DHD_MEMDUMP_SIZE          (800 * 1024)\r
 \r
-#define WLAN_SECTION_SIZE_0    (PREALLOC_WLAN_BUF_NUM * 128)\r
-#define WLAN_SECTION_SIZE_1    (PREALLOC_WLAN_BUF_NUM * 128)\r
-#define WLAN_SECTION_SIZE_2    (PREALLOC_WLAN_BUF_NUM * 512)\r
-#define WLAN_SECTION_SIZE_3    (PREALLOC_WLAN_BUF_NUM * 1024)\r
-#define WLAN_SECTION_SIZE_7    (PREALLOC_WLAN_BUF_NUM * 128)\r
-#define WLAN_SECTION_SIZE_8    (PREALLOC_WLAN_BUF_NUM * 512)\r
+#ifdef CONFIG_BCMDHD_PCIE\r
+#define DHD_SKB_1PAGE_BUFSIZE  (PAGE_SIZE*1)\r
+#define DHD_SKB_2PAGE_BUFSIZE  (PAGE_SIZE*2)\r
+#define DHD_SKB_4PAGE_BUFSIZE  (PAGE_SIZE*4)\r
 \r
-#define DHD_SKB_HDRSIZE                        336\r
+#define DHD_SKB_1PAGE_BUF_NUM  0\r
+#define DHD_SKB_2PAGE_BUF_NUM  64\r
+#define DHD_SKB_4PAGE_BUF_NUM  0\r
+#else\r
+#define DHD_SKB_HDRSIZE                336\r
 #define DHD_SKB_1PAGE_BUFSIZE  ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE)\r
 #define DHD_SKB_2PAGE_BUFSIZE  ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE)\r
 #define DHD_SKB_4PAGE_BUFSIZE  ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE)\r
 \r
-#define WLAN_SKB_BUF_NUM       17\r
+#define DHD_SKB_1PAGE_BUF_NUM  8\r
+#define DHD_SKB_2PAGE_BUF_NUM  8\r
+#define DHD_SKB_4PAGE_BUF_NUM  1\r
+#endif /* CONFIG_BCMDHD_PCIE */\r
 \r
-static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];\r
+/* The number is defined in linux_osl.c\r
+ * WLAN_SKB_1_2PAGE_BUF_NUM => STATIC_PKT_1_2PAGE_NUM\r
+ * WLAN_SKB_BUF_NUM => STATIC_PKT_MAX_NUM\r
+ */\r
+#define WLAN_SKB_1_2PAGE_BUF_NUM ((DHD_SKB_1PAGE_BUF_NUM) + \\r
+               (DHD_SKB_2PAGE_BUF_NUM))\r
+#define WLAN_SKB_BUF_NUM ((WLAN_SKB_1_2PAGE_BUF_NUM) + (DHD_SKB_4PAGE_BUF_NUM))\r
 \r
-struct wlan_mem_prealloc {\r
-       void *mem_ptr;\r
-       unsigned long size;\r
-};\r
+void *wlan_static_prot = NULL;\r
+void *wlan_static_rxbuf = NULL;\r
+void *wlan_static_databuf = NULL;\r
+void *wlan_static_osl_buf = NULL;\r
+void *wlan_static_scan_buf0 = NULL;\r
+void *wlan_static_scan_buf1 = NULL;\r
+void *wlan_static_dhd_info_buf = NULL;\r
+void *wlan_static_dhd_wlfc_info_buf = NULL;\r
+void *wlan_static_if_flow_lkup = NULL;\r
+void *wlan_static_dhd_wlfc_hanger_buf = NULL;\r
 \r
-static struct wlan_mem_prealloc wlan_mem_array[PREALLOC_WLAN_SEC_NUM] = {\r
-       {NULL, (WLAN_SECTION_SIZE_0 + PREALLOC_WLAN_SECTION_HEADER)},\r
-       {NULL, (WLAN_SECTION_SIZE_1 + PREALLOC_WLAN_SECTION_HEADER)},\r
-       {NULL, (WLAN_SECTION_SIZE_2 + PREALLOC_WLAN_SECTION_HEADER)},\r
-       {NULL, (WLAN_SECTION_SIZE_3 + PREALLOC_WLAN_SECTION_HEADER)},\r
-       {NULL, (WLAN_SECTION_SIZE_7 + PREALLOC_WLAN_SECTION_HEADER)},\r
-       {NULL, (WLAN_SECTION_SIZE_8 + PREALLOC_WLAN_SECTION_HEADER)}\r
-};\r
+static struct sk_buff *wlan_static_skb[WLAN_SKB_BUF_NUM];\r
 \r
-void *wlan_static_scan_buf0;\r
-void *wlan_static_scan_buf1;\r
-void *bcmdhd_mem_prealloc(int section, unsigned long size)\r
+void *dhd_wlan_mem_prealloc(int section, unsigned long size)\r
 {\r
-       if (section == WLAN_STATIC_PKT_BUF) {\r
-               printk("1 %s: section=%d, wlan_static_skb=%p\n",\r
-                       __FUNCTION__, section, wlan_static_skb);\r
+       printk("%s: sectoin %d, %ld\n", __FUNCTION__, section, size);\r
+       if (section == DHD_PREALLOC_PROT)\r
+               return wlan_static_prot;\r
+\r
+       if (section == DHD_PREALLOC_RXBUF)\r
+               return wlan_static_rxbuf;\r
+\r
+       if (section == DHD_PREALLOC_DATABUF)\r
+               return wlan_static_databuf;\r
+\r
+       if (section == DHD_PREALLOC_SKB_BUF)\r
                return wlan_static_skb;\r
-       }\r
-       if (section == WLAN_STATIC_SCAN_BUF0) {\r
-               printk("2 %s: section=%d, wlan_static_scan_buf0=%p\n",\r
-                       __FUNCTION__, section, wlan_static_scan_buf0);\r
+\r
+       if (section == DHD_PREALLOC_WIPHY_ESCAN0)\r
                return wlan_static_scan_buf0;\r
-       }\r
-       if (section == WLAN_STATIC_SCAN_BUF1) {\r
-               printk("3 %s: section=%d, wlan_static_scan_buf1=%p\n",\r
-                       __FUNCTION__, section, wlan_static_scan_buf1);\r
+\r
+       if (section == DHD_PREALLOC_WIPHY_ESCAN1)\r
                return wlan_static_scan_buf1;\r
+\r
+       if (section == DHD_PREALLOC_OSL_BUF) {\r
+               if (size > DHD_PREALLOC_OSL_BUF_SIZE) {\r
+                       pr_err("request OSL_BUF(%lu) is bigger than static size(%ld).\n",\r
+                               size, DHD_PREALLOC_OSL_BUF_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_osl_buf;\r
        }\r
-       if (section == WLAN_STATIC_DHD_INFO) {\r
-               printk("4 %s: section=%d, wlan_mem_array[4]=%p\n",\r
-                       __FUNCTION__, section, wlan_mem_array[4].mem_ptr);\r
-               return wlan_mem_array[4].mem_ptr;\r
-       }\r
-       if (section == WLAN_STATIC_DHD_WLFC_INFO) {\r
-               printk("5 %s: section=%d, wlan_mem_array[5]=%p\n",\r
-                       __FUNCTION__, section, wlan_mem_array[5].mem_ptr);\r
-               return wlan_mem_array[5].mem_ptr;\r
+\r
+       if (section == DHD_PREALLOC_DHD_INFO) {\r
+               if (size > DHD_PREALLOC_DHD_INFO_SIZE) {\r
+                       pr_err("request DHD_INFO size(%lu) is bigger than static size(%d).\n",\r
+                               size, DHD_PREALLOC_DHD_INFO_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_dhd_info_buf;\r
        }\r
-       if ((section < 0) || (section > PREALLOC_WLAN_SEC_NUM)) {\r
-               printk("6 %s: out of section %d\n", __FUNCTION__, section);\r
-               return NULL;\r
+       if (section == DHD_PREALLOC_DHD_WLFC_INFO) {\r
+               if (size > WLAN_DHD_WLFC_BUF_SIZE) {\r
+                       pr_err("request DHD_WLFC_INFO size(%lu) is bigger than static size(%d).\n",\r
+                               size, WLAN_DHD_WLFC_BUF_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_dhd_wlfc_info_buf;\r
        }\r
+       if (section == DHD_PREALLOC_IF_FLOW_LKUP)  {\r
+               if (size > DHD_PREALLOC_IF_FLOW_LKUP_SIZE) {\r
+                       pr_err("request DHD_IF_FLOW_LKUP size(%lu) is bigger than static size(%d).\n",\r
+                               size, DHD_PREALLOC_IF_FLOW_LKUP_SIZE);\r
+                       return NULL;\r
+               }\r
 \r
-       if (wlan_mem_array[section].size < size) {\r
-               printk("7 %s: wlan_mem_array[section].size=%lu, size=%lu\n",\r
-                       __FUNCTION__, wlan_mem_array[section].size, size);\r
-               return NULL;\r
+               return wlan_static_if_flow_lkup;\r
+       }\r
+       if (section == DHD_PREALLOC_DHD_WLFC_HANGER) {\r
+               if (size > DHD_PREALLOC_DHD_WLFC_HANGER_SIZE) {\r
+                       pr_err("request DHD_WLFC_HANGER size(%lu) is bigger than static size(%d).\n",\r
+                               size, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);\r
+                       return NULL;\r
+               }\r
+               return wlan_static_dhd_wlfc_hanger_buf;\r
        }\r
-       printk("8 %s: wlan_mem_array[section].mem_ptr=%p, size=%lu\n",\r
-               __FUNCTION__, &wlan_mem_array[section], size);\r
+       if ((section < 0) || (section > DHD_PREALLOC_MAX))\r
+               pr_err("request section id(%d) is out of max index %d\n",\r
+                               section, DHD_PREALLOC_MAX);\r
 \r
-       return wlan_mem_array[section].mem_ptr;\r
-}\r
+       pr_err("%s: failed to alloc section %d, size=%ld\n", __FUNCTION__, section, size);\r
 \r
-EXPORT_SYMBOL(bcmdhd_mem_prealloc);\r
+       return NULL;\r
+}\r
+EXPORT_SYMBOL(dhd_wlan_mem_prealloc);\r
 \r
-int bcmdhd_init_wlan_mem(void)
+static int dhd_init_wlan_mem(void)\r
 {\r
        int i;\r
        int j;\r
 \r
-       for (i=0; i<8; i++) {\r
+       for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
                wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_1PAGE_BUFSIZE);\r
-               if (!wlan_static_skb[i])\r
-                       goto err_skb_alloc;
-               printk("1 %s: wlan_static_skb[%d]=%p, size=%lu\n",\r
-                       __FUNCTION__, i, wlan_static_skb[i], DHD_SKB_1PAGE_BUFSIZE);\r
+               if (!wlan_static_skb[i]) {\r
+                       goto err_skb_alloc;\r
+               }\r
+               printk("%s: sectoin %d skb[%d], size=%ld\n", __FUNCTION__, DHD_PREALLOC_SKB_BUF, i, DHD_SKB_1PAGE_BUFSIZE);\r
        }\r
 \r
-       for (; i<16; i++) {\r
+       for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {\r
                wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_2PAGE_BUFSIZE);\r
-               if (!wlan_static_skb[i])\r
-                       goto err_skb_alloc;
-               printk("2 %s: wlan_static_skb[%d]=%p, size=%lu\n",\r
-                       __FUNCTION__, i, wlan_static_skb[i], DHD_SKB_2PAGE_BUFSIZE);\r
+               if (!wlan_static_skb[i]) {\r
+                       goto err_skb_alloc;\r
+               }\r
+               printk("%s: sectoin %d skb[%d], size=%ld\n", __FUNCTION__, DHD_PREALLOC_SKB_BUF, i, DHD_SKB_2PAGE_BUFSIZE);\r
        }\r
 \r
+#if !defined(CONFIG_BCMDHD_PCIE)\r
        wlan_static_skb[i] = dev_alloc_skb(DHD_SKB_4PAGE_BUFSIZE);\r
-       if (!wlan_static_skb[i])\r
-               goto err_skb_alloc;
-       printk("3 %s: wlan_static_skb[%d]=%p, size=%lu\n",\r
-               __FUNCTION__, i, wlan_static_skb[i], DHD_SKB_4PAGE_BUFSIZE);\r
+       if (!wlan_static_skb[i]) {\r
+               goto err_skb_alloc;\r
+       }\r
+#endif /* !CONFIG_BCMDHD_PCIE */\r
+\r
+       wlan_static_prot = kmalloc(DHD_PREALLOC_PROT_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_prot) {\r
+               pr_err("Failed to alloc wlan_static_prot\n");\r
+               goto err_mem_alloc;\r
+       }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_PROT, DHD_PREALLOC_PROT_SIZE);\r
+\r
+#if defined(CONFIG_BCMDHD_SDIO)\r
+       wlan_static_rxbuf = kmalloc(DHD_PREALLOC_RXBUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_rxbuf) {\r
+               pr_err("Failed to alloc wlan_static_rxbuf\n");\r
+               goto err_mem_alloc;\r
+       }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_RXBUF, DHD_PREALLOC_RXBUF_SIZE);\r
+\r
+       wlan_static_databuf = kmalloc(DHD_PREALLOC_DATABUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_databuf) {\r
+               pr_err("Failed to alloc wlan_static_databuf\n");\r
+               goto err_mem_alloc;\r
+       }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DATABUF, DHD_PREALLOC_DATABUF_SIZE);\r
+#endif\r
 \r
-       for (i=0; i<PREALLOC_WLAN_SEC_NUM; i++) {\r
-               wlan_mem_array[i].mem_ptr =\r
-                               kmalloc(wlan_mem_array[i].size, GFP_KERNEL);\r
+       wlan_static_osl_buf = kmalloc(DHD_PREALLOC_OSL_BUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_osl_buf) {\r
+               pr_err("Failed to alloc wlan_static_osl_buf\n");\r
+               goto err_mem_alloc;\r
+       }\r
+       printk("%s: sectoin %d, size=%ld\n", __FUNCTION__, DHD_PREALLOC_OSL_BUF, DHD_PREALLOC_OSL_BUF_SIZE);\r
+\r
+       wlan_static_scan_buf0 = kmalloc(DHD_PREALLOC_WIPHY_ESCAN0_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_scan_buf0) {\r
+               pr_err("Failed to alloc wlan_static_scan_buf0\n");\r
+               goto err_mem_alloc;\r
+       }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_WIPHY_ESCAN0, DHD_PREALLOC_WIPHY_ESCAN0_SIZE);\r
 \r
-               if (!wlan_mem_array[i].mem_ptr)\r
-                       goto err_mem_alloc;\r
-               printk("4 %s: wlan_mem_array[%d]=%p, size=%lu\n",\r
-                       __FUNCTION__, i, wlan_static_skb[i], wlan_mem_array[i].size);\r
+       wlan_static_dhd_info_buf = kmalloc(DHD_PREALLOC_DHD_INFO_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_info_buf) {\r
+               pr_err("Failed to alloc wlan_static_dhd_info_buf\n");\r
+               goto err_mem_alloc;\r
        }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_INFO, DHD_PREALLOC_DHD_INFO_SIZE);\r
 \r
-       wlan_static_scan_buf0 = kmalloc (65536, GFP_KERNEL);\r
-       if (!wlan_static_scan_buf0)
+       wlan_static_dhd_wlfc_info_buf = kmalloc(WLAN_DHD_WLFC_BUF_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_wlfc_info_buf) {\r
+               pr_err("Failed to alloc wlan_static_dhd_wlfc_info_buf\n");\r
                goto err_mem_alloc;\r
-       printk("5 %s: wlan_static_scan_buf0=%p, size=%d\n",\r
-               __FUNCTION__, wlan_static_scan_buf0, 65536);\r
+       }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_WLFC_INFO, WLAN_DHD_WLFC_BUF_SIZE);\r
 \r
-       wlan_static_scan_buf1 = kmalloc (65536, GFP_KERNEL);\r
-       if (!wlan_static_scan_buf1)
+       wlan_static_dhd_wlfc_hanger_buf = kmalloc(DHD_PREALLOC_DHD_WLFC_HANGER_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_dhd_wlfc_hanger_buf) {\r
+               pr_err("Failed to alloc wlan_static_dhd_wlfc_hanger_buf\n");\r
                goto err_mem_alloc;\r
-       printk("6 %s: wlan_static_scan_buf1=%p, size=%d\n",\r
-               __FUNCTION__, wlan_static_scan_buf1, 65536);\r
+       }\r
+       printk("%s: sectoin %d, size=%d\n", __FUNCTION__, DHD_PREALLOC_DHD_WLFC_HANGER, DHD_PREALLOC_DHD_WLFC_HANGER_SIZE);\r
+\r
+#ifdef CONFIG_BCMDHD_PCIE\r
+       wlan_static_if_flow_lkup = kmalloc(DHD_PREALLOC_IF_FLOW_LKUP_SIZE, GFP_KERNEL);\r
+       if (!wlan_static_if_flow_lkup) {\r
+               pr_err("Failed to alloc wlan_static_if_flow_lkup\n");\r
+               goto err_mem_alloc;\r
+       }\r
+#endif /* CONFIG_BCMDHD_PCIE */\r
 \r
-       printk("%s: WIFI MEM Allocated\n", __FUNCTION__);\r
        return 0;\r
 \r
 err_mem_alloc:\r
+\r
+       if (wlan_static_prot)\r
+               kfree(wlan_static_prot);\r
+\r
+#if defined(CONFIG_BCMDHD_SDIO)\r
+       if (wlan_static_rxbuf)\r
+               kfree(wlan_static_rxbuf);\r
+\r
+       if (wlan_static_databuf)\r
+               kfree(wlan_static_databuf);\r
+#endif\r
+\r
+       if (wlan_static_dhd_info_buf)\r
+               kfree(wlan_static_dhd_info_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_info_buf)\r
+               kfree(wlan_static_dhd_wlfc_info_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_hanger_buf)\r
+               kfree(wlan_static_dhd_wlfc_hanger_buf);\r
+\r
+       if (wlan_static_scan_buf1)\r
+               kfree(wlan_static_scan_buf1);\r
+\r
+       if (wlan_static_scan_buf0)\r
+               kfree(wlan_static_scan_buf0);\r
+\r
+       if (wlan_static_osl_buf)\r
+               kfree(wlan_static_osl_buf);\r
+\r
+#ifdef CONFIG_BCMDHD_PCIE\r
+       if (wlan_static_if_flow_lkup)\r
+               kfree(wlan_static_if_flow_lkup);\r
+#endif\r
        pr_err("Failed to mem_alloc for WLAN\n");\r
-       for (j=0; j<i; j++)\r
-               kfree(wlan_mem_array[j].mem_ptr);\r
 \r
        i = WLAN_SKB_BUF_NUM;\r
 \r
 err_skb_alloc:\r
        pr_err("Failed to skb_alloc for WLAN\n");\r
-       for (j=0; j<i; j++)\r
+       for (j = 0; j < i; j++) {\r
                dev_kfree_skb(wlan_static_skb[j]);\r
+       }\r
 \r
        return -ENOMEM;\r
 }\r
-#endif /* CONFIG_BROADCOM_WIFI_RESERVED_MEM */\r
 \r
-static int __init bcmdhd_wlan_init(void)\r
+static int __init\r
+dhd_static_buf_init(void)\r
 {\r
-       printk("%s()\n", __FUNCTION__);\r
+       printk(KERN_ERR "%s()\n", __FUNCTION__);\r
 \r
-#ifdef CONFIG_BROADCOM_WIFI_RESERVED_MEM\r
-       bcmdhd_init_wlan_mem();\r
-#endif\r
+       dhd_init_wlan_mem();\r
 \r
        return 0;\r
 }\r
 \r
-__initcall(bcmdhd_wlan_init);\r
+static void __exit\r
+dhd_static_buf_exit(void)\r
+{\r
+       int i;\r
+\r
+       printk(KERN_ERR "%s()\n", __FUNCTION__);\r
+\r
+       for (i = 0; i < DHD_SKB_1PAGE_BUF_NUM; i++) {\r
+               if (wlan_static_skb[i])\r
+                       dev_kfree_skb(wlan_static_skb[i]);\r
+       }\r
+\r
+       for (i = DHD_SKB_1PAGE_BUF_NUM; i < WLAN_SKB_1_2PAGE_BUF_NUM; i++) {\r
+               if (wlan_static_skb[i])\r
+                       dev_kfree_skb(wlan_static_skb[i]);\r
+       }\r
+\r
+#if !defined(CONFIG_BCMDHD_PCIE)\r
+       if (wlan_static_skb[i])\r
+               dev_kfree_skb(wlan_static_skb[i]);\r
+#endif /* !CONFIG_BCMDHD_PCIE */\r
+\r
+       if (wlan_static_prot)\r
+               kfree(wlan_static_prot);\r
+\r
+#if defined(CONFIG_BCMDHD_SDIO)\r
+       if (wlan_static_rxbuf)\r
+               kfree(wlan_static_rxbuf);\r
+\r
+       if (wlan_static_databuf)\r
+               kfree(wlan_static_databuf);\r
+#endif\r
+\r
+       if (wlan_static_osl_buf)\r
+               kfree(wlan_static_osl_buf);\r
+\r
+       if (wlan_static_scan_buf0)\r
+               kfree(wlan_static_scan_buf0);\r
+\r
+       if (wlan_static_dhd_info_buf)\r
+               kfree(wlan_static_dhd_info_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_info_buf)\r
+               kfree(wlan_static_dhd_wlfc_info_buf);\r
+\r
+       if (wlan_static_dhd_wlfc_hanger_buf)\r
+               kfree(wlan_static_dhd_wlfc_hanger_buf);\r
+\r
+       if (wlan_static_scan_buf1)\r
+               kfree(wlan_static_scan_buf1);\r
+\r
+#ifdef CONFIG_BCMDHD_PCIE\r
+       if (wlan_static_if_flow_lkup)\r
+               kfree(wlan_static_if_flow_lkup);\r
+#endif\r
+       return;\r
+}\r
+\r
+module_init(dhd_static_buf_init);\r
+\r
+module_exit(dhd_static_buf_exit);\r
index 0e74318d173a3b7b2a21693b71e1d7ae5d8fc722..81cf51fcc4ee8c289eb9649ce86d00567e5ef7ab 100644 (file)
@@ -41,6 +41,7 @@
 #include <dhd_bus.h>
 
 #include <dhd_dbg.h>
+#include <dhd_config.h>
 
 #ifdef PROP_TXSTATUS /* a form of flow control between host and dongle */
 #include <wlfc_proto.h>
@@ -2909,6 +2910,7 @@ int dhd_wlfc_enable(dhd_pub_t *dhd)
 
 
 exit:
+       DHD_ERROR(("%s: ret=%d\n", __FUNCTION__, rc));
        dhd_os_wlfc_unblock(dhd);
 
        return rc;
@@ -3538,7 +3540,7 @@ dhd_wlfc_init(dhd_pub_t *dhd)
 
        dhd_os_wlfc_block(dhd);
        if (dhd->wlfc_enabled) {
-               DHD_INFO(("%s():%d, Already enabled!\n", __FUNCTION__, __LINE__));
+               DHD_ERROR(("%s():%d, Already enabled!\n", __FUNCTION__, __LINE__));
                dhd_os_wlfc_unblock(dhd);
                return BCME_OK;
        }
@@ -3563,7 +3565,7 @@ dhd_wlfc_init(dhd_pub_t *dhd)
                Leaving the message for now, it should be removed after a while; once
                the tlv situation is stable.
                */
-               DHD_INFO(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n",
+               DHD_ERROR(("dhd_wlfc_init(): successfully %s bdcv2 tlv signaling, %d\n",
                        dhd->wlfc_enabled?"enabled":"disabled", tlv));
        }
 
@@ -3573,7 +3575,7 @@ dhd_wlfc_init(dhd_pub_t *dhd)
        ret = dhd_wl_ioctl_get_intiovar(dhd, "wlfc_mode", &fw_caps, WLC_GET_VAR, FALSE, 0);
 
        if (!ret) {
-               DHD_INFO(("%s: query wlfc_mode succeed, fw_caps=0x%x\n", __FUNCTION__, fw_caps));
+               DHD_ERROR(("%s: query wlfc_mode succeed, fw_caps=0x%x\n", __FUNCTION__, fw_caps));
 
                if (WLFC_IS_OLD_DEF(fw_caps)) {
                        /* enable proptxtstatus v2 by default */
@@ -3597,7 +3599,7 @@ dhd_wlfc_init(dhd_pub_t *dhd)
                }
        }
 
-       DHD_INFO(("dhd_wlfc_init(): wlfc_mode=0x%x, ret=%d\n", dhd->wlfc_mode, ret));
+       DHD_ERROR(("dhd_wlfc_init(): wlfc_mode=0x%x, ret=%d\n", dhd->wlfc_mode, ret));
 
        dhd_os_wlfc_unblock(dhd);
 
@@ -3639,6 +3641,8 @@ dhd_wlfc_hostreorder_init(dhd_pub_t *dhd)
        dhd_os_wlfc_block(dhd);
        dhd->proptxstatus_mode = WLFC_ONLY_AMPDU_HOSTREORDER;
        dhd_os_wlfc_unblock(dhd);
+       /* terence 20161229: enable ampdu_hostreorder if tlv enable hostreorder */
+       dhd_conf_set_intiovar(dhd, WLC_SET_VAR, "ampdu_hostreorder", 1, 0, TRUE);
 
        return BCME_OK;
 }
@@ -3757,6 +3761,8 @@ dhd_wlfc_deinit(dhd_pub_t *dhd)
        dhd->proptxstatus_mode = hostreorder ?
                WLFC_ONLY_AMPDU_HOSTREORDER : WLFC_FCMODE_NONE;
 
+       DHD_ERROR(("%s: wlfc_mode=0x%x, tlv=%d\n", __FUNCTION__, dhd->wlfc_mode, tlv));
+
        dhd_os_wlfc_unblock(dhd);
 
        if (dhd->plat_deinit)
index efaf92bed3524a7b131883b958ffd58e9128b474..56ea1d49b40f7d413d0946ae981b4689d0fae376 100644 (file)
@@ -53,7 +53,7 @@
 #ifdef CUSTOM_MAX_TXGLOM_SIZE
 #define SDPCM_MAXGLOM_SIZE  CUSTOM_MAX_TXGLOM_SIZE
 #else
-#define SDPCM_MAXGLOM_SIZE     32
+#define SDPCM_MAXGLOM_SIZE     36
 #endif /* CUSTOM_MAX_TXGLOM_SIZE */
 
 #define SDPCM_TXGLOM_CPY 0                     /* SDIO 2.0 should use copy mode */
 #define SDPCM_DEFGLOM_SIZE SDPCM_MAXGLOM_SIZE
 #endif
 
+#ifdef PKT_STATICS
+typedef struct pkt_statics {
+       uint16  event_count;
+       uint32  event_size;
+       uint16  ctrl_count;
+       uint32  ctrl_size;
+       uint32  data_count;
+       uint32  data_size;
+       uint32  glom_cnt[SDPCM_MAXGLOM_SIZE];
+       uint16  glom_max;
+       uint16  glom_count;
+       uint32  glom_size;
+       uint16  test_count;
+       uint32  test_size;
+} pkt_statics_t;
+#endif
+
 typedef int SDIOH_API_RC;
 
 /* SDio Host structure */
index cd468a36fa81e56a0ee73f2834d7b1666832b2d1..1bd35b527b9d0449487f58e12855751739f0a52f 100644 (file)
@@ -60,7 +60,7 @@
 /* private bus modes */
 #define SDIOH_MODE_SD4         2
 #define CLIENT_INTR                    0x100   /* Get rid of this! */
-#define SDIOH_SDMMC_MAX_SG_ENTRIES     64
+#define SDIOH_SDMMC_MAX_SG_ENTRIES     SDPCM_MAXGLOM_SIZE
 
 #if defined(SWTXGLOM)
 typedef struct glom_buf {
index 0b7862bd6b36615f3b6262a68ec9a8ec866c296f..931576e9eb021eaa96127365293a41e93cfb07b6 100644 (file)
@@ -46,6 +46,6 @@
 #define EPI_VERSION_DEV                1.363.59
 
 /* Driver Version String, ASCII, 32 chars max */
-#define        EPI_VERSION_STR         "1.363.59.144.2.git (r)"
+#define        EPI_VERSION_STR         "1.363.59.144.9 (r)"
 
 #endif /* _epivers_h_ */
index 7e47a4f4f9790d220728aaf3ac61fdf60b42f2c1..d560feca11e8094b00631490721cfa3ae231b769 100644 (file)
@@ -446,12 +446,10 @@ extern int osl_error(int bcmerror);
 #define PKTSETID(skb, id)       ({BCM_REFERENCE(skb); BCM_REFERENCE(id);})
 #define PKTSHRINK(osh, m)              ({BCM_REFERENCE(osh); m;})
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)) && defined(TSQ_MULTIPLIER)
-#define PKTORPHAN(skb)          osl_pkt_orphan_partial(skb)
-extern void osl_pkt_orphan_partial(struct sk_buff *skb);
-#elif (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
-#define PKTORPHAN(skb)          skb_orphan(skb)
+#define PKTORPHAN(skb, tsq)          osl_pkt_orphan_partial(skb, tsq)
+extern void osl_pkt_orphan_partial(struct sk_buff *skb, int tsq);
 #else
-#define PKTORPHAN(skb)          ({BCM_REFERENCE(skb); 0;})
+#define PKTORPHAN(skb, tsq)          ({BCM_REFERENCE(skb); 0;})
 #endif /* LINUX VERSION >= 3.6 */
 
 
index 0f8c52e1c220d0069414742c99e826ec43676b9f..6d2389d17d67b9cd412112916ff7ec182c5cd7fd 100644 (file)
@@ -92,8 +92,19 @@ typedef volatile struct {
        uint32  pmuintmask1;            /* 0x704 */
        uint32  PAD[14];
        uint32  pmuintstatus;           /* 0x740 */
-       uint32  PAD[15];
-       uint32  pmuintctrl0;            /* 0x780 */
+       uint32  extwakeupstatus;        /* 0x744 */
+       uint32  watchdog_res_mask;      /* 0x748 */
+       uint32  PAD[1];         /* 0x74C */
+       uint32  swscratch;              /* 0x750 */
+       uint32  PAD[3];         /* 0x754-0x75C */
+       uint32  extwakemask[2]; /* 0x760-0x764 */
+       uint32  PAD[2];         /* 0x768-0x76C */
+       uint32  extwakereqmask[2]; /* 0x770-0x774 */
+       uint32  PAD[2];         /* 0x778-0x77C */
+       uint32  pmuintctrl0;    /* 0x780 */
+       uint32  pmuintctrl1;    /* 0x784 */
+       uint32  PAD[2];
+       uint32  extwakectrl[2] ;   /* 0x790 */
 } pmuregs_t;
 
 typedef struct eci_prerev35 {
@@ -345,7 +356,7 @@ typedef volatile struct {
        uint32  res_req_timer_sel;
        uint32  res_req_timer;
        uint32  res_req_mask;
-       uint32  PAD;
+       uint32  core_cap_ext;           /* 0x64c */
        uint32  chipcontrol_addr;       /* 0x650 */
        uint32  chipcontrol_data;       /* 0x654 */
        uint32  regcontrol_addr;
@@ -1069,6 +1080,9 @@ typedef volatile struct {
 #define        PCTL_XTALFREQ_SHIFT     2
 #define        PCTL_ILP_DIV_EN         0x00000002
 #define        PCTL_LPO_SEL            0x00000001
+#define PCTL_EXT_FASTLPO_SWENAB        0x00000200
+
+#define DEFAULT_43012_MIN_RES_MASK             0x0f8bfe77
 
 /*  Retention Control */
 #define PMU_RCTL_CLK_DIV_SHIFT         0
@@ -1326,6 +1340,7 @@ typedef volatile struct {
 #define        PST_ALPAVAIL    0x0008
 #define        PST_HTAVAIL     0x0004
 #define        PST_RESINIT     0x0003
+#define        PST_ILPFASTLPO  0x00010000
 
 /* pmucapabilities */
 #define PCAP_REV_MASK  0x000000ff
index cfe12e1bb09aef7366eefd1b2a381c221fddf039..ad7b1fcf2fe8dd1783b67cdfdf318819c718c2f0 100644 (file)
@@ -123,6 +123,8 @@ typedef volatile struct sbsocramregs {
 #define        SRCI_SRBSZ_MASK         0xf
 #define        SRCI_SRBSZ_SHIFT        0
 
+#define        SRCI_SRNB_MASK_EXT      0x100
+
 #define SR_BSZ_BASE            14
 
 /* Standby control register */
index 27ad7c484455c373b19d07d815a560b06800921c..4393a7426d34956065788ed16523a39b86eea273 100644 (file)
@@ -119,6 +119,8 @@ typedef const struct si_pub si_t;
 
 #define        ISSIM_ENAB(sih) FALSE
 
+#define INVALID_ADDR (~0)
+
 /* PMU clock/power control */
 #if defined(BCMPMUCTL)
 #define PMUCTL_ENAB(sih)       (BCMPMUCTL)
@@ -453,6 +455,7 @@ extern uint32 si_gci_preinit_upd_indirect(uint32 regidx, uint32 setval, uint32 m
 extern uint8 si_enable_device_wake(si_t *sih, uint8 *wake_status, uint8 *cur_status);
 extern void si_swdenable(si_t *sih, uint32 swdflag);
 
+extern uint32 si_get_pmu_reg_addr(si_t *sih, uint32 offset);
 #define CHIPCTRLREG1 0x1
 #define CHIPCTRLREG2 0x2
 #define CHIPCTRLREG3 0x3
@@ -505,6 +508,17 @@ extern void si_d11rsdb_core_reset(si_t *sih, uint32 bits, uint32 resetbits);
                               OFFSETOF(pmuregs_t, member), mask, val): \
                si_pmu_corereg(si, cc_idx, OFFSETOF(chipcregs_t, member), mask, val))
 
+/* Used only for the regs present in the pmu core and not present in the old cc core */
+#define PMU_REG_NEW(si, member, mask, val) \
+               si_corereg(si, si_findcoreidx(si, PMU_CORE_ID, 0), \
+                       OFFSETOF(pmuregs_t, member), mask, val)
+
+#define PMU_REG(si, member, mask, val) \
+       (AOB_ENAB(si) ? \
+               si_corereg(si, si_findcoreidx(si, PMU_CORE_ID, 0), \
+                       OFFSETOF(pmuregs_t, member), mask, val): \
+               si_corereg(si, SI_CC_IDX, OFFSETOF(chipcregs_t, member), mask, val))
+
 /* GCI Macros */
 #define ALLONES_32                             0xFFFFFFFF
 #define GCI_CCTL_SECIRST_OFFSET                        0 /**< SeciReset */
index 2cac71bef1cd89f97e7c3e24d58215fe45c88d2c..d8dac6c48420cef02b11efe38855dc946a827281 100644 (file)
@@ -51,6 +51,7 @@
 #include <asm-generic/pci-dma-compat.h>
 #endif
 
+
 #ifdef BCM_SECURE_DMA
 #include <linux/module.h>
 #include <linux/kernel.h>
@@ -2617,11 +2618,14 @@ osl_sec_dma_free_consistent(osl_t *osh, void *va, uint size, dmaaddr_t pa)
 #include <linux/kallsyms.h>
 #include <net/sock.h>
 void
-osl_pkt_orphan_partial(struct sk_buff *skb)
+osl_pkt_orphan_partial(struct sk_buff *skb, int tsq)
 {
        uint32 fraction;
        static void *p_tcp_wfree = NULL;
 
+       if (tsq <= 0)
+               return;
+
        if (!skb->destructor || skb->destructor == sock_wfree)
                return;
 
@@ -2642,7 +2646,7 @@ osl_pkt_orphan_partial(struct sk_buff *skb)
         * sk_wmem_alloc to allow more skb can be allocated for this
         * socket for better cusion meeting WiFi device requirement
         */
-       fraction = skb->truesize * (TSQ_MULTIPLIER - 1) / TSQ_MULTIPLIER;
+       fraction = skb->truesize * (tsq - 1) / tsq;
        skb->truesize -= fraction;
        atomic_sub(fraction, &skb->sk->sk_wmem_alloc);
        skb_orphan(skb);
index 26fd845ce703020dd161405c969b4121e8445977..e879cafd1bdf6e43f9c5e15a94718bfd8ddf5223 100644 (file)
@@ -246,6 +246,34 @@ si_buscore_prep(si_info_t *sii, uint bustype, uint devid, void *sdh)
        return TRUE;
 }
 
+uint32
+si_get_pmu_reg_addr(si_t *sih, uint32 offset)
+{
+       si_info_t *sii = SI_INFO(sih);
+       uint32 pmuaddr = INVALID_ADDR;
+       uint origidx = 0;
+
+       SI_MSG(("%s: pmu access, offset: %x\n", __FUNCTION__, offset));
+       if (!(sii->pub.cccaps & CC_CAP_PMU)) {
+               goto done;
+       }
+       if (AOB_ENAB(&sii->pub)) {
+               uint pmucoreidx;
+               pmuregs_t *pmu;
+               SI_MSG(("%s: AOBENAB: %x\n", __FUNCTION__, offset));
+               origidx = sii->curidx;
+               pmucoreidx = si_findcoreidx(&sii->pub, PMU_CORE_ID, 0);
+               pmu = si_setcoreidx(&sii->pub, pmucoreidx);
+               pmuaddr = (uint32)(uintptr)((volatile uint8*)pmu + offset);
+               si_setcoreidx(sih, origidx);
+       } else
+               pmuaddr = SI_ENUM_BASE + offset;
+
+done:
+       SI_MSG(("%s: pmuaddr: %x\n", __FUNCTION__, pmuaddr));
+       return pmuaddr;
+}
+
 static bool
 si_buscore_setup(si_info_t *sii, chipcregs_t *cc, uint bustype, uint32 savewin,
        uint *origidx, void *regs)
@@ -1527,6 +1555,9 @@ si_chip_hostif(si_t *sih)
 
        switch (CHIPID(sih->chip)) {
 
+       case BCM43012_CHIP_ID:
+               hosti = CHIP_HOSTIF_SDIOMODE;
+               break;
        CASE_BCM43602_CHIP:
                hosti = CHIP_HOSTIF_PCIEMODE;
                break;
@@ -1630,6 +1661,14 @@ si_watchdog(si_t *sih, uint ticks)
                        ticks = 2;
                else if (ticks > maxt)
                        ticks = maxt;
+               if (CHIPID(sih->chip) == BCM43012_CHIP_ID) {
+                       PMU_REG_NEW(sih, min_res_mask, ~0, DEFAULT_43012_MIN_RES_MASK);
+                       PMU_REG_NEW(sih, watchdog_res_mask, ~0, DEFAULT_43012_MIN_RES_MASK);
+                       PMU_REG_NEW(sih, pmustatus, PST_WDRESET, PST_WDRESET);
+                       PMU_REG_NEW(sih, pmucontrol_ext, PCTL_EXT_FASTLPO_SWENAB, 0);
+                       SPINWAIT((PMU_REG(sih, pmustatus, 0, 0) & PST_ILPFASTLPO),
+                               PMU_MAX_TRANSITION_DLY);
+               }
 
                pmu_corereg(sih, SI_CC_IDX, pmuwatchdog, ~0, ticks);
        } else {
@@ -2431,7 +2470,13 @@ si_socram_size(si_t *sih)
                        memsize += (1 << ((lss - 1) + SR_BSZ_BASE));
        } else {
                uint8 i;
-               uint nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+               uint nb;
+               /* length of SRAM Banks increased for corerev greater than 23 */
+               if (corerev >= 23) {
+                       nb = (coreinfo & (SRCI_SRNB_MASK | SRCI_SRNB_MASK_EXT)) >> SRCI_SRNB_SHIFT;
+               } else {
+                       nb = (coreinfo & SRCI_SRNB_MASK) >> SRCI_SRNB_SHIFT;
+               }
                for (i = 0; i < nb; i++)
                        memsize += socram_banksize(sii, regs, i, SOCRAM_MEMTYPE_RAM);
        }
@@ -3024,6 +3069,8 @@ si_is_sprom_available(si_t *sih)
        case BCM43228_CHIP_ID:
        case BCM43428_CHIP_ID:
                return (sih->chipst & CST43228_OTP_PRESENT) != CST43228_OTP_PRESENT;
+       case BCM43012_CHIP_ID:
+               return FALSE;
        default:
                return TRUE;
        }
index 28277e7b82c9f0794c067f2d2442c0f1789ae258..1961e6a7795cfcc751c518879168de588c5738b0 100644 (file)
 #define dtohchanspec(i) i
 #endif
 
-/* message levels */
-#define ANDROID_ERROR_LEVEL    0x0001
-#define ANDROID_TRACE_LEVEL    0x0002
-#define ANDROID_INFO_LEVEL     0x0004
-
 uint android_msg_level = ANDROID_ERROR_LEVEL;
 
-#define ANDROID_ERROR(x) \
-       do { \
-               if (android_msg_level & ANDROID_ERROR_LEVEL) { \
-                       printk(KERN_ERR "ANDROID-ERROR) ");     \
-                       printk x; \
-               } \
-       } while (0)
-#define ANDROID_TRACE(x) \
-       do { \
-               if (android_msg_level & ANDROID_TRACE_LEVEL) { \
-                       printk(KERN_ERR "ANDROID-TRACE) ");     \
-                       printk x; \
-               } \
-       } while (0)
-#define ANDROID_INFO(x) \
-       do { \
-               if (android_msg_level & ANDROID_INFO_LEVEL) { \
-                       printk(KERN_ERR "ANDROID-INFO) ");      \
-                       printk x; \
-               } \
-       } while (0)
-
 /*
  * Android private command strings, PLEASE define new private commands here
  * so they can be updated easily in the future (if needed)
@@ -143,13 +116,6 @@ uint android_msg_level = ANDROID_ERROR_LEVEL;
 #define CMD_ULB_MODE "ULB_MODE"
 #define CMD_ULB_BW "ULB_BW"
 #endif /* WL11ULB */
-#define CMD_GET_CHANNEL                        "GET_CHANNEL"
-#define CMD_SET_ROAM                   "SET_ROAM_TRIGGER"
-#define CMD_GET_ROAM                   "GET_ROAM_TRIGGER"
-#define CMD_GET_KEEP_ALIVE             "GET_KEEP_ALIVE"
-#define CMD_GET_PM                             "GET_PM"
-#define CMD_SET_PM                             "SET_PM"
-#define CMD_MONITOR                    "MONITOR"
 
 #if defined(WL_SUPPORT_AUTO_CHANNEL)
 #define CMD_GET_BEST_CHANNELS  "GET_BEST_CHANNELS"
@@ -1358,6 +1324,10 @@ int wl_android_wifi_on(struct net_device *dev)
 {
        int ret = 0;
        int retry = POWERUP_MAX_RETRY;
+#ifdef IAPSTA_PREINIT
+       int bytes_written = 0;
+       struct dhd_conf *conf;
+#endif
 
        if (!dev) {
                ANDROID_ERROR(("%s: dev is null\n", __FUNCTION__));
@@ -1405,6 +1375,15 @@ int wl_android_wifi_on(struct net_device *dev)
                        }
                }
 #endif /* !BCMPCIE */
+
+#ifdef IAPSTA_PREINIT
+               conf = dhd_get_conf(dev);
+               if (conf) {
+                       wl_android_ext_priv_cmd(dev, conf->iapsta_init, 0, &bytes_written);
+                       wl_android_ext_priv_cmd(dev, conf->iapsta_config, 0, &bytes_written);
+                       wl_android_ext_priv_cmd(dev, conf->iapsta_enable, 0, &bytes_written);
+               }
+#endif
                g_wifi_on = TRUE;
        }
 
@@ -2679,6 +2658,7 @@ int wl_keep_alive_set(struct net_device *dev, char* extra, int total_len)
        return res;
 }
 
+#ifdef WL_CFG80211
 static const char *
 get_string_by_separator(char *result, int result_len, const char *src, char separator)
 {
@@ -2693,7 +2673,6 @@ get_string_by_separator(char *result, int result_len, const char *src, char sepa
        return src;
 }
 
-#ifdef WL_CFG80211
 int
 wl_android_set_roam_offload_bssid_list(struct net_device *dev, const char *cmd)
 {
@@ -2870,172 +2849,6 @@ wl_android_murx_bfe_cap(struct net_device *dev, int val)
 }
 #endif
 
-int
-wl_android_get_channel(
-struct net_device *dev, char* command, int total_len)
-{
-       int ret;
-       channel_info_t ci;
-       int bytes_written = 0;
-
-       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);
-               ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
-       }
-
-       return bytes_written;
-}
-
-int
-wl_android_set_roam_trigger(
-struct net_device *dev, char* command, int total_len)
-{
-       int ret = 0;
-       int roam_trigger[2];
-
-       sscanf(command, "%*s %10d", &roam_trigger[0]);
-       roam_trigger[1] = WLC_BAND_ALL;
-
-       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));
-
-       return ret;
-}
-
-int
-wl_android_get_roam_trigger(
-struct net_device *dev, char *command, int total_len)
-{
-       int ret;
-       int bytes_written;
-       int roam_trigger[2] = {0, 0};
-       int trigger[2]= {0, 0};
-
-       roam_trigger[1] = WLC_BAND_2G;
-       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));
-
-       roam_trigger[1] = WLC_BAND_5G;
-       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_TRACE(("roam_trigger %d %d\n", trigger[0], trigger[1]));
-       bytes_written = snprintf(command, total_len, "%d %d", trigger[0], trigger[1]);
-
-       return bytes_written;
-}
-
-s32
-wl_android_get_keep_alive(struct net_device *dev, char *command, int total_len) {
-
-       wl_mkeep_alive_pkt_t *mkeep_alive_pktp;
-       int bytes_written = -1;
-       int res = -1, len, i = 0;
-       char* str = "mkeep_alive";
-
-       ANDROID_TRACE(("%s: command = %s\n", __FUNCTION__, command));
-
-       len = WLC_IOCTL_MEDLEN;
-       mkeep_alive_pktp = kmalloc(len, GFP_KERNEL);
-       memset(mkeep_alive_pktp, 0, len);
-       strcpy((char*)mkeep_alive_pktp, str);
-
-       if ((res = wldev_ioctl(dev, WLC_GET_VAR, mkeep_alive_pktp, len, FALSE))<0) {
-               ANDROID_ERROR(("%s: GET mkeep_alive ERROR %d\n", __FUNCTION__, res));
-               goto exit;
-       } else {
-               printf("Id            :%d\n"
-                          "Period (msec) :%d\n"
-                          "Length        :%d\n"
-                          "Packet        :0x",
-                          mkeep_alive_pktp->keep_alive_id,
-                          dtoh32(mkeep_alive_pktp->period_msec),
-                          dtoh16(mkeep_alive_pktp->len_bytes));
-               for (i=0; i<mkeep_alive_pktp->len_bytes; i++) {
-                       printf("%02x", mkeep_alive_pktp->data[i]);
-               }
-               printf("\n");
-       }
-       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]);
-       }
-       ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
-
-exit:
-       kfree(mkeep_alive_pktp);
-       return bytes_written;
-}
-
-int
-wl_android_set_pm(struct net_device *dev,char *command, int total_len)
-{
-       int pm, ret = -1;
-
-       ANDROID_TRACE(("%s: cmd %s\n", __FUNCTION__, command));
-
-       sscanf(command, "%*s %d", &pm);
-
-       ret = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), FALSE);
-       if (ret)
-               ANDROID_ERROR(("WLC_SET_PM ERROR %d ret=%d\n", pm, ret));
-
-       return ret;
-}
-
-int
-wl_android_get_pm(struct net_device *dev,char *command, int total_len)
-{
-
-       int ret = 0;
-       int pm_local;
-       char *pm;
-       int bytes_written=-1;
-
-       ret = wldev_ioctl(dev, WLC_GET_PM, &pm_local, sizeof(pm_local),FALSE);
-       if (!ret) {
-               ANDROID_TRACE(("%s: PM = %d\n", __func__, pm_local));
-               if (pm_local == PM_OFF)
-                       pm = "PM_OFF";
-               else if(pm_local == PM_MAX)
-                       pm = "PM_MAX";
-               else if(pm_local == PM_FAST)
-                       pm = "PM_FAST";
-               else {
-                       pm_local = 0;
-                       pm = "Invalid";
-               }
-               bytes_written = snprintf(command, total_len, "PM %s", pm);
-               ANDROID_TRACE(("%s: command result is %s\n", __FUNCTION__, command));
-       }
-       return bytes_written;
-}
-
-static int
-wl_android_set_monitor(struct net_device *dev, char *command, int total_len)
-{
-       int val;
-       int ret = 0;
-       int bytes_written;
-
-       sscanf(command, "%*s %d", &val);
-       bytes_written = wldev_ioctl(dev, WLC_SET_MONITOR, &val, sizeof(int), 1);
-       if (bytes_written)
-               ANDROID_ERROR(("WLC_SET_MONITOR ERROR %d ret=%d\n", val, ret));
-       return bytes_written;
-}
-
 int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 {
 #define PRIVATE_COMMAND_MAX_LEN        8192
@@ -3540,28 +3353,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd)
 #endif /* DHD_DEBUG && BCMPCIE && DHD_FW_COREDUMP */
        }
 #endif /* DHD_LOG_DUMP */
-       else if(strnicmp(command, CMD_GET_CHANNEL, strlen(CMD_GET_CHANNEL)) == 0) {
-               bytes_written = wl_android_get_channel(net, command, priv_cmd.total_len);
-       }
-       else if (strnicmp(command, CMD_SET_ROAM, strlen(CMD_SET_ROAM)) == 0) {
-               bytes_written = wl_android_set_roam_trigger(net, command, priv_cmd.total_len);
-       }
-       else if (strnicmp(command, CMD_GET_ROAM, strlen(CMD_GET_ROAM)) == 0) {
-               bytes_written = wl_android_get_roam_trigger(net, command, priv_cmd.total_len);
+       else if (wl_android_ext_priv_cmd(net, command, priv_cmd.total_len, &bytes_written) == 0) {
        }
-       else if (strnicmp(command, CMD_GET_KEEP_ALIVE, strlen(CMD_GET_KEEP_ALIVE)) == 0) {
-               int skip = strlen(CMD_GET_KEEP_ALIVE) + 1;
-               bytes_written = wl_android_get_keep_alive(net, command+skip, priv_cmd.total_len-skip);
-       }
-       else if (strnicmp(command, CMD_GET_PM, strlen(CMD_GET_PM)) == 0) {
-               bytes_written = wl_android_get_pm(net, command, priv_cmd.total_len);
-       }
-       else if (strnicmp(command, CMD_SET_PM, strlen(CMD_SET_PM)) == 0) {
-               bytes_written = wl_android_set_pm(net, command, priv_cmd.total_len);
-       }
-       else if (strnicmp(command, CMD_MONITOR, strlen(CMD_MONITOR)) == 0) {
-               bytes_written = wl_android_set_monitor(net, command, priv_cmd.total_len);
-       } else {
+       else {
                ANDROID_ERROR(("Unknown PRIVATE command %s - ignored\n", command));
                snprintf(command, 3, "OK");
                bytes_written = strlen("OK");
@@ -3645,581 +3439,3 @@ void wl_android_post_init(void)
        if (!dhd_download_fw_on_driverload)
                g_wifi_on = FALSE;
 }
-
-#if defined(RSSIAVG)
-void
-wl_free_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
-{
-       wl_rssi_cache_t *node, *cur, **rssi_head;
-       int i=0;
-
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-       node = *rssi_head;
-
-       for (;node;) {
-               ANDROID_INFO(("%s: Free %d with BSSID %pM\n",
-                       __FUNCTION__, i, &node->BSSID));
-               cur = node;
-               node = cur->next;
-               kfree(cur);
-               i++;
-       }
-       *rssi_head = NULL;
-}
-
-void
-wl_delete_dirty_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
-{
-       wl_rssi_cache_t *node, *prev, **rssi_head;
-       int i = -1, tmp = 0;
-       struct timeval now;
-
-       do_gettimeofday(&now);
-
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-       node = *rssi_head;
-       prev = node;
-       for (;node;) {
-               i++;
-               if (now.tv_sec > node->tv.tv_sec) {
-                       if (node == *rssi_head) {
-                               tmp = 1;
-                               *rssi_head = node->next;
-                       } else {
-                               tmp = 0;
-                               prev->next = node->next;
-                       }
-                       ANDROID_INFO(("%s: Del %d with BSSID %pM\n",
-                               __FUNCTION__, i, &node->BSSID));
-                       kfree(node);
-                       if (tmp == 1) {
-                               node = *rssi_head;
-                               prev = node;
-                       } else {
-                               node = prev->next;
-                       }
-                       continue;
-               }
-               prev = node;
-               node = node->next;
-       }
-}
-
-void
-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;
-
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-       node = *rssi_head;
-       prev = node;
-       for (;node;) {
-               i++;
-               if (!memcmp(&node->BSSID, bssid, ETHER_ADDR_LEN)) {
-                       if (node == *rssi_head) {
-                               tmp = 1;
-                               *rssi_head = node->next;
-                       } else {
-                               tmp = 0;
-                               prev->next = node->next;
-                       }
-                       ANDROID_INFO(("%s: Del %d with BSSID %pM\n",
-                               __FUNCTION__, i, &node->BSSID));
-                       kfree(node);
-                       if (tmp == 1) {
-                               node = *rssi_head;
-                               prev = node;
-                       } else {
-                               node = prev->next;
-                       }
-                       continue;
-               }
-               prev = node;
-               node = node->next;
-       }
-}
-
-void
-wl_reset_rssi_cache(wl_rssi_cache_ctrl_t *rssi_cache_ctrl)
-{
-       wl_rssi_cache_t *node, **rssi_head;
-
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-
-       /* reset dirty */
-       node = *rssi_head;
-       for (;node;) {
-               node->dirty += 1;
-               node = node->next;
-       }
-}
-
-int
-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;
-       scb_val_t scbval;
-       struct ether_addr bssid;
-       struct timeval now, timeout;
-
-       if (!g_wifi_on)
-               return 0;
-
-       error = wldev_ioctl(net, WLC_GET_BSSID, &bssid, sizeof(bssid), false);
-       if (error == BCME_NOTASSOCIATED) {
-               ANDROID_INFO(("%s: Not Associated! res:%d\n", __FUNCTION__, error));
-               return 0;
-       }
-       if (error) {
-               ANDROID_ERROR(("%s: Could not get bssid (%d)\n", __FUNCTION__, error));
-       }
-       memset(&scbval, 0, sizeof(scb_val_t));
-       error = wldev_get_rssi(net, &scbval);
-       rssi = scbval.val;
-       if (error) {
-               ANDROID_ERROR(("%s: Could not get rssi (%d)\n", __FUNCTION__, error));
-               return error;
-       }
-
-       do_gettimeofday(&now);
-       timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
-       if (timeout.tv_sec < now.tv_sec) {
-               /*
-                * Integer overflow - assume long enough timeout to be assumed
-                * to be infinite, i.e., the timeout would never happen.
-                */
-               ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu",
-                       __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec));
-       }
-
-       /* update RSSI */
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-       node = *rssi_head;
-       prev = NULL;
-       for (;node;) {
-               if (!memcmp(&node->BSSID, &bssid, ETHER_ADDR_LEN)) {
-                       ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%d\n",
-                               __FUNCTION__, k, &bssid, rssi));
-                       for (j=0; j<RSSIAVG_LEN-1; j++)
-                               node->RSSI[j] = node->RSSI[j+1];
-                       node->RSSI[j] = rssi;
-                       node->dirty = 0;
-                       node->tv = timeout;
-                       goto exit;
-               }
-               prev = node;
-               node = node->next;
-               k++;
-       }
-
-       leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL);
-       if (!leaf) {
-               ANDROID_ERROR(("%s: Memory alloc failure %d\n",
-                       __FUNCTION__, (int)sizeof(wl_rssi_cache_t)));
-               return 0;
-       }
-       ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d in the leaf\n",
-                       __FUNCTION__, k, &bssid, rssi));
-
-       leaf->next = NULL;
-       leaf->dirty = 0;
-       leaf->tv = timeout;
-       memcpy(&leaf->BSSID, &bssid, ETHER_ADDR_LEN);
-       for (j=0; j<RSSIAVG_LEN; j++)
-               leaf->RSSI[j] = rssi;
-
-       if (!prev)
-               *rssi_head = leaf;
-       else
-               prev->next = leaf;
-
-exit:
-       *rssi_avg = (int)wl_get_avg_rssi(rssi_cache_ctrl, &bssid);
-
-       return error;
-}
-
-void
-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;
-       int i, j, k;
-       struct timeval now, timeout;
-
-       if (!ss_list->count)
-               return;
-
-       do_gettimeofday(&now);
-       timeout.tv_sec = now.tv_sec + RSSICACHE_TIMEOUT;
-       if (timeout.tv_sec < now.tv_sec) {
-               /*
-                * Integer overflow - assume long enough timeout to be assumed
-                * to be infinite, i.e., the timeout would never happen.
-                */
-               ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu",
-                       __FUNCTION__, RSSICACHE_TIMEOUT, now.tv_sec, timeout.tv_sec));
-       }
-
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-
-       /* update RSSI */
-       for (i = 0; i < ss_list->count; i++) {
-               node = *rssi_head;
-               prev = NULL;
-               k = 0;
-               bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
-               for (;node;) {
-                       if (!memcmp(&node->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
-                               ANDROID_INFO(("%s: Update %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
-                                       __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
-                               for (j=0; j<RSSIAVG_LEN-1; j++)
-                                       node->RSSI[j] = node->RSSI[j+1];
-                               node->RSSI[j] = dtoh16(bi->RSSI);
-                               node->dirty = 0;
-                               node->tv = timeout;
-                               break;
-                       }
-                       prev = node;
-                       node = node->next;
-                       k++;
-               }
-
-               if (node)
-                       continue;
-
-               leaf = kmalloc(sizeof(wl_rssi_cache_t), GFP_KERNEL);
-               if (!leaf) {
-                       ANDROID_ERROR(("%s: Memory alloc failure %d\n",
-                               __FUNCTION__, (int)sizeof(wl_rssi_cache_t)));
-                       return;
-               }
-               ANDROID_INFO(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\" in the leaf\n",
-                               __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
-
-               leaf->next = NULL;
-               leaf->dirty = 0;
-               leaf->tv = timeout;
-               memcpy(&leaf->BSSID, &bi->BSSID, ETHER_ADDR_LEN);
-               for (j=0; j<RSSIAVG_LEN; j++)
-                       leaf->RSSI[j] = dtoh16(bi->RSSI);
-
-               if (!prev)
-                       *rssi_head = leaf;
-               else
-                       prev->next = leaf;
-       }
-}
-
-int16
-wl_get_avg_rssi(wl_rssi_cache_ctrl_t *rssi_cache_ctrl, void *addr)
-{
-       wl_rssi_cache_t *node, **rssi_head;
-       int j, rssi_sum, rssi=RSSI_MINVAL;
-
-       rssi_head = &rssi_cache_ctrl->m_cache_head;
-
-       node = *rssi_head;
-       for (;node;) {
-               if (!memcmp(&node->BSSID, addr, ETHER_ADDR_LEN)) {
-                       rssi_sum = 0;
-                       rssi = 0;
-                       for (j=0; j<RSSIAVG_LEN; j++)
-                               rssi_sum += node->RSSI[RSSIAVG_LEN-j-1];
-                       rssi = rssi_sum / j;
-                       break;
-               }
-               node = node->next;
-       }
-       rssi = MIN(rssi, RSSI_MAXVAL);
-       if (rssi == RSSI_MINVAL) {
-               ANDROID_ERROR(("%s: BSSID %pM does not in RSSI cache\n",
-               __FUNCTION__, addr));
-       }
-       return (int16)rssi;
-}
-#endif
-
-#if defined(RSSIOFFSET)
-int
-wl_update_rssi_offset(struct net_device *net, int rssi)
-{
-#if defined(RSSIOFFSET_NEW)
-       int j;
-#endif
-
-       if (!g_wifi_on)
-               return rssi;
-
-#if defined(RSSIOFFSET_NEW)
-       for (j=0; j<RSSI_OFFSET; j++) {
-               if (rssi - (RSSI_OFFSET_MINVAL+RSSI_OFFSET_INTVAL*(j+1)) < 0)
-                       break;
-       }
-       rssi += j;
-#else
-       rssi += RSSI_OFFSET;
-#endif
-       return MIN(rssi, RSSI_MAXVAL);
-}
-#endif
-
-#if defined(BSSCACHE)
-void
-wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
-{
-       wl_bss_cache_t *node, *cur, **bss_head;
-       int i=0;
-
-       ANDROID_TRACE(("%s called\n", __FUNCTION__));
-
-       bss_head = &bss_cache_ctrl->m_cache_head;
-       node = *bss_head;
-
-       for (;node;) {
-               ANDROID_TRACE(("%s: Free %d with BSSID %pM\n",
-                       __FUNCTION__, i, &node->results.bss_info->BSSID));
-               cur = node;
-               node = cur->next;
-               kfree(cur);
-               i++;
-       }
-       *bss_head = NULL;
-}
-
-void
-wl_delete_dirty_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
-{
-       wl_bss_cache_t *node, *prev, **bss_head;
-       int i = -1, tmp = 0;
-       struct timeval now;
-
-       do_gettimeofday(&now);
-
-       bss_head = &bss_cache_ctrl->m_cache_head;
-       node = *bss_head;
-       prev = node;
-       for (;node;) {
-               i++;
-               if (now.tv_sec > node->tv.tv_sec) {
-                       if (node == *bss_head) {
-                               tmp = 1;
-                               *bss_head = node->next;
-                       } else {
-                               tmp = 0;
-                               prev->next = node->next;
-                       }
-                       ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
-                               __FUNCTION__, i, &node->results.bss_info->BSSID,
-                               dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID));
-                       kfree(node);
-                       if (tmp == 1) {
-                               node = *bss_head;
-                               prev = node;
-                       } else {
-                               node = prev->next;
-                       }
-                       continue;
-               }
-               prev = node;
-               node = node->next;
-       }
-}
-
-void
-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;
-
-       bss_head = &bss_cache_ctrl->m_cache_head;
-       node = *bss_head;
-       prev = node;
-       for (;node;) {
-               i++;
-               if (!memcmp(&node->results.bss_info->BSSID, bssid, ETHER_ADDR_LEN)) {
-                       if (node == *bss_head) {
-                               tmp = 1;
-                               *bss_head = node->next;
-                       } else {
-                               tmp = 0;
-                               prev->next = node->next;
-                       }
-                       ANDROID_TRACE(("%s: Del %d with BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
-                               __FUNCTION__, i, &node->results.bss_info->BSSID,
-                               dtoh16(node->results.bss_info->RSSI), node->results.bss_info->SSID));
-                       kfree(node);
-                       if (tmp == 1) {
-                               node = *bss_head;
-                               prev = node;
-                       } else {
-                               node = prev->next;
-                       }
-                       continue;
-               }
-               prev = node;
-               node = node->next;
-       }
-}
-
-void
-wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl)
-{
-       wl_bss_cache_t *node, **bss_head;
-
-       bss_head = &bss_cache_ctrl->m_cache_head;
-
-       /* reset dirty */
-       node = *bss_head;
-       for (;node;) {
-               node->dirty += 1;
-               node = node->next;
-       }
-}
-
-void dump_bss_cache(
-#if defined(RSSIAVG)
-       wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
-#endif
-       wl_bss_cache_t *node)
-{
-       int k = 0;
-       int16 rssi;
-
-       for (;node;) {
-#if defined(RSSIAVG)
-               rssi = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
-#else
-               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));
-               k++;
-               node = node->next;
-       }
-}
-
-void
-wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
-#if defined(RSSIAVG)
-       wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
-#endif
-       wl_scan_results_t *ss_list)
-{
-       wl_bss_cache_t *node, *prev, *leaf, **bss_head;
-       wl_bss_info_t *bi = NULL;
-       int i, k=0;
-#if defined(SORT_BSS_BY_RSSI)
-       int16 rssi, rssi_node;
-#endif
-       struct timeval now, timeout;
-
-       if (!ss_list->count)
-               return;
-
-       do_gettimeofday(&now);
-       timeout.tv_sec = now.tv_sec + BSSCACHE_TIMEOUT;
-       if (timeout.tv_sec < now.tv_sec) {
-               /*
-                * Integer overflow - assume long enough timeout to be assumed
-                * to be infinite, i.e., the timeout would never happen.
-                */
-               ANDROID_TRACE(("%s: Too long timeout (secs=%d) to ever happen - now=%lu, timeout=%lu",
-                       __FUNCTION__, BSSCACHE_TIMEOUT, now.tv_sec, timeout.tv_sec));
-       }
-
-       bss_head = &bss_cache_ctrl->m_cache_head;
-
-       for (i=0; i < ss_list->count; i++) {
-               node = *bss_head;
-               prev = NULL;
-               bi = bi ? (wl_bss_info_t *)((uintptr)bi + dtoh32(bi->length)) : ss_list->bss_info;
-
-               for (;node;) {
-                       if (!memcmp(&node->results.bss_info->BSSID, &bi->BSSID, ETHER_ADDR_LEN)) {
-                               if (node == *bss_head)
-                                       *bss_head = node->next;
-                               else {
-                                       prev->next = node->next;
-                               }
-                               break;
-                       }
-                       prev = node;
-                       node = node->next;
-               }
-
-               leaf = kmalloc(dtoh32(bi->length) + sizeof(wl_bss_cache_t), GFP_KERNEL);
-               if (!leaf) {
-                       ANDROID_ERROR(("%s: Memory alloc failure %d\n", __FUNCTION__,
-                               dtoh32(bi->length) + (int)sizeof(wl_bss_cache_t)));
-                       return;
-               }
-               if (node) {
-                       kfree(node);
-                       node = NULL;
-                       ANDROID_TRACE(("%s: Update %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
-                               __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
-               } else
-                       ANDROID_TRACE(("%s: Add %d with cached BSSID %pM, RSSI=%3d, SSID \"%s\"\n",
-                               __FUNCTION__, k, &bi->BSSID, dtoh16(bi->RSSI), bi->SSID));
-
-               memcpy(leaf->results.bss_info, bi, dtoh32(bi->length));
-               leaf->next = NULL;
-               leaf->dirty = 0;
-               leaf->tv = timeout;
-               leaf->results.count = 1;
-               leaf->results.version = ss_list->version;
-               k++;
-
-               if (*bss_head == NULL)
-                       *bss_head = leaf;
-               else {
-#if defined(SORT_BSS_BY_RSSI)
-                       node = *bss_head;
-#if defined(RSSIAVG)
-                       rssi = wl_get_avg_rssi(rssi_cache_ctrl, &leaf->results.bss_info->BSSID);
-#else
-                       rssi = dtoh16(leaf->results.bss_info->RSSI);
-#endif
-                       for (;node;) {
-#if defined(RSSIAVG)
-                               rssi_node = wl_get_avg_rssi(rssi_cache_ctrl, &node->results.bss_info->BSSID);
-#else
-                               rssi_node = dtoh16(node->results.bss_info->RSSI);
-#endif
-                               if (rssi > rssi_node) {
-                                       leaf->next = node;
-                                       if (node == *bss_head)
-                                               *bss_head = leaf;
-                                       else
-                                               prev->next = leaf;
-                                       break;
-                               }
-                               prev = node;
-                               node = node->next;
-                       }
-                       if (node == NULL)
-                               prev->next = leaf;
-#else
-                       leaf->next = *bss_head;
-                       *bss_head = leaf;
-#endif
-               }
-       }
-       dump_bss_cache(
-#if defined(RSSIAVG)
-               rssi_cache_ctrl,
-#endif
-               *bss_head);
-}
-
-void
-wl_release_bss_cache_ctrl(wl_bss_cache_ctrl_t *bss_cache_ctrl)
-{
-       ANDROID_TRACE(("%s:\n", __FUNCTION__));
-       wl_free_bss_cache(bss_cache_ctrl);
-}
-#endif
index 31dfac6a271c2f2bddf444c9f9245ce422f5b3f3..aa6f5552ae5979443b1bb348db95ef6f7f187d21 100644 (file)
  * or cfg, define them as static in wl_android.c
  */
 
+/* message levels */
+#define ANDROID_ERROR_LEVEL    0x0001
+#define ANDROID_TRACE_LEVEL    0x0002
+#define ANDROID_INFO_LEVEL     0x0004
+
+#define ANDROID_ERROR(x) \
+       do { \
+               if (android_msg_level & ANDROID_ERROR_LEVEL) { \
+                       printk(KERN_ERR "ANDROID-ERROR) ");     \
+                       printk x; \
+               } \
+       } while (0)
+#define ANDROID_TRACE(x) \
+       do { \
+               if (android_msg_level & ANDROID_TRACE_LEVEL) { \
+                       printk(KERN_ERR "ANDROID-TRACE) ");     \
+                       printk x; \
+               } \
+       } while (0)
+#define ANDROID_INFO(x) \
+       do { \
+               if (android_msg_level & ANDROID_INFO_LEVEL) { \
+                       printk(KERN_ERR "ANDROID-INFO) ");      \
+                       printk x; \
+               } \
+       } while (0)
+
 /**
  * wl_android_init will be called from module init function (dhd_module_init now), similarly
  * wl_android_exit will be called from module exit function (dhd_module_cleanup now)
@@ -59,6 +86,86 @@ void wl_android_post_init(void);
 int wl_android_wifi_on(struct net_device *dev);
 int wl_android_wifi_off(struct net_device *dev, bool on_failure);
 int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd);
+#ifdef WL_EXT_IAPSTA
+int wl_android_ext_attach_netdev(struct net_device *net, uint8 bssidx);
+int wl_android_ext_dettach_netdev(void);
+void wl_android_ext_iapsta_disconnect_sta(struct net_device *dev, u32 channel);
+#endif
+int wl_android_ext_priv_cmd(struct net_device *net, char *command, int total_len,
+       int *bytes_written);
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 0, 0))
+#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,
+       IGOSTA_MODE,
+       IGCSTA_MODE
+} apstamode_t;
+
+typedef enum IFMODE {
+       ISTA_MODE = 1,
+       IAP_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;
+
+/* 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_apsta_if_t;
+
+typedef struct wl_apsta_params {
+       struct wl_if_info pif; // primary device
+       struct wl_if_info vif; // virtual device
+       int ioctl_ver;
+       bool init;
+       apstamode_t apstamode;
+} wl_apsta_params_t;
 
 s32 wl_netlink_send_msg(int pid, int type, int seq, void *data, size_t size);
 
@@ -158,7 +265,7 @@ void wl_free_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl);
 void 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);
 void wl_reset_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl);
-void wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,  
+void wl_update_bss_cache(wl_bss_cache_ctrl_t *bss_cache_ctrl,
 #if defined(RSSIAVG)
        wl_rssi_cache_ctrl_t *rssi_cache_ctrl,
 #endif
index 04f6633ed00a07e57ceea1f6df7c3c7034105694..f10029d2daf7fe00ac54b59dcdf9e01ba16e17b9 100644 (file)
@@ -1721,6 +1721,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
                        val = 1;
                        /* Disable firmware roaming for P2P interface  */
                        wldev_iovar_setint(new_ndev, "roam_off", val);
+                       wldev_iovar_setint(new_ndev, "bcn_timeout", dhd->conf->bcn_timeout);
 #ifdef WL11ULB
                        if (cfg->p2p_wdev && is_p2p_group_iface(new_ndev->ieee80211_ptr)) {
                                u32 ulb_bw = wl_cfg80211_get_ulb_bw(cfg->p2p_wdev);
@@ -1815,7 +1816,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy,
 #if defined(BCMSDIO)
                        dhd_wlfc_get_enable(dhd, &enabled);
                        if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-                               dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+                               dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
                                dhd_wlfc_deinit(dhd);
                                cfg->wlfc_on = false;
                        }
@@ -2246,7 +2247,7 @@ static s32 wl_cfg80211_handle_ifdel(struct bcm_cfg80211 *cfg, wl_if_event_info *
 #if defined(BCMSDIO)
                dhd_wlfc_get_enable(dhd, &enabled);
                if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-                       dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+                       dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
                        dhd_wlfc_deinit(dhd);
                        cfg->wlfc_on = false;
                }
@@ -2798,7 +2799,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
         */
        if (request && (scan_req_iftype(request) == NL80211_IFTYPE_AP)) {
                WL_INFORM(("Scan Command on SoftAP Interface. Ignoring...\n"));
-               return 0;
+// terence 20161023: let it scan in SoftAP mode
+//             return 0;
        }
 
        ndev = ndev_to_wlc_ndev(ndev, cfg);
@@ -2931,7 +2933,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev,
                                        request->ie_len);
 
                                if (unlikely(err)) {
-                                       goto scan_out;
+// terence 20161023: let it scan in SoftAP mode
+//                                     goto scan_out;
                                }
 
                        }
@@ -4582,6 +4585,9 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
                kfree(ext_join_params);
                return BCME_ERROR;
        }
+#ifdef WL_EXT_IAPSTA
+       wl_android_ext_iapsta_disconnect_sta(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);
 
@@ -5201,6 +5207,13 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev,
                        params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
                        WL_DBG(("WLAN_CIPHER_SUITE_AES_CMAC\n"));
                        break;
+#if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
+               /* to connect to mixed mode AP */
+               case (AES_ENABLED | TKIP_ENABLED): /* TKIP CCMP */
+                       params.cipher = WLAN_CIPHER_SUITE_AES_CMAC;
+                       WL_DBG(("WLAN_CIPHER_SUITE_TKIP\n"));
+                       break;
+#endif
                default:
                        WL_ERR(("Invalid algo (0x%x)\n", wsec));
                        return -EINVAL;
@@ -5549,7 +5562,8 @@ wl_cfg80211_suspend(struct wiphy *wiphy)
        unsigned long flags;
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
        struct cfg80211_scan_info info;
-       #endif
+#endif
+
        if (unlikely(!wl_get_drv_status(cfg, READY, ndev))) {
                WL_INFORM(("device is not ready : status (%d)\n",
                        (int)cfg->status));
@@ -7223,6 +7237,249 @@ exit:
        return 0;
 }
 
+#if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
+static u32 wl_get_cipher_type(uint8 type)
+{
+       u32 ret = 0;
+       switch (type) {
+               case WPA_CIPHER_NONE:
+                       ret = 0;
+                       break;
+               case WPA_CIPHER_WEP_40:
+               case WPA_CIPHER_WEP_104:
+                       ret = WEP_ENABLED;
+                       break;
+               case WPA_CIPHER_TKIP:
+                       ret = TKIP_ENABLED;
+                       break;
+               case WPA_CIPHER_AES_CCM:
+                       ret = AES_ENABLED;
+                       break;
+#ifdef BCMWAPI_WPI
+               case WAPI_CIPHER_SMS4:
+                       ret = SMS4_ENABLED;
+                       break;
+#endif
+               default:
+                       WL_ERR(("No Security Info\n"));
+       }
+       return ret;
+}
+
+static u32 wl_get_suite_auth_key_mgmt_type(uint8 type)
+{
+       u32 ret = 0;
+       switch (type) {
+               case RSN_AKM_NONE:
+                       ret = WPA_AUTH_NONE;
+                       break;
+               case RSN_AKM_UNSPECIFIED:
+                       ret = WPA_AUTH_UNSPECIFIED;
+                       break;
+               case RSN_AKM_PSK:
+                       ret = WPA_AUTH_PSK;
+                       break;
+               default:
+                       WL_ERR(("No Key Mgmt Info\n"));
+       }
+       return ret;
+}
+
+static u32 wl_get_suite_auth2_key_mgmt_type(uint8 type)
+{
+       u32 ret = 0;
+       switch (type) {
+               case RSN_AKM_NONE:
+                       ret = WPA_AUTH_NONE;
+                       break;
+               case RSN_AKM_UNSPECIFIED:
+                       ret = WPA2_AUTH_UNSPECIFIED;
+                       break;
+               case RSN_AKM_PSK:
+                       ret = WPA2_AUTH_PSK;
+                       break;
+               default:
+                       WL_ERR(("No Key Mgmt Info\n"));
+       }
+       return ret;
+}
+
+static s32
+wl_validate_wpaie_wpa2ie(struct net_device *dev, wpa_ie_fixed_t *wpaie,
+       bcm_tlv_t *wpa2ie, s32 bssidx)
+{
+       wpa_suite_mcast_t *mcast;
+       wpa_suite_ucast_t *ucast;
+       wpa_suite_auth_key_mgmt_t *mgmt;
+       u16 auth = 0; /* d11 open authentication */
+       u16 count;
+       s32 err = BCME_OK;
+       u32 wme_bss_disable;
+       u16 suite_count;
+       u8 rsn_cap[2];
+       s32 len = 0;
+       u32 i;
+       u32 wsec1, wsec2, wsec;
+       u32 pval = 0;
+       u32 gval = 0;
+       u32 wpa_auth = 0;
+       u32 wpa_auth1 = 0;
+       u32 wpa_auth2 = 0;
+       u8* ptmp;
+
+       if (wpaie == NULL || wpa2ie == NULL)
+               goto exit;
+
+       WL_DBG(("Enter \n"));
+       len = wpaie->length;    /* value length */
+       len -= WPA_IE_TAG_FIXED_LEN;
+       /* check for multicast cipher suite */
+       if (len < WPA_SUITE_LEN) {
+               WL_INFORM(("no multicast cipher suite\n"));
+               goto exit;
+       }
+
+       /* pick up multicast cipher */
+       mcast = (wpa_suite_mcast_t *)&wpaie[1];
+       len -= WPA_SUITE_LEN;
+       if (!bcmp(mcast->oui, WPA_OUI, WPA_OUI_LEN)) {
+               if (IS_WPA_CIPHER(mcast->type)) {
+                       gval |= wl_get_cipher_type(mcast->type);
+               }
+       }
+       WL_ERR(("\nwpa ie validate\n"));
+       WL_ERR(("wpa ie mcast cipher = 0x%X\n", gval));
+
+       /* Check for unicast suite(s) */
+       if (len < WPA_IE_SUITE_COUNT_LEN) {
+               WL_INFORM(("no unicast suite\n"));
+               goto exit;
+       }
+
+       /* walk thru unicast cipher list and pick up what we recognize */
+       ucast = (wpa_suite_ucast_t *)&mcast[1];
+       count = ltoh16_ua(&ucast->count);
+       len -= WPA_IE_SUITE_COUNT_LEN;
+       for (i = 0; i < count && len >= WPA_SUITE_LEN;
+               i++, len -= WPA_SUITE_LEN) {
+               if (!bcmp(ucast->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
+                       if (IS_WPA_CIPHER(ucast->list[i].type)) {
+                               pval |= wl_get_cipher_type(ucast->list[i].type);
+                       }
+               }
+       }
+       WL_ERR(("wpa ie ucast count =%d, cipher = 0x%X\n", count, pval));
+
+       /* FOR WPS , set SEC_OW_ENABLED */
+       wsec1 = (pval | gval | SES_OW_ENABLED);
+       WL_ERR(("wpa ie wsec = 0x%X\n", wsec1));
+
+       len -= (count - i) * WPA_SUITE_LEN;
+       /* Check for auth key management suite(s) */
+       if (len < WPA_IE_SUITE_COUNT_LEN) {
+               WL_INFORM((" no auth key mgmt suite\n"));
+               goto exit;
+       }
+       /* walk thru auth management suite list and pick up what we recognize */
+       mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[count];
+       count = ltoh16_ua(&mgmt->count);
+       len -= WPA_IE_SUITE_COUNT_LEN;
+       for (i = 0; i < count && len >= WPA_SUITE_LEN;
+               i++, len -= WPA_SUITE_LEN) {
+               if (!bcmp(mgmt->list[i].oui, WPA_OUI, WPA_OUI_LEN)) {
+                       if (IS_WPA_AKM(mgmt->list[i].type)) {
+
+                               wpa_auth1 |= wl_get_suite_auth_key_mgmt_type(mgmt->list[i].type);
+                       }
+               }
+
+       }
+       WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth1));
+       WL_ERR(("\nwpa2 ie validate\n"));
+
+       pval = 0;
+       gval = 0;
+       len =  wpa2ie->len;
+       /* check the mcast cipher */
+       mcast = (wpa_suite_mcast_t *)&wpa2ie->data[WPA2_VERSION_LEN];
+       ptmp = mcast->oui;
+       gval = wl_get_cipher_type(ptmp[DOT11_OUI_LEN]);
+
+       WL_ERR(("wpa2 ie mcast cipher = 0x%X\n", gval));
+       if ((len -= WPA_SUITE_LEN) <= 0)
+       {
+               WL_ERR(("P:wpa2 ie len[%d]", len));
+               return BCME_BADLEN;
+       }
+
+       /* check the unicast cipher */
+       ucast = (wpa_suite_ucast_t *)&mcast[1];
+       suite_count = ltoh16_ua(&ucast->count);
+       WL_ERR((" WPA2 ucast cipher count=%d\n", suite_count));
+       pval |= wl_get_cipher_type(ucast->list[0].type);
+
+       if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) <= 0)
+               return BCME_BADLEN;
+
+       WL_ERR(("wpa2 ie ucast cipher = 0x%X\n", pval));
+
+       /* FOR WPS , set SEC_OW_ENABLED */
+       wsec2 = (pval | gval | SES_OW_ENABLED);
+       WL_ERR(("wpa2 ie wsec = 0x%X\n", wsec2));
+
+       /* check the AKM */
+       mgmt = (wpa_suite_auth_key_mgmt_t *)&ucast->list[suite_count];
+       suite_count = ltoh16_ua(&mgmt->count);
+       ptmp = (u8 *)&mgmt->list[0];
+       wpa_auth2 = wl_get_suite_auth2_key_mgmt_type(ptmp[DOT11_OUI_LEN]);
+       WL_ERR(("wpa ie wpa_suite_auth_key_mgmt count=%d, key_mgmt = 0x%X\n", count, wpa_auth2));
+
+       if ((len -= (WPA_IE_SUITE_COUNT_LEN + (WPA_SUITE_LEN * suite_count))) >= RSN_CAP_LEN) {
+               rsn_cap[0] = *(u8 *)&mgmt->list[suite_count];
+               rsn_cap[1] = *((u8 *)&mgmt->list[suite_count] + 1);
+               if (rsn_cap[0] & (RSN_CAP_16_REPLAY_CNTRS << RSN_CAP_PTK_REPLAY_CNTR_SHIFT)) {
+                       wme_bss_disable = 0;
+               } else {
+                       wme_bss_disable = 1;
+               }
+               WL_DBG(("P:rsn_cap[0]=[0x%X]:wme_bss_disabled[%d]\n", rsn_cap[0], wme_bss_disable));
+
+               /* set wme_bss_disable to sync RSN Capabilities */
+               err = wldev_iovar_setint_bsscfg(dev, "wme_bss_disable", wme_bss_disable, bssidx);
+               if (err < 0) {
+                       WL_ERR(("wme_bss_disable error %d\n", err));
+                       return BCME_ERROR;
+               }
+       } else {
+               WL_DBG(("There is no RSN Capabilities. remained len %d\n", len));
+       }
+
+       wsec = (wsec1 | wsec2);
+       wpa_auth = (wpa_auth1 | wpa_auth2);
+       WL_ERR(("wpa_wpa2 wsec=0x%X wpa_auth=0x%X\n", wsec, wpa_auth));
+
+       /* set auth */
+       err = wldev_iovar_setint_bsscfg(dev, "auth", auth, bssidx);
+       if (err < 0) {
+               WL_ERR(("auth error %d\n", err));
+               return BCME_ERROR;
+       }
+       /* set wsec */
+       err = wldev_iovar_setint_bsscfg(dev, "wsec", wsec, bssidx);
+       if (err < 0) {
+               WL_ERR(("wsec error %d\n", err));
+               return BCME_ERROR;
+       }
+       /* set upper-layer auth */
+       err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", wpa_auth, bssidx);
+       if (err < 0) {
+               WL_ERR(("wpa_auth error %d\n", err));
+               return BCME_ERROR;
+       }
+exit:
+       return 0;
+}
+#endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
 
 static s32
 wl_cfg80211_bcn_validate_sec(
@@ -7251,6 +7508,15 @@ wl_cfg80211_bcn_validate_sec(
                WL_DBG(("SoftAP: validating security"));
                /* If wpa2_ie or wpa_ie is present validate it */
 
+#if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
+               if ((ies->wpa_ie != NULL && ies->wpa2_ie != NULL)) {
+                       if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie, ies->wpa2_ie, bssidx)  < 0) {
+                               bss->security_mode = false;
+                               return BCME_ERROR;
+                       }
+               }
+               else {
+#endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
                if ((ies->wpa2_ie || ies->wpa_ie) &&
                        ((wl_validate_wpa2ie(dev, ies->wpa2_ie, bssidx)  < 0 ||
                        wl_validate_wpaie(dev, ies->wpa_ie, bssidx) < 0))) {
@@ -7284,6 +7550,9 @@ wl_cfg80211_bcn_validate_sec(
                                ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
                                GFP_KERNEL);
                }
+#if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
+               }
+#endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
                if (!ies->wpa2_ie && !ies->wpa_ie) {
                        wl_validate_opensecurity(dev, bssidx, privacy);
                        bss->security_mode = false;
@@ -7521,6 +7790,7 @@ wl_cfg80211_bcn_bringup_ap(
                        WL_ERR(("failed to disable uapsd, error=%d\n", err));
                }
 #endif /* SOFTAP_UAPSD_OFF */
+               dhd_conf_set_wme(cfg->pub, 1);
 
                err = wldev_ioctl(dev, WLC_UP, &ap, sizeof(s32), true);
                if (unlikely(err)) {
@@ -7711,6 +7981,75 @@ static s32 wl_cfg80211_hostapd_sec(
                        bss->wps_ie = kmemdup(ies->wps_ie, ies->wps_ie_len, GFP_KERNEL);
                }
 
+#if defined(SUPPORT_SOFTAP_WPAWPA2_MIXED)
+               if (ies->wpa_ie != NULL && ies->wpa2_ie != NULL) {
+                       WL_ERR(("update bss - wpa_ie and  wpa2_ie is not null\n"));
+                       if (!bss->security_mode) {
+                               /* change from open mode to security mode */
+                               update_bss = true;
+                               bss->wpa_ie =
+                                       kmemdup(ies->wpa_ie,
+                                       ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+                                       GFP_KERNEL);
+                               bss->rsn_ie =
+                                       kmemdup(ies->wpa2_ie,
+                                       ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+                                       GFP_KERNEL);
+                       } else {
+                               /* change from (WPA or WPA2 or WPA/WPA2) to WPA/WPA2 mixed mode */
+                               if (bss->wpa_ie) {
+                                       if (memcmp(bss->wpa_ie,
+                                       ies->wpa_ie, ies->wpa_ie->length +
+                                       WPA_RSN_IE_TAG_FIXED_LEN)) {
+                                               kfree(bss->wpa_ie);
+                                               update_bss = true;
+                                               bss->wpa_ie = kmemdup(ies->wpa_ie,
+                                               ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+                                               GFP_KERNEL);
+                                       }
+                               }
+                               else {
+                                       update_bss = true;
+                                       bss->wpa_ie =
+                                               kmemdup(ies->wpa_ie,
+                                               ies->wpa_ie->length + WPA_RSN_IE_TAG_FIXED_LEN,
+                                               GFP_KERNEL);
+                               }
+                               if (bss->rsn_ie) {
+                                       if (memcmp(bss->rsn_ie,
+                                       ies->wpa2_ie,
+                                       ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN)) {
+                                               update_bss = true;
+                                               kfree(bss->rsn_ie);
+                                               bss->rsn_ie =
+                                                       kmemdup(ies->wpa2_ie,
+                                                       ies->wpa2_ie->len +
+                                                       WPA_RSN_IE_TAG_FIXED_LEN,
+                                                       GFP_KERNEL);
+                                       }
+                               }
+                               else {
+                                       update_bss = true;
+                                       bss->rsn_ie =
+                                               kmemdup(ies->wpa2_ie,
+                                               ies->wpa2_ie->len + WPA_RSN_IE_TAG_FIXED_LEN,
+                                               GFP_KERNEL);
+                               }
+                       }
+                       WL_ERR(("update_bss=%d\n", update_bss));
+                       if (update_bss) {
+                               bss->security_mode = true;
+                               wl_cfgp2p_bss(cfg, dev, bssidx, 0);
+                               if (wl_validate_wpaie_wpa2ie(dev, ies->wpa_ie,
+                                       ies->wpa2_ie, bssidx)  < 0) {
+                                       return BCME_ERROR;
+                               }
+                               wl_cfgp2p_bss(cfg, dev, bssidx, 1);
+                       }
+
+               }
+               else
+#endif /* SUPPORT_SOFTAP_WPAWPA2_MIXED */
                if ((ies->wpa_ie != NULL || ies->wpa2_ie != NULL)) {
                        if (!bss->security_mode) {
                                /* change from open mode to security mode */
@@ -8441,7 +8780,7 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev,
        /* Set GC/STA SCB expiry timings. */
        if ((err = wl_cfg80211_set_scb_timings(cfg, dev))) {
                WL_ERR(("scb setting failed \n"));
-               goto fail;
+//             goto fail;
        }
 
        if (wl_get_drv_status(cfg, AP_CREATED, dev)) {
@@ -8946,8 +9285,27 @@ WL_CFG80211_REG_NOTIFIER()
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0))
 static const struct wiphy_wowlan_support brcm_wowlan_support = {
        .flags = WIPHY_WOWLAN_ANY,
+       .n_patterns = WL_WOWLAN_MAX_PATTERNS,
+       .pattern_min_len = WL_WOWLAN_MIN_PATTERN_LEN,
+       .pattern_max_len = WL_WOWLAN_MAX_PATTERN_LEN,
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0))
+       .max_pkt_offset = WL_WOWLAN_MAX_PATTERN_LEN,
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 9, 0) */
 };
 #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0) */
+
+/* terence 20161107: remove to fix:
+ * PC is at kfree+0x174/0x180
+ * LR is at nl80211_set_wowlan+0x55c/0x614 [cfg80211]
+ */
+#if 0
+static struct cfg80211_wowlan brcm_wowlan_config = {
+       .disconnect = true,
+       .gtk_rekey_failure = true,
+       .eap_identity_req = true,
+       .four_way_handshake = true,
+};
+#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0) */
 #endif /* CONFIG_PM */
 
 static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev, dhd_pub_t *context)
@@ -9086,6 +9444,14 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev
 
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
        wdev->wiphy->wowlan = &brcm_wowlan_support;
+       /* If this is not provided cfg stack will get disconnect
+        * during suspend.
+        */
+       /* terence 20161107: remove to fix:
+        * PC is at kfree+0x174/0x180
+        * LR is at nl80211_set_wowlan+0x55c/0x614 [cfg80211]
+        */
+//     wdev->wiphy->wowlan_config = &brcm_wowlan_config;
 #else
        wdev->wiphy->wowlan.flags = WIPHY_WOWLAN_ANY;
        wdev->wiphy->wowlan.n_patterns = WL_WOWLAN_MAX_PATTERNS;
@@ -9331,7 +9697,7 @@ static s32 wl_inform_single_bss(struct bcm_cfg80211 *cfg, struct wl_bss_info *bi
                offsetof(struct wl_cfg80211_bss_info, frame_buf));
        notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt,
                u.beacon.variable) + wl_get_ielen(cfg);
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
        freq = ieee80211_channel_to_frequency(notif_bss_info->channel);
        (void)band->band;
 #else
@@ -9570,7 +9936,7 @@ wl_notify_connect_status_ap(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                        kfree(body);
                return -EINVAL;
        }
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
        freq = ieee80211_channel_to_frequency(channel);
        (void)band->band;
 #else
@@ -9870,7 +10236,7 @@ int wl_get_bss_info(struct bcm_cfg80211 *cfg, struct net_device *dev, uint8 *mac
        bi = (struct wl_bss_info *)(cfg->extra_buf + 4);
        channel = wf_chspec_ctlchan(bi->chanspec);
 
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
        freq = ieee80211_channel_to_frequency(channel);
 #else
        if (channel > 14) {
@@ -10123,7 +10489,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                        printf("wl_bss_connect_done succeeded with " MACDBG "\n",
                                                MAC2STRDBG((const u8*)(&e->addr)));
                                        wl_bss_connect_done(cfg, ndev, e, data, true);
-                                       dhd_conf_set_fw_string_cmd(cfg->pub, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
+                                       dhd_conf_set_intiovar(cfg->pub, WLC_SET_VAR, "phy_oclscdenable", cfg->pub->conf->phy_oclscdenable, 0, FALSE);
                                        WL_DBG(("joined in BSS network \"%s\"\n",
                                        ((struct wlc_ssid *)
                                         wl_read_prof(cfg, ndev, WL_PROF_SSID))->SSID));
@@ -10137,7 +10503,7 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                }
                        wl_update_prof(cfg, ndev, e, &act, WL_PROF_ACT);
                        wl_update_prof(cfg, ndev, NULL, (const void *)&e->addr, WL_PROF_BSSID);
-                       dhd_conf_set_wme(cfg->pub);
+                       dhd_conf_set_wme(cfg->pub, 0);
 
                } else if (wl_is_linkdown(cfg, e)) {
 #ifdef DHD_LOSSLESS_ROAMING
@@ -10219,6 +10585,12 @@ wl_notify_connect_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                                if (!memcmp(ndev->name, WL_P2P_INTERFACE_PREFIX, strlen(WL_P2P_INTERFACE_PREFIX))) {
                                        // terence 20130703: Fix for wrong group_capab (timing issue)
                                        cfg->p2p_disconnected = 1;
+#if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 11, 0))
+                                       if (wl_get_drv_status(cfg, DISCONNECTING, ndev)) {
+                                               CFG80211_DISCONNECTED(ndev, reason, NULL, 0,
+                                                               false, GFP_KERNEL);
+                                       }
+#endif
                                }
                                memcpy(&cfg->disconnected_bssid, curbssid, ETHER_ADDR_LEN);
                                wl_clr_drv_status(cfg, CONNECTED, ndev);
@@ -10822,7 +11194,7 @@ wl_bss_roaming_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
 #endif 
        printf("wl_bss_roaming_done succeeded to " MACDBG "\n",
                MAC2STRDBG((const u8*)(&e->addr)));
-       dhd_conf_set_wme(cfg->pub);
+       dhd_conf_set_wme(cfg->pub, 0);
 
        cfg80211_roamed(ndev,
 #if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39))
@@ -10921,7 +11293,7 @@ wl_bss_connect_done(struct bcm_cfg80211 *cfg, struct net_device *ndev,
                        GFP_KERNEL);
                if (completed) {
                        WL_INFORM(("Report connect result - connection succeeded\n"));
-                       dhd_conf_set_wme(cfg->pub);
+                       dhd_conf_set_wme(cfg->pub, 0);
                } else
                        WL_ERR(("Report connect result - connection failed\n"));
        }
@@ -11090,10 +11462,10 @@ wl_notify_scan_status(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
        u32 len = WL_SCAN_BUF_MAX;
        s32 err = 0;
        unsigned long flags;
-
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
        struct cfg80211_scan_info info;
 #endif
+
        WL_DBG(("Enter \n"));
        if (!wl_get_drv_status(cfg, SCANNING, ndev)) {
                WL_ERR(("scan is not ready \n"));
@@ -11301,7 +11673,7 @@ wl_notify_rx_mgmt_frame(struct bcm_cfg80211 *cfg, bcm_struct_cfgdev *cfgdev,
                WL_ERR(("No valid band\n"));
                return -EINVAL;
        }
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
        freq = ieee80211_channel_to_frequency(channel);
        (void)band->band;
 #else
@@ -11951,9 +12323,9 @@ static void wl_scan_timeout(unsigned long data)
 #endif /* CUSTOMER_HW4_DEBUG */
 
        // terence 20130729: workaround to fix out of memory in firmware
-//     if (dhd_conf_get_chip(dhd_get_pub(dev)) == BCM43362_CHIP_ID) {
+//     if (dhd_conf_get_chip(dhd_get_pub(ndev)) == BCM43362_CHIP_ID) {
 //             WL_ERR(("Send hang event\n"));
-//             net_os_send_hang_message(dev);
+//             net_os_send_hang_message(ndev);
 //     }
 }
 
@@ -12148,6 +12520,7 @@ static s32 wl_notify_escan_complete(struct bcm_cfg80211 *cfg,
        struct cfg80211_scan_info info;
        info.aborted = aborted;
 #endif
+
        WL_DBG(("Enter \n"));
 
        mutex_lock(&cfg->scan_complete);
@@ -13625,7 +13998,7 @@ static int wl_construct_reginfo(struct bcm_cfg80211 *cfg, s32 bw_cap)
                if (!dhd_conf_match_channel(cfg->pub, channel))
                        continue;
                if (index <  array_size) {
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
                        band_chan_arr[index].center_freq =
                                ieee80211_channel_to_frequency(channel);
 #else
@@ -14020,7 +14393,6 @@ static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
        dhd_pub_t *dhd =  (dhd_pub_t *)(cfg->pub);
 #endif
 #endif /* PROP_TXSTATUS_VSDB */
-
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
        struct cfg80211_scan_info info;
 #endif
@@ -14041,7 +14413,7 @@ static s32 __wl_cfg80211_down(struct bcm_cfg80211 *cfg)
                        bool enabled = false;
                        dhd_wlfc_get_enable(dhd, &enabled);
                        if (enabled && cfg->wlfc_on && dhd->op_mode != DHD_FLAG_HOSTAP_MODE &&
-                               dhd->op_mode != DHD_FLAG_IBSS_MODE) {
+                               dhd->op_mode != DHD_FLAG_IBSS_MODE && dhd->conf->disable_proptx!=0) {
                                dhd_wlfc_deinit(dhd);
                                cfg->wlfc_on = false;
                        }
@@ -14627,7 +14999,7 @@ s32 wl_cfg80211_channel_to_freq(u32 channel)
 {
        int freq = 0;
 
-#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38)
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39)
        freq = ieee80211_channel_to_frequency(channel);
 #else
        {
@@ -14960,6 +15332,7 @@ wl_cfg80211_set_auto_channel_scan_state(struct net_device *ndev)
        ret = wl_notify_escan_complete(cfg, ndev, true, true);
        if (ret < 0) {
                WL_ERR(("set scan abort failed, error = %d\n", ret));
+               ret = BCME_OK; // terence 20140115: fix escan_complete error
                goto done;
        }
 
@@ -15188,61 +15561,71 @@ wl_cfg80211_get_best_channels(struct net_device *dev, char* cmd, int total_len)
                goto done;
        }
 
-       /* Best channel selection in 2.4GHz band. */
-       ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
-       if (ret < 0) {
-               WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
-               goto done;
-       }
+       ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
+       if (band_cur != WLC_BAND_5G) {
+               /* Best channel selection in 2.4GHz band. */
+               ret = wl_cfg80211_get_chanspecs_2g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
+               if (ret < 0) {
+                       WL_ERR(("can't get chanspecs in 2.4GHz, error = %d\n", ret));
+                       goto done;
+               }
 
-       ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
-               &channel);
-       if (ret < 0) {
-               WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
-               goto done;
-       }
+               ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
+                       &channel);
+               if (ret < 0) {
+                       WL_ERR(("can't select best channel scan in 2.4GHz, error = %d\n", ret));
+                       goto done;
+               }
 
-       if (CHANNEL_IS_2G(channel)) {
-               channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
-       } else {
-               WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
-               channel = 0;
+               if (CHANNEL_IS_2G(channel)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
+                       channel = ieee80211_channel_to_frequency(channel);
+#else
+                       channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_2GHZ);
+#endif
+               } else {
+                       WL_ERR(("invalid 2.4GHz channel, channel = %d\n", channel));
+                       channel = 0;
+               }
        }
-
        pos += snprintf(pos, total_len, "%04d ", channel);
 
-       // terence 20140120: fix for some chipsets only return 2.4GHz channel (4330b2/43341b0/4339a0)
-       ret = wldev_ioctl(dev, WLC_GET_BAND, &band_cur, sizeof(band_cur), false);
-       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)
-               WL_ERR(("WLC_SET_BAND error %d\n", ret));
-
-       /* Best channel selection in 5GHz band. */
-       ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
-       if (ret < 0) {
-               WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
-               goto done;
-       }
+       if (band_cur != WLC_BAND_2G) {
+               // 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)
+                       WL_ERR(("WLC_SET_BAND error %d\n", ret));
 
-       ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
-               &channel);
-       if (ret < 0) {
-               WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
-               goto done;
-       }
+               /* Best channel selection in 5GHz band. */
+               ret = wl_cfg80211_get_chanspecs_5g(ndev, (void *)buf, CHANSPEC_BUF_SIZE);
+               if (ret < 0) {
+                       WL_ERR(("can't get chanspecs in 5GHz, error = %d\n", ret));
+                       goto done;
+               }
 
-       if (CHANNEL_IS_5G(channel)) {
-               channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
-       } else {
-               WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
-               channel = 0;
-       }
+               ret = wl_cfg80211_get_best_channel(ndev, (void *)buf, CHANSPEC_BUF_SIZE,
+                       &channel);
+               if (ret < 0) {
+                       WL_ERR(("can't select best channel scan in 5GHz, error = %d\n", ret));
+                       goto done;
+               }
 
-       ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
-       if (ret < 0)
-               WL_ERR(("WLC_SET_BAND error %d\n", ret));
+               if (CHANNEL_IS_5G(channel)) {
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 39) && !defined(WL_COMPAT_WIRELESS)
+                       channel = ieee80211_channel_to_frequency(channel);
+#else
+                       channel = ieee80211_channel_to_frequency(channel, IEEE80211_BAND_5GHZ);
+#endif
+               } else {
+                       WL_ERR(("invalid 5GHz channel, channel = %d\n", channel));
+                       channel = 0;
+               }
 
+               ret = wldev_ioctl(dev, WLC_SET_BAND, &band_cur, sizeof(band_cur), true);
+               if (ret < 0)
+                       WL_ERR(("WLC_SET_BAND error %d\n", ret));
+       }
        pos += snprintf(pos, total_len, "%04d ", channel);
 
        /* Set overall best channel same as 5GHz best channel. */
@@ -16103,6 +16486,7 @@ int wl_cfg80211_scan_stop(bcm_struct_cfgdev *cfgdev)
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(4, 8, 0))
        struct cfg80211_scan_info info;
 #endif
+
        WL_TRACE(("Enter\n"));
 
        cfg = g_bcm_cfg;
index 7e2dc0daa18c4381c1cf7f882b0f73467d5d8a05..9e970400175a3fe1fa6b31791495c411bebc848d 100644 (file)
@@ -192,6 +192,18 @@ enum wl_cfgp2p_status {
                add_timer(timer); \
        } while (0);
 
+#if (LINUX_VERSION_CODE <= KERNEL_VERSION(3, 0, 8))
+#ifdef WL_SUPPORT_BACKPORTED_KPATCHES
+#undef WL_SUPPORT_BACKPORTED_KPATCHES
+#endif
+#endif
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#ifdef WL_CFG80211_STA_EVENT
+#undef WL_CFG80211_STA_EVENT
+#endif
+#endif
+
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0)) && !defined(WL_CFG80211_P2P_DEV_IF)
 #define WL_CFG80211_P2P_DEV_IF
 
index f70e5bf495c4074324fb5a5bcbd6926bd25d2db1..a26b4ca6eb29c43e1673e3dc07141c948ddeb8a8 100644 (file)
@@ -46,6 +46,9 @@
 #include <wlioctl_utils.h>
 #endif
 #include <wl_android.h>
+#ifdef WL_ESCAN
+#include <wl_escan.h>
+#endif
 
 typedef const struct si_pub    si_t;
 
@@ -129,7 +132,7 @@ extern int dhd_wait_pend8021x(struct net_device *dev);
 #define IW_EVENT_IDX(cmd)      ((cmd) - IWEVFIRST)
 #endif /* WIRELESS_EXT < 19 */
 
-
+#ifndef WL_ESCAN
 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 8, 0))
 #define DAEMONIZE(a)   do { \
                allow_signal(SIGKILL);  \
@@ -183,6 +186,7 @@ iscan_info_t *g_iscan = NULL;
 static void wl_iw_timerfunc(ulong data);
 static void wl_iw_set_event_mask(struct net_device *dev);
 static int wl_iw_iscan(iscan_info_t *iscan, wlc_ssid_t *ssid, uint16 action);
+#endif /* WL_ESCAN */
 
 /* priv_link becomes netdev->priv and is the link between netdev and wlif struct */
 typedef struct priv_link {
@@ -280,6 +284,7 @@ dev_wlc_intvar_set(
        return (dev_wlc_ioctl(dev, WLC_SET_VAR, buf, len));
 }
 
+#ifndef WL_ESCAN
 static int
 dev_iw_iovar_setbuf(
        struct net_device *dev,
@@ -315,6 +320,7 @@ dev_iw_iovar_getbuf(
 
        return (dev_wlc_ioctl(dev, WLC_GET_VAR, bufptr, buflen));
 }
+#endif
 
 #if WIRELESS_EXT > 17
 static int
@@ -902,6 +908,7 @@ wl_iw_get_range(
        return 0;
 }
 
+#ifndef WL_ESCAN
 static int
 rssi_to_qual(int rssi)
 {
@@ -918,6 +925,7 @@ rssi_to_qual(int rssi)
        else
                return 5;
 }
+#endif /* WL_ESCAN */
 
 static int
 wl_iw_set_spy(
@@ -1074,6 +1082,7 @@ wl_iw_mlme(
 }
 #endif /* WIRELESS_EXT > 17 */
 
+#ifndef WL_ESCAN
 static int
 wl_iw_get_aplist(
        struct net_device *dev,
@@ -1221,8 +1230,10 @@ wl_iw_iscan_get_aplist(
 
        return 0;
 }
+#endif
 
 #if WIRELESS_EXT > 13
+#ifndef WL_ESCAN
 static int
 wl_iw_set_scan(
        struct net_device *dev,
@@ -1304,6 +1315,7 @@ wl_iw_iscan_set_scan(
 
        return 0;
 }
+#endif /* WL_ESCAN */
 
 #if WIRELESS_EXT > 17
 static bool
@@ -1352,7 +1364,10 @@ ie_is_wps_ie(uint8 **wpsie, uint8 **tlvs, int *tlvs_len)
 #endif /* WIRELESS_EXT > 17 */
 
 
-static int
+#ifndef WL_ESCAN
+static
+#endif
+int
 wl_iw_handle_scanresults_ies(char **event_p, char *end,
        struct iw_request_info *info, wl_bss_info_t *bi)
 {
@@ -1420,6 +1435,7 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end,
        return 0;
 }
 
+#ifndef WL_ESCAN
 static int
 wl_iw_get_scan(
        struct net_device *dev,
@@ -1474,7 +1490,7 @@ wl_iw_get_scan(
                // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
                rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
                channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
-               WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, merge broadcast SSID=\"%s\"\n",
+               WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
                __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
 
                /* First entry must be the BSSID */
@@ -1608,7 +1624,7 @@ wl_iw_iscan_get_scan(
                        // terence 20150419: limit the max. rssi to -2 or the bss will be filtered out in android OS
                        rssi = MIN(dtoh16(bi->RSSI), RSSI_MAXVAL);
                        channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch;
-                       WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, merge broadcast SSID=\"%s\"\n",
+                       WL_SCAN(("%s: BSSID="MACSTR", channel=%d, RSSI=%d, SSID=\"%s\"\n",
                        __FUNCTION__, MAC2STR(bi->BSSID.octet), channel, rssi, bi->SSID));
 
                        /* First entry must be the BSSID */
@@ -1681,10 +1697,11 @@ wl_iw_iscan_get_scan(
 
        dwrq->length = event - extra;
        dwrq->flags = 0;        /* todo */
+       WL_SCAN(("%s: apcnt=%d\n", __FUNCTION__, apcnt));
 
        return 0;
 }
-
+#endif /* WL_ESCAN */
 #endif /* WIRELESS_EXT > 13 */
 
 
@@ -2953,10 +2970,19 @@ static const iw_handler wl_iw_handler[] =
 #else
        (iw_handler) NULL,                      /* -- hole -- */
 #endif
+#ifdef WL_ESCAN
+       (iw_handler) NULL,                      /* SIOCGIWAPLIST */
+#else
        (iw_handler) wl_iw_iscan_get_aplist,    /* SIOCGIWAPLIST */
+#endif
 #if WIRELESS_EXT > 13
+#ifdef WL_ESCAN
+       (iw_handler) wl_escan_set_scan, /* SIOCSIWSCAN */
+       (iw_handler) wl_escan_get_scan, /* SIOCGIWSCAN */
+#else
        (iw_handler) wl_iw_iscan_set_scan,      /* SIOCSIWSCAN */
        (iw_handler) wl_iw_iscan_get_scan,      /* SIOCGIWSCAN */
+#endif
 #else  /* WIRELESS_EXT > 13 */
        (iw_handler) NULL,                      /* SIOCSIWSCAN */
        (iw_handler) NULL,                      /* SIOCGIWSCAN */
@@ -3095,9 +3121,11 @@ wl_iw_ioctl(
 
 #if WIRELESS_EXT > 13
        case SIOCGIWSCAN:
+#ifndef WL_ESCAN
        if (g_iscan)
                max_tokens = wrq->u.data.length;
        else
+#endif
                max_tokens = IW_SCAN_MAX_DATA;
                break;
 #endif /* WIRELESS_EXT > 13 */
@@ -3377,6 +3405,13 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
        }
 #endif /* WIRELESS_EXT > 17 */
 
+#ifdef WL_ESCAN
+       case WLC_E_ESCAN_RESULT:
+               WL_TRACE(("event WLC_E_ESCAN_RESULT\n"));
+               wl_escan_event(dev, e, data);
+               break;
+#else
+
        case WLC_E_SCAN_COMPLETE:
 #if WIRELESS_EXT > 14
                cmd = SIOCGIWSCAN;
@@ -3388,6 +3423,7 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
                        (g_iscan->iscan_state != ISCAN_STATE_IDLE))
                        up(&g_iscan->sysioc_sem);
                break;
+#endif
 
        default:
                /* Cannot translate event */
@@ -3395,11 +3431,13 @@ wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data)
        }
 
        if (cmd) {
+#ifndef WL_ESCAN
                if (cmd == SIOCGIWSCAN) {
                        if ((!g_iscan) || (g_iscan->sysioc_pid < 0)) {
                                wireless_send_event(dev, cmd, &wrqu, NULL);
                        };
                } else
+#endif
                        wireless_send_event(dev, cmd, &wrqu, extra);
        }
 
@@ -3504,6 +3542,7 @@ int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstat
                goto done;
 
        rssi = dtoh32(scb_val.val);
+       rssi = MIN(rssi, RSSI_MAXVAL);
        WL_TRACE(("wl_iw_get_wireless_stats rssi=%d ****** \n", rssi));
        if (rssi <= WL_IW_RSSI_NO_SIGNAL)
                wstats->qual.qual = 0;
@@ -3597,6 +3636,7 @@ done:
        return res;
 }
 
+#ifndef WL_ESCAN
 static void
 wl_iw_timerfunc(ulong data)
 {
@@ -3810,10 +3850,12 @@ _iscan_sysioc_thread(void *data)
        printf("%s: was terminated\n", __FUNCTION__);
        complete_and_exit(&iscan->sysioc_exited, 0);
 }
+#endif /* WL_ESCAN */
 
 int
 wl_iw_attach(struct net_device *dev, void * dhdp)
 {
+#ifndef WL_ESCAN
        iscan_info_t *iscan = NULL;
 
        printf("%s: Enter\n", __FUNCTION__);
@@ -3834,7 +3876,6 @@ wl_iw_attach(struct net_device *dev, void * dhdp)
        iscan->dev = dev;
        iscan->iscan_state = ISCAN_STATE_IDLE;
 
-
        /* Set up the timer */
        iscan->timer_ms    = 2000;
        init_timer(&iscan->timer);
@@ -3851,11 +3892,13 @@ wl_iw_attach(struct net_device *dev, void * dhdp)
 #endif
        if (iscan->sysioc_pid < 0)
                return -ENOMEM;
+#endif /* WL_ESCAN */
        return 0;
 }
 
 void wl_iw_detach(void)
 {
+#ifndef WL_ESCAN
        iscan_buf_t  *buf;
        iscan_info_t *iscan = g_iscan;
        if (!iscan)
@@ -3872,6 +3915,7 @@ void wl_iw_detach(void)
        }
        kfree(iscan);
        g_iscan = NULL;
+#endif
 }
 
 #endif /* USE_IW */
index 6b86bb13a32c72d131d269a9e65e25f12da80ee9..dc80b2af0f05f6797ac30a87b3272588bee05e5c 100644 (file)
@@ -130,6 +130,10 @@ extern void wl_iw_event(struct net_device *dev, wl_event_msg_t *e, void* data);
 extern int wl_iw_get_wireless_stats(struct net_device *dev, struct iw_statistics *wstats);
 int wl_iw_attach(struct net_device *dev, void * dhdp);
 int wl_iw_send_priv_event(struct net_device *dev, char *flag);
+#ifdef WL_ESCAN
+int wl_iw_handle_scanresults_ies(char **event_p, char *end,
+       struct iw_request_info *info, wl_bss_info_t *bi);
+#endif
 
 void wl_iw_detach(void);
 
index 247e0dfdeb3b7c8c7b160d2426e7d81dc7ba629d..c09e4512c1265a87e674a572e87a03932702ab1b 100644 (file)
@@ -355,6 +355,7 @@ int wldev_get_datarate(struct net_device *dev, int *datarate)
        return error;
 }
 
+#ifdef WL_CFG80211
 extern chanspec_t
 wl_chspec_driver_to_host(chanspec_t chanspec);
 #define WL_EXTRA_BUF_MAX 2048
@@ -406,6 +407,8 @@ int wldev_get_mode(
        }
        return error;
 }
+#endif
+
 int wldev_set_country(
        struct net_device *dev, char *country_code, bool notify, bool user_enforced, int revinfo)
 {
@@ -441,9 +444,9 @@ 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_get_country_from_config(dhd_get_pub(dev), &cspec);\r
-               if (error)\r
-                       dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);\r
+               error = dhd_conf_get_country_from_config(dhd_get_pub(dev), &cspec);
+               if (error)
+                       dhd_get_customized_country_code(dev, (char *)&cspec.country_abbrev, &cspec);
                error = wldev_iovar_setbuf(dev, "country", &cspec, sizeof(cspec),
                        smbuf, sizeof(smbuf), NULL);
                if (error < 0) {