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