diff options
author | sbrissen <sbrissen@hotmail.com> | 2013-04-24 13:09:33 -0400 |
---|---|---|
committer | sbrissen <sbrissen@hotmail.com> | 2013-04-25 10:50:50 -0400 |
commit | c421809918b7106b40a81134f9fb5103146fc715 (patch) | |
tree | 89b0147d51d2b2650c5ded666a08613ba0cab3c1 | |
parent | 43aaedbcde478c8e032771d62a1956133b29b1d4 (diff) | |
download | kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.zip kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.tar.gz kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.tar.bz2 |
update bcmdhd driver from GT-9505 Source
drivers pulled from http://review.cyanogenmod.org/#/c/36122/
Change-Id: Ide4aef99ee1d594f4222ae69aca0bdb7d563e80a
79 files changed, 9568 insertions, 3753 deletions
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig index 3d06eeb..da5c179 100644 --- a/drivers/net/wireless/bcmdhd/Kconfig +++ b/drivers/net/wireless/bcmdhd/Kconfig @@ -1,47 +1,47 @@ -config BCMDHD - tristate "Broadcom 43xx wireless cards support" - depends on MMC - default m - ---help--- - This module adds support for wireless adapters based on - Broadcom 4329/30 chipset. - - This driver uses the kernel's wireless extensions subsystem. - - If you choose to build a module, it'll be called dhd. Say M if - unsure. - config BCM4330 - bool "Broadcom 4330 wireless cards support" - depends on BCMDHD + tristate "Broadcom 4330 wireless cards support" + depends on WLAN ---help--- This module adds support for wireless adapters based on Broadcom 4330 chipset. config BCM4334 - bool "Broadcom 4334 wireless cards support" - depends on BCMDHD - default y + tristate "Broadcom 4334 wireless cards support" + depends on WLAN ---help--- This module adds support for wireless adapters based on Broadcom 4334 chipset. +config BCM4335 + tristate "Broadcom 4335 wireless cards support" + depends on WLAN + ---help--- + This module adds support for wireless adapters based on + Broadcom 4335 chipset. + config BCM43241 - bool "Broadcom 43241 wireless cards support" - depends on BCMDHD + tristate "Broadcom 43241 wireless cards support" + depends on WLAN ---help--- This module adds support for wireless adapters based on Broadcom 43241 chipset. +config BROADCOM_WIFI + bool "Broadcom WiFi Driver" + depends on (BCM4330 || BCM4334 || BCM43241) + default y + ---help--- + This is a configuration for broadcom WLAN driver. + config BCMDHD_FW_PATH - depends on BCMDHD + depends on WLAN string "Firmware path" default "/system/etc/firmware/fw_bcmdhd.bin" ---help--- Path to the firmware file. config BCMDHD_NVRAM_PATH - depends on BCMDHD + depends on WLAN string "NVRAM path" default "/system/etc/wifi/bcmdhd.cal" ---help--- @@ -71,13 +71,20 @@ config DHD_USE_SCHED_SCAN config BROADCOM_WIFI_RESERVED_MEM bool "BROADCOM Reserved memory for wifi device" - depends on (BCM4330 || BCM4334 || BCM43241) + depends on (BCM4330 || BCM4334 || BCM4335 || BCM43241) ---help--- This is a configuration for broadcom WLAN driver. +config BCM4335BT + bool "BROADCOM BTLOCK Enable" + depends on BCM4335 + default y + ---help--- + This is a configuration for bt lock enable. + config WLAN_REGION_CODE int "---Region codes for Broadcom WiFi Driver" - depends on (BCM4330 || BCM4334 || BCM43241) + depends on (BCM4330 || BCM4334 || BCM4335 || BCM43241) default 100 ---help--- This is a region code for Broadcom Wi-Fi featured functions. @@ -88,3 +95,4 @@ config WLAN_REGION_CODE - 202 : KOR KTT - 203 : KOR LGT - 300 : CHN OPEN + - 400 : JPN OPEN diff --git a/drivers/net/wireless/bcmdhd/Makefile b/drivers/net/wireless/bcmdhd/Makefile index e115d07..40bc790 100644 --- a/drivers/net/wireless/bcmdhd/Makefile +++ b/drivers/net/wireless/bcmdhd/Makefile @@ -3,7 +3,7 @@ # SDIO Basic feature ##################### -DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ +DHDCFLAGS += -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ -DBCMDONGLEHOST -DUNRELEASEDCHIP -DBCMDMA32 -DBCMFILEIMAGE \ -DDHDTHREAD -DBDC -DOOB_INTR_ONLY \ -DDHD_BCMEVENTS -DSHOW_EVENTS -DBCMDBG \ @@ -17,10 +17,14 @@ DHDCFLAGS = -Wall -Wstrict-prototypes -Dlinux -DLINUX -DBCMDRIVER \ ################# DHDCFLAGS += -DCUSTOMER_HW4 -#DHDCFLAGS += -DBLOCK_IPV6_PACKET -DPASS_IPV4_SUSPEND +DHDCFLAGS += -DDEBUGFS_CFG80211 +DHDCFLAGS += -DBLOCK_IPV6_PACKET -DPASS_IPV4_SUSPEND DHDCFLAGS += -DSUPPORT_DEEP_SLEEP DHDCFLAGS += -DSIMPLE_MAC_PRINT +# Print out kernel panic point of file and line info when assertion happened +DHDCFLAGS += -DBCMASSERT_LOG + # For p2p connection issue DHDCFLAGS += -DWL_CFG80211_GON_COLLISION DHDCFLAGS += -DWL_SCB_TIMEOUT=10 @@ -38,9 +42,7 @@ DHDCFLAGS += -DESCAN_RESULT_PATCH DHDCFLAGS += -DDUAL_ESCAN_RESULT_BUFFER DHDCFLAGS += -DROAM_ENABLE -DROAM_CHANNEL_CACHE -DROAM_API -DHDCFLAGS += -DDISABLE_FW_ROAM_SUSPEND -DHDCFLAGS += -DCUSTOM_ROAM_TRIGGER_SETTING=-65 -DHDCFLAGS += -DCUSTOM_ROAM_DELTA_SETTING=15 +DHDCFLAGS += -DENABLE_FW_ROAM_SUSPEND # For Static Buffer ifeq ($(CONFIG_BROADCOM_WIFI_RESERVED_MEM),y) @@ -62,11 +64,20 @@ DHDCFLAGS += -DSUPPORT_SOFTAP_SINGL_DISASSOC DHDCFLAGS += -DUSE_STAMAC_4SOFTAP # DPC priority -DHDCFLAGS += -DCUSTOM_DPC_PRIO_SETTING=98 +DHDCFLAGS += -DCUSTOM_DPC_PRIO_SETTING=49 # WiFi turn off delay DHDCFLAGS += -DWIFI_TURNOFF_DELAY=100 +# DTIM listen interval in suspend mode(0 means follow AP's DTIM period) +DHDCFLAGS += -DCUSTOM_SUSPEND_BCN_LI_DTIM=0 + +# Priority mismatch fix with kernel stack +DHDCFLAGS += -DPKTPRIO_OVERRIDE + +# Ioctl timeout 5000ms +DHDCFLAGS += -DIOCTL_RESP_TIMEOUT=5000 + # WiFi Kernel thread type DHDCFLAGS += -DUSE_KTHREAD_API @@ -81,21 +92,57 @@ DHDCFLAGS += -DWL_CFG80211_STA_EVENT # Chip dependent feature ######################### +ifneq ($(CONFIG_BCM4335),) + DHDCFLAGS += -DBCM4335_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION + DHDCFLAGS += -DDHD_USE_IDLECOUNT + DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=128 + DHDCFLAGS += -DUSE_CID_CHECK -DCONFIG_CONTROL_PM + DHDCFLAGS += -DPROP_TXSTATUS -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DVSDB + DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 -DCUSTOM_RXCHAIN=1 + DHDCFLAGS += -DENABLE_BCN_LI_BCN_WAKEUP + DHDCFLAGS += -DROAM_AP_ENV_DETECTION + DHDCFLAGS += -DBCMSDIOH_TXGLOM -DCUSTOM_TXGLOM=1 -DBCMSDIOH_TXGLOM_HIGHSPEED + DHDCFLAGS += -DDHDTCPACK_SUPPRESS +# DHDCFLAGS += -DDHD_SET_FW_HIGHSPEED + DHDCFLAGS += -DUSE_WL_TXBF + DHDCFLAGS += -DUSE_WL_FRAMEBURST + DHDCFLAGS += -DSDIO_CRC_ERROR_FIX + DHDCFLAGS += -DRXFRAME_THREAD + DHDCFLAGS += -DREPEAT_READFRAME + DHDCFLAGS += -DCUSTOM_DPC_CPUCORE=0 + DHDCFLAGS += -DCUSTOM_AMPDU_BA_WSIZE=40 + DHDCFLAGS += -DWL11U + DHDCFLAGS += -DBCMCCX + DHDCFLAGS += -DWES_SUPPORT + DHDCFLAGS += -DOKC_SUPPORT + DHDCFLAGS += -DWLTDLS +# DHDCFLAGS += -DTPUT_DEBUG + DHDCFLAGS += -DWLFBT + DHDCFLAGS += -DCUSTOM_MAX_TXGLOM_SIZE=32 +# For BT LOCK +ifeq ($(CONFIG_BCM4335BT),y) + DHDCFLAGS += -DENABLE_4335BT_WAR +endif + # Remove define for BCM4335 + DHDCFLAGS :=$(filter-out -DWL_CFG80211_GON_COLLISION,$(DHDCFLAGS)) +endif + ifneq ($(CONFIG_BCM4334),) DHDCFLAGS += -DBCM4334_CHIP -DHW_OOB -DSUPPORT_MULTIPLE_REVISION DHDCFLAGS += -DUSE_CID_CHECK -DCONFIG_CONTROL_PM - DHDCFLAGS += -DPROP_TXSTATUS - DHDCFLAGS += -DVSDB -DHT40_GO - DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST -DSDIO_CRC_ERROR_FIX - DHDCFLAGS += -DCUSTOM_SDIO_F2_BLKSIZE=128 + DHDCFLAGS += -DPROP_TXSTATUS -DPROP_TXSTATUS_VSDB + DHDCFLAGS += -DVSDB + DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST DHDCFLAGS += -DDHD_USE_IDLECOUNT DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD - DHDCFLAGS += -DVSDB_DYNAMIC_F2_BLKSIZE -DSDIO_F2_BLKSIZE=512 -DVSDB_F2_BLKSIZE=64 + DHDCFLAGS += -DUSE_DYNAMIC_F2_BLKSIZE -DDYNAMIC_F2_BLKSIZE_FOR_NONLEGACY=64 DHDCFLAGS += -DCUSTOM_GLOM_SETTING=5 -DENABLE_BCN_LI_BCN_WAKEUP -# DHDCFLAGS += -DUSE_WEP_AUTH_SHARED_OPEN DHDCFLAGS += -DROAM_AP_ENV_DETECTION DHDCFLAGS += -DWES_SUPPORT - DHDCFLAGS += -DPASS_ARP_PACKET + DHDCFLAGS :=$(filter-out -DWL_CFG80211_GON_COLLISION,$(DHDCFLAGS)) endif ifneq ($(CONFIG_BCM4330),) @@ -104,45 +151,49 @@ ifneq ($(CONFIG_BCM4330),) DHDCFLAGS += -DCONFIG_CONTROL_PM DHDCFLAGS += -DCUSTOM_GLOM_SETTING=0 DHDCFLAGS += -DPASS_ARP_PACKET + DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST endif ifneq ($(CONFIG_BCM43241),) DHDCFLAGS += -DBCM43241_CHIP -DHW_OOB - DHDCFLAGS += -DMCAST_LIST_ACCUMULATION - DHDCFLAGS += -DMIMO_ANT_SETTING -DCONFIG_CONTROL_PM - DHDCFLAGS += -DAMPDU_HOSTREORDER -DDHD_USE_IDLECOUNT - DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 + DHDCFLAGS += -DCONFIG_CONTROL_PM DHDCFLAGS += -DPROP_TXSTATUS - DHDCFLAGS += -DVSDB -DHT40_GO + DHDCFLAGS += -DVSDB DHDCFLAGS += -DWL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST + DHDCFLAGS += -DDHD_USE_IDLECOUNT DHDCFLAGS += -DSUPPORT_AMPDU_MPDU_CMD + DHDCFLAGS += -DMIMO_ANT_SETTING -DAMPDU_HOSTREORDER + DHDCFLAGS += -DCUSTOM_GLOM_SETTING=1 -DCUSTOM_SDIO_F2_BLKSIZE=128 DHDCFLAGS += -DROAM_AP_ENV_DETECTION + DHDCFLAGS += -DSDIO_CRC_ERROR_FIX + DHDCFLAGS :=$(filter-out -DWL_CFG80211_GON_COLLISION,$(DHDCFLAGS)) ifeq ($(CONFIG_BCM43241),m) DHDCFLAGS += -fno-pic endif endif + ############################# # Platform dependent feature ############################# ifeq ($(CONFIG_SPI_SC8810),y) -DHDCFLAGS += -DREAD_MACADDR -DBCMSPI -DBCMSPI_ANDROID -DSPI_PIO_32BIT_RW -DSPI_PIO_RW_BIGENDIAN -DDISABLE_11N + DHDCFLAGS += -DREAD_MACADDR -DBCMSPI -DBCMSPI_ANDROID -DSPI_PIO_32BIT_RW -DSPI_PIO_RW_BIGENDIAN -DDISABLE_11N -#Remove defines for SDMMC -DHDCFLAGS :=$(filter-out -DOOB_INTR_ONLY,$(DHDCFLAGS)) -DHDCFLAGS :=$(filter-out -DBCMLXSDMMC,$(DHDCFLAGS)) + #Remove defines for SDMMC + DHDCFLAGS :=$(filter-out -DOOB_INTR_ONLY,$(DHDCFLAGS)) + DHDCFLAGS :=$(filter-out -DBCMLXSDMMC,$(DHDCFLAGS)) -#Remove defines for JB -DHDCFLAGS :=$(filter-out -DWL_ENABLE_P2P_IF,$(DHDCFLAGS)) -DHDCFLAGS :=$(filter-out -DMULTIPLE_SUPPLICANT,$(DHDCFLAGS)) -DHDCFLAGS :=$(filter-out -DWL_CFG80211_STA_EVENT,$(DHDCFLAGS)) + #Remove defines for JB + DHDCFLAGS :=$(filter-out -DWL_ENABLE_P2P_IF,$(DHDCFLAGS)) + DHDCFLAGS :=$(filter-out -DMULTIPLE_SUPPLICANT,$(DHDCFLAGS)) + DHDCFLAGS :=$(filter-out -DWL_CFG80211_STA_EVENT,$(DHDCFLAGS)) endif #For INITIAL 2G scan features -ifneq ($(CONFIG_TARGET_LOCALE_KOR),y) - DHDCFLAGS += -DUSE_INITIAL_2G_SCAN -endif +#ifneq ($(CONFIG_TARGET_LOCALE_KOR),y) +# DHDCFLAGS += -DUSE_INITIAL_2G_SCAN +#endif # For SLP feature ifeq ($(CONFIG_SLP),y) @@ -157,35 +208,13 @@ ifeq ($(GGSM_WIFI_5GHz_CHANNELS),true) DHDCFLAGS += -DCUSTOMER_SET_COUNTRY endif -############################################################## -# dhd_sec_feature.h - -REGION_CODE := 100 - -ifeq ($(CONFIG_TARGET_LOCALE_KOR),y) -REGION_CODE=200 -endif - -ifeq ($(CONFIG_MACH_U1_KOR_KT), y) -REGION_CODE=202 -endif - ifeq ($(CONFIG_TARGET_LOCALE_CHN),y) -REGION_CODE=300 + DHDCFLAGS += -DBCMWAPI_WPI -DBCMWAPI_WAI endif -ifeq ($(SEC_MODEL_NAME),U1) -ifeq ($(X_BUILD_LOCALE),EUR_ORG) -REGION_CODE=101 -endif -endif - -ifdef CONFIG_WLAN_REGION_CODE -REGION_CODE=$(CONFIG_WLAN_REGION_CODE) -endif - -DHDCFLAGS += -DWLAN_REGION_CODE=$(REGION_CODE) - +############################################################## +# dhd_sec_feature.h +DHDCFLAGS += -include "dhd_sec_feature.h" ############################################################## ######### @@ -212,6 +241,17 @@ DHDOFILES :=$(filter-out bcmsdh_sdmmc.o,$(DHDOFILES)) DHDOFILES :=$(filter-out bcmsdh_sdmmc_linux.o,$(DHDOFILES)) endif -obj-$(CONFIG_BCMDHD) += dhd.o -dhd-objs += $(DHDOFILES) +dhd-y := $(DHDOFILES) +obj-m += dhd.o + +all: + @echo "$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules" + @$(MAKE) --no-print-directory -C $(KDIR) SUBDIRS=$(CURDIR) modules + +clean: + rm -rf *.o *.ko *.mod.c *~ .*.cmd *.o.cmd .*.o.cmd \ + Module.symvers modules.order .tmp_versions modules.builtin +install: + @$(MAKE) --no-print-directory -C $(KDIR) \ + SUBDIRS=$(CURDIR) modules_install diff --git a/drivers/net/wireless/bcmdhd/aiutils.c b/drivers/net/wireless/bcmdhd/aiutils.c index 3ca1725..ea94da5 100644 --- a/drivers/net/wireless/bcmdhd/aiutils.c +++ b/drivers/net/wireless/bcmdhd/aiutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: aiutils.c 347614 2012-07-27 10:24:51Z $ + * $Id: aiutils.c 363711 2012-10-19 01:36:13Z $ */ #include <bcm_cfg.h> #include <typedefs.h> @@ -38,6 +38,7 @@ #define BCM47162_DMP() (0) #define BCM5357_DMP() (0) +#define BCM4707_DMP() (0) #define remap_coreid(sih, coreid) (coreid) #define remap_corerev(sih, corerev) (corerev) @@ -207,7 +208,7 @@ ai_scan(si_t *sih, void *regs, uint devid) sii->oob_router = addrl; } } - if (cid != GMAC_COMMON_4706_CORE_ID) + if (cid != GMAC_COMMON_4706_CORE_ID && cid != NS_CCB_CORE_ID) continue; } @@ -247,10 +248,10 @@ ai_scan(si_t *sih, void *regs, uint devid) "0x%x\n", addrh, sizeh, sizel)); SI_ERROR(("First Slave ASD for" "core 0x%04x malformed " - "(0x%08x)\n", cid, asd)); - goto error; + "(0x%08x)\n", cid, asd)); + goto error; + } } - } } while (1); } sii->coresba[idx] = addrl; @@ -358,7 +359,7 @@ ai_setcoreidx(si_t *sih, uint coreidx) ASSERT(GOODREGS(sii->regs[coreidx])); } sii->curmap = regs = sii->regs[coreidx]; - if (!sii->wrappers[coreidx]) { + if (!sii->wrappers[coreidx] && (wrap != 0)) { sii->wrappers[coreidx] = REG_MAP(wrap, SI_CORE_SIZE); ASSERT(GOODREGS(sii->wrappers[coreidx])); } @@ -534,6 +535,11 @@ ai_flag(si_t *sih) SI_ERROR(("%s: Attempting to read USB20H DMP registers on 5357b0\n", __FUNCTION__)); return sii->curidx; } + if (BCM4707_DMP()) { + SI_ERROR(("%s: Attempting to read CHIPCOMMONB DMP registers on 4707\n", + __FUNCTION__)); + return sii->curidx; + } ai = sii->curwrap; return (R_REG(sii->osh, &ai->oobselouta30) & 0x1f); @@ -707,15 +713,15 @@ ai_core_disable(si_t *sih, uint32 bits) } - W_REG(sii->osh, &ai->ioctrl, bits); - dummy = R_REG(sii->osh, &ai->ioctrl); - BCM_REFERENCE(dummy); - OSL_DELAY(10); - W_REG(sii->osh, &ai->resetctrl, AIRC_RESET); dummy = R_REG(sii->osh, &ai->resetctrl); BCM_REFERENCE(dummy); OSL_DELAY(1); + + W_REG(sii->osh, &ai->ioctrl, bits); + dummy = R_REG(sii->osh, &ai->ioctrl); + BCM_REFERENCE(dummy); + OSL_DELAY(10); } @@ -768,6 +774,11 @@ ai_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) __FUNCTION__)); return; } + if (BCM4707_DMP()) { + SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", + __FUNCTION__)); + return; + } ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; @@ -798,6 +809,11 @@ ai_core_cflags(si_t *sih, uint32 mask, uint32 val) __FUNCTION__)); return 0; } + if (BCM4707_DMP()) { + SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", + __FUNCTION__)); + return 0; + } ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; @@ -830,6 +846,11 @@ ai_core_sflags(si_t *sih, uint32 mask, uint32 val) __FUNCTION__)); return 0; } + if (BCM4707_DMP()) { + SI_ERROR(("%s: Accessing CHIPCOMMONB DMP register (ioctrl) on 4707\n", + __FUNCTION__)); + return 0; + } ASSERT(GOODREGS(sii->curwrap)); ai = sii->curwrap; diff --git a/drivers/net/wireless/bcmdhd/bcmevent.c b/drivers/net/wireless/bcmdhd/bcmevent.c index e41c738..e7ed416 100644 --- a/drivers/net/wireless/bcmdhd/bcmevent.c +++ b/drivers/net/wireless/bcmdhd/bcmevent.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmevent.c 327460 2012-04-13 18:38:41Z $ + * $Id: bcmevent.c 374256 2012-12-12 08:34:34Z $ */ #include <typedefs.h> @@ -29,7 +29,7 @@ #include <proto/bcmeth.h> #include <proto/bcmevent.h> -#if WLC_E_LAST != 94 +#if WLC_E_LAST != 108 #error "You need to add an entry to bcmevent_names[] for the new event" #endif @@ -109,6 +109,7 @@ const bcmevent_name_t bcmevent_names[] = { { WLC_E_REASSOC_IND_NDIS, "REASSOC_IND_NDIS"}, { WLC_E_ACTION_FRAME_RX_NDIS, "WLC_E_ACTION_FRAME_RX_NDIS" }, { WLC_E_AUTH_REQ, "WLC_E_AUTH_REQ" }, + { WLC_E_IBSS_COALESCE, "IBSS COALESCE" }, #endif #ifdef BCMWAPI_WAI { WLC_E_WAI_STA_EVENT, "WAI_STA_EVENT" }, @@ -143,6 +144,13 @@ const bcmevent_name_t bcmevent_names[] = { #ifdef WLTDLS { WLC_E_TDLS_PEER_EVENT, "TDLS_PEER_EVENT" }, #endif /* WLTDLS */ + { WLC_E_NATIVE, "NATIVE" }, +#ifdef WLPKTDLYSTAT + { WLC_E_PKTDELAY_IND, "PKTDELAY_IND" }, +#endif /* WLPKTDLYSTAT */ + { WLC_E_SERVICE_FOUND, "SERVICE_FOUND" }, + { WLC_E_P2PO_ADD_DEVICE, "P2PO_DEV_FOUND" }, + { WLC_E_P2PO_DEL_DEVICE, "P2PO_DEV_FOUND" } }; const int bcmevent_names_size = ARRAYSIZE(bcmevent_names); diff --git a/drivers/net/wireless/bcmdhd/bcmsdh.c b/drivers/net/wireless/bcmdhd/bcmsdh.c index 2f7c451..b65dbdc 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.c 347614 2012-07-27 10:24:51Z $ + * $Id: bcmsdh.c 369547 2012-11-19 08:57:31Z $ */ /** @@ -45,7 +45,9 @@ #include <sdio.h> /* SDIO Device and Protocol Specs */ +#ifdef CUSTOMER_HW4 #include <dhd_sec_feature.h> +#endif /* CUSTOMER_HW4 */ #define SDIOH_API_ACCESS_RETRY_LIMIT 2 const uint bcmsdh_msglevel = BCMSDH_ERROR_VAL; @@ -764,10 +766,10 @@ bcmsdh_gpioout(void *sdh, uint32 gpio, bool enab) #ifdef BCMSDIOH_TXGLOM void -bcmsdh_glom_post(void *sdh, uint8 *frame, uint len) +bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len) { bcmsdh_info_t *bcmsdh = (bcmsdh_info_t *)sdh; - sdioh_glom_post(bcmsdh->sdioh, frame, len); + sdioh_glom_post(bcmsdh->sdioh, frame, pkt, len); } void diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c index cd62e4b..fe19e15 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_linux.c 347638 2012-07-27 11:39:03Z $ + * $Id: bcmsdh_linux.c 384888 2013-02-13 13:25:17Z $ */ /** @@ -49,11 +49,6 @@ extern void dhdsdio_isr(void * args); #include <dhd.h> #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ -#if defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) -/* SLP_wakelock_alternative_code */ -struct device *pm_dev; -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ - /** * SDIO Host Controller info */ @@ -80,6 +75,8 @@ struct bcmsdh_hc { }; static bcmsdh_hc_t *sdhcinfo = NULL; +struct device *pm_dev; + /* driver info, initialized when bcmsdh_register is called */ static bcmsdh_driver_t drvinfo = {NULL, NULL}; @@ -157,7 +154,7 @@ static int bcmsdh_probe(struct device *dev) { osl_t *osh = NULL; - bcmsdh_hc_t *sdhc = NULL; + bcmsdh_hc_t *sdhc = NULL, *sdhc_org = sdhcinfo; ulong regs = 0; bcmsdh_info_t *sdh = NULL; #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) && !defined(BCMSPI_ANDROID) @@ -167,15 +164,12 @@ int bcmsdh_probe(struct device *dev) int irq = 0; uint32 vendevid; unsigned long irq_flags = 0; -#if defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) - int ret = 0; -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ #if !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) && !defined(BCMSPI_ANDROID) pdev = to_platform_device(dev); r = platform_get_resource(pdev, IORESOURCE_MEM, 0); irq = platform_get_irq(pdev, 0); - if (!r || irq == NO_IRQ) + if (!r || irq < 0) return -ENXIO; #endif /* !defined(BCMLXSDMMC) && defined(BCMPLATFORM_BUS) && !defined(BCMSPI_ANDROID) */ @@ -191,7 +185,7 @@ int bcmsdh_probe(struct device *dev) irq = dhd_customer_oob_irq_map(&irq_flags); if (irq < 0) { SDLX_MSG(("%s: Host irq is not defined\n", __FUNCTION__)); - return 1; + goto err; } #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ /* allocate SDIO Host Controller state info */ @@ -236,12 +230,10 @@ int bcmsdh_probe(struct device *dev) sdhc->next = sdhcinfo; sdhcinfo = sdhc; -#if defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) - /* SLP_wakelock_alternative_code */ - pm_dev = sdhc->dev; - ret = device_init_wakeup(pm_dev, 1); - printf("%s : device_init_wakeup(pm_dev) enable, ret = %d\n", __func__, ret); -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ +#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) + if (!device_init_wakeup(dev, 1)) + pm_dev = dev; +#endif /* !CONFIG_HAS_WAKELOCK */ /* Read the vendor/device ID from the CIS */ vendevid = bcmsdh_query_device(sdh); @@ -261,6 +253,7 @@ err: if (sdhc->sdh) bcmsdh_detach(sdhc->osh, sdhc->sdh); MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); + sdhcinfo = sdhc_org; } if (osh) osl_detach(osh); @@ -274,23 +267,20 @@ int bcmsdh_remove(struct device *dev) { bcmsdh_hc_t *sdhc, *prev; osl_t *osh; - - sdhc = sdhcinfo; -#if defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) - /* SLP_wakelock_alternative_code */ - device_init_wakeup(pm_dev, 0); - printf("%s : device_init_wakeup(pm_dev) disable\n", __func__); -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ - drvinfo.detach(sdhc->ch); - bcmsdh_detach(sdhc->osh, sdhc->sdh); + int sdhcinfo_null = false; /* find the SDIO Host Controller state for this pdev and take it out from the list */ for (sdhc = sdhcinfo, prev = NULL; sdhc; sdhc = sdhc->next) { if (sdhc->dev == (void *)dev) { if (prev) prev->next = sdhc->next; - else - sdhcinfo = NULL; + else { + if (sdhc->next != NULL) { + SDLX_MSG(("%s: more SDHC exist, should be care about it\n", + __FUNCTION__)); + } + sdhcinfo_null = true; + } break; } prev = sdhc; @@ -300,6 +290,20 @@ int bcmsdh_remove(struct device *dev) return 0; } + /* detach ch & sdhc if dev is valid */ + drvinfo.detach(sdhc->ch); + bcmsdh_detach(sdhc->osh, sdhc->sdh); + +#if !defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) + if (pm_dev) { + device_init_wakeup(pm_dev, 0); + pm_dev = NULL; + } +#endif /* !CONFIG_HAS_WAKELOCK */ + + if (sdhcinfo_null == true) + sdhcinfo = NULL; + /* release SDIO Host Controller info */ osh = sdhc->osh; MFREE(osh, sdhc, sizeof(bcmsdh_hc_t)); @@ -424,6 +428,10 @@ bcmsdh_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) /* match this pci device with what we support */ /* we can't solely rely on this to believe it is our SDIO Host Controller! */ if (!bcmsdh_chipmatch(pdev->vendor, pdev->device)) { + if (pdev->vendor == VENDOR_BROADCOM) { + SDLX_MSG(("%s: Unknown Broadcom device (vendor: %#x, device: %#x).\n", + __FUNCTION__, pdev->vendor, pdev->device)); + } return -ENODEV; } @@ -737,6 +745,10 @@ module_param(sd_f2_blocksize, int, 0); #ifdef BCMSDIOH_STD extern int sd_uhsimode; module_param(sd_uhsimode, int, 0); +extern uint sd_tuning_period; +module_param(sd_tuning_period, uint, 0); +extern int sd_delay_value; +module_param(sd_delay_value, uint, 0); #endif #ifdef BCMSDIOH_TXGLOM diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c index 8137701..8af2ca6 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.c 347640 2012-07-27 11:53:21Z $ + * $Id: bcmsdh_sdmmc.c 383350 2013-02-06 12:59:26Z $ */ #include <typedefs.h> @@ -76,6 +76,18 @@ uint sd_clock = 1; /* Default to SD Clock turned ON */ uint sd_hiok = FALSE; /* Don't use hi-speed mode by default */ uint sd_msglevel = 0x01; uint sd_use_dma = TRUE; + +#ifdef BCMSDIOH_TXGLOM +#ifndef CUSTOM_TXGLOM +#define CUSTOM_TXGLOM 0 +#endif +uint sd_txglom = CUSTOM_TXGLOM; +#endif /* BCMSDIOH_TXGLOM */ + +#ifndef CUSTOM_RXCHAIN +#define CUSTOM_RXCHAIN 0 +#endif + DHD_PM_RESUME_WAIT_INIT(sdioh_request_byte_wait); DHD_PM_RESUME_WAIT_INIT(sdioh_request_word_wait); DHD_PM_RESUME_WAIT_INIT(sdioh_request_packet_wait); @@ -154,7 +166,7 @@ sdioh_attach(osl_t *osh, void *bar0, uint irq) sd->sd_blockmode = TRUE; sd->use_client_ints = TRUE; sd->client_block_size[0] = 64; - sd->use_rxchain = FALSE; + sd->use_rxchain = CUSTOM_RXCHAIN; gInstance->sd = sd; @@ -250,9 +262,9 @@ sdioh_enable_func_intr(void) return SDIOH_API_RC_FAIL; } - /* Enable F1 and F2 interrupts, set master enable */ - reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN | INTR_CTL_MASTER_EN); - + /* Enable F1 and F2 interrupts, clear master enable */ + reg &= ~INTR_CTL_MASTER_EN; + reg |= (INTR_CTL_FUNC1_EN | INTR_CTL_FUNC2_EN); sdio_writeb(gInstance->func[0], reg, SDIOD_CCCR_INTEN, &err); sdio_release_host(gInstance->func[0]); @@ -525,7 +537,7 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, /* Now set it */ si->client_block_size[func] = blksize; -#if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) if (gInstance == NULL || gInstance->func[func] == NULL) { sd_err(("%s: SDIO Device not present\n", __FUNCTION__)); bcmerror = BCME_NORESOURCE; @@ -533,12 +545,11 @@ sdioh_iovar_op(sdioh_info_t *si, const char *name, } sdio_claim_host(gInstance->func[func]); bcmerror = sdio_set_block_size(gInstance->func[func], blksize); - if (bcmerror) { - sd_err(("%s: Failed to set F%d blocksize to %d\n", __FUNCTION__, func, - blksize)); - } + if (bcmerror) + sd_err(("%s: Failed to set F%d blocksize to %d\n", + __FUNCTION__, func, blksize)); sdio_release_host(gInstance->func[func]); -#endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ break; } @@ -793,10 +804,11 @@ sdioh_cis_read(sdioh_info_t *sd, uint func, uint8 *cisd, uint32 length) extern SDIOH_API_RC sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *byte) { - int err_ret; + int err_ret = 0; #if defined(MMC_SDIO_ABORT) int sdio_abort_retry = MMC_SDIO_ABORT_RETRY_LIMIT; #endif + sd_info(("%s: rw=%d, func=%d, addr=0x%05x\n", __FUNCTION__, rw, func, regaddr)); DHD_PM_RESUME_WAIT(sdioh_request_byte_wait); @@ -830,14 +842,18 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by #if defined(MMC_SDIO_ABORT) /* to allow abort command through F1 */ else if (regaddr == SDIOD_CCCR_IOABORT) { + /* Because of SDIO3.0 host issue on Manta, + * sometimes the abort fails. + * Retrying again will fix this issue. + */ while (sdio_abort_retry--) { if (gInstance->func[func]) { sdio_claim_host(gInstance->func[func]); /* - * this sdio_f0_writeb() can be replaced with - * another api depending upon MMC driver change. - * As of this time, this is temporaray one - */ + * this sdio_f0_writeb() can be replaced with + * another api depending upon MMC driver change. + * As of this time, this is temporaray one + */ sdio_writeb(gInstance->func[func], *byte, regaddr, &err_ret); sdio_release_host(gInstance->func[func]); @@ -880,8 +896,9 @@ sdioh_request_byte(sdioh_info_t *sd, uint rw, uint func, uint regaddr, uint8 *by } if (err_ret) { - sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", - rw ? "Write" : "Read", func, regaddr, *byte, err_ret)); + if (regaddr != 0x1001F && err_ret != -110) + sd_err(("bcmsdh_sdmmc: Failed to %s byte F%d:@0x%05x=%02x, Err: %d\n", + rw ? "Write" : "Read", func, regaddr, *byte, err_ret)); } return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); @@ -906,6 +923,7 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add DHD_PM_RESUME_WAIT(sdioh_request_word_wait); DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); + /* Claim host controller */ sdio_claim_host(gInstance->func[func]); @@ -937,10 +955,10 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add if (gInstance->func[0]) { sdio_claim_host(gInstance->func[0]); /* - * this sdio_f0_writeb() can be replaced with another api - * depending upon MMC driver change. - * As of this time, this is temporaray one - */ + * this sdio_f0_writeb() can be replaced with another api + * depending upon MMC driver change. + * As of this time, this is temporaray one + */ sdio_writeb(gInstance->func[0], func, SDIOD_CCCR_IOABORT, &err_ret); sdio_release_host(gInstance->func[0]); @@ -951,14 +969,83 @@ sdioh_request_word(sdioh_info_t *sd, uint cmd_type, uint rw, uint func, uint add if (err_ret) #endif /* MMC_SDIO_ABORT */ { - sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x\n", - rw ? "Write" : "Read", err_ret)); + sd_err(("bcmsdh_sdmmc: Failed to %s word, Err: 0x%08x", + rw ? "Write" : "Read", err_ret)); } } return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); } +#ifdef BCMSDIOH_TXGLOM +void +sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, void *pkt, uint len) +{ + void *phead = sd->glom_info.glom_pkt_head; + void *ptail = sd->glom_info.glom_pkt_tail; + + BCM_REFERENCE(frame); + + ASSERT(!PKTLINK(pkt)); + if (!phead) { + ASSERT(!phead); + sd->glom_info.glom_pkt_head = sd->glom_info.glom_pkt_tail = pkt; + } + else { + ASSERT(ptail); + PKTSETNEXT(sd->osh, ptail, pkt); + sd->glom_info.glom_pkt_tail = pkt; + } + sd->glom_info.count++; +} + +void +sdioh_glom_clear(sdioh_info_t *sd) +{ + void *pnow, *pnext; + uint8 i = 0; + + pnext = sd->glom_info.glom_pkt_head; + + if (!pnext) { + sd_err(("sdioh_glom_clear: no first packet to clear!\n")); + return; + } + + while (pnext) { + pnow = pnext; + pnext = PKTNEXT(sd->osh, pnow); + PKTSETNEXT(sd->osh, pnow, NULL); + sd->glom_info.count--; + i++; + } + + sd->glom_info.glom_pkt_head = NULL; + sd->glom_info.glom_pkt_tail = NULL; + if (sd->glom_info.count != 0) { + sd_err(("sdioh_glom_clear: glom count mismatch!\n")); + sd->glom_info.count = 0; + } +} + +uint +sdioh_set_mode(sdioh_info_t *sd, uint mode) +{ + if (mode == SDPCM_TXGLOM_CPY) + sd->txglom_mode = mode; + else if (mode == SDPCM_TXGLOM_MDESC) + sd->txglom_mode = mode; + + return (sd->txglom_mode); +} + +bool +sdioh_glom_enabled(void) +{ + return sd_txglom; +} +#endif /* BCMSDIOH_TXGLOM */ + static SDIOH_API_RC sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, uint addr, void *pkt) @@ -966,12 +1053,20 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, bool fifo = (fix_inc == SDIOH_DATA_FIX); uint32 SGCount = 0; int err_ret = 0; - void *pnext, *pprev; + void *pnext; uint ttl_len, dma_len, lft_len, xfred_len, pkt_len; uint blk_num; + int blk_size; struct mmc_request mmc_req; struct mmc_command mmc_cmd; struct mmc_data mmc_dat; +#ifdef BCMSDIOH_TXGLOM + uint8 *localbuf = NULL; + uint local_plen = 0; + bool need_txglom = write && sdioh_glom_enabled() && + (pkt == sd->glom_info.glom_pkt_tail) && + (sd->glom_info.glom_pkt_head != sd->glom_info.glom_pkt_tail); +#endif /* BCMSDIOH_TXGLOM */ sd_trace(("%s: Enter\n", __FUNCTION__)); @@ -980,17 +1075,29 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, DHD_PM_RESUME_RETURN_ERROR(SDIOH_API_RC_FAIL); ttl_len = xfred_len = 0; +#ifdef BCMSDIOH_TXGLOM + if (need_txglom) { + pkt = sd->glom_info.glom_pkt_head; + } +#endif /* BCMSDIOH_TXGLOM */ + /* at least 4 bytes alignment of skb buff is guaranteed */ for (pnext = pkt; pnext; pnext = PKTNEXT(sd->osh, pnext)) ttl_len += PKTLEN(sd->osh, pnext); - if (!sd->use_rxchain || ttl_len <= sd->client_block_size[func]) { + blk_size = sd->client_block_size[func]; + if (((!write && sd->use_rxchain) || +#ifdef BCMSDIOH_TXGLOM + (need_txglom && sd->txglom_mode == SDPCM_TXGLOM_MDESC) || +#endif + 0) && (ttl_len > blk_size)) { + blk_num = ttl_len / blk_size; + dma_len = blk_num * blk_size; + } else { blk_num = 0; dma_len = 0; - } else { - blk_num = ttl_len / sd->client_block_size[func]; - dma_len = blk_num * sd->client_block_size[func]; } + lft_len = ttl_len - dma_len; sd_trace(("%s: %s %dB to func%d:%08x, %d blks with DMA, %dB leftover\n", @@ -1003,7 +1110,6 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, memset(&mmc_dat, 0, sizeof(struct mmc_data)); /* Set up DMA descriptors */ - pprev = pkt; for (pnext = pkt; pnext && dma_len; pnext = PKTNEXT(sd->osh, pnext)) { @@ -1030,7 +1136,7 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, mmc_dat.sg = sd->sg_list; mmc_dat.sg_len = SGCount; - mmc_dat.blksz = sd->client_block_size[func]; + mmc_dat.blksz = blk_size; mmc_dat.blocks = blk_num; mmc_dat.flags = write ? MMC_DATA_WRITE : MMC_DATA_READ; @@ -1057,12 +1163,8 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, __FUNCTION__, write ? "write" : "read", err_ret)); - sd_err(("%s:Disabling rxchain and fire it with PIO\n", - __FUNCTION__)); - sd->use_rxchain = FALSE; - pkt = pprev; - lft_len = ttl_len; - } else if (!fifo) { + } + if (!fifo) { addr = addr + ttl_len - lft_len - dma_len; } } @@ -1079,20 +1181,40 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, pkt_len -= xfred_len; xfred_len = 0; } +#ifdef BCMSDIOH_TXGLOM + if (need_txglom) { + if (!localbuf) { + localbuf = (uint8 *)MALLOC(sd->osh, lft_len); + if (localbuf == NULL) { + sd_err(("%s: %s TXGLOM: localbuf malloc FAILED\n", + __FUNCTION__, (write) ? "TX" : "RX")); + goto txglomfail; + } + } + bcopy(buf, (localbuf + local_plen), pkt_len); + local_plen += pkt_len; - /* Align Patch - * read or small packet(ex:BDC header) skip 32 byte align - * otherwise, padding DHD_SDALIGN for performance - */ - if (write == 0 || pkt_len < 32) + if (PKTNEXT(sd->osh, pnext)) { + continue; + } + + buf = localbuf; + pkt_len = local_plen; + } + +txglomfail: +#endif /* BCMSDIOH_TXGLOM */ + + /* Align Patch */ + if (!write || pkt_len < 32) pkt_len = (pkt_len + 3) & 0xFFFFFFFC; - else if (pkt_len % DHD_SDALIGN) - pkt_len += DHD_SDALIGN - (pkt_len % DHD_SDALIGN); + else if (pkt_len % blk_size) + pkt_len += blk_size - (pkt_len % blk_size); -#if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) if (write && pkt_len > 64 && (pkt_len % 64) == 32) pkt_len += 32; -#endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ #ifdef CONFIG_MMC_MSM7X00A if ((pkt_len % 64) == 32) { sd_trace(("%s: Rounding up TX packet +=32\n", __FUNCTION__)); @@ -1134,6 +1256,10 @@ sdioh_request_packet(sdioh_info_t *sd, uint fix_inc, uint write, uint func, } sdio_release_host(gInstance->func[func]); } +#ifdef BCMSDIOH_TXGLOM + if (localbuf) + MFREE(sd->osh, localbuf, lft_len); +#endif /* BCMSDIOH_TXGLOM */ sd_trace(("%s: Exit\n", __FUNCTION__)); return ((err_ret == 0) ? SDIOH_API_RC_SUCCESS : SDIOH_API_RC_FAIL); @@ -1192,7 +1318,7 @@ sdioh_request_buffer(sdioh_info_t *sd, uint pio_dma, uint fix_inc, uint write, u #else PKTFREE(sd->osh, mypkt, write ? TRUE : FALSE); #endif /* CONFIG_DHD_USE_STATIC_BUF */ - } else if (((uint32)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { + } else if (((ulong)(PKTDATA(sd->osh, pkt)) & DMA_ALIGN_MASK) != 0) { /* Case 2: We have a packet, but it is unaligned. */ /* In this case, we cannot have a chain. */ @@ -1380,7 +1506,10 @@ sdioh_start(sdioh_info_t *si, int stage) int ret; sdioh_info_t *sd = gInstance->sd; - if (!sd) return (0); + if (!sd) { + sd_err(("%s Failed, sd is NULL\n", __FUNCTION__)); + return (0); + } /* Need to do this stages as we can't enable the interrupt till downloading of the firmware is complete, other wise polling diff --git a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c index ed37e8c..609f8d0 100644 --- a/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc_linux.c 355594 2012-09-07 10:22:02Z $ + * $Id: bcmsdh_sdmmc_linux.c 381717 2013-01-29 07:10:21Z $ */ #include <typedefs.h> @@ -136,6 +136,8 @@ static int bcmsdh_sdmmc_probe(struct sdio_func *func, #endif sd_trace(("F2 found, calling bcmsdh_probe...\n")); ret = bcmsdh_probe(&func->dev); + if (ret < 0 && gInstance) + gInstance->func[2] = NULL; } } else { ret = -ENODEV; @@ -153,10 +155,12 @@ static void bcmsdh_sdmmc_remove(struct sdio_func *func) sd_info(("sdio_device: 0x%04x\n", func->device)); sd_info(("Function#: 0x%04x\n", func->num)); - if (func->num == 2) { + if (gInstance->func[2]) { sd_trace(("F2 found, calling bcmsdh_remove...\n")); bcmsdh_remove(&func->dev); - } else if (func->num == 1) { + gInstance->func[2] = NULL; + } + if (func->num == 1) { sdio_claim_host(func); sdio_disable_func(func); sdio_release_host(func); @@ -192,11 +196,13 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) if (func->num != 2) return 0; - sd_trace_hw4(("%s Enter\n", __FUNCTION__)); - +#ifdef CUSTOMER_HW4 + sd_err(("%s Enter\n", __FUNCTION__)); +#else + sd_trace(("%s Enter\n", __FUNCTION__)); +#endif if (dhd_os_check_wakelock(bcmsdh_get_drvdata())) return -EBUSY; - sdio_flags = sdio_get_host_pm_caps(func); if (!(sdio_flags & MMC_PM_KEEP_POWER)) { @@ -210,16 +216,10 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) sd_err(("%s: error while trying to keep power\n", __FUNCTION__)); return ret; } - -#if !defined(CUSTOMER_HW4) -#if defined(OOB_INTR_ONLY) +#if defined(OOB_INTR_ONLY) && !defined(CUSTOMER_HW4) bcmsdh_oob_intr_set(0); -#endif /* defined(OOB_INTR_ONLY) */ -#endif /* !defined(CUSTOMER_HW4) */ +#endif /* OOB_INTR_ONLY && !CUSTOMER_HW4 */ dhd_mmc_suspend = TRUE; -#if defined(CUSTOMER_HW4) && defined(CONFIG_ARCH_TEGRA) - irq_set_irq_wake(390, 1); -#endif smp_mb(); return 0; @@ -227,24 +227,20 @@ static int bcmsdh_sdmmc_suspend(struct device *pdev) static int bcmsdh_sdmmc_resume(struct device *pdev) { -#if !defined(CUSTOMER_HW4) -#if defined(OOB_INTR_ONLY) +#if defined(OOB_INTR_ONLY) && !defined(CUSTOMER_HW4) struct sdio_func *func = dev_to_sdio_func(pdev); -#endif /* defined(OOB_INTR_ONLY) */ -#endif /* defined(CUSTOMER_HW4) */ - sd_trace_hw4(("%s Enter\n", __FUNCTION__)); - +#endif /* OOB_INTR_ONLY && !CUSTOMER_HW4 */ +#ifdef CUSTOMER_HW4 + sd_err(("%s Enter\n", __FUNCTION__)); +#else + sd_trace(("%s Enter\n", __FUNCTION__)); +#endif dhd_mmc_suspend = FALSE; -#if !defined(CUSTOMER_HW4) -#if defined(OOB_INTR_ONLY) +#if defined(OOB_INTR_ONLY) && !defined(CUSTOMER_HW4) if ((func->num == 2) && dhd_os_check_if_up(bcmsdh_get_drvdata())) bcmsdh_oob_intr_set(1); -#endif /* (OOB_INTR_ONLY) */ -#endif /* !(CUSTOMER_HW4) */ -#if defined(CUSTOMER_HW4) && defined(CONFIG_ARCH_TEGRA) - if (func->num == 2) - irq_set_irq_wake(390, 0); -#endif +#endif /* OOB_INTR_ONLY && !CUSTOMER_HW4 */ + smp_mb(); return 0; } @@ -412,7 +408,7 @@ int sdio_function_init(void) error = sdio_register_driver(&bcmsdh_sdmmc_driver); if (error && gInstance) { kfree(gInstance); - gInstance = 0; + gInstance = NULL; } return error; @@ -429,6 +425,8 @@ void sdio_function_cleanup(void) sdio_unregister_driver(&bcmsdh_sdmmc_driver); - if (gInstance) + if (gInstance) { kfree(gInstance); + gInstance = NULL; + } } diff --git a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c index 2dbb168..9e3922b 100755 --- a/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c +++ b/drivers/net/wireless/bcmdhd/bcmsdspi_linux.c @@ -2,13 +2,13 @@ * Broadcom SPI Host Controller Driver - Linux Per-port * * Copyright (C) 1999-2012, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,12 +16,12 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdspi_linux.c 355376 2012-09-06 13:23:59Z $ + * $Id: bcmsdspi_linux.c 356773 2012-09-13 22:50:30Z $ */ #include <typedefs.h> @@ -34,6 +34,7 @@ #include <pcicfg.h> #include <sdio.h> /* SDIO Device and Protocol Specs */ #include <linux/sched.h> /* request_irq(), free_irq() */ + #include <bcmsdspi.h> #include <bcmspi.h> @@ -214,7 +215,7 @@ spi_osinit(sdioh_info_t *sd) spin_lock_init(&sdos->lock); init_waitqueue_head(&sdos->intr_wait_queue); #endif /* !BCMSPI_ANDROID */ -return BCME_OK; + return BCME_OK; } void diff --git a/drivers/net/wireless/bcmdhd/bcmspibrcm.c b/drivers/net/wireless/bcmdhd/bcmspibrcm.c index d5f5754..2dd7c10 100755 --- a/drivers/net/wireless/bcmdhd/bcmspibrcm.c +++ b/drivers/net/wireless/bcmdhd/bcmspibrcm.c @@ -2,13 +2,13 @@ * Broadcom BCMSDH to gSPI Protocol Conversion Layer * * Copyright (C) 1999-2012, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,12 +16,12 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmspibrcm.c 355377 2012-09-06 13:25:35Z $ + * $Id: bcmspibrcm.c 359460 2012-09-28 01:51:23Z $ */ #define HSMODE @@ -72,7 +72,7 @@ extern void spi_sendrecv(sdioh_info_t *sd, uint8 *msg_out, uint8 *msg_in, int ms uint sd_msglevel = SDH_ERROR_VAL; #else uint sd_msglevel = 0; -#endif +#endif uint sd_hiok = FALSE; /* Use hi-speed mode if available? */ uint sd_sdmode = SDIOH_MODE_SPI; /* Use SD4 mode by default */ @@ -336,7 +336,7 @@ enum { }; const bcm_iovar_t sdioh_iovars[] = { - {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, + {"sd_msglevel", IOV_MSGLEVEL, 0, IOVT_UINT32, 0 }, {"sd_blocksize", IOV_BLOCKSIZE, 0, IOVT_UINT32, 0 }, /* ((fn << 16) | size) */ {"sd_dma", IOV_DMA, 0, IOVT_BOOL, 0 }, {"sd_ints", IOV_USEINTS, 0, IOVT_BOOL, 0 }, diff --git a/drivers/net/wireless/bcmdhd/bcmutils.c b/drivers/net/wireless/bcmdhd/bcmutils.c index 0646195..c50e66c 100644 --- a/drivers/net/wireless/bcmdhd/bcmutils.c +++ b/drivers/net/wireless/bcmdhd/bcmutils.c @@ -20,7 +20,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. - * $Id: bcmutils.c 312855 2012-02-04 02:01:18Z $ + * $Id: bcmutils.c 367039 2012-11-06 11:31:19Z $ */ #include <bcm_cfg.h> @@ -192,7 +192,7 @@ pktsegcnt_war(osl_t *osh, void *p) } uint8 * BCMFASTPATH -pktoffset(osl_t *osh, void *p, uint offset) +pktdataoffset(osl_t *osh, void *p, uint offset) { uint total = pkttotlen(osh, p); uint pkt_off = 0, len = 0; @@ -211,6 +211,25 @@ pktoffset(osl_t *osh, void *p, uint offset) return (uint8*) (pdata+pkt_off); } + +/* given a offset in pdata, find the pkt seg hdr */ +void * +pktoffset(osl_t *osh, void *p, uint offset) +{ + uint total = pkttotlen(osh, p); + uint len = 0; + + if (offset > total) + return NULL; + + for (; p; p = PKTNEXT(osh, p)) { + len += PKTLEN(osh, p); + if (len > offset) + break; + } + return p; +} + /* * osl multiple-precedence packet queue * hi_prec is always >= the number of the highest non-empty precedence @@ -324,6 +343,44 @@ pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p) } void * BCMFASTPATH +pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg) +{ + struct pktq_prec *q; + void *p, *prev = NULL; + + ASSERT(prec >= 0 && prec < pq->num_prec); + + q = &pq->q[prec]; + p = q->head; + + while (p) { + if (fn == NULL || (*fn)(p, arg)) { + break; + } else { + prev = p; + p = PKTLINK(p); + } + } + if (p == NULL) + return NULL; + + if (prev == NULL) { + if ((q->head = PKTLINK(p)) == NULL) + q->tail = NULL; + } else { + PKTSETLINK(prev, PKTLINK(p)); + } + + q->len--; + + pq->len--; + + PKTSETLINK(p, NULL); + + return p; +} + +void * BCMFASTPATH pktq_pdeq_tail(struct pktq *pq, int prec) { struct pktq_prec *q; @@ -654,6 +711,7 @@ pktq_mdeq(struct pktq *pq, uint prec_bmp, int *prec_out) #endif /* BCMDRIVER */ +#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) const unsigned char bcm_ctype[] = { _BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C,_BCM_C, /* 0-7 */ @@ -967,6 +1025,7 @@ bcm_ether_atoe(const char *p, struct ether_addr *ea) return (i == 6); } +#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ #if defined(CONFIG_USBRNDIS_RETAIL) || defined(NDIS_MINIPORT_DRIVER) @@ -1078,7 +1137,7 @@ pktsetprio(void *pkt, bool update_vtag) eh = (struct ether_header *) pktdata; - if (ntoh16(eh->ether_type) == ETHER_TYPE_8021Q) { + if (eh->ether_type == hton16(ETHER_TYPE_8021Q)) { uint16 vlan_tag; int vlan_prio, dscp_prio = 0; @@ -1087,7 +1146,7 @@ pktsetprio(void *pkt, bool update_vtag) vlan_tag = ntoh16(evh->vlan_tag); vlan_prio = (int) (vlan_tag >> VLAN_PRI_SHIFT) & VLAN_PRI_MASK; - if (ntoh16(evh->ether_type) == ETHER_TYPE_IP) { + if (evh->ether_type == hton16(ETHER_TYPE_IP)) { uint8 *ip_body = pktdata + sizeof(struct ethervlan_header); uint8 tos_tc = IP_TOS46(ip_body); dscp_prio = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); @@ -1114,7 +1173,7 @@ pktsetprio(void *pkt, bool update_vtag) evh->vlan_tag = hton16(vlan_tag); rc |= PKTPRIO_UPD; } - } else if (ntoh16(eh->ether_type) == ETHER_TYPE_IP) { + } else if (eh->ether_type == hton16(ETHER_TYPE_IP)) { uint8 *ip_body = pktdata + sizeof(struct ether_header); uint8 tos_tc = IP_TOS46(ip_body); priority = (int)(tos_tc >> IPV4_TOS_PREC_SHIFT); @@ -1223,6 +1282,7 @@ bcm_iovar_lencheck(const bcm_iovar_t *vi, void *arg, int len, bool set) #endif /* BCMDRIVER */ +#if !defined(BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS) /******************************************************************************* * crc8 * @@ -1579,10 +1639,36 @@ bcm_parse_ordered_tlvs(void *buf, int buflen, uint key) } return NULL; } +#endif /* !BCMROMOFFLOAD_EXCLUDE_BCMUTILS_FUNCS */ #if defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || defined(WLMSG_ASSOC) || \ defined(DHD_DEBUG) int +bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 flags, char* buf, int len) +{ + int i, slen = 0; + uint32 bit, mask; + const char *name; + mask = bd->mask; + if (len < 2 || !buf) + return 0; + + buf[0] = '\0'; + + for (i = 0; (name = bd->bitfield[i].name) != NULL; i++) { + bit = bd->bitfield[i].bit; + if ((flags & mask) == bit) { + if (len > (int)strlen(name)) { + slen = strlen(name); + strncpy(buf, name, slen+1); + } + break; + } + } + return slen; +} + +int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len) { int i; diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_channels.c b/drivers/net/wireless/bcmdhd/bcmwifi_channels.c index 0a570f6..0cbc1cb 100644 --- a/drivers/net/wireless/bcmdhd/bcmwifi_channels.c +++ b/drivers/net/wireless/bcmdhd/bcmwifi_channels.c @@ -440,7 +440,7 @@ wf_chspec_aton(const char *a) return 0; - c = tolower(a[0]); + c = tolower((int)a[0]); if (c == 'g') { a ++; @@ -456,7 +456,7 @@ wf_chspec_aton(const char *a) if (!read_uint(&a, &ctl_ch)) return 0; - c = tolower(a[0]); + c = tolower((int)a[0]); } else { @@ -503,7 +503,7 @@ wf_chspec_aton(const char *a) - c = tolower(a[0]); + c = tolower((int)a[0]); if (chspec_band == WL_CHANSPEC_BAND_2G && bw == 40) { @@ -842,6 +842,56 @@ wf_chspec_ctlchspec(chanspec_t chspec) return ctl_chspec; } + +uint16 +wf_channel2chspec(uint ctl_ch, uint bw) +{ + uint16 chspec; + const uint8 *center_ch = NULL; + int num_ch = 0; + int sb = -1; + int i = 0; + + chspec = ((ctl_ch <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); + + chspec |= bw; + + if (bw == WL_CHANSPEC_BW_40) { + center_ch = wf_5g_40m_chans; + num_ch = WF_NUM_5G_40M_CHANS; + bw = 40; + } else if (bw == WL_CHANSPEC_BW_80) { + center_ch = wf_5g_80m_chans; + num_ch = WF_NUM_5G_80M_CHANS; + bw = 80; + } else if (bw == WL_CHANSPEC_BW_160) { + center_ch = wf_5g_160m_chans; + num_ch = WF_NUM_5G_160M_CHANS; + bw = 160; + } else if (bw == WL_CHANSPEC_BW_20) { + chspec |= ctl_ch; + return chspec; + } else { + return 0; + } + + for (i = 0; i < num_ch; i ++) { + sb = channel_to_sb(center_ch[i], ctl_ch, bw); + if (sb >= 0) { + chspec |= center_ch[i]; + chspec |= (sb << WL_CHANSPEC_CTL_SB_SHIFT); + break; + } + } + + + if (sb < 0) { + return 0; + } + + return chspec; +} + #endif diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_channels.h b/drivers/net/wireless/bcmdhd/bcmwifi_channels.h index c797047..d988413 100644 --- a/drivers/net/wireless/bcmdhd/bcmwifi_channels.h +++ b/drivers/net/wireless/bcmdhd/bcmwifi_channels.h @@ -44,7 +44,8 @@ typedef uint16 chanspec_t; #define CH_5MHZ_APART 1 #define CH_MAX_2G_CHANNEL 14 #define MAXCHANNEL 224 -#define CHSPEC_CTLOVLP(sp1, sp2, sep) ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < (sep) +#define CHSPEC_CTLOVLP(sp1, sp2, sep) (ABS(wf_chspec_ctlchan(sp1) - wf_chspec_ctlchan(sp2)) < \ + (sep)) #undef D11AC_IOTYPES @@ -69,6 +70,12 @@ typedef uint16 chanspec_t; #define WL_CHANSPEC_BAND_MASK 0xf000 #define WL_CHANSPEC_BAND_SHIFT 12 +#ifdef WL_CHANSPEC_BAND_5G +#undef WL_CHANSPEC_BAND_5G +#endif +#ifdef WL_CHANSPEC_BAND_2G +#undef WL_CHANSPEC_BAND_2G +#endif #define WL_CHANSPEC_BAND_5G 0x1000 #define WL_CHANSPEC_BAND_2G 0x2000 #define INVCHANSPEC 255 @@ -77,6 +84,13 @@ typedef uint16 chanspec_t; #define LOWER_20_SB(channel) (((channel) > CH_10MHZ_APART) ? ((channel) - CH_10MHZ_APART) : 0) #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ((channel) + CH_10MHZ_APART) : 0) + +#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) +#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ + ((channel) + 3 * CH_10MHZ_APART) : 0) +#define LU_20_SB(channel) LOWER_20_SB(channel) +#define UL_20_SB(channel) UPPER_20_SB(channel) + #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) #define CH20MHZ_CHSPEC(channel) (chanspec_t)((chanspec_t)(channel) | WL_CHANSPEC_BW_20 | \ WL_CHANSPEC_CTL_SB_NONE | (((channel) <= CH_MAX_2G_CHANNEL) ? \ @@ -175,6 +189,13 @@ typedef uint16 chanspec_t; ((channel) - CH_10MHZ_APART) : 0) #define UPPER_20_SB(channel) (((channel) < (MAXCHANNEL - CH_10MHZ_APART)) ? \ ((channel) + CH_10MHZ_APART) : 0) + +#define LL_20_SB(channel) (((channel) > 3 * CH_10MHZ_APART) ? ((channel) - 3 * CH_10MHZ_APART) : 0) +#define UU_20_SB(channel) (((channel) < (MAXCHANNEL - 3 * CH_10MHZ_APART)) ? \ + ((channel) + 3 * CH_10MHZ_APART) : 0) +#define LU_20_SB(channel) LOWER_20_SB(channel) +#define UL_20_SB(channel) UPPER_20_SB(channel) + #define LOWER_40_SB(channel) ((channel) - CH_20MHZ_APART) #define UPPER_40_SB(channel) ((channel) + CH_20MHZ_APART) #define CHSPEC_WLCBANDUNIT(chspec) (CHSPEC_IS5G(chspec) ? BAND_5G_INDEX : BAND_2G_INDEX) @@ -298,21 +319,6 @@ typedef uint16 chanspec_t; #define WF_CHAN_FACTOR_4_G 8000 - -#define WLC_MAXRATE 108 -#define WLC_RATE_1M 2 -#define WLC_RATE_2M 4 -#define WLC_RATE_5M5 11 -#define WLC_RATE_11M 22 -#define WLC_RATE_6M 12 -#define WLC_RATE_9M 18 -#define WLC_RATE_12M 24 -#define WLC_RATE_18M 36 -#define WLC_RATE_24M 48 -#define WLC_RATE_36M 72 -#define WLC_RATE_48M 96 -#define WLC_RATE_54M 108 - #define WLC_2G_25MHZ_OFFSET 5 @@ -342,4 +348,7 @@ extern int wf_mhz2channel(uint freq, uint start_factor); extern int wf_channel2mhz(uint channel, uint start_factor); + +extern uint16 wf_channel2chspec(uint ctl_ch, uint bw); + #endif diff --git a/drivers/net/wireless/bcmdhd/bcmwifi_rates.h b/drivers/net/wireless/bcmdhd/bcmwifi_rates.h index 9896b23..213fb93 100644 --- a/drivers/net/wireless/bcmdhd/bcmwifi_rates.h +++ b/drivers/net/wireless/bcmdhd/bcmwifi_rates.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmwifi_rates.h 252708 2011-04-12 06:45:56Z $ + * $Id: bcmwifi_rates.h 5187 2012-06-29 06:17:50Z $ */ #ifndef _bcmwifi_rates_h_ @@ -58,7 +58,8 @@ typedef enum wl_tx_mode { WL_TX_MODE_NONE, WL_TX_MODE_STBC, WL_TX_MODE_CDD, - WL_TX_MODE_SDM + WL_TX_MODE_TXBF, + WL_NUM_TX_MODES } wl_tx_mode_t; @@ -195,7 +196,6 @@ typedef enum clm_rates { WL_RATE_2X2_VHT8SS2 = 62, WL_RATE_2X2_VHT9SS2 = 63, - @@ -295,10 +295,140 @@ typedef enum clm_rates { WL_RATE_3X3_VHT8SS3 = 114, WL_RATE_3X3_VHT9SS3 = 115, + + + + + + WL_RATE_1X2_TXBF_OFDM_6 = 116, + WL_RATE_1X2_TXBF_OFDM_9 = 117, + WL_RATE_1X2_TXBF_OFDM_12 = 118, + WL_RATE_1X2_TXBF_OFDM_18 = 119, + WL_RATE_1X2_TXBF_OFDM_24 = 120, + WL_RATE_1X2_TXBF_OFDM_36 = 121, + WL_RATE_1X2_TXBF_OFDM_48 = 122, + WL_RATE_1X2_TXBF_OFDM_54 = 123, + + WL_RATE_1X2_TXBF_MCS0 = 124, + WL_RATE_1X2_TXBF_MCS1 = 125, + WL_RATE_1X2_TXBF_MCS2 = 126, + WL_RATE_1X2_TXBF_MCS3 = 127, + WL_RATE_1X2_TXBF_MCS4 = 128, + WL_RATE_1X2_TXBF_MCS5 = 129, + WL_RATE_1X2_TXBF_MCS6 = 130, + WL_RATE_1X2_TXBF_MCS7 = 131, + + WL_RATE_1X2_TXBF_VHT0SS1 = 124, + WL_RATE_1X2_TXBF_VHT1SS1 = 125, + WL_RATE_1X2_TXBF_VHT2SS1 = 126, + WL_RATE_1X2_TXBF_VHT3SS1 = 127, + WL_RATE_1X2_TXBF_VHT4SS1 = 128, + WL_RATE_1X2_TXBF_VHT5SS1 = 129, + WL_RATE_1X2_TXBF_VHT6SS1 = 130, + WL_RATE_1X2_TXBF_VHT7SS1 = 131, + WL_RATE_1X2_TXBF_VHT8SS1 = 132, + WL_RATE_1X2_TXBF_VHT9SS1 = 133, + + + + WL_RATE_2X2_TXBF_SDM_MCS8 = 134, + WL_RATE_2X2_TXBF_SDM_MCS9 = 135, + WL_RATE_2X2_TXBF_SDM_MCS10 = 136, + WL_RATE_2X2_TXBF_SDM_MCS11 = 137, + WL_RATE_2X2_TXBF_SDM_MCS12 = 138, + WL_RATE_2X2_TXBF_SDM_MCS13 = 139, + WL_RATE_2X2_TXBF_SDM_MCS14 = 140, + WL_RATE_2X2_TXBF_SDM_MCS15 = 141, + + WL_RATE_2X2_TXBF_VHT0SS2 = 134, + WL_RATE_2X2_TXBF_VHT1SS2 = 135, + WL_RATE_2X2_TXBF_VHT2SS2 = 136, + WL_RATE_2X2_TXBF_VHT3SS2 = 137, + WL_RATE_2X2_TXBF_VHT4SS2 = 138, + WL_RATE_2X2_TXBF_VHT5SS2 = 139, + WL_RATE_2X2_TXBF_VHT6SS2 = 140, + WL_RATE_2X2_TXBF_VHT7SS2 = 141, + + - WL_NUMRATES = 116 + + + + WL_RATE_1X3_TXBF_OFDM_6 = 142, + WL_RATE_1X3_TXBF_OFDM_9 = 143, + WL_RATE_1X3_TXBF_OFDM_12 = 144, + WL_RATE_1X3_TXBF_OFDM_18 = 145, + WL_RATE_1X3_TXBF_OFDM_24 = 146, + WL_RATE_1X3_TXBF_OFDM_36 = 147, + WL_RATE_1X3_TXBF_OFDM_48 = 148, + WL_RATE_1X3_TXBF_OFDM_54 = 149, + + WL_RATE_1X3_TXBF_MCS0 = 150, + WL_RATE_1X3_TXBF_MCS1 = 151, + WL_RATE_1X3_TXBF_MCS2 = 152, + WL_RATE_1X3_TXBF_MCS3 = 153, + WL_RATE_1X3_TXBF_MCS4 = 154, + WL_RATE_1X3_TXBF_MCS5 = 155, + WL_RATE_1X3_TXBF_MCS6 = 156, + WL_RATE_1X3_TXBF_MCS7 = 157, + + WL_RATE_1X3_TXBF_VHT0SS1 = 150, + WL_RATE_1X3_TXBF_VHT1SS1 = 151, + WL_RATE_1X3_TXBF_VHT2SS1 = 152, + WL_RATE_1X3_TXBF_VHT3SS1 = 153, + WL_RATE_1X3_TXBF_VHT4SS1 = 154, + WL_RATE_1X3_TXBF_VHT5SS1 = 155, + WL_RATE_1X3_TXBF_VHT6SS1 = 156, + WL_RATE_1X3_TXBF_VHT7SS1 = 157, + WL_RATE_1X3_TXBF_VHT8SS1 = 158, + WL_RATE_1X3_TXBF_VHT9SS1 = 159, + + + + WL_RATE_2X3_TXBF_SDM_MCS8 = 160, + WL_RATE_2X3_TXBF_SDM_MCS9 = 161, + WL_RATE_2X3_TXBF_SDM_MCS10 = 162, + WL_RATE_2X3_TXBF_SDM_MCS11 = 163, + WL_RATE_2X3_TXBF_SDM_MCS12 = 164, + WL_RATE_2X3_TXBF_SDM_MCS13 = 165, + WL_RATE_2X3_TXBF_SDM_MCS14 = 166, + WL_RATE_2X3_TXBF_SDM_MCS15 = 167, + + WL_RATE_2X3_TXBF_VHT0SS2 = 160, + WL_RATE_2X3_TXBF_VHT1SS2 = 161, + WL_RATE_2X3_TXBF_VHT2SS2 = 162, + WL_RATE_2X3_TXBF_VHT3SS2 = 163, + WL_RATE_2X3_TXBF_VHT4SS2 = 164, + WL_RATE_2X3_TXBF_VHT5SS2 = 165, + WL_RATE_2X3_TXBF_VHT6SS2 = 166, + WL_RATE_2X3_TXBF_VHT7SS2 = 167, + WL_RATE_2X3_TXBF_VHT8SS2 = 168, + WL_RATE_2X3_TXBF_VHT9SS2 = 169, + + + + WL_RATE_3X3_TXBF_SDM_MCS16 = 170, + WL_RATE_3X3_TXBF_SDM_MCS17 = 171, + WL_RATE_3X3_TXBF_SDM_MCS18 = 172, + WL_RATE_3X3_TXBF_SDM_MCS19 = 173, + WL_RATE_3X3_TXBF_SDM_MCS20 = 174, + WL_RATE_3X3_TXBF_SDM_MCS21 = 175, + WL_RATE_3X3_TXBF_SDM_MCS22 = 176, + WL_RATE_3X3_TXBF_SDM_MCS23 = 177, + + WL_RATE_3X3_TXBF_VHT0SS3 = 170, + WL_RATE_3X3_TXBF_VHT1SS3 = 171, + WL_RATE_3X3_TXBF_VHT2SS3 = 172, + WL_RATE_3X3_TXBF_VHT3SS3 = 173, + WL_RATE_3X3_TXBF_VHT4SS3 = 174, + WL_RATE_3X3_TXBF_VHT5SS3 = 175, + WL_RATE_3X3_TXBF_VHT6SS3 = 176, + WL_RATE_3X3_TXBF_VHT7SS3 = 177 } clm_rates_t; + +#define WL_NUMRATES 178 + #ifdef __cplusplus } #endif diff --git a/drivers/net/wireless/bcmdhd/dhd.h b/drivers/net/wireless/bcmdhd/dhd.h index 94cbe91..4afdb8c 100644 --- a/drivers/net/wireless/bcmdhd/dhd.h +++ b/drivers/net/wireless/bcmdhd/dhd.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd.h 356711 2012-09-13 15:58:32Z $ + * $Id: dhd.h 393894 2013-03-29 07:14:35Z $ */ /**************** @@ -58,17 +58,16 @@ int setScheduler(struct task_struct *p, int policy, struct sched_param *param); #include <wlioctl.h> #include <wlfc_proto.h> +#ifdef CUSTOMER_HW4 #include <dhd_sec_feature.h> +#endif /* CUSTOMER_HW4 */ -#if defined(CUSTOMER_HW4_RELEASE) -/* Customer requirement */ -#undef CONFIG_WIRELESS_EXT -#endif /* Forward decls */ struct dhd_bus; struct dhd_prot; struct dhd_info; +struct dhd_ioctl; /* The level of bus communication with the dongle */ enum dhd_bus_state { @@ -79,34 +78,37 @@ enum dhd_bus_state { enum dhd_op_flags { /* Firmware requested operation mode */ - DHD_FLAG_STA_MODE = BIT(0), /* STA only */ - DHD_FLAG_HOSTAP_MODE = BIT(1), /* SOFTAP only */ - DHD_FLAG_P2P_MODE = BIT(2), /* P2P Only */ + DHD_FLAG_STA_MODE = (1 << (0)), /* STA only */ + DHD_FLAG_HOSTAP_MODE = (1 << (1)), /* SOFTAP only */ + DHD_FLAG_P2P_MODE = (1 << (2)), /* P2P Only */ /* STA + P2P */ DHD_FLAG_CONCURR_SINGLE_CHAN_MODE = (DHD_FLAG_STA_MODE | DHD_FLAG_P2P_MODE), - DHD_FLAG_CONCURR_MULTI_CHAN_MODE = BIT(4), /* STA + P2P */ + DHD_FLAG_CONCURR_MULTI_CHAN_MODE = (1 << (4)), /* STA + P2P */ /* Current P2P mode for P2P connection */ - DHD_FLAG_P2P_GC_MODE = BIT(5), - DHD_FLAG_P2P_GO_MODE = BIT(6), - DHD_FLAG_MBSS_MODE = BIT(7) /* MBSS in future */ + DHD_FLAG_P2P_GC_MODE = (1 << (5)), + DHD_FLAG_P2P_GO_MODE = (1 << (6)), + DHD_FLAG_MBSS_MODE = (1 << (7)) /* MBSS in future */ }; #define MANUFACTRING_FW "WLTEST" -/* max sequential rxcntl timeouts to set HANG event */ -#ifndef MAX_CNTL_TIMEOUT -#define MAX_CNTL_TIMEOUT 2 -#endif +/* Max sequential TX/RX Control timeouts to set HANG event */ +#ifndef MAX_CNTL_TX_TIMEOUT +#define MAX_CNTL_TX_TIMEOUT 2 +#endif /* MAX_CNTL_TX_TIMEOUT */ +#ifndef MAX_CNTL_RX_TIMEOUT +#define MAX_CNTL_RX_TIMEOUT 1 +#endif /* MAX_CNTL_RX_TIMEOUT */ #define DHD_SCAN_ASSOC_ACTIVE_TIME 40 /* ms: Embedded default Active setting from DHD */ -#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ +#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms: Embedded def. Unassoc Active setting from DHD */ #define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ #ifndef POWERUP_MAX_RETRY #define POWERUP_MAX_RETRY 3 /* how many times we retry to power up the chip */ #endif #ifndef POWERUP_WAIT_MS -#define POWERUP_WAIT_MS (2000) /* ms: time out in waiting wifi to come up */ +#define POWERUP_WAIT_MS 2000 /* ms: time out in waiting wifi to come up */ #endif enum dhd_bus_wake_state { @@ -130,15 +132,14 @@ enum dhd_prealloc_index { DHD_PREALLOC_PROT = 0, DHD_PREALLOC_RXBUF, DHD_PREALLOC_DATABUF, -#if defined(STATIC_WL_PRIV_STRUCT) DHD_PREALLOC_OSL_BUF, +#if defined(STATIC_WL_PRIV_STRUCT) DHD_PREALLOC_WIPHY_ESCAN0 = 5, -#if defined(DUAL_ESCAN_RESULT_BUFFER) - DHD_PREALLOC_WIPHY_ESCAN1 -#endif -#else - DHD_PREALLOC_OSL_BUF +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) + DHD_PREALLOC_WIPHY_ESCAN1, +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ #endif /* STATIC_WL_PRIV_STRUCT */ + DHD_PREALLOC_DHD_INFO = 7 }; typedef enum { @@ -180,6 +181,19 @@ typedef struct reorder_info { uint8 pend_pkts; } reorder_info_t; +#ifdef DHDTCPACK_SUPPRESS +#define MAXTCPSTREAMS 4 /* Keep this to be power of 2 */ +typedef struct tcp_ack_info { + void *p_tcpackinqueue; + uint32 tcpack_number; + uint ip_tcp_ttllen; + uint8 ipaddrs[8]; /* Each 4bytes src and dst IP addrs */ + uint8 tcpports[4]; /* Each 2bytes src and dst port number */ +} tcp_ack_info_t; + +void dhd_onoff_tcpack_sup(void *pub, bool on); +#endif /* DHDTCPACK_SUPPRESS */ + /* Common structure for module and instance linkage */ typedef struct dhd_pub { /* Linkage ponters */ @@ -239,8 +253,10 @@ typedef struct dhd_pub { int pno_enable; /* pno status : "1" is pno enable */ int pno_suspend; /* pno suspend status : "1" is pno suspended */ #endif /* PNO_SUPPORT */ - int dtim_skip; /* dtim skip , default 0 means wake each dtim */ - + /* DTIM skip value, default 0(or 1) means wake each DTIM + * 3 means skip 2 DTIMs and wake up 3rd DTIM(9th beacon when AP DTIM is 3) + */ + int suspend_bcn_li_dtim; /* bcn_li_dtim value in suspend mode */ #ifdef PKT_FILTER_SUPPORT int early_suspended; /* Early suspend status */ int dhcp_in_progress; /* DHCP period */ @@ -260,6 +276,9 @@ typedef struct dhd_pub { */ /* #define WL_ENABLE_P2P_IF 1 */ +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_HAS_WAKELOCK) + struct wake_lock wakelock[WAKE_LOCK_MAX]; +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined (CONFIG_HAS_WAKELOCK) */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 struct mutex wl_start_stop_lock; /* lock/unlock for Android start/stop */ struct mutex wl_softap_lock; /* lock/unlock for any SoftAP/STA settings */ @@ -284,8 +303,25 @@ typedef struct dhd_pub { uint8 htsfdlystat_sz; /* Size of delay stats, max 255B */ #endif struct reorder_info *reorder_bufs[WLHOST_REORDERDATA_MAXFLOWS]; -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) - struct wake_lock pno_wakelock; +#ifdef RXFRAME_THREAD +#ifdef CUSTOMER_HW4 +#define MAXSKBPEND 1024 +#else +#define MAXSKBPEND 0x10000 +#endif + void *skbbuf[MAXSKBPEND]; + uint32 store_idx; + uint32 sent_idx; +#endif /* RXFRAME_THREAD */ +#ifdef DHDTCPACK_SUPPRESS + int tcp_ack_info_cnt; + tcp_ack_info_t tcp_ack_info_tbl[MAXTCPSTREAMS]; +#endif /* DHDTCPACK_SUPPRESS */ +#if defined(ARP_OFFLOAD_SUPPORT) + uint32 arp_version; +#endif +#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) + bool fw_4way_handshake; /* Whether firmware will to do the 4way handshake. */ #endif } dhd_pub_t; @@ -358,6 +394,8 @@ extern int dhd_os_wake_unlock(dhd_pub_t *pub); extern int dhd_os_wake_lock_timeout(dhd_pub_t *pub); extern int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val); extern int dhd_os_wake_lock_ctrl_timeout_enable(dhd_pub_t *pub, int val); +extern int dhd_os_wd_wake_lock(dhd_pub_t *pub); +extern int dhd_os_wd_wake_unlock(dhd_pub_t *pub); inline static void MUTEX_LOCK_SOFTAP_SET_INIT(dhd_pub_t * dhdp) { @@ -399,9 +437,23 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) __FUNCTION__, __LINE__); \ dhd_os_wake_lock_timeout(pub); \ } while (0) +#define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \ + do { \ + printf("call wake_lock_rx_timeout_enable[%d]: %s %d\n", \ + val, __FUNCTION__, __LINE__); \ + dhd_os_wake_lock_rx_timeout_enable(pub, val); \ + } while (0) +#define DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(pub, val) \ + do { \ + printf("call wake_lock_ctrl_timeout_enable[%d]: %s %d\n", \ + val, __FUNCTION__, __LINE__); \ + dhd_os_wake_lock_ctrl_timeout_enable(pub, val); \ + } while (0) #else -#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) -#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) +#define DHD_OS_WAKE_LOCK(pub) dhd_os_wake_lock(pub) +#define DHD_OS_WAKE_UNLOCK(pub) dhd_os_wake_unlock(pub) +#define DHD_OS_WD_WAKE_LOCK(pub) dhd_os_wd_wake_lock(pub) +#define DHD_OS_WD_WAKE_UNLOCK(pub) dhd_os_wd_wake_unlock(pub) #define DHD_OS_WAKE_LOCK_TIMEOUT(pub) dhd_os_wake_lock_timeout(pub) #define DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(pub, val) \ dhd_os_wake_lock_rx_timeout_enable(pub, val) @@ -411,12 +463,20 @@ inline static void MUTEX_UNLOCK_SOFTAP_SET(dhd_pub_t * dhdp) #define DHD_PACKET_TIMEOUT_MS 1000 #define DHD_EVENT_TIMEOUT_MS 1500 +#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) +#define DHD_PNO_TIMEOUT_MS 10000 +#endif + /* interface operations (register, remove) should be atomic, use this lock to prevent race * condition among wifi on/off and interface operation functions */ void dhd_net_if_lock(struct net_device *dev); void dhd_net_if_unlock(struct net_device *dev); +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 1 +extern struct mutex _dhd_sdio_mutex_lock_; +#endif + typedef struct dhd_if_event { uint8 ifidx; uint8 action; @@ -505,6 +565,11 @@ extern void dhd_os_sdunlock_txq(dhd_pub_t * pub); extern void dhd_os_sdlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdunlock_rxq(dhd_pub_t * pub); extern void dhd_os_sdlock_sndup_rxq(dhd_pub_t * pub); +#ifdef DHDTCPACK_SUPPRESS +extern void dhd_os_tcpacklock(dhd_pub_t *pub); +extern void dhd_os_tcpackunlock(dhd_pub_t *pub); +#endif /* DHDTCPACK_SUPPRESS */ + extern void dhd_customer_gpio_wlan_ctrl(int onoff); extern int dhd_custom_get_mac_address(unsigned char *buf); extern void dhd_os_sdunlock_sndup_rxq(dhd_pub_t * pub); @@ -512,7 +577,6 @@ extern void dhd_os_sdlock_eventq(dhd_pub_t * pub); extern void dhd_os_sdunlock_eventq(dhd_pub_t * pub); extern bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret); extern int dhd_os_send_hang_message(dhd_pub_t *dhdp); -extern void dhd_set_version_info(dhd_pub_t *pub, char *fw); #ifdef PNO_SUPPORT extern int dhd_pno_enable(dhd_pub_t *dhd, int pfn_enabled); @@ -532,14 +596,14 @@ extern int dhd_dev_get_pno_status(struct net_device *dev); #define DHD_BROADCAST_FILTER_NUM 1 #define DHD_MULTICAST4_FILTER_NUM 2 #define DHD_MULTICAST6_FILTER_NUM 3 -#define DHD_MDNS_FILTER_NUM 4 -extern void dhd_set_packet_filter(dhd_pub_t *dhd); +#define DHD_MDNS_FILTER_NUM 4 +extern int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val); extern void dhd_enable_packet_filter(int value, dhd_pub_t *dhd); extern int net_os_enable_packet_filter(struct net_device *dev, int val); extern int net_os_rxfilter_add_remove(struct net_device *dev, int val, int num); #endif /* PKT_FILTER_SUPPORT */ -extern int dhd_get_dtim_skip(dhd_pub_t *dhd); +extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); extern bool dhd_support_sta_mode(dhd_pub_t *dhd); #ifdef DHD_DEBUG @@ -601,17 +665,11 @@ extern int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *da extern void dhd_print_buf(void *pbuf, int len, int bytes_per_line); extern bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval); extern uint dhd_bus_chip_id(dhd_pub_t *dhdp); -extern uint dhd_bus_chiprev_id(dhd_pub_t *dhdp); -extern uint dhd_bus_chippkg_id(dhd_pub_t *dhdp); #if defined(KEEP_ALIVE) extern int dhd_keep_alive_onoff(dhd_pub_t *dhd); #endif /* KEEP_ALIVE */ -#ifdef ARP_OFFLOAD_SUPPORT -extern void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); -extern void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); -#endif /* ARP_OFFLOAD_SUPPORT */ extern bool dhd_is_concurrent_mode(dhd_pub_t *dhd); typedef enum cust_gpio_modes { @@ -679,15 +737,19 @@ extern uint dhd_sdiod_drive_strength; /* Override to force tx queueing all the time */ extern uint dhd_force_tx_queueing; /* Default KEEP_ALIVE Period is 55 sec to prevent AP from sending Keep Alive probe frame */ -#define KEEP_ALIVE_PERIOD 28000 +#define DEFAULT_KEEP_ALIVE_VALUE 55000 /* msec */ +#ifndef CUSTOM_KEEP_ALIVE_SETTING +#define CUSTOM_KEEP_ALIVE_SETTING DEFAULT_KEEP_ALIVE_VALUE +#endif /* DEFAULT_KEEP_ALIVE_VALUE */ + #define NULL_PKT_STR "null_pkt" /* hooks for custom glom setting option via Makefile */ -#define DEFAULT_GLOM_VALUE -1 +#define DEFAULT_GLOM_VALUE -1 #ifndef CUSTOM_GLOM_SETTING -#define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE +#define CUSTOM_GLOM_SETTING DEFAULT_GLOM_VALUE #endif - +#define WL_AUTO_ROAM_TRIGGER -75 /* hooks for custom Roaming Trigger setting via Makefile */ #define DEFAULT_ROAM_TRIGGER_VALUE -75 /* dBm default roam trigger all band */ #define DEFAULT_ROAM_TRIGGER_SETTING -1 @@ -702,13 +764,24 @@ extern uint dhd_force_tx_queueing; #define CUSTOM_ROAM_DELTA_SETTING DEFAULT_ROAM_DELTA_VALUE #endif - /* hooks for custom dhd_dpc_prio setting option via Makefile */ #define DEFAULT_DHP_DPC_PRIO 1 #ifndef CUSTOM_DPC_PRIO_SETTING -#define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO +#define CUSTOM_DPC_PRIO_SETTING DEFAULT_DHP_DPC_PRIO +#endif + +#define DEFAULT_SUSPEND_BCN_LI_DTIM 3 +#ifndef CUSTOM_SUSPEND_BCN_LI_DTIM +#define CUSTOM_SUSPEND_BCN_LI_DTIM DEFAULT_SUSPEND_BCN_LI_DTIM #endif +#ifdef RXFRAME_THREAD +#ifndef CUSTOM_RXF_PRIO_SETTING +#define CUSTOM_RXF_PRIO_SETTING (DEFAULT_DHP_DPC_PRIO + 1) +#endif +#endif /* RXFRAME_THREAD */ + +#define MAX_DTIM_SKIP_BEACON_ITERVAL 100 /* max allowed associated AP beacon for dtim skip */ #ifdef SDTEST /* Echo packet generator (SDIO), pkts/s */ @@ -725,8 +798,6 @@ extern uint dhd_pktgen_len; extern char fw_path[MOD_PARAM_PATHLEN]; extern char nv_path[MOD_PARAM_PATHLEN]; -#define MOD_PARAM_INFOLEN 512 - #ifdef SOFTAP extern char fw_path2[MOD_PARAM_PATHLEN]; #endif @@ -738,7 +809,7 @@ extern uint dhd_download_fw_on_driverload; /* Flags to indicate if we distingish power off policy when * user set the memu "Keep Wi-Fi on during sleep" to "Never" */ -extern int sleep_never; +extern int trigger_deep_sleep; int dhd_deepsleep(struct net_device *dev, int flag); #endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */ @@ -746,8 +817,6 @@ int dhd_deepsleep(struct net_device *dev, int flag); #define DHD_MAX_IFS 16 #define DHD_DEL_IF -0xe #define DHD_BAD_IF -0xf -#define WL_AUTO_ROAM_TRIGGER -75 - #ifdef PROP_TXSTATUS /* Please be mindful that total pkttag space is 32 octets only */ @@ -895,18 +964,21 @@ extern int dhd_pno_suspend(dhd_pub_t *dhd, int pfn_suspend); #endif /* PNO_SUPPORT */ #ifdef ARP_OFFLOAD_SUPPORT #define MAX_IPV4_ENTRIES 8 +void dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode); +void dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable); + /* dhd_commn arp offload wrapers */ -void dhd_aoe_hostip_clr(dhd_pub_t *dhd); -void dhd_aoe_arp_clr(dhd_pub_t *dhd); -int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen); -void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr); +void dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx); +void dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx); +int dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx); +void dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx); #endif /* ARP_OFFLOAD_SUPPORT */ -#if defined(CUSTOMER_HW4) && defined(RDWR_KORICS_MACADDR) +/* ioctl processing for nl80211 */ +int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, struct dhd_ioctl *ioc); + +#if defined(CUSTOMER_HW4) && defined(SUPPORT_MULTIPLE_REVISION) extern int -dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac); -#endif -#if defined(SUPPORT_MULTIPLE_REVISION) -extern int concate_revision(struct dhd_bus *bus, char *path, int path_len); -#endif /* SUPPORT_MULTIPLE_REVISION */ +concate_revision(struct dhd_bus *bus, char *fwpath, int fw_path_len, char *nvpath, int nv_path_len); +#endif /* CUSTOMER_HW4 && SUPPORT_MULTIPLE_REVISION */ #endif /* _dhd_h_ */ diff --git a/drivers/net/wireless/bcmdhd/dhd_bus.h b/drivers/net/wireless/bcmdhd/dhd_bus.h index fcb4bbd..5f2c9ea 100644 --- a/drivers/net/wireless/bcmdhd/dhd_bus.h +++ b/drivers/net/wireless/bcmdhd/dhd_bus.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_bus.h 347614 2012-07-27 10:24:51Z $ + * $Id: dhd_bus.h 335569 2012-05-29 12:04:43Z $ */ #ifndef _dhd_bus_h_ diff --git a/drivers/net/wireless/bcmdhd/dhd_cdc.c b/drivers/net/wireless/bcmdhd/dhd_cdc.c index cd44b92..9e405b0 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cdc.c +++ b/drivers/net/wireless/bcmdhd/dhd_cdc.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_cdc.c 355825 2012-09-10 03:22:40Z $ + * $Id: dhd_cdc.c 390461 2013-03-12 07:21:34Z $ * * BDC is like CDC, except it includes a header for data packets to convey * packet priority over the bus, and flags (e.g. to indicate checksum status @@ -69,11 +69,10 @@ typedef struct dhd_wlfc_commit_info { } dhd_wlfc_commit_info_t; #endif /* PROP_TXSTATUS */ -#if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) extern uint sd_f2_blocksize; -extern int -dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size); -#endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ +extern int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size); +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ typedef struct dhd_prot { uint16 reqid; @@ -121,7 +120,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len) #if defined(CUSTOMER_HW4) DHD_OS_WAKE_LOCK(dhd); -#endif +#endif /* OEM_ANDROID && CUSTOMER_HW4 */ do { ret = dhd_bus_rxctl(dhd->bus, (uchar*)&prot->msg, cdc_len); @@ -131,7 +130,7 @@ dhdcdc_cmplt(dhd_pub_t *dhd, uint32 id, uint32 len) #if defined(CUSTOMER_HW4) DHD_OS_WAKE_UNLOCK(dhd); -#endif +#endif /* OEM_ANDROID && CUSTOMER_HW4 */ return ret; } @@ -234,9 +233,9 @@ done: return ret; } -#ifdef CONFIG_CONTROL_PM +#if defined(CUSTOMER_HW4) && defined(CONFIG_CONTROL_PM) extern bool g_pm_control; -#endif +#endif /* CUSTOMER_HW4 & CONFIG_CONTROL_PM */ static int dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 action) @@ -261,13 +260,13 @@ dhdcdc_set_ioctl(dhd_pub_t *dhd, int ifidx, uint cmd, void *buf, uint len, uint8 return -EIO; } -#ifdef CONFIG_CONTROL_PM +#if defined(CUSTOMER_HW4) && defined(CONFIG_CONTROL_PM) if ((g_pm_control == TRUE) && (cmd == WLC_SET_PM)) { DHD_ERROR(("SET PM ignored!!!!!!!!!!!!!!!!!!!!!!\n")); goto done; } -#endif +#endif /* CUSTOMER_HW4 && CONFIG_CONTROL_PM */ memset(msg, 0, sizeof(cdc_ioctl_t)); @@ -441,29 +440,21 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) } bcm_bprintf(strbuf, "wlfc fail(tlv,credit_rqst,mac_update,psmode_update), " - "(dq_full,sendq_full, rollback_fail) = (%d,%d,%d,%d), (%d,%d,%d)\n", + "(dq_full,rollback_fail) = (%d,%d,%d,%d), (%d,%d)\n", wlfc->stats.tlv_parse_failed, wlfc->stats.credit_request_failed, wlfc->stats.mac_update_failed, wlfc->stats.psmode_update_failed, wlfc->stats.delayq_full_error, - wlfc->stats.sendq_full_error, wlfc->stats.rollback_failed); - bcm_bprintf(strbuf, "SENDQ (len,credit,sent) " - "(AC0[%d,%d,%d],AC1[%d,%d,%d],AC2[%d,%d,%d],AC3[%d,%d,%d],BC_MC[%d,%d,%d])\n", - wlfc->SENDQ.q[0].len, wlfc->FIFO_credit[0], wlfc->stats.sendq_pkts[0], - wlfc->SENDQ.q[1].len, wlfc->FIFO_credit[1], wlfc->stats.sendq_pkts[1], - wlfc->SENDQ.q[2].len, wlfc->FIFO_credit[2], wlfc->stats.sendq_pkts[2], - wlfc->SENDQ.q[3].len, wlfc->FIFO_credit[3], wlfc->stats.sendq_pkts[3], - wlfc->SENDQ.q[4].len, wlfc->FIFO_credit[4], wlfc->stats.sendq_pkts[4]); - -#ifdef PROP_TXSTATUS_DEBUG - bcm_bprintf(strbuf, "SENDQ dropped: AC[0-3]:(%d,%d,%d,%d), (bcmc,atim):(%d,%d)\n", - wlfc->stats.dropped_qfull[0], wlfc->stats.dropped_qfull[1], - wlfc->stats.dropped_qfull[2], wlfc->stats.dropped_qfull[3], - wlfc->stats.dropped_qfull[4], wlfc->stats.dropped_qfull[5]); -#endif + bcm_bprintf(strbuf, "PKTS (credit,sent) " + "(AC0[%d,%d],AC1[%d,%d],AC2[%d,%d],AC3[%d,%d],BC_MC[%d,%d])\n", + wlfc->FIFO_credit[0], wlfc->stats.send_pkts[0], + wlfc->FIFO_credit[1], wlfc->stats.send_pkts[1], + wlfc->FIFO_credit[2], wlfc->stats.send_pkts[2], + wlfc->FIFO_credit[3], wlfc->stats.send_pkts[3], + wlfc->FIFO_credit[4], wlfc->stats.send_pkts[4]); bcm_bprintf(strbuf, "\n"); for (i = 0; i < WLFC_MAX_IFNUM; i++) { @@ -659,6 +650,8 @@ dhd_wlfc_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) wlfc->stats.psq_d11sup_retx, wlfc->stats.psq_wlsup_retx, wlfc->stats.psq_hostq_retx); + bcm_bprintf(strbuf, "wlfc- generic error: %d", wlfc->stats.generic_error); + return; } @@ -703,13 +696,22 @@ dhd_wlfc_hanger_delete(osl_t *osh, void* hanger) static uint16 dhd_wlfc_hanger_get_free_slot(void* hanger) { - int i; + uint32 i; wlfc_hanger_t* h = (wlfc_hanger_t*)hanger; if (h) { - for (i = 0; i < h->max_items; i++) { - if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) + i = h->slot_pos + 1; + if (i == h->max_items) { + i = 0; + } + while (i != h->slot_pos) { + if (h->items[i].state == WLFC_HANGER_ITEM_STATE_FREE) { + h->slot_pos = i; return (uint16)i; + } + i++; + if (i == h->max_items) + i = 0; } h->failed_slotfind++; } @@ -895,6 +897,7 @@ _dhd_wlfc_pullheader(athost_wl_status_info_t* ctx, void* pktbuf) PKTLEN(ctx->osh, pktbuf), (h->dataOffset << 2))); return BCME_ERROR; } + /* pull wl-header */ PKTPULL(ctx->osh, pktbuf, (h->dataOffset << 2)); return BCME_OK; @@ -933,8 +936,6 @@ _dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, /* put the packet back to the head of queue - - a packet from send-q will need to go back to send-q and not delay-q - since that will change the order of packets. - suppressed packet goes back to suppress sub-queue - pull out the header, if new or delayed packet @@ -958,7 +959,7 @@ _dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, else { /* remove header first */ rc = _dhd_wlfc_pullheader(ctx, p); - if (rc != BCME_OK) { + if (rc != BCME_OK) { WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); /* free the hanger slot */ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); @@ -974,13 +975,7 @@ _dhd_wlfc_rollback_packet_toq(athost_wl_status_info_t* ctx, rc = BCME_ERROR; } } - else { - /* these are going to SENDQ */ - if (WLFC_PKTQ_PENQ_HEAD(&ctx->SENDQ, prec, p) == NULL) { - WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); - rc = BCME_ERROR; - } - } + /* free the hanger slot */ dhd_wlfc_hanger_poppkt(ctx->hanger, hslot, &pktout, 1); @@ -1018,7 +1013,9 @@ _dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint pq->len, if_id, __FUNCTION__)); */ WLFC_DBGMESG(("F")); + dhd_txflowcontrol(ctx->dhdp, if_id, OFF); + ctx->toggle_host_if = 0; } if ((pq->len >= WLFC_FLOWCONTROL_HIWATER) && (ctx->hostif_flow_state[if_id] == OFF)) { @@ -1029,7 +1026,9 @@ _dhd_wlfc_flow_control_check(athost_wl_status_info_t* ctx, struct pktq* pq, uint pq->len, if_id, __FUNCTION__)); */ WLFC_DBGMESG(("N")); + dhd_txflowcontrol(ctx->dhdp, if_id, ON); + ctx->host_ifidx = if_id; ctx->toggle_host_if = 1; } @@ -1176,6 +1175,7 @@ _dhd_wlfc_pretx_pktprocess(athost_wl_status_info_t* ctx, WL_TXSTATUS_SET_FLAGS(htod, WLFC_PKTFLAG_PKTFROMHOST); WL_TXSTATUS_SET_FIFO(htod, DHD_PKTTAG_FIFO(PKTTAG(p))); + if (!DHD_PKTTAG_CREDITCHECK(PKTTAG(p))) { /* Indicate that this packet is being sent in response to an @@ -1287,7 +1287,7 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, * i.e. suppressed packets before delayed ones */ NBITVAL((prec << 1) + 1), &pout); - *needs_hdr = 0; + *needs_hdr = 0; if (p == NULL) { if (entry->suppressed == TRUE) { @@ -1348,56 +1348,44 @@ _dhd_wlfc_deque_delayedq(athost_wl_status_info_t* ctx, return NULL; } -static void* -_dhd_wlfc_deque_sendq(athost_wl_status_info_t* ctx, int prec) +static int +_dhd_wlfc_enque_delayq(athost_wl_status_info_t* ctx, void* pktbuf, int prec) { wlfc_mac_descriptor_t* entry; - void* p; - - p = pktq_pdeq(&ctx->SENDQ, prec); - if (p != NULL) { - if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(p)))) - /* bc/mc packets do not have a delay queue */ - return p; - - entry = _dhd_wlfc_find_table_entry(ctx, p); + if (pktbuf != NULL) { + entry = _dhd_wlfc_find_table_entry(ctx, pktbuf); if (entry == NULL) { WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); - return p; + return BCME_ERROR; } - while ((p != NULL)) { - /* - - suppressed packets go to sub_queue[2*prec + 1] AND - - delayed packets go to sub_queue[2*prec + 0] to ensure - order of delivery. - */ - if (WLFC_PKTQ_PENQ(&entry->psq, (prec << 1), p) == NULL) { - WLFC_DBGMESG(("D")); - /* dhd_txcomplete(ctx->dhdp, p, FALSE); */ - PKTFREE(ctx->osh, p, TRUE); - ctx->stats.delayq_full_error++; - } - /* - A packet has been pushed, update traffic availability bitmap, - if applicable - */ - _dhd_wlfc_traffic_pending_check(ctx, entry, prec); - - p = pktq_pdeq(&ctx->SENDQ, prec); - if (p == NULL) - break; - - entry = _dhd_wlfc_find_table_entry(ctx, p); - - if ((entry == NULL) || (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(p))))) { - return p; - } + /* + - suppressed packets go to sub_queue[2*prec + 1] AND + - delayed packets go to sub_queue[2*prec + 0] to ensure + order of delivery. + */ + if (WLFC_PKTQ_PENQ(&entry->psq, (prec << 1), pktbuf) == NULL) { + WLFC_DBGMESG(("D")); + /* dhd_txcomplete(ctx->dhdp, p, FALSE); */ + PKTFREE(ctx->osh, pktbuf, TRUE); + ctx->stats.delayq_full_error++; + return BCME_ERROR; } + /* + A packet has been pushed, update traffic availability bitmap, + if applicable + */ + _dhd_wlfc_traffic_pending_check(ctx, entry, prec); + } - return p; + return BCME_OK; +} + +bool ifpkt_fn(void* p, int ifid) +{ + return (ifid == DHD_PKTTAG_IF(PKTTAG(p))); } static int @@ -1436,6 +1424,12 @@ _dhd_wlfc_mac_entry_update(athost_wl_status_info_t* ctx, wlfc_mac_descriptor_t* /* enable after packets are queued-deqeued properly. pktq_flush(dhd->osh, &entry->psq, FALSE, NULL, 0); */ + + memset(&entry->ea[0],0, ETHER_ADDR_LEN); + entry->transit_count = 0; + entry->suppr_transit_count = 0; + entry->suppress_count = 0; + entry->suppressed = 0; } return rc; } @@ -1471,12 +1465,16 @@ dhd_wlfc_interface_entry_update(void* state, { athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; wlfc_mac_descriptor_t* entry; + int ret; if (ifid >= WLFC_MAX_IFNUM) return BCME_BADARG; entry = &ctx->destination_entries.interfaces[ifid]; - return _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea); + ret = _dhd_wlfc_mac_entry_update(ctx, entry, action, ifid, iftype, ea); + if (action == eWLFC_MAC_ENTRY_ACTION_DEL) + dhd_wlfc_cleanup(ctx->dhdp, ifpkt_fn, ifid); + return ret; } int @@ -1497,34 +1495,6 @@ dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits) } int -dhd_wlfc_enque_sendq(void* state, int prec, void* p) -{ - athost_wl_status_info_t* ctx = (athost_wl_status_info_t*)state; - - if ((state == NULL) || - /* prec = AC_COUNT is used for bc/mc queue */ - (prec > AC_COUNT) || - (p == NULL)) { - WLFC_DBGMESG(("Error: %s():%d\n", __FUNCTION__, __LINE__)); - return BCME_BADARG; - } - if (FALSE == dhd_prec_enq(ctx->dhdp, &ctx->SENDQ, p, prec)) { - ctx->stats.sendq_full_error++; - /* - WLFC_DBGMESG(("Error: %s():%d, qlen:%d\n", - __FUNCTION__, __LINE__, ctx->SENDQ.len)); - */ - WLFC_HOST_FIFO_DROPPEDCTR_INC(ctx, prec); - WLFC_DBGMESG(("Q")); - PKTFREE(ctx->osh, p, TRUE); - return BCME_ERROR; - } - ctx->stats.pktin++; - /* _dhd_wlfc_flow_control_check(ctx, &ctx->SENDQ, DHD_PKTTAG_IF(PKTTAG(p))); */ - return BCME_OK; -} - -int _dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, dhd_wlfc_commit_info_t *commit_info, f_commitpkt_t fcommit, void* commit_ctx) { @@ -1556,10 +1526,11 @@ _dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, if (rc == BCME_OK) { ctx->stats.pkt2bus++; if (commit_info->ac_fifo_credit_spent) { - ctx->stats.sendq_pkts[ac]++; + ctx->stats.send_pkts[ac]++; WLFC_HOST_FIFO_CREDIT_INC_SENTCTRS(ctx, ac); } - } + } else if (rc == BCME_NORESOURCE) + rc = BCME_ERROR; else { /* bus commit has failed, rollback. @@ -1578,7 +1549,7 @@ _dhd_wlfc_handle_packet_commit(athost_wl_status_info_t* ctx, int ac, } int -dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) +dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx, void *pktbuf) { int ac; int credit; @@ -1610,45 +1581,51 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) low priority packet starvation. */ - for (ac = AC_COUNT; ac >= 0; ac--) { - - int initial_credit_count = ctx->FIFO_credit[ac]; - - /* packets from SENDQ are fresh and they'd need header and have no MAC entry */ - commit_info.needs_hdr = 1; - commit_info.mac_entry = NULL; - commit_info.pkt_type = eWLFC_PKTTYPE_NEW; - - do { - commit_info.p = _dhd_wlfc_deque_sendq(ctx, ac); - if (commit_info.p == NULL) - break; - else if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(commit_info.p)))) { + if (pktbuf) { + ac = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); + if (ETHER_ISMULTI(DHD_PKTTAG_DSTN(PKTTAG(pktbuf)))) { ASSERT(ac == AC_COUNT); - - if (ctx->FIFO_credit[ac]) { - rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, - fcommit, commit_ctx); + commit_info.needs_hdr = 1; + commit_info.mac_entry = NULL; + commit_info.pkt_type = eWLFC_PKTTYPE_NEW; + commit_info.p = pktbuf; + if (ctx->FIFO_credit[ac]) { + rc = _dhd_wlfc_handle_packet_commit(ctx, ac, &commit_info, + fcommit, commit_ctx); /* Bus commits may fail (e.g. flow control); abort after retries */ - if (rc == BCME_OK) { - if (commit_info.ac_fifo_credit_spent) { - (void) _dhd_wlfc_borrow_credit(ctx, - ac_available, ac); - credit_count--; - } - } else { - bus_retry_count++; - if (bus_retry_count >= BUS_RETRIES) { - DHD_ERROR((" %s: bus error\n", - __FUNCTION__)); - return rc; - } + if (rc == BCME_OK) { + if (commit_info.ac_fifo_credit_spent) { + (void) _dhd_wlfc_borrow_credit(ctx, + ac_available, ac); + credit_count--; + } + } else { + bus_retry_count++; + if (bus_retry_count >= BUS_RETRIES) { + DHD_ERROR((" %s: bus error %d\n", + __FUNCTION__, rc)); + return rc; } } } + } + else { + /* en-queue the packets to respective queue. */ + rc = _dhd_wlfc_enque_delayq(ctx, pktbuf, ac); + } + } + + for (ac = AC_COUNT; ac >= 0; ac--) { - } while (commit_info.p); + int initial_credit_count = ctx->FIFO_credit[ac]; + + /* packets from delayQ with less priority are fresh and they'd need header and + * have no MAC entry + */ + commit_info.needs_hdr = 1; + commit_info.mac_entry = NULL; + commit_info.pkt_type = eWLFC_PKTTYPE_NEW; for (credit = 0; credit < ctx->FIFO_credit[ac];) { commit_info.p = _dhd_wlfc_deque_delayedq(ctx, ac, @@ -1674,7 +1651,7 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) else { bus_retry_count++; if (bus_retry_count >= BUS_RETRIES) { - DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n")); + DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); ctx->FIFO_credit[ac] -= credit; return rc; } @@ -1760,7 +1737,7 @@ dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx) else { bus_retry_count++; if (bus_retry_count >= BUS_RETRIES) { - DHD_ERROR(("dhd_wlfc_commit_packets(): bus error\n")); + DHD_ERROR(("%s: bus error %d\n", __FUNCTION__, rc)); return rc; } } @@ -1794,15 +1771,13 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) void* p; int fifo_id; - dhd_os_wlfc_block(dhd); if (DHD_PKTTAG_SIGNALONLY(PKTTAG(txp))) { #ifdef PROP_TXSTATUS_DEBUG wlfc->stats.signal_only_pkts_freed++; #endif + /* is this a signal-only packet? */ if (success) - /* is this a signal-only packet? */ PKTFREE(wlfc->osh, txp, TRUE); - dhd_os_wlfc_unblock(dhd); return; } if (!success) { @@ -1837,10 +1812,182 @@ dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success) PKTFREE(wlfc->osh, txp, TRUE); } - dhd_os_wlfc_unblock(dhd); return; } +static int +dhd_wlfc_compressed_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info, uint8 len) +{ + uint8 status_flag; + uint32 status; + int ret; + int remove_from_hanger = 1; + void* pktbuf; + uint8 fifo_id; + uint8 count = 0; + uint32 status_g; + uint32 hslot, hcnt; + wlfc_mac_descriptor_t* entry = NULL; + athost_wl_status_info_t* wlfc = (athost_wl_status_info_t*) + dhd->wlfc_state; + + memcpy(&status, pkt_info, sizeof(uint32)); + status_flag = WL_TXSTATUS_GET_FLAGS(status); + status_g = status & 0xff000000; + hslot = (status & 0x00ffff00) >> 8; + hcnt = status & 0xff; + len = pkt_info[4]; + + wlfc->stats.txstatus_in++; + + if (status_flag == WLFC_CTL_PKTFLAG_DISCARD) { + wlfc->stats.pkt_freed++; + } + + else if (status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) { + wlfc->stats.d11_suppress++; + remove_from_hanger = 0; + } + + else if (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS) { + wlfc->stats.wl_suppress++; + remove_from_hanger = 0; + } + + else if (status_flag == WLFC_CTL_PKTFLAG_TOSSED_BYWLC) { + wlfc->stats.wlc_tossed_pkts++; + } + while (count < len) { + status = (status_g << 24) | (hslot << 8) | (hcnt); + count++; + hslot++; + hcnt++; + + ret = dhd_wlfc_hanger_poppkt(wlfc->hanger, + WLFC_PKTID_HSLOT_GET(status), &pktbuf, remove_from_hanger); + if (ret != BCME_OK) { + /* do something */ + continue; + } + + entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); + + if (!remove_from_hanger) { + /* this packet was suppressed */ + if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { + entry->suppressed = TRUE; + entry->suppress_count = pktq_mlen(&entry->psq, + NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); + entry->suppr_transit_count = entry->transit_count; + } + entry->generation = WLFC_PKTID_GEN(status); + } + +#ifdef PROP_TXSTATUS_DEBUG + { + uint32 new_t = OSL_SYSUPTIME(); + uint32 old_t; + uint32 delta; + old_t = ((wlfc_hanger_t*)(wlfc->hanger))->items[ + WLFC_PKTID_HSLOT_GET(status)].push_time; + + + wlfc->stats.latency_sample_count++; + if (new_t > old_t) + delta = new_t - old_t; + else + delta = 0xffffffff + new_t - old_t; + wlfc->stats.total_status_latency += delta; + wlfc->stats.latency_most_recent = delta; + + wlfc->stats.deltas[wlfc->stats.idx_delta++] = delta; + if (wlfc->stats.idx_delta == sizeof(wlfc->stats.deltas)/sizeof(uint32)) + wlfc->stats.idx_delta = 0; + } +#endif /* PROP_TXSTATUS_DEBUG */ + + fifo_id = DHD_PKTTAG_FIFO(PKTTAG(pktbuf)); + + /* pick up the implicit credit from this packet */ + if (DHD_PKTTAG_CREDITCHECK(PKTTAG(pktbuf))) { + if (wlfc->proptxstatus_mode == WLFC_FCMODE_IMPLIED_CREDIT) { + + int lender, credit_returned = 0; /* Note that borrower is fifo_id */ + + /* Return credits to highest priority lender first */ + for (lender = AC_COUNT; lender >= 0; lender--) { + if (wlfc->credits_borrowed[fifo_id][lender] > 0) { + wlfc->FIFO_credit[lender]++; + wlfc->credits_borrowed[fifo_id][lender]--; + credit_returned = 1; + break; + } + } + + if (!credit_returned) { + wlfc->FIFO_credit[fifo_id]++; + } + } + } + else { + /* + if this packet did not count against FIFO credit, it must have + taken a requested_credit from the destination entry (for pspoll etc.) + */ + if (!entry) { + + entry = _dhd_wlfc_find_table_entry(wlfc, pktbuf); + } + if (!DHD_PKTTAG_ONETIMEPKTRQST(PKTTAG(pktbuf))) + entry->requested_credit++; +#ifdef PROP_TXSTATUS_DEBUG + entry->dstncredit_acks++; +#endif + } + if ((status_flag == WLFC_CTL_PKTFLAG_D11SUPPRESS) || + (status_flag == WLFC_CTL_PKTFLAG_WLSUPPRESS)) { + + ret = _dhd_wlfc_enque_suppressed(wlfc, fifo_id, pktbuf); + if (ret != BCME_OK) { + /* delay q is full, drop this packet */ + dhd_wlfc_hanger_poppkt(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), + &pktbuf, 1); + + /* indicate failure and free the packet */ + dhd_txcomplete(dhd, pktbuf, FALSE); + entry->transit_count--; + /* packet is transmitted Successfully by dongle + * after first suppress. + */ + if (entry->suppressed) { + entry->suppr_transit_count--; + } + PKTFREE(wlfc->osh, pktbuf, TRUE); + } else { + /* Mark suppressed to avoid a double free during wlfc cleanup */ + + dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, + WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); + entry->suppress_count++; + } + } + else { + dhd_txcomplete(dhd, pktbuf, TRUE); + entry->transit_count--; + + /* This packet is transmitted Successfully by dongle + * even after first suppress. + */ + if (entry->suppressed) { + entry->suppr_transit_count--; + } + /* free the packet */ + PKTFREE(wlfc->osh, pktbuf, TRUE); + } + } + return BCME_OK; +} + /* Handle discard or suppress indication */ static int dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) @@ -1891,7 +2038,7 @@ dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) if (!entry->suppressed || entry->generation != WLFC_PKTID_GEN(status)) { entry->suppressed = TRUE; entry->suppress_count = pktq_mlen(&entry->psq, - NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); + NBITVAL((WL_TXSTATUS_GET_FIFO(status) << 1) + 1)); entry->suppr_transit_count = entry->transit_count; } entry->generation = WLFC_PKTID_GEN(status); @@ -1970,15 +2117,14 @@ dhd_wlfc_txstatus_update(dhd_pub_t *dhd, uint8* pkt_info) /* indicate failure and free the packet */ dhd_txcomplete(dhd, pktbuf, FALSE); entry->transit_count--; - /* This packet is transmitted Successfully by - * dongle even after first suppress. - */ + /* packet is transmitted Successfully by dongle after first suppress. */ if (entry->suppressed) { entry->suppr_transit_count--; } PKTFREE(wlfc->osh, pktbuf, TRUE); } else { /* Mark suppressed to avoid a double free during wlfc cleanup */ + dhd_wlfc_hanger_mark_suppressed(wlfc->hanger, WLFC_PKTID_HSLOT_GET(status), WLFC_PKTID_GEN(status)); entry->suppress_count++; @@ -2293,6 +2439,8 @@ dhd_wlfc_parse_header_info(dhd_pub_t *dhd, void* pktbuf, int tlv_hdr_len, uchar processed += 2 + len; if (type == WLFC_CTL_TYPE_TXSTATUS) dhd_wlfc_txstatus_update(dhd, value); + if (type == WLFC_CTL_TYPE_COMP_TXSTATUS) + dhd_wlfc_compressed_txstatus_update(dhd, value, len); else if (type == WLFC_CTL_TYPE_HOST_REORDER_RXPKTS) dhd_wlfc_reorderinfo_indicate(value, len, reorder_info_buf, @@ -2380,7 +2528,10 @@ dhd_wlfc_enable(dhd_pub_t *dhd) /* allocate space to track txstatus propagated from firmware */ dhd->wlfc_state = MALLOC(dhd->osh, sizeof(athost_wl_status_info_t)); if (dhd->wlfc_state == NULL) + { + DHD_ERROR(("Failed to malloc dhd->wlfc_state\n")); return BCME_NOMEM; + } /* initialize state space */ wlfc = (athost_wl_status_info_t*)dhd->wlfc_state; @@ -2403,12 +2554,6 @@ dhd_wlfc_enable(dhd_pub_t *dhd) wlfc->hostif_flow_state[i] = OFF; } - /* - create the SENDQ containing - sub-queues for all AC precedences + 1 for bc/mc traffic - */ - pktq_init(&wlfc->SENDQ, (AC_COUNT + 1), WLFC_SENDQ_LEN); - wlfc->destination_entries.other.state = WLFC_STATE_OPEN; /* bc/mc FIFO is always open [credit aside], i.e. b[5] */ wlfc->destination_entries.other.ac_bitmap = 0x1f; @@ -2418,15 +2563,15 @@ dhd_wlfc_enable(dhd_pub_t *dhd) wlfc->allow_credit_borrow = TRUE; wlfc->borrow_defer_timestamp = 0; -#if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) - dhdsdio_func_blocksize(dhd, 2, VSDB_F2_BLKSIZE); -#endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) + dhdsdio_func_blocksize(dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY); +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ return BCME_OK; } /* release all packet resources */ void -dhd_wlfc_cleanup(dhd_pub_t *dhd) +dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg) { int i; int total_entries; @@ -2448,29 +2593,25 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) table = (wlfc_mac_descriptor_t*)&wlfc->destination_entries; for (i = 0; i < total_entries; i++) { - if (table[i].occupied) { + if (table[i].occupied && (fn == NULL || (arg == table[i].interface_id))) { if (table[i].psq.len) { WLFC_DBGMESG(("%s(): DELAYQ[%d].len = %d\n", __FUNCTION__, i, table[i].psq.len)); /* release packets held in DELAYQ */ - pktq_flush(wlfc->osh, &table[i].psq, TRUE, NULL, 0); + pktq_flush(wlfc->osh, &table[i].psq, TRUE, fn, arg); } - table[i].occupied = 0; + if (fn == NULL) + table[i].occupied = 0; } } - /* release packets held in SENDQ */ - if (wlfc->SENDQ.len) - pktq_flush(wlfc->osh, &wlfc->SENDQ, TRUE, NULL, 0); for (prec = 0; prec < txq->num_prec; prec++) { - pkt = pktq_pdeq(txq, prec); + pkt = pktq_pdeq_with_fn(txq, prec, fn, arg); while (pkt) { for (i = 0; i < h->max_items; i++) { if (pkt == h->items[i].pkt) { if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; - h->items[i].pkt = NULL; - h->items[i].identifier = 0; } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { /* These are already freed from the psq */ @@ -2485,17 +2626,15 @@ dhd_wlfc_cleanup(dhd_pub_t *dhd) /* flush remained pkt in hanger queue, not in bus->txq */ for (i = 0; i < h->max_items; i++) { if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE) { - if (!dhd->hang_was_sent) { + if (fn == NULL || (*fn)(h->items[i].pkt, arg)) { PKTFREE(wlfc->osh, h->items[i].pkt, TRUE); - } else { - printk("%s: Skip freeing skb %p\n", __func__, h->items[i].pkt); + h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; } - h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; - h->items[i].pkt = NULL; - h->items[i].identifier = 0; } else if (h->items[i].state == WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED) { - /* These are freed from the psq so no need to free again */ - h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; + if (fn == NULL || (*fn)(h->items[i].pkt, arg)) { + /* These are freed from the psq so no need to free again */ + h->items[i].state = WLFC_HANGER_ITEM_STATE_FREE; + } } } return; @@ -2513,6 +2652,7 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) dhd_os_wlfc_unblock(dhd); return; } + #ifdef PROP_TXSTATUS_DEBUG { int i; @@ -2532,10 +2672,10 @@ dhd_wlfc_deinit(dhd_pub_t *dhd) /* free top structure */ MFREE(dhd->osh, dhd->wlfc_state, sizeof(athost_wl_status_info_t)); dhd->wlfc_state = NULL; -#if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) - dhdsdio_func_blocksize(dhd, 2, sd_f2_blocksize); -#endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ dhd_os_wlfc_unblock(dhd); +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) + dhdsdio_func_blocksize(dhd, 2, sd_f2_blocksize); +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ return; } #endif /* PROP_TXSTATUS */ @@ -2545,15 +2685,17 @@ dhd_prot_dump(dhd_pub_t *dhdp, struct bcmstrbuf *strbuf) { bcm_bprintf(strbuf, "Protocol CDC: reqid %d\n", dhdp->prot->reqid); #ifdef PROP_TXSTATUS - dhd_os_wlfc_block(dhdp); if (dhdp->wlfc_state) dhd_wlfc_dump(dhdp, strbuf); - dhd_os_wlfc_unblock(dhdp); #endif } +/* The FreeBSD PKTPUSH could change the packet buf pinter + so we need to make it changable +*/ +#define PKTBUF pktbuf void -dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) +dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *PKTBUF) { #ifdef BDC struct bdc_header *h; @@ -2564,21 +2706,22 @@ dhd_prot_hdrpush(dhd_pub_t *dhd, int ifidx, void *pktbuf) #ifdef BDC /* Push BDC header used to convey priority for buses that don't */ - PKTPUSH(dhd->osh, pktbuf, BDC_HEADER_LEN); + PKTPUSH(dhd->osh, PKTBUF, BDC_HEADER_LEN); - h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); + h = (struct bdc_header *)PKTDATA(dhd->osh, PKTBUF); h->flags = (BDC_PROTO_VER << BDC_FLAG_VER_SHIFT); - if (PKTSUMNEEDED(pktbuf)) + if (PKTSUMNEEDED(PKTBUF)) h->flags |= BDC_FLAG_SUM_NEEDED; - h->priority = (PKTPRIO(pktbuf) & BDC_PRIORITY_MASK); + h->priority = (PKTPRIO(PKTBUF) & BDC_PRIORITY_MASK); h->flags2 = 0; h->dataOffset = 0; #endif /* BDC */ BDC_SET_IF_IDX(h, ifidx); } +#undef PKTBUF /* Only defined in the above routine */ int dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_info, @@ -2587,6 +2730,7 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in #ifdef BDC struct bdc_header *h; #endif + uint8 data_offset = 0; DHD_TRACE(("%s: Enter\n", __FUNCTION__)); @@ -2603,15 +2747,23 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in h = (struct bdc_header *)PKTDATA(dhd->osh, pktbuf); +#if defined(NDIS630) + h->dataOffset = 0; +#endif + + if (!ifidx) { + /* for tx packet, skip the analysis */ + data_offset = h->dataOffset; + PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); + goto exit; + } + if ((*ifidx = BDC_GET_IF_IDX(h)) >= DHD_MAX_IFS) { DHD_ERROR(("%s: rx data ifnum out of range (%d)\n", __FUNCTION__, *ifidx)); return BCME_ERROR; } -#if defined(NDIS630) - h->dataOffset = 0; -#endif if (((h->flags & BDC_FLAG_VER_MASK) >> BDC_FLAG_VER_SHIFT) != BDC_PROTO_VER) { DHD_ERROR(("%s: non-BDC packet received, flags = 0x%x\n", dhd_ifname(dhd, *ifidx), h->flags)); @@ -2628,17 +2780,19 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in } PKTSETPRIO(pktbuf, (h->priority & BDC_PRIORITY_MASK)); + data_offset = h->dataOffset; PKTPULL(dhd->osh, pktbuf, BDC_HEADER_LEN); #endif /* BDC */ #if !defined(NDIS630) - if (PKTLEN(dhd->osh, pktbuf) < (uint32) (h->dataOffset << 2)) { + if (PKTLEN(dhd->osh, pktbuf) < (uint32) (data_offset << 2)) { DHD_ERROR(("%s: rx data too short (%d < %d)\n", __FUNCTION__, - PKTLEN(dhd->osh, pktbuf), (h->dataOffset * 4))); + PKTLEN(dhd->osh, pktbuf), (data_offset * 4))); return BCME_ERROR; } #endif #ifdef PROP_TXSTATUS + dhd_os_wlfc_block(dhd); if (dhd->wlfc_state && ((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode != WLFC_FCMODE_NONE && @@ -2646,21 +2800,36 @@ dhd_prot_hdrpull(dhd_pub_t *dhd, int *ifidx, void *pktbuf, uchar *reorder_buf_in /* - parse txstatus only for packets that came from the firmware */ - dhd_os_wlfc_block(dhd); - dhd_wlfc_parse_header_info(dhd, pktbuf, (h->dataOffset << 2), + dhd_wlfc_parse_header_info(dhd, pktbuf, (data_offset << 2), reorder_buf_info, reorder_info_len); ((athost_wl_status_info_t*)dhd->wlfc_state)->stats.dhd_hdrpulls++; - dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, - (void *)dhd->bus); - dhd_os_wlfc_unblock(dhd); } + dhd_os_wlfc_unblock(dhd); #endif /* PROP_TXSTATUS */ + +exit: #if !defined(NDIS630) - PKTPULL(dhd->osh, pktbuf, (h->dataOffset << 2)); + PKTPULL(dhd->osh, pktbuf, (data_offset << 2)); #endif return 0; } +#if defined(PROP_TXSTATUS) +void +dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd) +{ + dhd_os_wlfc_block(dhd); + if (dhd->wlfc_state && + (((athost_wl_status_info_t*)dhd->wlfc_state)->proptxstatus_mode + != WLFC_FCMODE_NONE)) { + dhd_wlfc_commit_packets(dhd->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, + (void *)dhd->bus, NULL); + } + dhd_os_wlfc_unblock(dhd); +} +#endif + + int dhd_prot_attach(dhd_pub_t *dhd) { @@ -2735,15 +2904,15 @@ dhd_prot_init(dhd_pub_t *dhd) goto done; -#ifdef PROP_TXSTATUS - ret = dhd_wlfc_init(dhd); -#endif - #if defined(WL_CFG80211) if (dhd_download_fw_on_driverload) #endif /* defined(WL_CFG80211) */ ret = dhd_preinit_ioctls(dhd); +#ifdef PROP_TXSTATUS + ret = dhd_wlfc_init(dhd); +#endif + /* Always assumes wl for now */ dhd->iswl = TRUE; @@ -2777,7 +2946,7 @@ dhd_get_hostreorder_pkts(void *osh, struct reorder_info *ptr, void **pkt, i = ptr->max_idx + 1; else { if (start > end) - i = (ptr->max_idx - end) + start; + i = ((ptr->max_idx + 1) - start) + end; else i = end - start; } @@ -2844,7 +3013,7 @@ dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, uint reord __FUNCTION__, flow_id)); if (ptr == NULL) { - DHD_ERROR(("%s: received flags to cleanup, but no flow (%d) yet\n", + DHD_REORDER(("%s: received flags to cleanup, but no flow (%d) yet\n", __FUNCTION__, flow_id)); *pkt_count = 1; *pkt = cur_pkt; diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c index e6a6837..781a78b 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.c @@ -82,9 +82,11 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val) dhd->op_mode |= val; WL_ERR(("Set : op_mode=0x%04x\n", dhd->op_mode)); #ifdef ARP_OFFLOAD_SUPPORT - /* IF P2P is enabled, disable arpoe */ - dhd_arp_offload_set(dhd, 0); - dhd_arp_offload_enable(dhd, false); + if (dhd->arp_version == 1) { + /* IF P2P is enabled, disable arpoe */ + dhd_arp_offload_set(dhd, 0); + dhd_arp_offload_enable(dhd, false); + } #endif /* ARP_OFFLOAD_SUPPORT */ return 0; @@ -96,10 +98,12 @@ s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl) dhd->op_mode &= ~(DHD_FLAG_P2P_GC_MODE | DHD_FLAG_P2P_GO_MODE); WL_ERR(("Clean : op_mode=0x%04x\n", dhd->op_mode)); -#if defined(ARP_OFFLOAD_SUPPORT) - /* IF P2P is disabled, enable arpoe back for STA mode. */ - dhd_arp_offload_set(dhd, dhd_arp_mode); - dhd_arp_offload_enable(dhd, true); +#ifdef ARP_OFFLOAD_SUPPORT + if (dhd->arp_version == 1) { + /* IF P2P is disabled, enable arpoe back for STA mode. */ + dhd_arp_offload_set(dhd, dhd_arp_mode); + dhd_arp_offload_enable(dhd, true); + } #endif /* ARP_OFFLOAD_SUPPORT */ return 0; @@ -148,6 +152,43 @@ default_conf_out: } +#ifdef CONFIG_NL80211_TESTMODE +int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + struct sk_buff *reply; + struct wl_priv *wl; + dhd_pub_t *dhd; + dhd_ioctl_t *ioc = data; + int err = 0; + + WL_TRACE(("entry: cmd = %d\n", ioc->cmd)); + wl = wiphy_priv(wiphy); + dhd = wl->pub; + + DHD_OS_WAKE_LOCK(dhd); + + /* send to dongle only if we are not waiting for reload already */ + if (dhd->hang_was_sent) { + WL_ERR(("HANG was sent up earlier\n")); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhd, DHD_EVENT_TIMEOUT_MS); + DHD_OS_WAKE_UNLOCK(dhd); + return OSL_ERROR(BCME_DONGLE_DOWN); + } + + /* currently there is only one wiphy for ifidx 0 */ + err = dhd_ioctl_process(dhd, 0, ioc); + if (err) + goto done; + + /* response data is in ioc->buf so return ioc here */ + reply = cfg80211_testmode_alloc_reply_skb(wiphy, sizeof(*ioc)); + nla_put(reply, NL80211_ATTR_TESTDATA, sizeof(*ioc), ioc); + err = cfg80211_testmode_reply(reply); +done: + DHD_OS_WAKE_UNLOCK(dhd); + return err; +} +#endif /* CONFIG_NL80211_TESTMODE */ /* TODO: clean up the BT-Coex code, it still have some legacy ioctl/iovar functions */ #define COEX_DHCP @@ -233,11 +274,10 @@ static bool btcoex_is_sco_active(struct net_device *dev) ioc_res = dev_wlc_intvar_get_reg(dev, "btc_params", 27, ¶m27); - WL_TRACE(("%s, sample[%d], btc params: 27:%x\n", - __FUNCTION__, i, param27)); + WL_TRACE(("sample[%d], btc params: 27:%x\n", i, param27)); if (ioc_res < 0) { - WL_ERR(("%s ioc read btc params error\n", __FUNCTION__)); + WL_ERR(("ioc read btc params error\n")); break; } @@ -246,8 +286,7 @@ static bool btcoex_is_sco_active(struct net_device *dev) } if (sco_id_cnt > 2) { - WL_TRACE(("%s, sco/esco detected, pkt id_cnt:%d samples:%d\n", - __FUNCTION__, sco_id_cnt, i)); + WL_TRACE(("sco/esco detected, pkt id_cnt:%d samples:%d\n", sco_id_cnt, i)); res = TRUE; break; } @@ -295,9 +334,9 @@ static int set_btc_esco_params(struct net_device *dev, bool trump_sco) (!dev_wlc_intvar_get_reg(dev, "btc_params", 65, &saved_reg65)) && (!dev_wlc_intvar_get_reg(dev, "btc_params", 71, &saved_reg71))) { saved_status = TRUE; - WL_TRACE(("%s saved bt_params[50,51,64,65,71]:" + WL_TRACE(("saved bt_params[50,51,64,65,71]:" "0x%x 0x%x 0x%x 0x%x 0x%x\n", - __FUNCTION__, saved_reg50, saved_reg51, + saved_reg50, saved_reg51, saved_reg64, saved_reg65, saved_reg71)); } else { WL_ERR((":%s: save btc_params failed\n", @@ -394,7 +433,7 @@ wl_cfg80211_bt_setflag(struct net_device *dev, bool set) static void wl_cfg80211_bt_timerfunc(ulong data) { struct btcoex_info *bt_local = (struct btcoex_info *)data; - WL_TRACE(("%s\n", __FUNCTION__)); + WL_TRACE(("Enter\n")); bt_local->timer_on = 0; schedule_work(&bt_local->work); } @@ -415,8 +454,7 @@ static void wl_cfg80211_bt_handler(struct work_struct *work) /* DHCP started * provide OPPORTUNITY window to get DHCP address */ - WL_TRACE(("%s bt_dhcp stm: started \n", - __FUNCTION__)); + WL_TRACE(("bt_dhcp stm: started \n")); btcx_inf->bt_state = BT_DHCP_OPPR_WIN; mod_timer(&btcx_inf->timer, jiffies + msecs_to_jiffies(BT_DHCP_OPPR_WIN_TIME)); @@ -425,16 +463,14 @@ static void wl_cfg80211_bt_handler(struct work_struct *work) case BT_DHCP_OPPR_WIN: if (btcx_inf->dhcp_done) { - WL_TRACE(("%s DHCP Done before T1 expiration\n", - __FUNCTION__)); + WL_TRACE(("DHCP Done before T1 expiration\n")); goto btc_coex_idle; } /* DHCP is not over yet, start lowering BT priority * enforce btc_params + flags if necessary */ - WL_TRACE(("%s DHCP T1:%d expired\n", __FUNCTION__, - BT_DHCP_OPPR_WIN_TIME)); + WL_TRACE(("DHCP T1:%d expired\n", BT_DHCP_OPPR_WIN_TIME)); if (btcx_inf->dev) wl_cfg80211_bt_setflag(btcx_inf->dev, TRUE); btcx_inf->bt_state = BT_DHCP_FLAG_FORCE_TIMEOUT; @@ -445,13 +481,11 @@ static void wl_cfg80211_bt_handler(struct work_struct *work) case BT_DHCP_FLAG_FORCE_TIMEOUT: if (btcx_inf->dhcp_done) { - WL_TRACE(("%s DHCP Done before T2 expiration\n", - __FUNCTION__)); + WL_TRACE(("DHCP Done before T2 expiration\n")); } else { /* Noo dhcp during T1+T2, restore BT priority */ - WL_TRACE(("%s DHCP wait interval T2:%d" - "msec expired\n", __FUNCTION__, - BT_DHCP_FLAG_FORCE_TIME)); + WL_TRACE(("DHCP wait interval T2:%d msec expired\n", + BT_DHCP_FLAG_FORCE_TIME)); } /* Restoring default bt priority */ @@ -463,8 +497,7 @@ btc_coex_idle: break; default: - WL_ERR(("%s error g_status=%d !!!\n", __FUNCTION__, - btcx_inf->bt_state)); + WL_ERR(("error g_status=%d !!!\n", btcx_inf->bt_state)); if (btcx_inf->dev) wl_cfg80211_bt_setflag(btcx_inf->dev, FALSE); btcx_inf->bt_state = BT_DHCP_IDLE; @@ -505,7 +538,7 @@ void wl_cfg80211_btcoex_deinit(struct wl_priv *wl) if (!wl->btcoex_info) return; - if (!wl->btcoex_info->timer_on) { + if (wl->btcoex_info->timer_on) { wl->btcoex_info->timer_on = 0; del_timer_sync(&wl->btcoex_info->timer); } @@ -515,7 +548,6 @@ void wl_cfg80211_btcoex_deinit(struct wl_priv *wl) kfree(wl->btcoex_info); wl->btcoex_info = NULL; } -#endif int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) { @@ -545,7 +577,7 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) strncpy((char *)&powermode_val, command + strlen("BTCOEXMODE") +1, 1); if (strnicmp((char *)&powermode_val, "1", strlen("1")) == 0) { - WL_TRACE_HW4(("%s: DHCP session starts\n", __FUNCTION__)); + WL_TRACE_HW4(("DHCP session starts\n")); #ifdef PKT_FILTER_SUPPORT dhd->dhcp_in_progress = 1; @@ -588,13 +620,12 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) btco_inf->bt_state = BT_DHCP_START; btco_inf->timer_on = 1; mod_timer(&btco_inf->timer, btco_inf->timer.expires); - WL_TRACE(("%s enable BT DHCP Timer\n", - __FUNCTION__)); + WL_TRACE(("enable BT DHCP Timer\n")); } #endif /* COEX_DHCP */ } else if (saved_status == TRUE) { - WL_ERR(("%s was called w/o DHCP OFF. Continue\n", __FUNCTION__)); + WL_ERR(("was called w/o DHCP OFF. Continue\n")); } } else if (strnicmp((char *)&powermode_val, "2", strlen("2")) == 0) { @@ -602,7 +633,7 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) #ifdef PKT_FILTER_SUPPORT dhd->dhcp_in_progress = 0; - WL_TRACE_HW4(("%s: DHCP is complete \n", __FUNCTION__)); + WL_TRACE_HW4(("DHCP is complete \n")); /* Enable packet filtering */ if (dhd->early_suspended) { @@ -615,15 +646,14 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) #ifdef COEX_DHCP /* Stop any bt timer because DHCP session is done */ - WL_TRACE(("%s disable BT DHCP Timer\n", __FUNCTION__)); + WL_TRACE(("disable BT DHCP Timer\n")); if (btco_inf->timer_on) { btco_inf->timer_on = 0; del_timer_sync(&btco_inf->timer); if (btco_inf->bt_state != BT_DHCP_IDLE) { /* need to restore original btc flags & extra btc params */ - WL_TRACE(("%s bt->bt_state:%d\n", - __FUNCTION__, btco_inf->bt_state)); + WL_TRACE(("bt->bt_state:%d\n", btco_inf->bt_state)); /* wake up btcoex thread to restore btlags+params */ schedule_work(&btco_inf->work); } @@ -654,11 +684,11 @@ int wl_cfg80211_set_btcoex_dhcp(struct net_device *dev, char *command) } else { - WL_ERR(("%s Unkwown yet power setting, ignored\n", - __FUNCTION__)); + WL_ERR(("Unkwown yet power setting, ignored\n")); } snprintf(command, 3, "OK"); return (strlen("OK")); } +#endif diff --git a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h index 922d6ed..985d9d2 100644 --- a/drivers/net/wireless/bcmdhd/dhd_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/dhd_cfg80211.h @@ -38,6 +38,15 @@ s32 dhd_cfg80211_set_p2p_info(struct wl_priv *wl, int val); s32 dhd_cfg80211_clean_p2p_info(struct wl_priv *wl); s32 dhd_config_dongle(struct wl_priv *wl, bool need_lock); +#ifdef CONFIG_NL80211_TESTMODE +int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len); +#else +static inline int dhd_cfg80211_testmode_cmd(struct wiphy *wiphy, void *data, int len) +{ + return 0; +} +#endif + int wl_cfg80211_btcoex_init(struct wl_priv *wl); void wl_cfg80211_btcoex_deinit(struct wl_priv *wl); diff --git a/drivers/net/wireless/bcmdhd/dhd_common.c b/drivers/net/wireless/bcmdhd/dhd_common.c index dab9686..c4ac414 100644 --- a/drivers/net/wireless/bcmdhd/dhd_common.c +++ b/drivers/net/wireless/bcmdhd/dhd_common.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_common.c 356374 2012-09-12 10:37:44Z $ + * $Id: dhd_common.c 383289 2013-02-06 06:42:35Z $ */ #include <typedefs.h> #include <osl.h> @@ -278,12 +278,12 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le ret = dhd_prot_ioctl(dhd_pub, ifindex, ioc, buf, len); #if defined(CUSTOMER_HW4) - if ((ret || ret == -ETIMEDOUT) && (dhd_pub->up)) + if ((ret || ret == -ETIMEDOUT) && (dhd_pub->up)) #else - if ((ret) && (dhd_pub->up)) + if ((ret) && (dhd_pub->up)) #endif /* CUSTOMER_HW4 */ - /* Send hang event only if dhd_open() was success */ - dhd_os_check_hang(dhd_pub, ifindex, ret); + /* Send hang event only if dhd_open() was success */ + dhd_os_check_hang(dhd_pub, ifindex, ret); dhd_os_proto_unblock(dhd_pub); @@ -299,7 +299,7 @@ dhd_wl_ioctl(dhd_pub_t *dhd_pub, int ifindex, wl_ioctl_t *ioc, void *buf, int le DHD_ERROR(("%s: WLC_IOCTL: cmd: %d, ret = %d\n", __FUNCTION__, ioc->cmd, ret)); } -#endif +#endif /* OEM_ANDROID && CUSTOMER_HW4 */ return ret; } @@ -579,7 +579,8 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) if (pktq_pfull(q, prec)) eprec = prec; else if (pktq_full(q)) { - pktq_peek_tail(q, &eprec); + p = pktq_peek_tail(q, &eprec); + ASSERT(p); if (eprec > prec || eprec < 0) return FALSE; } @@ -599,7 +600,8 @@ dhd_prec_enq(dhd_pub_t *dhdp, struct pktq *q, void *pkt, int prec) } /* Enqueue */ - pktq_penq(q, prec, pkt); + p = pktq_penq(q, prec, pkt); + ASSERT(p); return TRUE; } @@ -677,7 +679,7 @@ dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buflen) case DHD_GET_VERSION: if (buflen < sizeof(int)) - bcmerror = -BCME_BUFTOOSHORT; + bcmerror = BCME_BUFTOOSHORT; else *(int*)buf = DHD_IOCTL_VERSION; break; @@ -967,6 +969,12 @@ wl_show_host_event(wl_event_msg_t *event, void *event_data) DHD_EVENT(("MACEVENT: %s %d\n", event_name, ntoh32(*((int *)event_data)))); break; + case WLC_E_SERVICE_FOUND: + case WLC_E_P2PO_ADD_DEVICE: + case WLC_E_P2PO_DEL_DEVICE: + DHD_EVENT(("MACEVENT: %s, MAC %s\n", event_name, eabuf)); + break; + default: DHD_EVENT(("MACEVENT: %s %d, MAC %s, status %d, reason %d, auth %d\n", event_name, event_type, eabuf, (int)status, (int)reason, @@ -1034,6 +1042,11 @@ wl_host_event(dhd_pub_t *dhd_pub, int *ifidx, void *pktdata, case WLC_E_IF: { dhd_if_event_t *ifevent = (dhd_if_event_t *)event_data; + /* Ignore the event if NOIF is set */ + if (ifevent->flags & WLC_E_IF_FLAGS_BSSCFG_NOIF) { + DHD_ERROR(("WLC_E_IF: NO_IF set, event Ignored\r\n")); + return (BCME_OK); + } #ifdef PROP_TXSTATUS { uint8* ea = pvt_data->eth.ether_dhost; @@ -1454,10 +1467,10 @@ dhd_arp_offload_set(dhd_pub_t * dhd, int arp_mode) retcode = retcode >= 0 ? 0 : retcode; if (retcode) DHD_TRACE(("%s: failed to set ARP offload mode to 0x%x, retcode = %d\n", - __FUNCTION__, arp_mode, retcode)); + __FUNCTION__, arp_mode, retcode)); else DHD_TRACE(("%s: successfully set ARP offload mode to 0x%x\n", - __FUNCTION__, arp_mode)); + __FUNCTION__, arp_mode)); } void @@ -1471,49 +1484,73 @@ dhd_arp_offload_enable(dhd_pub_t * dhd, int arp_enable) retcode = retcode >= 0 ? 0 : retcode; if (retcode) DHD_TRACE(("%s: failed to enabe ARP offload to %d, retcode = %d\n", - __FUNCTION__, arp_enable, retcode)); + __FUNCTION__, arp_enable, retcode)); else DHD_TRACE(("%s: successfully enabed ARP offload to %d\n", - __FUNCTION__, arp_enable)); + __FUNCTION__, arp_enable)); + if (arp_enable) { + uint32 version; + bcm_mkiovar("arp_version", 0, 0, iovbuf, sizeof(iovbuf)); + retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0); + if (retcode) { + DHD_INFO(("%s: fail to get version (maybe version 1:retcode = %d\n", + __FUNCTION__, retcode)); + dhd->arp_version = 1; + } + else { + memcpy(&version, iovbuf, sizeof(version)); + DHD_INFO(("%s: ARP Version= %x\n", __FUNCTION__, version)); + dhd->arp_version = version; + } + } } void -dhd_aoe_arp_clr(dhd_pub_t *dhd) +dhd_aoe_arp_clr(dhd_pub_t *dhd, int idx) { int ret = 0; int iov_len = 0; char iovbuf[128]; if (dhd == NULL) return; + if (dhd->arp_version == 1) + idx = 0; iov_len = bcm_mkiovar("arp_table_clear", 0, 0, iovbuf, sizeof(iovbuf)); - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0) < 0)) + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0) DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); } void -dhd_aoe_hostip_clr(dhd_pub_t *dhd) +dhd_aoe_hostip_clr(dhd_pub_t *dhd, int idx) { int ret = 0; int iov_len = 0; char iovbuf[128]; if (dhd == NULL) return; + if (dhd->arp_version == 1) + idx = 0; iov_len = bcm_mkiovar("arp_hostip_clear", 0, 0, iovbuf, sizeof(iovbuf)); - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0)) < 0) + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx)) < 0) DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); } void -dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr) +dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr, int idx) { int iov_len = 0; char iovbuf[32]; int retcode; - iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, 4, iovbuf, sizeof(iovbuf)); - retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, 0); + + if (dhd == NULL) return; + if (dhd->arp_version == 1) + idx = 0; + iov_len = bcm_mkiovar("arp_hostip", (char *)&ipaddr, + sizeof(ipaddr), iovbuf, sizeof(iovbuf)); + retcode = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, iov_len, TRUE, idx); if (retcode) DHD_TRACE(("%s: ARP ip addr add failed, retcode = %d\n", @@ -1524,7 +1561,7 @@ dhd_arp_offload_add_ip(dhd_pub_t *dhd, uint32 ipaddr) } int -dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen) +dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen, int idx) { int retcode, i; int iov_len; @@ -1533,10 +1570,13 @@ dhd_arp_get_arp_hostip_table(dhd_pub_t *dhd, void *buf, int buflen) if (!buf) return -1; + if (dhd == NULL) return -1; + if (dhd->arp_version == 1) + idx = 0; iov_len = bcm_mkiovar("arp_hostip", 0, 0, buf, buflen); BCM_REFERENCE(iov_len); - retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, FALSE, 0); + retcode = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, buf, buflen, FALSE, idx); if (retcode) { DHD_TRACE(("%s: ioctl WLC_GET_VAR error %d\n", @@ -1804,16 +1844,12 @@ bool dhd_is_associated(dhd_pub_t *dhd, void *bss_buf, int *retval) /* Function to estimate possible DTIM_SKIP value */ int -dhd_get_dtim_skip(dhd_pub_t *dhd) +dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd) { - int bcn_li_dtim; + int bcn_li_dtim = 1; /* deafult no dtim skip setting */ int ret = -1; int dtim_assoc = 0; - - if ((dhd->dtim_skip == 0) || (dhd->dtim_skip == 1)) - bcn_li_dtim = 3; - else - bcn_li_dtim = dhd->dtim_skip; + int ap_beacon = 0; /* Check if associated */ if (dhd_is_associated(dhd, NULL, NULL) == FALSE) { @@ -1821,21 +1857,34 @@ dhd_get_dtim_skip(dhd_pub_t *dhd) goto exit; } - /* if assoc grab ap's dtim value */ + /* read associated AP beacon interval */ + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_BCNPRD, + &ap_beacon, sizeof(ap_beacon), FALSE, 0)) < 0) { + DHD_ERROR(("%s get beacon failed code %d\n", __FUNCTION__, ret)); + goto exit; + } + + /* if associated APs Beacon more that 100msec do no dtim skip */ + if (ap_beacon > MAX_DTIM_SKIP_BEACON_ITERVAL) { + DHD_ERROR(("%s NO dtim skip for AP with beacon %d ms\n", __FUNCTION__, ap_beacon)); + goto exit; + } + + /* read associated ap's dtim setup */ if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_DTIMPRD, &dtim_assoc, sizeof(dtim_assoc), FALSE, 0)) < 0) { DHD_ERROR(("%s failed code %d\n", __FUNCTION__, ret)); goto exit; } - DHD_ERROR(("%s bcn_li_dtim=%d DTIM=%d Listen=%d\n", - __FUNCTION__, bcn_li_dtim, dtim_assoc, LISTEN_INTERVAL)); - /* if not assocated just eixt */ if (dtim_assoc == 0) { goto exit; } + /* attemp to use platform defined dtim skip interval */ + bcn_li_dtim = dhd->suspend_bcn_li_dtim; + /* check if sta listen interval fits into AP dtim */ if (dtim_assoc > LISTEN_INTERVAL) { /* AP DTIM to big for our Listen Interval : no dtim skiping */ @@ -1851,6 +1900,9 @@ dhd_get_dtim_skip(dhd_pub_t *dhd) DHD_TRACE(("%s agjust dtim_skip as %d\n", __FUNCTION__, bcn_li_dtim)); } + DHD_ERROR(("%s beacon=%d bcn_li_dtim=%d DTIM=%d Listen=%d\n", + __FUNCTION__, ap_beacon, bcn_li_dtim, dtim_assoc, LISTEN_INTERVAL)); + exit: return bcn_li_dtim; } @@ -1959,7 +2011,6 @@ dhd_pno_set(dhd_pub_t *dhd, wlc_ssid_t* ssids_local, int nssid, ushort scan_fr, err = -1; return err; } - #ifndef WL_SCHED_SCAN if (!dhd_support_sta_mode(dhd)) return err; @@ -2074,7 +2125,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) { char buf[256]; const char *str; - wl_mkeep_alive_pkt_t mkeep_alive_pkt; + wl_mkeep_alive_pkt_t mkeep_alive_pkt = {0}; wl_mkeep_alive_pkt_t *mkeep_alive_pktp; int buf_len; int str_len; @@ -2090,7 +2141,7 @@ int dhd_keep_alive_onoff(dhd_pub_t *dhd) strncpy(buf, str, str_len); buf[ str_len ] = '\0'; mkeep_alive_pktp = (wl_mkeep_alive_pkt_t *) (buf + str_len + 1); - mkeep_alive_pkt.period_msec = KEEP_ALIVE_PERIOD; + mkeep_alive_pkt.period_msec = CUSTOM_KEEP_ALIVE_SETTING; buf_len = str_len + 1; mkeep_alive_pkt.version = htod16(WL_MKEEP_ALIVE_VERSION); mkeep_alive_pkt.length = htod16(WL_MKEEP_ALIVE_FIXED_LEN); diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c index 9421e98..ba833b3 100644 --- a/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_gpio.c @@ -20,7 +20,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * -* $Id: dhd_custom_gpio.c 353167 2012-08-24 22:11:30Z $ +* $Id: dhd_custom_gpio.c 353280 2012-08-26 04:33:17Z $ */ #include <typedefs.h> diff --git a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c index 1683501..be129b5 100644..100755 --- a/drivers/net/wireless/bcmdhd/dhd_custom_sec.c +++ b/drivers/net/wireless/bcmdhd/dhd_custom_sec.c @@ -2,13 +2,13 @@ * Customer HW 4 dependant file * * Copyright (C) 1999-2012, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,7 +16,7 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. @@ -49,9 +49,18 @@ struct cntry_locales_custom { /* Locale table for sec */ const struct cntry_locales_custom translate_custom_table[] = { -#ifdef BCM4334_CHIP - {"", "XZ", 11}, /* Universal if Country code is unknown or empty */ +#if defined(BCM4334_CHIP) || defined(BCM43241_CHIP) || defined(BCM4335_CHIP) + {"", "XZ", 11}, /* Universal if Country code is unknown or empty */ + {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */ + {"SD", "XZ", 11}, /* Universal if Country code is SUDAN */ + {"SY", "XZ", 11}, /* Universal if Country code is SYRIAN ARAB REPUBLIC */ + {"GL", "XZ", 11}, /* Universal if Country code is GREENLAND */ + {"PS", "XZ", 11}, /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */ + {"TL", "XZ", 11}, /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */ + {"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */ + {"PK", "XZ", 11}, /* Universal if Country code is PAKISTAN */ #endif +#if defined(BCM4330_CHIP) || defined(BCM4334_CHIP) || defined(BCM43241_CHIP) {"AE", "AE", 1}, {"AR", "AR", 1}, {"AT", "AT", 1}, @@ -61,7 +70,6 @@ const struct cntry_locales_custom translate_custom_table[] = { {"BN", "BN", 1}, {"CA", "CA", 2}, {"CH", "CH", 1}, - {"CN", "CN", 0}, {"CY", "CY", 1}, {"CZ", "CZ", 1}, {"DE", "DE", 3}, @@ -84,7 +92,6 @@ const struct cntry_locales_custom translate_custom_table[] = { {"LT", "LT", 1}, {"LU", "LU", 1}, {"LV", "LV", 1}, - {"MA", "MA", 1}, {"MT", "MT", 1}, {"MX", "MX", 1}, {"NL", "NL", 1}, @@ -96,26 +103,175 @@ const struct cntry_locales_custom translate_custom_table[] = { {"SE", "SE", 1}, {"SI", "SI", 1}, {"SK", "SK", 1}, - {"TR", "TR", 7}, - {"UA", "UA", 2}, {"TW", "TW", 2}, - {"IR", "XZ", 11}, /* Universal if Country code is IRAN, (ISLAMIC REPUBLIC OF) */ - {"SD", "XZ", 11}, /* Universal if Country code is SUDAN */ - {"SY", "XZ", 11}, /* Universal if Country code is SYRIAN ARAB REPUBLIC */ - {"GL", "XZ", 11}, /* Universal if Country code is GREENLAND */ - {"PS", "XZ", 11}, /* Universal if Country code is PALESTINIAN TERRITORY, OCCUPIED */ - {"TL", "XZ", 11}, /* Universal if Country code is TIMOR-LESTE (EAST TIMOR) */ - {"MH", "XZ", 11}, /* Universal if Country code is MARSHALL ISLANDS */ - {"PK", "XZ", 11}, /* Universal if Country code is PAKISTAN */ -#ifdef BCM4334_CHIP - {"RU", "RU", 5}, +#endif /* defined(BCM4330_CHIP) || defined(BCM4334_CHIP) || defined(BCM43241_CHIP) */ +#if defined(BCM4334_CHIP) || defined(BCM43241_CHIP) + {"RU", "RU", 13}, {"SG", "SG", 4}, - {"US", "US", 46} -#endif + {"US", "US", 46}, + {"UA", "UA", 8}, + {"CO", "CO", 4}, + {"ID", "ID", 1}, + {"LA", "LA", 1}, + {"LB", "LB", 2}, + {"VN", "VN", 4}, + {"MA", "MA", 1}, + {"TR", "TR", 7}, +#endif /* defined(BCM4334_CHIP) || defined(BCM43241_CHIP) */ #ifdef BCM4330_CHIP - {"RU", "RU", 1}, - {"US", "US", 5} -#endif + {"", "XZ", 1}, /* Universal if Country code is unknown or empty */ + {"RU", "RU", 13}, + {"US", "US", 5}, + {"UA", "UY", 0}, + {"AD", "AL", 0}, + {"CX", "AU", 2}, + {"GE", "GB", 1}, + {"ID", "MW", 0}, + {"KI", "AU", 2}, + {"NP", "SA", 0}, + {"WS", "SA", 0}, + {"LR", "BR", 0}, + {"ZM", "IN", 0}, + {"AN", "AG", 0}, + {"AI", "AS", 0}, + {"BM", "AS", 0}, + {"DZ", "IL", 0}, + {"LC", "AG", 0}, + {"MF", "BY", 0}, + {"GY", "CU", 0}, + {"LA", "GB", 1}, + {"LB", "BR", 0}, + {"MA", "IL", 0}, + {"MO", "BD", 0}, + {"MW", "BD", 0}, + {"QA", "BD", 0}, + {"TR", "GB", 1}, + {"TZ", "BF", 0}, + {"VN", "BR", 0}, + {"JO", "XZ", 1}, + {"PG", "XZ", 1}, + {"SA", "XZ", 1}, +#endif /* BCM4330_CHIP */ +#ifdef BCM4335_CHIP + {"AL", "AL", 2}, + {"DZ", "DZ", 1}, + {"AS", "AS", 2}, + {"AI", "AI", 1}, + {"AG", "AG", 2}, + {"AR", "AR", 21}, + {"AW", "AW", 2}, + {"AU", "AU", 6}, + {"AT", "AT", 4}, + {"AZ", "AZ", 2}, + {"BS", "BS", 2}, + {"BH", "BH", 24}, + {"BD", "BD", 1}, + {"BY", "BY", 3}, + {"BE", "BE", 4}, + {"BM", "BM", 12}, + {"BA", "BA", 2}, + {"BR", "BR", 4}, + {"VG", "VG", 2}, + {"BN", "BN", 4}, + {"BG", "BG", 4}, + {"KH", "KH", 2}, + {"CA", "CA", 31}, + {"KY", "KY", 3}, + {"CN", "CN", 9}, + {"CO", "CO", 17}, + {"CR", "CR", 17}, + {"HR", "HR", 4}, + {"CY", "CY", 4}, + {"CZ", "CZ", 4}, + {"DK", "DK", 4}, + {"EE", "EE", 4}, + {"ET", "ET", 2}, + {"FI", "FI", 4}, + {"FR", "FR", 5}, + {"GF", "GF", 2}, + {"DE", "DE", 7}, + {"GR", "GR", 4}, + {"GD", "GD", 2}, + {"GP", "GP", 2}, + {"GU", "GU", 12}, + {"HK", "HK", 2}, + {"HU", "HU", 4}, + {"IS", "IS", 4}, + {"IN", "IN", 3}, + {"ID", "ID", 1}, + {"IE", "IE", 5}, + {"IL", "IL", 7}, + {"IT", "IT", 4}, + {"JP", "JP", 45}, + {"JO", "JO", 3}, + {"KW", "KW", 5}, + {"LA", "LA", 2}, + {"LV", "LV", 4}, + {"LB", "LB", 5}, + {"LS", "LS", 2}, + {"LI", "LI", 4}, + {"LT", "LT", 4}, + {"LU", "LU", 1}, + {"MO", "MO", 2}, + {"MK", "MK", 2}, + {"MW", "MW", 1}, + {"MY", "MY", 3}, + {"MV", "MV", 3}, + {"MT", "MT", 4}, + {"MQ", "MQ", 2}, + {"MR", "MR", 2}, + {"MU", "MU", 2}, + {"YT", "YT", 2}, + {"MX", "MX", 20}, + {"MD", "MD", 2}, + {"MC", "MC", 1}, + {"ME", "ME", 2}, + {"MA", "MA", 2}, + {"NP", "NP", 3}, + {"NL", "NL", 4}, + {"AN", "AN", 2}, + {"NZ", "NZ", 4}, + {"NO", "NO", 4}, + {"OM", "OM", 4}, + {"PA", "PA", 17}, + {"PG", "PG", 2}, + {"PY", "PY", 2}, + {"PE", "PE", 20}, + {"PH", "PH", 5}, + {"PL", "PL", 4}, + {"PT", "PT", 4}, + {"PR", "PR", 20}, + {"RE", "RE", 2}, + {"RO", "RO", 4}, + {"SN", "SN", 2}, + {"RS", "RS", 2}, + {"SG", "SG", 4}, + {"SK", "SK", 4}, + {"SI", "SI", 4}, + {"ES", "ES", 4}, + {"LK", "LK", 3}, + {"SE", "SE", 4}, + {"CH", "CH", 4}, + {"TW", "TW", 1}, + {"TH", "TH", 5}, + {"TT", "TT", 3}, + {"TR", "TR", 7}, + {"AE", "AE", 4}, + {"UG", "UG", 2}, + {"GB", "GB", 6}, + {"UY", "UY", 1}, + {"VI", "VI", 13}, + {"VA", "VA", 2}, + {"VE", "VE", 3}, + {"VN", "VN", 4}, + {"MA", "MA", 1}, + {"ZM", "ZM", 2}, + {"EC", "EC", 21}, + {"SV", "SV", 19}, + {"KR", "KR", 48}, + {"RU", "RU", 13}, + {"UA", "UA", 8}, +#endif /* BCM4335_CHIP */ }; /* Customized Locale convertor @@ -160,6 +316,14 @@ void get_customized_country_code(char *country_iso_code, wl_country_t *cspec) #define PSMINFO "/data/.psm.info" #endif /* SLP_PATH */ +#ifdef BCM4330_CHIP +#define CIS_BUF_SIZE 128 +#elif defined(BCM4334_CHIP) +#define CIS_BUF_SIZE 256 +#else /* BCM4335_CHIP */ +#define CIS_BUF_SIZE 512 +#endif /* BCM4330_CHIP */ + #ifdef READ_MACADDR int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac) { @@ -169,43 +333,38 @@ int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac) char randommac[3] = {0}; char buf[18] = {0}; char *filepath_efs = MACINFO_EFS; -#ifdef CONFIG_TARGET_LOCALE_VZW - char *nvfilepath = "/data/misc/wifi/.nvmac.info"; -#else - char *nvfilepath = NVMACINFO; -#endif int ret = 0; - fp = filp_open(filepath_efs, O_RDONLY, 0); - if (IS_ERR(fp)) { + fp = filp_open(filepath_efs, O_RDONLY, 0); + if (IS_ERR(fp)) { start_readmac: - /* File Doesn't Exist. Create and write mac addr. */ - fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); - if (IS_ERR(fp)) { + /* File Doesn't Exist. Create and write mac addr. */ + fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); + if (IS_ERR(fp)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); - return -1; - } - oldfs = get_fs(); - set_fs(get_ds()); + return -1; + } + oldfs = get_fs(); + set_fs(get_ds()); - /* Generating the Random Bytes for 3 last octects of the MAC address */ - get_random_bytes(randommac, 3); + /* Generating the Random Bytes for 3 last octects of the MAC address */ + get_random_bytes(randommac, 3); - sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", - 0x00, 0x12, 0x34, randommac[0], randommac[1], randommac[2]); - DHD_ERROR(("[WIFI]The Random Generated MAC ID: %s\n", macbuffer)); + sprintf(macbuffer, "%02X:%02X:%02X:%02X:%02X:%02X\n", + 0x00, 0x12, 0x34, randommac[0], randommac[1], randommac[2]); + DHD_ERROR(("[WIFI]The Random Generated MAC ID: %s\n", macbuffer)); - if (fp->f_mode & FMODE_WRITE) { + if (fp->f_mode & FMODE_WRITE) { ret = fp->f_op->write(fp, (const char *)macbuffer, - sizeof(macbuffer), &fp->f_pos); - if (ret < 0) + sizeof(macbuffer), &fp->f_pos); + if (ret < 0) DHD_ERROR(("[WIFI]MAC address [%s] Failed to write into File: %s\n", macbuffer, filepath_efs)); - else + else DHD_ERROR(("[WIFI]MAC address [%s] written into File: %s\n", macbuffer, filepath_efs)); - } - set_fs(oldfs); + } + set_fs(oldfs); /* Reading the MAC Address from .mac.info file ( the existed file or just created file) */ @@ -215,7 +374,9 @@ start_readmac: .mac.info file( the existed file or just created file) */ ret = kernel_read(fp, 0, buf, 18); -/* to prevent abnormal string display when mac address is displayed on the screen. */ + /* to prevent abnormal string display + * when mac address is displayed on the screen. + */ buf[17] = '\0'; if (strncmp(buf, "00:00:00:00:00:00", 17) < 1) { DHD_ERROR(("goto start_readmac \r\n")); @@ -273,8 +434,8 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) mac->octet[0], mac->octet[1], mac->octet[2], mac->octet[3], mac->octet[4], mac->octet[5]); - /* /data/.mac.info will be created */ - fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666); + /* /efs/wifi/.mac.info will be created */ + fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath_data)); return -1; @@ -295,8 +456,8 @@ int dhd_write_rdwr_macaddr(struct ether_addr *mac) set_fs(oldfs); filp_close(fp_mac, NULL); } - /* /efs/wifi/.mac.info will be created */ - fp_mac = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); + /* /data/.mac.info will be created */ + fp_mac = filp_open(filepath_data, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp_mac)) { DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); return -1; @@ -335,7 +496,7 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, #ifdef CONFIG_TARGET_LOCALE_NA char *nvfilepath = "/data/misc/wifi/.nvmac.info"; #else - char *nvfilepath = NVMACINFO; + char *nvfilepath = "/efs/wifi/.nvmac.info"; #endif char cur_mac[128] = {0}; char dummy_mac[ETHER_ADDR_LEN] = {0x00, 0x90, 0x4C, 0xC5, 0x12, 0x38}; @@ -347,11 +508,6 @@ int dhd_check_rdwr_macaddr(struct dhd_info *dhd, dhd_pub_t *dhdp, fp_nvm = filp_open(nvfilepath, O_RDONLY, 0); if (IS_ERR(fp_nvm)) { /* file does not exist */ - /* Create the .nvmac.info */ - fp_nvm = filp_open(nvfilepath, O_RDWR | O_CREAT, 0666); - if (!IS_ERR(fp_nvm)) - filp_close(fp_nvm, NULL); - /* read MAC Address */ strcpy(cur_mac, "cur_etheraddr"); ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, cur_mac, @@ -635,16 +791,16 @@ int dhd_write_rdwr_korics_macaddr(struct dhd_info *dhd, struct ether_addr *mac) #endif /* RDWR_KORICS_MACADDR */ #ifdef USE_CID_CHECK -static int dhd_write_cid_file(const char *filepath_efs, const char *buf, int buf_len) +static int dhd_write_cid_file(const char *filepath_cid, const char *buf, int buf_len) { struct file *fp = NULL; mm_segment_t oldfs = {0}; int ret = 0; /* File is always created. */ - fp = filp_open(filepath_efs, O_RDWR | O_CREAT, 0666); + fp = filp_open(filepath_cid, O_RDWR | O_CREAT, 0666); if (IS_ERR(fp)) { - DHD_ERROR(("[WIFI] %s: File open error\n", filepath_efs)); + DHD_ERROR(("[WIFI] %s: File open error\n", filepath_cid)); return -1; } else { oldfs = get_fs(); @@ -654,10 +810,10 @@ static int dhd_write_cid_file(const char *filepath_efs, const char *buf, int buf ret = fp->f_op->write(fp, buf, buf_len, &fp->f_pos); if (ret < 0) DHD_ERROR(("[WIFI] Failed to write CIS[%s]" - " into '%s'\n", buf, filepath_efs)); + " into '%s'\n", buf, filepath_cid)); else DHD_ERROR(("[WIFI] CID [%s] written into" - " '%s'\n", buf, filepath_efs)); + " '%s'\n", buf, filepath_cid)); } set_fs(oldfs); } @@ -678,27 +834,62 @@ static void dhd_dump_cis(const unsigned char *buf, int size) } #endif /* DUMP_CIS */ -#ifdef BCM4334_CHIP -#define CIS_CID_OFFSET 43 -#else -#define CIS_CID_OFFSET 31 -#endif /* BCM4334_CHIP */ +#define MAX_VID_LEN 8 +#define MAX_VNAME_LEN 16 +#define CIS_TUPLE_START 0x80 +#define CIS_TUPLE_VENDOR 0x81 + +typedef struct { + uint8 vid_length; + unsigned char vid[MAX_VID_LEN]; + char vname[MAX_VNAME_LEN]; +} vid_info_t; + +#if defined(BCM4330_CHIP) +vid_info_t vid_info[] = { + { 6, { 0x00, 0x20, 0xc7, 0x00, 0x00, }, { "murata" } }, + { 2, { 0x99, }, { "semcove" } }, + { 0, { 0x00, }, { "samsung" } } +}; +#elif defined(BCM4334_CHIP) +vid_info_t vid_info[] = { + { 3, { 0x33, 0x33, }, { "semco" } }, + { 3, { 0xfb, 0x50, }, { "semcosh" } }, + { 6, { 0x00, 0x20, 0xc7, 0x00, 0x00, }, { "murata" } }, + { 0, { 0x00, }, { "samsung" } } +}; +#else /* BCM4335_CHIP */ +vid_info_t vid_info[] = { + { 3, { 0x33, 0x66, }, { "semcosh" } }, /* B0 Sharp 5G-FEM */ + { 3, { 0x33, 0x33, }, { "semco" } }, /* B0 Skyworks 5G-FEM and A0 chip */ + { 3, { 0x33, 0x88, }, { "semco3rd" } }, /* B0 Syri 5G-FEM */ + { 3, { 0x00, 0x11, }, { "muratafem1" } }, /* B0 ANADIGICS 5G-FEM */ + { 3, { 0x00, 0x22, }, { "muratafem2" } }, /* B0 TriQuint 5G-FEM */ + { 3, { 0x00, 0x33, }, { "muratafem3" } }, /* 3rd FEM: Reserved */ + { 0, { 0x00, }, { "murata" } } /* Default: for Murata A0 module */ +}; +#endif /* BCM_CHIP_ID */ int dhd_check_module_cid(dhd_pub_t *dhd) { int ret = -1; -#ifdef BCM4334_CHIP - unsigned char cis_buf[250] = {0}; + unsigned char cis_buf[CIS_BUF_SIZE] = {0}; + const char *cidfilepath = CIDINFO; + cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; + int idx, max; + vid_info_t *cur_info; + unsigned char *vid_start; + unsigned char vid_length; +#if defined(BCM4334_CHIP) || defined(BCM4335_CHIP) const char *revfilepath = REVINFO; - int flag_b3 = 0; +#ifdef BCM4334_CHIP + int flag_b3; #else - unsigned char cis_buf[128] = {0}; -#endif - const char *cidfilepath = CIDINFO; + char rev_str[10] = {0}; +#endif /* BCM4334_CHIP */ +#endif /* BCM4334_CHIP || BCM4335_CHIP */ /* Try reading out from CIS */ - cis_rw_t *cish = (cis_rw_t *)&cis_buf[8]; - cish->source = 0; cish->byteoff = 0; cish->nbytes = sizeof(cis_buf); @@ -707,93 +898,99 @@ int dhd_check_module_cid(dhd_pub_t *dhd) ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, sizeof(cis_buf), 0, 0); if (ret < 0) { - DHD_TRACE(("%s: CIS reading failed, err=%d\n", + DHD_ERROR(("%s: CIS reading failed, err=%d\n", __FUNCTION__, ret)); return ret; - } else { -#ifdef BCM4334_CHIP - unsigned char semco_id[4] = {0x00, 0x00, 0x33, 0x33}; + } - /* for SHARP FEM(new) */ - unsigned char semco_id_sh[4] = {0x00, 0x00, 0xFB, 0x50}; - DHD_ERROR(("%s: CIS reading success, ret=%d\n", - __FUNCTION__, ret)); + DHD_ERROR(("%s: CIS reading success, ret=%d\n", + __FUNCTION__, ret)); #ifdef DUMP_CIS - dump_cis(cis_buf, 48); + dhd_dump_cis(cis_buf, 48); #endif - if (memcmp(&cis_buf[CIS_CID_OFFSET], semco_id, 4) == 0) { - DHD_ERROR(("CID MATCH FOUND : Semco, " - "0x%02X 0x%02X 0x%02X 0x%02X\n", - cis_buf[CIS_CID_OFFSET], - cis_buf[CIS_CID_OFFSET+1], cis_buf[CIS_CID_OFFSET+2], - cis_buf[CIS_CID_OFFSET+3])); - dhd_write_cid_file(cidfilepath, "semco", 5); - } else if (memcmp(&cis_buf[CIS_CID_OFFSET], semco_id_sh, 4) == 0) { - DHD_ERROR(("CIS MATCH FOUND : Semco_sh, " - "0x%02X 0x%02X 0x%02X 0x%02X\n", - cis_buf[CIS_CID_OFFSET], - cis_buf[CIS_CID_OFFSET+1], cis_buf[CIS_CID_OFFSET+2], - cis_buf[CIS_CID_OFFSET+3])); - dhd_write_cid_file(cidfilepath, "semcosh", 7); - } else { - DHD_ERROR(("CID MATCH FOUND : Murata, " - "0x%02X 0x%02X 0x%02X 0x%02X\n", cis_buf[CIS_CID_OFFSET], - cis_buf[CIS_CID_OFFSET+1], cis_buf[CIS_CID_OFFSET+2], - cis_buf[CIS_CID_OFFSET+3])); - dhd_write_cid_file(cidfilepath, "murata", 6); + + max = sizeof(cis_buf) - 4; + for (idx = 0; idx < max; idx++) { + if (cis_buf[idx] == CIS_TUPLE_START) { + if (cis_buf[idx + 2] == CIS_TUPLE_VENDOR) { + vid_length = cis_buf[idx + 1]; + vid_start = &cis_buf[idx + 3]; + /* found CIS tuple */ + break; + } else { + /* Go to next tuple if tuple value is not vendor type */ + idx += (cis_buf[idx + 1] + 1); + } } + } - /* Try reading out from OTP to distinguish B2 or B3 */ - memset(cis_buf, 0, sizeof(cis_buf)); - cish = (cis_rw_t *)&cis_buf[8]; + if (idx < max) { + max = sizeof(vid_info) / sizeof(vid_info_t); + for (idx = 0; idx < max; idx++) { + cur_info = &vid_info[idx]; + if ((cur_info->vid_length == vid_length) && + (cur_info->vid_length != 0) && + (memcmp(cur_info->vid, vid_start, cur_info->vid_length - 1) == 0)) + goto write_cid; + } + } - cish->source = 0; - cish->byteoff = 0; - cish->nbytes = sizeof(cis_buf); + /* find default nvram, if exist */ + DHD_ERROR(("%s: cannot find CIS TUPLE set as default\n", __FUNCTION__)); + max = sizeof(vid_info) / sizeof(vid_info_t); + for (idx = 0; idx < max; idx++) { + cur_info = &vid_info[idx]; + if (cur_info->vid_length == 0) + goto write_cid; + } + DHD_ERROR(("%s: cannot find default CID\n", __FUNCTION__)); + return -1; - strcpy(cis_buf, "otpdump"); - ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, - sizeof(cis_buf), 0, 0); - if (ret < 0) { - DHD_ERROR(("%s: OTP reading failed, err=%d\n", - __FUNCTION__, ret)); - return ret; - } +write_cid: + DHD_ERROR(("CIS MATCH FOUND : %s\n", cur_info->vname)); + dhd_write_cid_file(cidfilepath, cur_info->vname, strlen(cur_info->vname)+1); +#if defined(BCM4334_CHIP) + /* Try reading out from OTP to distinguish B2 or B3 */ + memset(cis_buf, 0, sizeof(cis_buf)); + cish = (cis_rw_t *)&cis_buf[8]; - /* otp 33th character is identifier for 4334B3 */ - cis_buf[34] = '\0'; - flag_b3 = bcm_atoi(&cis_buf[33]); - if (flag_b3 & 0x1) { - DHD_ERROR(("REV MATCH FOUND : 4334B3, %c\n", cis_buf[33])); - dhd_write_cid_file(revfilepath, "4334B3", 6); - } + cish->source = 0; + cish->byteoff = 0; + cish->nbytes = sizeof(cis_buf); -#else /* BCM4330_CHIP */ - unsigned char murata_id[4] = {0x80, 0x06, 0x81, 0x00}; - unsigned char semco_ve[4] = {0x80, 0x02, 0x81, 0x99}; -#ifdef DUMP_CIS - dhd_dump_cis(cis_buf, 48); -#endif - if (memcmp(&cis_buf[CIS_CID_OFFSET], murata_id, 4) == 0) { - DHD_ERROR(("CID MATCH FOUND : Murata\n")); - dhd_write_cid_file(cidfilepath, "murata", 6); - } else if (memcmp(&cis_buf[CIS_CID_OFFSET], semco_ve, 4) - == 0) { - DHD_ERROR(("CID MATCH FOUND : Semco VE\n")); - dhd_write_cid_file(cidfilepath, "semcove", 7); + strcpy(cis_buf, "otpdump"); + ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, cis_buf, + sizeof(cis_buf), 0, 0); + if (ret < 0) { + DHD_ERROR(("%s: OTP reading failed, err=%d\n", + __FUNCTION__, ret)); + return ret; + } + + /* otp 33th character is identifier for 4334B3 */ + cis_buf[34] = '\0'; + flag_b3 = bcm_atoi(&cis_buf[33]); + if (flag_b3 & 0x1) { + DHD_ERROR(("REV MATCH FOUND : 4334B3, %c\n", cis_buf[33])); + dhd_write_cid_file(revfilepath, "4334B3", 6); + } +#endif /* BCM4334_CHIP */ +#if defined(BCM4335_CHIP) + DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); + if (concate_revision(dhd->bus, rev_str, sizeof(rev_str), + rev_str, sizeof(rev_str)) < 0) { + DHD_ERROR(("%s: fail to concate revision\n", __FUNCTION__)); + ret = -1; + } else { + if (strstr(rev_str, "_a0")) { + DHD_ERROR(("REV MATCH FOUND : 4335A0\n")); + dhd_write_cid_file(revfilepath, "BCM4335A0", 9); } else { - DHD_ERROR(("CID MISMATCH" - " 0x%02X 0x%02X 0x%02X 0x%02X\n", - cis_buf[CIS_CID_OFFSET], - cis_buf[CIS_CID_OFFSET + 1], - cis_buf[CIS_CID_OFFSET + 2], - cis_buf[CIS_CID_OFFSET + 3])); - dhd_write_cid_file(cidfilepath, "samsung", 7); + DHD_ERROR(("REV MATCH FOUND : 4335B0\n")); + dhd_write_cid_file(revfilepath, "BCM4335B0", 9); } -#endif /* BCM4334_CHIP */ - DHD_ERROR(("%s: CIS write success, err=%d\n", - __FUNCTION__, ret)); } +#endif /* BCM4335_CHIP */ return ret; } @@ -829,12 +1026,16 @@ static int dhd_write_mac_file(const char *filepath, const char *buf, int buf_len return 0; } +#ifdef BCM4335_CHIP +#define CIS_MAC_OFFSET 31 +#else #define CIS_MAC_OFFSET 33 +#endif /* BCM4335_CHIP */ int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac) { int ret = -1; - unsigned char cis_buf[250] = {0}; + unsigned char cis_buf[CIS_BUF_SIZE] = {0}; unsigned char mac_buf[20] = {0}; unsigned char otp_mac_buf[20] = {0}; const char *macfilepath = MACINFO_EFS; @@ -861,7 +1062,7 @@ int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac) } else { unsigned char mac_id[6] = {0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; #ifdef DUMP_CIS - dump_cis(cis_buf, 48); + dhd_dump_cis(cis_buf, 48); #endif mac_id[0] = cis_buf[CIS_MAC_OFFSET]; mac_id[1] = cis_buf[CIS_MAC_OFFSET + 1]; @@ -998,6 +1199,8 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode) mm_segment_t oldfs = {0}; char power_val = 0; char iovbuf[WL_EVENTING_MASK_LEN + 12]; + int ret = 0; + uint32 lpc = 0; g_pm_control = FALSE; @@ -1053,6 +1256,12 @@ void sec_control_pm(dhd_pub_t *dhd, uint *power_mode) dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); #endif + /* Set lpc 0 */ + bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set lpc failed %d\n", __FUNCTION__, ret)); + } } else { dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)power_mode, sizeof(uint), TRUE, 0); @@ -1145,6 +1354,7 @@ int dhd_sel_ant_from_file(dhd_pub_t *dhd) struct file *fp = NULL; int ret = -1; uint32 ant_val = 0; + uint32 btc_mode = 0; char *filepath = "/data/.ant.info"; char iovbuf[WLC_IOCTL_SMLEN]; @@ -1174,6 +1384,18 @@ int dhd_sel_ant_from_file(dhd_pub_t *dhd) } } + /* bt coex mode off */ + if (strstr(fw_path, "_mfg") != NULL) { + bcm_mkiovar("btc_mode", (char *)&btc_mode, 4, iovbuf, sizeof(iovbuf)); + ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + if (ret) { + DHD_ERROR(("[WIFI] %s: Fail to execute dhd_wl_ioctl_cmd(): " + "btc_mode, ret=%d\n", + __FUNCTION__, ret)); + return ret; + } + } + /* Select Antenna */ bcm_mkiovar("txchain", (char *)&ant_val, 4, iovbuf, sizeof(iovbuf)); ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); @@ -1194,4 +1416,30 @@ int dhd_sel_ant_from_file(dhd_pub_t *dhd) return 0; } #endif /* MIMO_ANTENNA_SETTING */ +#ifdef USE_WL_FRAMEBURST +uint32 sec_control_frameburst(void) +{ + struct file *fp = NULL; + char *filepath = "/data/.frameburst.info"; + char frameburst_val = 0; + uint32 frameburst = 1; /* default enabled */ + int ret = 0; + + fp = filp_open(filepath, O_RDONLY, 0); + if (IS_ERR(fp) || (fp == NULL)) { + DHD_INFO(("[WIFI] %s: File open failed, so enable frameburst as a default.\n", + __FUNCTION__)); + } else { + ret = kernel_read(fp, fp->f_pos, &frameburst_val, 1); + if (ret > 0 && frameburst_val == '0') { + /* Set frameburst to disable */ + frameburst = 0; + } + + DHD_INFO(("set frameburst value = %d\n", frameburst)); + filp_close(fp, NULL); + } + return frameburst; +} +#endif /* USE_WL_FRAMEBURST */ #endif /* CUSTOMER_HW4 */ diff --git a/drivers/net/wireless/bcmdhd/dhd_dbg.h b/drivers/net/wireless/bcmdhd/dhd_dbg.h index 314f0ee..df3f5b0 100644 --- a/drivers/net/wireless/bcmdhd/dhd_dbg.h +++ b/drivers/net/wireless/bcmdhd/dhd_dbg.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_dbg.h 353490 2012-08-27 21:10:02Z $ + * $Id: dhd_dbg.h 353883 2012-08-29 04:43:40Z $ */ #ifndef _dhd_dbg_ @@ -73,6 +73,7 @@ #define DHD_ISCAN_ON() (dhd_msg_level & DHD_ISCAN_VAL) #define DHD_ARPOE_ON() (dhd_msg_level & DHD_ARPOE_VAL) #define DHD_REORDER_ON() (dhd_msg_level & DHD_REORDER_VAL) +#define DHD_NOCHECKDIED_ON() (dhd_msg_level & DHD_NOCHECKDIED_VAL) #else /* defined(BCMDBG) || defined(DHD_DEBUG) */ @@ -113,6 +114,7 @@ #define DHD_ISCAN_ON() 0 #define DHD_ARPOE_ON() 0 #define DHD_REORDER_ON() 0 +#define DHD_NOCHECKDIED_ON() 0 #endif #define DHD_LOG(args) diff --git a/drivers/net/wireless/bcmdhd/dhd_linux.c b/drivers/net/wireless/bcmdhd/dhd_linux.c index 8702a44..ff8e634 100644 --- a/drivers/net/wireless/bcmdhd/dhd_linux.c +++ b/drivers/net/wireless/bcmdhd/dhd_linux.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_linux.c 358016 2012-09-20 22:36:51Z $ + * $Id: dhd_linux.c 394719 2013-04-03 13:22:12Z $ */ #include <typedefs.h> @@ -78,6 +78,7 @@ #define HTSF_BUS_DELAY 150 /* assume a fix propagation in us */ #define TSMAX 1000 /* max no. of timing record kept */ #define NUMBIN 34 + static uint32 tsidx = 0; static uint32 htsf_seqnum = 0; uint32 tsfsync; @@ -95,20 +96,14 @@ typedef struct histo_ { static histo_t vi_d1, vi_d2, vi_d3, vi_d4; #endif /* WLMEDIA_HTSF */ -#ifndef DTIM_COUNT -#define DTIM_COUNT 3 -#endif - -#if defined(PKT_FILTER_SUPPORT) -#if defined(BLOCK_IPV6_PACKET) +#if defined(BLOCK_IPV6_PACKET) && defined(CUSTOMER_HW4) #define HEX_PREF_STR "0x" #define UNI_FILTER_STR "010000000000" #define ZERO_ADDR_STR "000000000000" #define ETHER_TYPE_STR "0000" #define IPV6_FILTER_STR "20" #define ZERO_TYPE_STR "00" -#endif /* BLOCK_IPV6_PACKET */ -#endif /* PKT_FILTER_SUPPORT */ +#endif /* BLOCK_IPV6_PACKET && CUSTOMER_HW4 */ #if defined(SOFTAP) extern bool ap_cfg_running; @@ -130,7 +125,7 @@ extern bool ap_fw_loaded; #include <wl_android.h> #ifdef ARP_OFFLOAD_SUPPORT -void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add); +void aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx); static int dhd_device_event(struct notifier_block *this, unsigned long event, void *ptr); @@ -196,13 +191,14 @@ extern wl_iw_extra_params_t g_wl_iw_params; #endif /* defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) */ #endif /* CUSTOMER_HW4 && CONFIG_PARTIALSUSPEND_SLP */ -extern int dhd_get_dtim_skip(dhd_pub_t *dhd); +extern int dhd_get_suspend_bcn_li_dtim(dhd_pub_t *dhd); #ifdef PKT_FILTER_SUPPORT extern void dhd_pktfilter_offload_set(dhd_pub_t * dhd, char *arg); extern void dhd_pktfilter_offload_enable(dhd_pub_t * dhd, char *arg, int enable, int master_mode); #endif +#ifdef CUSTOMER_HW4 #ifdef READ_MACADDR extern int dhd_read_macaddr(struct dhd_info *dhd, struct ether_addr *mac); #endif @@ -222,11 +218,20 @@ extern int dhd_check_module_mac(dhd_pub_t *dhd, struct ether_addr *mac); #ifdef MIMO_ANT_SETTING extern int dhd_sel_ant_from_file(dhd_pub_t *dhd); #endif - #ifdef GLOBALCONFIG_WLAN_COUNTRY_CODE int dhd_customer_set_country(dhd_pub_t *dhd); #endif +#else + +#ifdef READ_MACADDR +extern int dhd_read_macaddr(struct dhd_info *dhd); +#endif +#ifdef WRITE_MACADDR +extern int dhd_write_macaddr(struct ether_addr *mac); +#endif +#endif /* CUSTOMER_HW4 */ + /* Interface control information */ typedef struct dhd_if { struct dhd_info *info; /* back pointer to dhd_info */ @@ -273,11 +278,6 @@ static uint32 maxdelay = 0, tspktcnt = 0, maxdelaypktno = 0; #endif /* WLMEDIA_HTSF */ -#if defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) -/* SLP_wakelock_alternative_code */ -extern struct device *pm_dev; -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ - /* Local private structure (extension of pub) */ typedef struct dhd_info { #if defined(CONFIG_WIRELESS_EXT) @@ -310,6 +310,10 @@ typedef struct dhd_info { tsk_ctl_t thr_dpc_ctl; tsk_ctl_t thr_wdt_ctl; +#ifdef RXFRAME_THREAD + tsk_ctl_t thr_rxf_ctl; + spinlock_t rxf_lock; +#endif /* RXFRAME_THREAD */ #endif /* DHDTHREAD */ bool dhd_tasklet_create; tsk_ctl_t thr_sysioc_ctl; @@ -319,9 +323,10 @@ typedef struct dhd_info { /* Wakelocks */ #if defined(CONFIG_HAS_WAKELOCK) && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - struct wake_lock wl_wifi; /* Wifi wakelock */ - struct wake_lock wl_rxwake; /* Wifi rx wakelock */ - struct wake_lock wl_ctrlwake; /* Wifi ctrl wakelock */ + struct wake_lock *wl_wifi; /* Wifi wakelock */ + struct wake_lock *wl_rxwake; /* Wifi rx wakelock */ + struct wake_lock *wl_ctrlwake; /* Wifi ctrl wakelock */ + struct wake_lock *wl_wdwake; /* Wifi wd wakelock */ #endif #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 @@ -333,6 +338,7 @@ typedef struct dhd_info { #endif spinlock_t wakelock_spinlock; int wakelock_counter; + int wakelock_wd_counter; int wakelock_rx_timeout_enable; int wakelock_ctrl_timeout_enable; @@ -345,7 +351,7 @@ typedef struct dhd_info { #if defined(CONFIG_HAS_EARLYSUSPEND) && defined(DHD_USE_EARLYSUSPEND) struct early_suspend early_suspend; -#endif /* CONFIG_HAS_EARLYSUSPEND && defined(DHD_USE_EARLYSUSPEND) */ +#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ #ifdef ARP_OFFLOAD_SUPPORT u32 pend_ipaddr; @@ -357,6 +363,9 @@ typedef struct dhd_info { bool rpcth_timer_active; bool fdaggr; #endif +#ifdef DHDTCPACK_SUPPRESS + spinlock_t tcpack_lock; +#endif /* DHDTCPACK_SUPPRESS */ } dhd_info_t; /* Flag to indicate if we should download firmware on driver load */ @@ -368,10 +377,6 @@ uint dhd_download_fw_on_driverload = TRUE; char firmware_path[MOD_PARAM_PATHLEN]; char nvram_path[MOD_PARAM_PATHLEN]; -/* information string to keep firmware, chio, cheip version info visiable from log */ -char info_string[MOD_PARAM_INFOLEN]; -module_param_string(info_string, info_string, MOD_PARAM_INFOLEN, 0444); - int op_mode = 0; int disable_proptx = 0; module_param(op_mode, int, 0644); @@ -391,11 +396,22 @@ module_param(dhd_sysioc, uint, 0); /* Error bits */ module_param(dhd_msg_level, int, 0); +#ifdef ARP_OFFLOAD_SUPPORT +/* ARP offload enable */ +uint dhd_arp_enable = TRUE; +module_param(dhd_arp_enable, uint, 0); +#endif /* ARP_OFFLOAD_SUPPORT */ + + /* Disable Prop tx */ module_param(disable_proptx, int, 0644); /* load firmware and/or nvram values from the filesystem */ module_param_string(firmware_path, firmware_path, MOD_PARAM_PATHLEN, 0660); +#ifdef CUSTOMER_HW4 module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0660); +#else +module_param_string(nvram_path, nvram_path, MOD_PARAM_PATHLEN, 0); +#endif /* CUSTOMER_HW4 */ /* Watchdog interval */ uint dhd_watchdog_ms = 10; @@ -407,16 +423,25 @@ uint dhd_console_ms = 0; module_param(dhd_console_ms, uint, 0644); #endif /* defined(DHD_DEBUG) */ +#ifdef REPEAT_READFRAME +uint dhd_doflow = 1; +module_param(dhd_doflow, uint, 0644); + +uint dhd_dpcpoll = 1; +module_param(dhd_dpcpoll, uint, 0644); +#endif /* REPEAT_READFRAME */ + uint dhd_slpauto = TRUE; module_param(dhd_slpauto, uint, 0); /* ARP offload agent mode : Enable ARP Host Auto-Reply and ARP Peer Auto-Reply */ +#if defined(CUSTOMER_HW4) uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY | ARP_OL_SNOOP; -module_param(dhd_arp_mode, uint, 0); +#else +uint dhd_arp_mode = ARP_OL_AGENT | ARP_OL_PEER_AUTO_REPLY; +#endif -/* ARP offload enable */ -uint dhd_arp_enable = TRUE; -module_param(dhd_arp_enable, uint, 0); +module_param(dhd_arp_mode, uint, 0); #ifdef PKT_FILTER_SUPPORT /* Global Pkt filter enable control */ @@ -444,6 +469,12 @@ module_param(dhd_watchdog_prio, int, 0); int dhd_dpc_prio = CUSTOM_DPC_PRIO_SETTING; module_param(dhd_dpc_prio, int, 0); +#ifdef RXFRAME_THREAD +/* RX frame thread priority */ +int dhd_rxf_prio = CUSTOM_RXF_PRIO_SETTING; +module_param(dhd_rxf_prio, int, 0); +#endif /* RXFRAME_THREAD */ + /* DPC thread priority, -1 to use tasklet */ extern int dhd_dongle_memsize; module_param(dhd_dongle_memsize, int, 0); @@ -546,10 +577,14 @@ static void dhd_dump_htsfhisto(histo_t *his, char *s); int dhd_monitor_init(void *dhd_pub); int dhd_monitor_uninit(void); -#ifdef CONFIG_CONTROL_PM +#if defined(CUSTOMER_HW4) && defined(CONFIG_CONTROL_PM) bool g_pm_control; void sec_control_pm(dhd_pub_t *dhd, uint *); -#endif +#endif /* CUSTOMER_HW4 & CONFIG_CONTROL_PM */ + +#if defined(CUSTOMER_HW4) && defined(USE_WL_FRAMEBURST) +uint32 sec_control_frameburst(void); +#endif /* CUSTOMER_HW4 & CONFIG_CONTROL_PM */ #if defined(CONFIG_WIRELESS_EXT) @@ -602,9 +637,77 @@ extern int register_pm_notifier(struct notifier_block *nb); extern int unregister_pm_notifier(struct notifier_block *nb); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && defined(CONFIG_PM_SLEEP) */ +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +/* Request scheduling of the bus rx frame */ +static void dhd_sched_rxf(dhd_pub_t *dhdp, void *skb); +static void dhd_os_rxflock(dhd_pub_t *pub); +static void dhd_os_rxfunlock(dhd_pub_t *pub); + +static inline int dhd_rxf_enqueue(dhd_pub_t *dhdp, void* skb) +{ + uint32 store_idx; + uint32 sent_idx; + + if (!skb) { + DHD_ERROR(("dhd_rxf_enqueue: NULL skb!!!\n")); + return BCME_ERROR; + } + + dhd_os_rxflock(dhdp); + store_idx = dhdp->store_idx; + sent_idx = dhdp->sent_idx; + if (dhdp->skbbuf[store_idx] != NULL) { + /* Make sure the previous packets are processed */ + /* Do I need to make this context sleep here? Definitely in Single processor case */ + dhd_os_rxfunlock(dhdp); + DHD_ERROR(("dhd_rxf_enqueue: pktbuf not consumed %p, store idx %d sent idx %d\n", + skb, store_idx, sent_idx)); + msleep(1); + return BCME_ERROR; + } + DHD_TRACE(("dhd_rxf_enqueue: Store SKB %p. idx %d -> %d\n", + skb, store_idx, (store_idx + 1) & (MAXSKBPEND - 1))); + dhdp->skbbuf[store_idx] = skb; + dhdp->store_idx = (store_idx + 1) & (MAXSKBPEND - 1); + dhd_os_rxfunlock(dhdp); + + return BCME_OK; +} + +static inline void* dhd_rxf_dequeue(dhd_pub_t *dhdp) +{ + uint32 store_idx; + uint32 sent_idx; + void *skb; + + dhd_os_rxflock(dhdp); + + store_idx = dhdp->store_idx; + sent_idx = dhdp->sent_idx; + skb = dhdp->skbbuf[sent_idx]; + + if (skb == NULL) { + dhd_os_rxfunlock(dhdp); + DHD_ERROR(("dhd_rxf_dequeue: Dequeued packet is NULL, store idx %d sent idx %d\n", + store_idx, sent_idx)); + return NULL; + } + + dhdp->skbbuf[sent_idx] = NULL; + dhdp->sent_idx = (sent_idx + 1) & (MAXSKBPEND - 1); + + DHD_TRACE(("dhd_rxf_dequeue: netif_rx_ni(%p), sent idx %d\n", + skb, sent_idx)); + + dhd_os_rxfunlock(dhdp); + + return skb; +} +#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ + void dhd_set_packet_filter(dhd_pub_t *dhd) -#ifdef PKT_FILTER_SUPPORT { +#ifdef PKT_FILTER_SUPPORT int i; DHD_TRACE(("%s: enter\n", __FUNCTION__)); @@ -613,7 +716,7 @@ void dhd_set_packet_filter(dhd_pub_t *dhd) dhd_pktfilter_offload_set(dhd, dhd->pktfilter[i]); } } -#endif +#endif /* PKT_FILTER_SUPPORT */ } void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) @@ -625,7 +728,8 @@ void dhd_enable_packet_filter(int value, dhd_pub_t *dhd) /* 1 - Enable packet filter, only allow unicast packet to send up */ /* 0 - Disable packet filter */ if (dhd_pkt_filter_enable && (!value || - (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) { + (dhd_support_sta_mode(dhd) && !dhd->dhcp_in_progress))) + { for (i = 0; i < dhd->pktfilter_count; i++) { #ifdef PASS_ARP_PACKET if (value && (i == dhd->pktfilter_count -1) && @@ -647,120 +751,127 @@ static int dhd_set_suspend(int value, dhd_pub_t *dhd) { #ifndef SUPPORT_PM2_ONLY int power_mode = PM_MAX; -#endif +#endif /* SUPPORT_PM2_ONLY */ /* wl_pkt_filter_enable_t enable_parm; */ char iovbuf[32]; -#if !defined(CUSTOMER_HW4) - int bcn_li_dtim = DTIM_COUNT; -#endif -#ifndef DISABLE_FW_ROAM_SUSPEND + int bcn_li_dtim = 0; /* Default bcn_li_dtim in resume mode is 0 */ +#ifndef ENABLE_FW_ROAM_SUSPEND uint roamvar = 1; -#endif -#ifdef ENABLE_BCN_LI_BCN_WAKEUP +#endif /* ENABLE_FW_ROAM_SUSPEND */ +#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP) int bcn_li_bcn; -#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ -#ifdef PASS_ALL_MCAST_PKTS +#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */ +#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4) + struct dhd_info *dhdinfo = dhd->info; uint32 allmulti; -#endif /* PASS_ALL_MCAST_PKTS */ + uint i; +#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */ + + if (!dhd) + return -ENODEV; DHD_TRACE(("%s: enter, value = %d in_suspend=%d\n", __FUNCTION__, value, dhd->in_suspend)); dhd_suspend_lock(dhd); - if (dhd && dhd->up) { + if (dhd->up) { if (value && dhd->in_suspend) { #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 1; #endif /* Kernel suspended */ - DHD_ERROR(("%s: force extra Suspend setting\n", __FUNCTION__)); + DHD_ERROR(("%s: force extra Suspend setting \n", __FUNCTION__)); #ifndef SUPPORT_PM2_ONLY dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); -#endif -#ifdef PKT_FILTER_SUPPORT +#endif /* SUPPORT_PM2_ONLY */ + /* Enable packet filter, only allow unicast packet to send up */ - if (!dhd->dhcp_in_progress) - dhd_enable_packet_filter(1, dhd); -#endif /* PKT_FILTER_SUPPORT */ -#ifdef PASS_ALL_MCAST_PKTS + dhd_enable_packet_filter(1, dhd); + +#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4) allmulti = 0; - bcm_mkiovar("allmulti", (char *)&allmulti, - 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* PASS_ALL_MCAST_PKTS */ + bcm_mkiovar("allmulti", (char *)&allmulti, 4, + iovbuf, sizeof(iovbuf)); + for (i = 0; i < DHD_MAX_IFS; i++) { + if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, i); + } +#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */ -#if !defined(CUSTOMER_HW4) /* If DTIM skip is set up as default, force it to wake * each third DTIM for better power savings. Note that * one side effect is a chance to miss BC/MC packet. */ - bcn_li_dtim = dhd_get_dtim_skip(dhd); + bcn_li_dtim = dhd_get_suspend_bcn_li_dtim(dhd); bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* !defined(CUSTOMER_HW4) */ -#ifndef DISABLE_FW_ROAM_SUSPEND + if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), + TRUE, 0) < 0) + DHD_ERROR(("%s: set dtim failed\n", __FUNCTION__)); + +#ifndef ENABLE_FW_ROAM_SUSPEND /* Disable firmware roaming during suspend */ bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif -#ifdef ENABLE_BCN_LI_BCN_WAKEUP +#endif /* ENABLE_FW_ROAM_SUSPEND */ +#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP) bcn_li_bcn = 0; bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ - +#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */ } else { #ifdef PKT_FILTER_SUPPORT dhd->early_suspended = 0; #endif /* Kernel resumed */ - DHD_ERROR(("%s: Remove extra suspend setting\n", __FUNCTION__)); + DHD_ERROR(("%s: Remove extra suspend setting \n", __FUNCTION__)); #ifndef SUPPORT_PM2_ONLY power_mode = PM_FAST; dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); -#endif +#endif /* SUPPORT_PM2_ONLY */ #ifdef PKT_FILTER_SUPPORT /* disable pkt filter */ dhd_enable_packet_filter(0, dhd); #endif /* PKT_FILTER_SUPPORT */ -#ifdef PASS_ALL_MCAST_PKTS +#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4) allmulti = 1; - bcm_mkiovar("allmulti", (char *)&allmulti, - 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* PASS_ALL_MCAST_PKTS */ + bcm_mkiovar("allmulti", (char *)&allmulti, 4, + iovbuf, sizeof(iovbuf)); + for (i = 0; i < DHD_MAX_IFS; i++) { + if (dhdinfo->iflist[i] && dhdinfo->iflist[i]->net) + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, i); + } +#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */ -#if !defined(CUSTOMER_HW4) /* restore pre-suspend setting for dtim_skip */ - bcm_mkiovar("bcn_li_dtim", (char *)&dhd->dtim_skip, + bcm_mkiovar("bcn_li_dtim", (char *)&bcn_li_dtim, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif -#ifndef DISABLE_FW_ROAM_SUSPEND +#ifndef ENABLE_FW_ROAM_SUSPEND roamvar = dhd_roam_disable; bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif -#ifdef ENABLE_BCN_LI_BCN_WAKEUP +#endif /* ENABLE_FW_ROAM_SUSPEND */ +#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP) bcn_li_bcn = 1; bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ - +#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */ } } - dhd_suspend_unlock(dhd); + return 0; } @@ -800,7 +911,7 @@ static void dhd_late_resume(struct early_suspend *h) if (dhd) dhd_suspend_resume_helper(dhd, 0, 0); } -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ +#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ /* * Generalized timeout mechanism. Uses spin sleep with exponential back-off until @@ -967,33 +1078,37 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) for (i = 0; i < DHD_MAX_IFS; i++) { if (dhd->iflist[i]) { dev = dhd->iflist[i]->net; + if (!dev) + continue; #else - ASSERT(dhd && dhd->iflist[ifidx]); - dev = dhd->iflist[ifidx]->net; + ASSERT(dhd && dhd->iflist[ifidx]); + dev = dhd->iflist[ifidx]->net; + if (!dev) + return; #endif /* MCAST_LIST_ACCUMULATION */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) - netif_addr_lock_bh(dev); + netif_addr_lock_bh(dev); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) #ifdef MCAST_LIST_ACCUMULATION cnt_iface[i] = netdev_mc_count(dev); cnt += cnt_iface[i]; #else - cnt = netdev_mc_count(dev); + cnt = netdev_mc_count(dev); #endif /* MCAST_LIST_ACCUMULATION */ #else #ifdef MCAST_LIST_ACCUMULATION cnt += dev->mc_count; #else - cnt = dev->mc_count; + cnt = dev->mc_count; #endif /* MCAST_LIST_ACCUMULATION */ #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) - netif_addr_unlock_bh(dev); + netif_addr_unlock_bh(dev); #endif - /* Determine initial value of allmulti flag */ + /* Determine initial value of allmulti flag */ #ifdef MCAST_LIST_ACCUMULATION allmulti |= (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; } @@ -1001,13 +1116,12 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) #else allmulti = (dev->flags & IFF_ALLMULTI) ? TRUE : FALSE; #endif /* MCAST_LIST_ACCUMULATION */ - -#ifdef PASS_ALL_MCAST_PKTS +#if defined(PASS_ALL_MCAST_PKTS) && defined(CUSTOMER_HW4) #ifdef PKT_FILTER_SUPPORT if (!dhd->pub.early_suspended) #endif /* PKT_FILTER_SUPPORT */ allmulti = TRUE; -#endif /* PASS_ALL_MCAST_PKTS */ +#endif /* PASS_ALL_MCAST_PKTS && CUSTOMER_HW4 */ /* Send down the multicast list first. */ @@ -1035,25 +1149,25 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) #endif /* MCAST_LIST_ACCUMULATION */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) - netif_addr_lock_bh(dev); + netif_addr_lock_bh(dev); #endif #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35) - netdev_for_each_mc_addr(ha, dev) { + netdev_for_each_mc_addr(ha, dev) { #ifdef MCAST_LIST_ACCUMULATION if (!cnt_iface[i]) #else - if (!cnt) + if (!cnt) #endif /* MCAST_LIST_ACCUMULATION */ - break; - memcpy(bufp, ha->addr, ETHER_ADDR_LEN); - bufp += ETHER_ADDR_LEN; + break; + memcpy(bufp, ha->addr, ETHER_ADDR_LEN); + bufp += ETHER_ADDR_LEN; #ifdef MCAST_LIST_ACCUMULATION DHD_TRACE(("_dhd_set_multicast_list: cnt " "%d " MACDBG "\n", cnt_iface[i], MAC2STRDBG(ha->addr))); cnt_iface[i]--; #else - cnt--; + cnt--; #endif /* MCAST_LIST_ACCUMULATION */ } #else @@ -1064,13 +1178,13 @@ _dhd_set_multicast_list(dhd_info_t *dhd, int ifidx) for (mclist = dev->mc_list; (mclist && (cnt > 0)); cnt--, mclist = mclist->next) { #endif /* MCAST_LIST_ACCUMULATION */ - memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); - bufp += ETHER_ADDR_LEN; - } + memcpy(bufp, (void *)mclist->dmi_addr, ETHER_ADDR_LEN); + bufp += ETHER_ADDR_LEN; + } #endif /* LINUX_VERSION_CODE */ #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) - netif_addr_unlock_bh(dev); + netif_addr_unlock_bh(dev); #endif #ifdef MCAST_LIST_ACCUMULATION } @@ -1224,7 +1338,7 @@ dhd_op_if(dhd_if_t *ifp) } /* Allocate etherdev, including space for private structure */ if (!(ifp->net = alloc_etherdev(sizeof(dhd)))) { - DHD_ERROR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); + DHD_ERROR(("%s: OOM - alloc_etherdev(%d)\n", __FUNCTION__, sizeof(dhd))); ret = -ENOMEM; } if (ret == 0) { @@ -1309,6 +1423,13 @@ dhd_op_if(dhd_if_t *ifp) } } + +#ifdef DHDTCPACK_SUPPRESS +uint dhd_use_tcpack_suppress = TRUE; +module_param(dhd_use_tcpack_suppress, uint, FALSE); +extern bool dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt); +#endif /* DHDTCPACK_SUPPRESS */ + static int _dhd_sysioc_thread(void *data) { @@ -1321,6 +1442,7 @@ _dhd_sysioc_thread(void *data) bool in_ap = FALSE; unsigned long flags; #endif + #ifndef USE_KTHREAD_API DAEMONIZE("dhd_sysioc"); @@ -1386,10 +1508,12 @@ _dhd_sysioc_thread(void *data) dhd->set_macaddress = 0; if (_dhd_set_mac_address(dhd, i, &dhd->macvalue) == 0) { DHD_INFO(( - "dhd_sysioc_thread: MACID is overwritten\n")); + "%s: MACID is overwritten\n", + __FUNCTION__)); } else { DHD_ERROR(( - "dhd_sysioc_thread: _dhd_set_mac_address() failed\n")); + "%s: _dhd_set_mac_address() failed\n", + __FUNCTION__)); } } } @@ -1470,7 +1594,7 @@ uint8 prio2fifo[8] = { 1, 0, 0, 1, 2, 2, 3, 3 }; int dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) { - int ret; + int ret = BCME_OK; dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); struct ether_header *eh = NULL; @@ -1496,7 +1620,9 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) } /* Look into the packet and update the packet priority */ +#ifndef PKTPRIO_OVERRIDE if (PKTPRIO(pktbuf) == 0) +#endif /* !CUSTOMER_HW4 */ pktsetprio(pktbuf, FALSE); #ifdef PROP_TXSTATUS @@ -1522,22 +1648,30 @@ dhd_sendpkt(dhd_pub_t *dhdp, int ifidx, void *pktbuf) #ifdef WLMEDIA_HTSF dhd_htsf_addtxts(dhdp, pktbuf); #endif +#ifdef DHDTCPACK_SUPPRESS + if (dhd_use_tcpack_suppress && dhd_tcpack_suppress(dhdp, pktbuf)) + ret = BCME_OK; + else +#endif /* DHDTCPACK_SUPPRESS */ #ifdef PROP_TXSTATUS - if (dhdp->wlfc_state && ((athost_wl_status_info_t*)dhdp->wlfc_state)->proptxstatus_mode - != WLFC_FCMODE_NONE) { + { dhd_os_wlfc_block(dhdp); - ret = dhd_wlfc_enque_sendq(dhdp->wlfc_state, DHD_PKTTAG_FIFO(PKTTAG(pktbuf)), - pktbuf); - dhd_wlfc_commit_packets(dhdp->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, - dhdp->bus); - if (((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if) { - ((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if = 0; + if (dhdp->wlfc_state && + ((athost_wl_status_info_t*)dhdp->wlfc_state)->proptxstatus_mode + != WLFC_FCMODE_NONE) { + dhd_wlfc_commit_packets(dhdp->wlfc_state, (f_commitpkt_t)dhd_bus_txdata, + dhdp->bus, pktbuf); + if (((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if) { + ((athost_wl_status_info_t*)dhdp->wlfc_state)->toggle_host_if = 0; + } + dhd_os_wlfc_unblock(dhdp); + } + else { + dhd_os_wlfc_unblock(dhdp); + /* non-proptxstatus way */ + ret = dhd_bus_txdata(dhdp->bus, pktbuf); } - dhd_os_wlfc_unblock(dhdp); } - else - /* non-proptxstatus way */ - ret = dhd_bus_txdata(dhdp->bus, pktbuf); #else ret = dhd_bus_txdata(dhdp->bus, pktbuf); #endif /* PROP_TXSTATUS */ @@ -1716,11 +1850,6 @@ static const char *_get_packet_type_str(uint16 type) } #endif /* DHD_RX_DUMP */ -#ifdef CUSTOMER_HW4 -extern int pkt_free; -extern int caller; -extern void *free_ptr; -#endif void dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) { @@ -1734,7 +1863,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) wl_event_msg_t event; int tout_rx = 0; int tout_ctrl = 0; - +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) + void *skbhead = NULL; + void *skbprev = NULL; +#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ #ifdef DHD_RX_DUMP #ifdef DHD_RX_FULL_DUMP int k; @@ -1751,6 +1883,9 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) struct dot11_llc_snap_header *lsh; #endif + pnext = PKTNEXT(dhdp->osh, pktbuf); + PKTSETNEXT(wl->sh.osh, pktbuf, NULL); + ifp = dhd->iflist[ifidx]; if (ifp == NULL) { DHD_ERROR(("%s: ifp is NULL. drop packet\n", @@ -1772,9 +1907,6 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ - pnext = PKTNEXT(dhdp->osh, pktbuf); - PKTSETNEXT(wl->sh.osh, pktbuf, NULL); - #ifdef WLBTAMP eh = (struct ether_header *)PKTDATA(wl->sh.osh, pktbuf); lsh = (struct dot11_llc_snap_header *)&eh[1]; @@ -1796,16 +1928,10 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) piggy-back on */ ((athost_wl_status_info_t*)dhdp->wlfc_state)->stats.wlfc_header_only_pkt++; -#ifdef CUSTOMER_HW4 - /*if (numpkt == 1 && pkt_free && (free_ptr == pktbuf)) { - DHD_ERROR(("DHD TRACE2(FREE):%d %d %p\n", - pkt_free, caller, free_ptr)); - }*/ -#endif PKTFREE(dhdp->osh, pktbuf, TRUE); continue; } -#endif /* PROP_TXSTATUS */ +#endif skb = PKTTONATIVE(dhdp->osh, pktbuf); @@ -1886,29 +2012,33 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) if (ntoh16(skb->protocol) == ETHER_TYPE_BRCM) { dhd_wl_host_event(dhd, &ifidx, #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) - skb->mac_header, + skb_mac_header(skb), #else skb->mac.raw, #endif &event, &data); +#if defined(WLBTAMP) || defined(PNO_SUPPORT) wl_event_to_host_order(&event); - if (!tout_ctrl) tout_ctrl = DHD_PACKET_TIMEOUT_MS; - #ifdef WLBTAMP if (event.event_type == WLC_E_BTA_HCI_EVENT) { dhd_bta_doevt(dhdp, data, event.datalen); } #endif /* WLBTAMP */ -#if defined(PNO_SUPPORT) +#ifdef PNO_SUPPORT if (event.event_type == WLC_E_PFN_NET_FOUND) { +#ifdef CUSTOMER_HW4 + tout_ctrl = DHD_PNO_TIMEOUT_MS; +#else tout_ctrl *= 2; +#endif } #endif /* PNO_SUPPORT */ +#endif /* defined(WLBTAMP) || defined(PNO_SUPPORT) */ } else { tout_rx = DHD_PACKET_TIMEOUT_MS; } @@ -1923,6 +2053,7 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) dhdp->dstats.rx_bytes += skb->len; dhdp->rx_packets++; /* Local count */ + if (in_interrupt()) { netif_rx(skb); } else { @@ -1932,6 +2063,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) * by netif_rx_ni(), but in earlier kernels, we need * to do it manually. */ +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) + if (!skbhead) + skbhead = skb; + else + PKTSETNEXT(wl->sh.osh, skbprev, skb); + skbprev = skb; +#else #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) netif_rx_ni(skb); #else @@ -1941,9 +2079,13 @@ dhd_rx_frame(dhd_pub_t *dhdp, int ifidx, void *pktbuf, int numpkt, uint8 chan) RAISE_RX_SOFTIRQ(); local_irq_restore(flags); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) */ +#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ } } - +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) + if (skbhead) + dhd_sched_rxf(dhdp, skbhead); +#endif DHD_OS_WAKE_LOCK_RX_TIMEOUT_ENABLE(dhdp, tout_rx); DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(dhdp, tout_ctrl); } @@ -1958,7 +2100,6 @@ dhd_event(struct dhd_info *dhd, char *evpkt, int evlen, int ifidx) void dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) { - uint ifidx; dhd_info_t *dhd = (dhd_info_t *)(dhdp->info); struct ether_header *eh; uint16 type; @@ -1966,7 +2107,7 @@ dhd_txcomplete(dhd_pub_t *dhdp, void *txp, bool success) uint len; #endif - dhd_prot_hdrpull(dhdp, &ifidx, txp, NULL, NULL); + dhd_prot_hdrpull(dhdp, NULL, txp, NULL, NULL); eh = (struct ether_header *)PKTDATA(dhdp->osh, txp); type = ntoh16(eh->ether_type); @@ -2055,6 +2196,8 @@ dhd_watchdog_thread(void *data) while (1) if (down_interruptible (&tsk->sema) == 0) { unsigned long flags; + unsigned long jiffies_at_start = jiffies; + unsigned long time_lapse; SMP_RD_BARRIER_DEPENDS(); if (tsk->terminated) { @@ -2065,20 +2208,24 @@ dhd_watchdog_thread(void *data) if (dhd->pub.dongle_reset == FALSE) { DHD_TIMER(("%s:\n", __FUNCTION__)); + /* Call the bus module watchdog */ dhd_bus_watchdog(&dhd->pub); flags = dhd_os_spin_lock(&dhd->pub); /* Count the tick for reference */ dhd->pub.tickcnt++; + time_lapse = jiffies - jiffies_at_start; + /* Reschedule the watchdog */ if (dhd->wd_timer_valid) mod_timer(&dhd->timer, - jiffies + msecs_to_jiffies(dhd_watchdog_ms)); + jiffies + + msecs_to_jiffies(dhd_watchdog_ms) - + min(msecs_to_jiffies(dhd_watchdog_ms), time_lapse)); dhd_os_spin_unlock(&dhd->pub, flags); } dhd_os_sdunlock(&dhd->pub); - DHD_OS_WAKE_UNLOCK(&dhd->pub); } else { break; } @@ -2092,9 +2239,7 @@ static void dhd_watchdog(ulong data) dhd_info_t *dhd = (dhd_info_t *)data; unsigned long flags; - DHD_OS_WAKE_LOCK(&dhd->pub); if (dhd->pub.dongle_reset) { - DHD_OS_WAKE_UNLOCK(&dhd->pub); return; } @@ -2118,7 +2263,6 @@ static void dhd_watchdog(ulong data) mod_timer(&dhd->timer, jiffies + msecs_to_jiffies(dhd_watchdog_ms)); dhd_os_spin_unlock(&dhd->pub, flags); dhd_os_sdunlock(&dhd->pub); - DHD_OS_WAKE_UNLOCK(&dhd->pub); } #ifdef DHDTHREAD @@ -2145,10 +2289,13 @@ dhd_dpc_thread(void *data) complete(&tsk->completed); #endif +#ifdef CUSTOM_DPC_CPUCORE + set_cpus_allowed_ptr(current, cpumask_of(CUSTOM_DPC_CPUCORE)); +#endif + /* Run until signal received */ while (1) { if (down_interruptible(&tsk->sema) == 0) { - SMP_RD_BARRIER_DEPENDS(); if (tsk->terminated) { break; @@ -2174,6 +2321,75 @@ dhd_dpc_thread(void *data) complete_and_exit(&tsk->completed, 0); } + +#ifdef RXFRAME_THREAD +static int +dhd_rxf_thread(void *data) +{ + tsk_ctl_t *tsk = (tsk_ctl_t *)data; + dhd_info_t *dhd = (dhd_info_t *)tsk->parent; + dhd_pub_t *pub = &dhd->pub; + + /* This thread doesn't need any user-level access, + * so get rid of all our resources + */ + if (dhd_rxf_prio > 0) + { + struct sched_param param; + param.sched_priority = (dhd_rxf_prio < MAX_RT_PRIO)?dhd_rxf_prio:(MAX_RT_PRIO-1); + setScheduler(current, SCHED_FIFO, ¶m); + } + + DAEMONIZE("dhd_rxf"); + /* DHD_OS_WAKE_LOCK is called in dhd_sched_dpc[dhd_linux.c] down below */ + + /* signal: thread has started */ + complete(&tsk->completed); + + /* Run until signal received */ + while (1) { + if (down_interruptible(&tsk->sema) == 0) { + void *skb; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 0) + ulong flags; +#endif + + SMP_RD_BARRIER_DEPENDS(); + + if (tsk->terminated) { + break; + } + skb = dhd_rxf_dequeue(pub); + + if (skb == NULL) { + continue; + } + + while (skb) { + void *skbnext = PKTNEXT(pub->osh, skb); + PKTSETNEXT(pub->osh, skb, NULL); + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0) + netif_rx_ni(skb); +#else + netif_rx(skb); + local_irq_save(flags); + RAISE_RX_SOFTIRQ(); + local_irq_restore(flags); + +#endif + skb = skbnext; + } + + DHD_OS_WAKE_UNLOCK(pub); + } + else + break; + } + + complete_and_exit(&tsk->completed, 0); +} +#endif /* RXFRAME_THREAD */ #endif /* DHDTHREAD */ static void @@ -2216,6 +2432,27 @@ dhd_sched_dpc(dhd_pub_t *dhdp) tasklet_schedule(&dhd->tasklet); } +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +static void +dhd_sched_rxf(dhd_pub_t *dhdp, void *skb) +{ + dhd_info_t *dhd = (dhd_info_t *)dhdp->info; + + DHD_OS_WAKE_LOCK(dhdp); + + DHD_TRACE(("dhd_sched_rxf: Enter\n")); + + do { + if (dhd_rxf_enqueue(dhdp, skb) == BCME_OK) + break; + } while (1); + if (dhd->thr_rxf_ctl.thr_pid >= 0) { + up(&dhd->thr_rxf_ctl.sema); + } + return; +} +#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ + #ifdef TOE /* Retrieve current toe component enables, which are kept as a bitmap in toe_ol iovar */ static int @@ -2423,7 +2660,7 @@ dhd_ethtool(dhd_info_t *dhd, void *uaddr) static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) { - dhd_info_t * dhd; + dhd_info_t *dhd; if (!dhdp) return FALSE; @@ -2444,128 +2681,60 @@ static bool dhd_check_hang(struct net_device *net, dhd_pub_t *dhdp, int error) return FALSE; } -static int -dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) +int dhd_ioctl_process(dhd_pub_t *pub, int ifidx, dhd_ioctl_t *ioc) { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); - dhd_ioctl_t ioc; - int bcmerror = 0; + int bcmerror = BCME_OK; int buflen = 0; void *buf = NULL; - uint driver = 0; - int ifidx; - int ret; - - DHD_OS_WAKE_LOCK(&dhd->pub); - - /* send to dongle only if we are not waiting for reload already */ - if (dhd->pub.hang_was_sent) { - DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); - DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); - DHD_OS_WAKE_UNLOCK(&dhd->pub); - return OSL_ERROR(BCME_DONGLE_DOWN); - } - - ifidx = dhd_net2idx(dhd, net); - DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); - - if (ifidx == DHD_BAD_IF) { - DHD_ERROR(("%s: BAD IF\n", __FUNCTION__)); - DHD_OS_WAKE_UNLOCK(&dhd->pub); - return -1; - } - -#if defined(CONFIG_WIRELESS_EXT) - /* linux wireless extensions */ - if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { - /* may recurse, do NOT lock */ - ret = wl_iw_ioctl(net, ifr, cmd); - DHD_OS_WAKE_UNLOCK(&dhd->pub); - return ret; - } -#endif /* defined(CONFIG_WIRELESS_EXT) */ - -#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) - if (cmd == SIOCETHTOOL) { - ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); - DHD_OS_WAKE_UNLOCK(&dhd->pub); - return ret; - } -#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ - - if (cmd == SIOCDEVPRIVATE+1) { - ret = wl_android_priv_cmd(net, ifr, cmd); - dhd_check_hang(net, &dhd->pub, ret); - DHD_OS_WAKE_UNLOCK(&dhd->pub); - return ret; - } - - if (cmd != SIOCDEVPRIVATE) { - DHD_OS_WAKE_UNLOCK(&dhd->pub); - return -EOPNOTSUPP; - } - - memset(&ioc, 0, sizeof(ioc)); + struct net_device *net; - /* Copy the ioc control structure part of ioctl request */ - if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) { - bcmerror = BCME_BADADDR; + net = dhd_idx2net(pub, ifidx); + if (!net) { + bcmerror = BCME_BADARG; goto done; } /* Copy out any buffer passed */ - if (ioc.buf) { - if (ioc.len == 0) { - DHD_TRACE(("%s: ioc.len=0, returns BCME_BADARG \n", __FUNCTION__)); + if (ioc->buf) { + if (ioc->len == 0) { + DHD_TRACE(("%s: ioc->len=0, returns BCME_BADARG \n", __FUNCTION__)); bcmerror = BCME_BADARG; goto done; } - buflen = MIN(ioc.len, DHD_IOCTL_MAXLEN); + buflen = MIN(ioc->len, DHD_IOCTL_MAXLEN); /* optimization for direct ioctl calls from kernel */ /* if (segment_eq(get_fs(), KERNEL_DS)) { - buf = ioc.buf; + buf = ioc->buf; } else { */ { - if (!(buf = (char*)MALLOC(dhd->pub.osh, buflen))) { + if (!(buf = (char*)MALLOC(pub->osh, buflen))) { bcmerror = BCME_NOMEM; goto done; } - if (copy_from_user(buf, ioc.buf, buflen)) { + if (copy_from_user(buf, ioc->buf, buflen)) { bcmerror = BCME_BADADDR; goto done; } } } - /* To differentiate between wl and dhd read 4 more byes */ - if ((copy_from_user(&driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t), - sizeof(uint)) != 0)) { - bcmerror = BCME_BADADDR; - goto done; - } - - if (!capable(CAP_NET_ADMIN)) { - bcmerror = BCME_EPERM; - goto done; - } - /* check for local dhd ioctl and handle it */ - if (driver == DHD_IOCTL_MAGIC) { - bcmerror = dhd_ioctl((void *)&dhd->pub, &ioc, buf, buflen); + if (ioc->driver == DHD_IOCTL_MAGIC) { + bcmerror = dhd_ioctl((void *)pub, ioc, buf, buflen); if (bcmerror) - dhd->pub.bcmerror = bcmerror; + pub->bcmerror = bcmerror; goto done; } /* send to dongle (must be up, and wl). */ - if (dhd->pub.busstate != DHD_BUS_DATA) { + if (pub->busstate != DHD_BUS_DATA) { bcmerror = BCME_DONGLE_DOWN; goto done; } - if (!dhd->pub.iswl) { + if (!pub->iswl) { bcmerror = BCME_DONGLE_DOWN; goto done; } @@ -2577,24 +2746,24 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) * intercept WLC_DISASSOC IOCTL - serialize WPS-DONE and WLC_DISASSOC IOCTL to * prevent disassoc frame being sent before WPS-DONE frame. */ - if (ioc.cmd == WLC_SET_KEY || - (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL && - strncmp("wsec_key", ioc.buf, 9) == 0) || - (ioc.cmd == WLC_SET_VAR && ioc.buf != NULL && - strncmp("bsscfg:wsec_key", ioc.buf, 15) == 0) || - ioc.cmd == WLC_DISASSOC) + if (ioc->cmd == WLC_SET_KEY || + (ioc->cmd == WLC_SET_VAR && ioc->buf != NULL && + strncmp("wsec_key", ioc->buf, 9) == 0) || + (ioc->cmd == WLC_SET_VAR && ioc->buf != NULL && + strncmp("bsscfg:wsec_key", ioc->buf, 15) == 0) || + ioc->cmd == WLC_DISASSOC) dhd_wait_pend8021x(net); #ifdef WLMEDIA_HTSF - if (ioc.buf) { + if (ioc->buf) { /* short cut wl ioctl calls here */ - if (strcmp("htsf", ioc.buf) == 0) { + if (strcmp("htsf", ioc->buf) == 0) { dhd_ioctl_htsf_get(dhd, 0); return BCME_OK; } - if (strcmp("htsflate", ioc.buf) == 0) { - if (ioc.set) { + if (strcmp("htsflate", ioc->buf) == 0) { + if (ioc->set) { memset(ts, 0, sizeof(tstamp_t)*TSMAX); memset(&maxdelayts, 0, sizeof(tstamp_t)); maxdelay = 0; @@ -2609,7 +2778,7 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) } return BCME_OK; } - if (strcmp("htsfclear", ioc.buf) == 0) { + if (strcmp("htsfclear", ioc->buf) == 0) { memset(&vi_d1.bin, 0, sizeof(uint32)*NUMBIN); memset(&vi_d2.bin, 0, sizeof(uint32)*NUMBIN); memset(&vi_d3.bin, 0, sizeof(uint32)*NUMBIN); @@ -2617,16 +2786,16 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) htsf_seqnum = 0; return BCME_OK; } - if (strcmp("htsfhis", ioc.buf) == 0) { + if (strcmp("htsfhis", ioc->buf) == 0) { dhd_dump_htsfhisto(&vi_d1, "H to D"); dhd_dump_htsfhisto(&vi_d2, "D to D"); dhd_dump_htsfhisto(&vi_d3, "D to H"); dhd_dump_htsfhisto(&vi_d4, "H to H"); return BCME_OK; } - if (strcmp("tsport", ioc.buf) == 0) { - if (ioc.set) { - memcpy(&tsport, ioc.buf + 7, 4); + if (strcmp("tsport", ioc->buf) == 0) { + if (ioc->set) { + memcpy(&tsport, ioc->buf + 7, 4); } else { DHD_ERROR(("current timestamp port: %d \n", tsport)); } @@ -2635,52 +2804,182 @@ dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) } #endif /* WLMEDIA_HTSF */ - if ((ioc.cmd == WLC_SET_VAR || ioc.cmd == WLC_GET_VAR) && - ioc.buf != NULL && strncmp("rpc_", ioc.buf, 4) == 0) { + if ((ioc->cmd == WLC_SET_VAR || ioc->cmd == WLC_GET_VAR) && + ioc->buf != NULL && strncmp("rpc_", ioc->buf, 4) == 0) { #ifdef BCM_FD_AGGR - bcmerror = dhd_fdaggr_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); + bcmerror = dhd_fdaggr_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, buf, buflen); #else bcmerror = BCME_UNSUPPORTED; #endif goto done; } - bcmerror = dhd_wl_ioctl(&dhd->pub, ifidx, (wl_ioctl_t *)&ioc, buf, buflen); + bcmerror = dhd_wl_ioctl(pub, ifidx, (wl_ioctl_t *)ioc, buf, buflen); done: - dhd_check_hang(net, &dhd->pub, bcmerror); + dhd_check_hang(net, pub, bcmerror); - if (!bcmerror && buf && ioc.buf) { - if (copy_to_user(ioc.buf, buf, buflen)) + if (!bcmerror && buf && ioc->buf) { + if (copy_to_user(ioc->buf, buf, buflen)) bcmerror = -EFAULT; } if (buf) - MFREE(dhd->pub.osh, buf, buflen); + MFREE(pub->osh, buf, buflen); + return bcmerror; +} + +static int +dhd_ioctl_entry(struct net_device *net, struct ifreq *ifr, int cmd) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(net); + dhd_ioctl_t ioc; + int bcmerror = 0; + int ifidx; + int ret; + + DHD_OS_WAKE_LOCK(&dhd->pub); + + /* send to dongle only if we are not waiting for reload already */ + if (dhd->pub.hang_was_sent) { + DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); + DHD_OS_WAKE_LOCK_CTRL_TIMEOUT_ENABLE(&dhd->pub, DHD_EVENT_TIMEOUT_MS); + DHD_OS_WAKE_UNLOCK(&dhd->pub); + return OSL_ERROR(BCME_DONGLE_DOWN); + } + + ifidx = dhd_net2idx(dhd, net); + DHD_TRACE(("%s: ifidx %d, cmd 0x%04x\n", __FUNCTION__, ifidx, cmd)); + + if (ifidx == DHD_BAD_IF) { + DHD_ERROR(("%s: BAD IF\n", __FUNCTION__)); + DHD_OS_WAKE_UNLOCK(&dhd->pub); + return -1; + } + +#if defined(CONFIG_WIRELESS_EXT) + /* linux wireless extensions */ + if ((cmd >= SIOCIWFIRST) && (cmd <= SIOCIWLAST)) { + /* may recurse, do NOT lock */ + ret = wl_iw_ioctl(net, ifr, cmd); + DHD_OS_WAKE_UNLOCK(&dhd->pub); + return ret; + } +#endif /* defined(CONFIG_WIRELESS_EXT) */ + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) + if (cmd == SIOCETHTOOL) { + ret = dhd_ethtool(dhd, (void*)ifr->ifr_data); + DHD_OS_WAKE_UNLOCK(&dhd->pub); + return ret; + } +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(2, 4, 2) */ + + if (cmd == SIOCDEVPRIVATE+1) { + ret = wl_android_priv_cmd(net, ifr, cmd); + dhd_check_hang(net, &dhd->pub, ret); + DHD_OS_WAKE_UNLOCK(&dhd->pub); + return ret; + } + + if (cmd != SIOCDEVPRIVATE) { + DHD_OS_WAKE_UNLOCK(&dhd->pub); + return -EOPNOTSUPP; + } + + memset(&ioc, 0, sizeof(ioc)); + + /* Copy the ioc control structure part of ioctl request */ + if (copy_from_user(&ioc, ifr->ifr_data, sizeof(wl_ioctl_t))) { + bcmerror = BCME_BADADDR; + goto done; + } + + /* To differentiate between wl and dhd read 4 more byes */ + if ((copy_from_user(&ioc.driver, (char *)ifr->ifr_data + sizeof(wl_ioctl_t), + sizeof(uint)) != 0)) { + bcmerror = BCME_BADADDR; + goto done; + } + + if (!capable(CAP_NET_ADMIN)) { + bcmerror = BCME_EPERM; + goto done; + } + + bcmerror = dhd_ioctl_process(&dhd->pub, ifidx, &ioc); + +done: DHD_OS_WAKE_UNLOCK(&dhd->pub); return OSL_ERROR(bcmerror); } #ifdef WL_CFG80211 +static void +dhd_delete_virt_iface(dhd_if_t *ifp) +{ + dhd_info_t *dhd; +#ifdef SOFTAP + unsigned long flags; +#endif + + if (!ifp || !ifp->info || !ifp->idx) + return; + ASSERT(ifp && ifp->info && ifp->idx); /* Virtual interfaces only */ + dhd = ifp->info; + + DHD_TRACE(("%s: idx %d, state %d\n", __FUNCTION__, ifp->idx, ifp->state)); + + if (wl_cfg80211_is_progress_ifchange()) + return; + + /* Make sure that we don't enter again here if .. */ + /* dhd_op_if is called again from some other context */ + ifp->state = DHD_IF_DELETING; + if (ifp->net != NULL) { + DHD_ERROR(("\n%s: got 'DHD_IF_DEL' state\n", __FUNCTION__)); + + ASSERT_RTNL(); + + netif_stop_queue(ifp->net); + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { + wl_cfg80211_ifdel_ops(ifp->net); + } + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33)) + if (rtnl_is_locked()) + unregister_netdevice_queue(ifp->net, NULL); + else +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 33) */ + unregister_netdev(ifp->net); + + if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { + wl_cfg80211_notify_ifdel(); + } + + free_netdev(ifp->net); + ifp->net = NULL; + } + + ifp->set_multicast = FALSE; + dhd->iflist[ifp->idx] = NULL; +#ifdef SOFTAP + flags = dhd_os_spin_lock(&dhd->pub); + if (ifp->net == ap_net_dev) + ap_net_dev = NULL; /* NULL SOFTAP global wl0.1 as well */ + dhd_os_spin_unlock(&dhd->pub, flags); +#endif /* SOFTAP */ + MFREE(dhd->pub.osh, ifp, sizeof(*ifp)); +} + static int dhd_cleanup_virt_ifaces(dhd_info_t *dhd) { int i = 1; /* Leave ifidx 0 [Primary Interface] */ -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - int rollback_lock = FALSE; -#endif DHD_TRACE(("%s: Enter \n", __func__)); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - /* release lock for unregister_netdev */ - if (rtnl_is_locked()) { - rtnl_unlock(); - rollback_lock = TRUE; - } -#endif - for (i = 1; i < DHD_MAX_IFS; i++) { dhd_net_if_lock_local(dhd); if (dhd->iflist[i]) { @@ -2689,17 +2988,12 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) (dhd->iflist[i]->state != DHD_IF_DELETING)) { dhd->iflist[i]->state = DHD_IF_DEL; dhd->iflist[i]->idx = i; - dhd_op_if(dhd->iflist[i]); + dhd_delete_virt_iface(dhd->iflist[i]); } } dhd_net_if_unlock_local(dhd); } -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - if (rollback_lock) - rtnl_lock(); -#endif - return 0; } #endif /* WL_CFG80211 */ @@ -2708,8 +3002,8 @@ dhd_cleanup_virt_ifaces(dhd_info_t *dhd) /* Flags to indicate if we distingish power off policy when * user set the memu "Keep Wi-Fi on during sleep" to "Never" */ -int sleep_never = 0; -#endif +int trigger_deep_sleep = 0; +#endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */ static int dhd_stop(struct net_device *net) @@ -2744,33 +3038,28 @@ dhd_stop(struct net_device *net) #endif #ifdef PROP_TXSTATUS - dhd_os_wlfc_block(&dhd->pub); - dhd_wlfc_cleanup(&dhd->pub); - dhd_os_wlfc_unblock(&dhd->pub); + dhd_wlfc_cleanup(&dhd->pub, NULL, 0); #endif - /* Stop the protocol module */ dhd_prot_stop(&dhd->pub); OLD_MOD_DEC_USE_COUNT; exit: #if defined(WL_CFG80211) - if (ifidx == 0) { - if (!dhd_download_fw_on_driverload) - wl_android_wifi_off(net); + if (ifidx == 0 && !dhd_download_fw_on_driverload) + wl_android_wifi_off(net); #ifdef SUPPORT_DEEP_SLEEP - else { - /* CSP#505233: Flags to indicate if we distingish - * power off policy when user set the memu - * "Keep Wi-Fi on during sleep" to "Never" - */ - if (sleep_never) { - dhd_deepsleep(net, 1); - sleep_never = 0; - } + else { + /* CSP#505233: Flags to indicate if we distingish + * power off policy when user set the memu + * "Keep Wi-Fi on during sleep" to "Never" + */ + if (trigger_deep_sleep) { + dhd_deepsleep(net, 1); + trigger_deep_sleep = 0; } -#endif /* SUPPORT_DEEP_SLEEP */ } +#endif /* SUPPORT_DEEP_SLEEP */ #endif dhd->pub.rxcnt_timeout = 0; dhd->pub.txcnt_timeout = 0; @@ -2789,31 +3078,49 @@ dhd_open(struct net_device *net) int ifidx; int32 ret = 0; + /* WAR : to prevent calling dhd_open abnormally in quick succession after hang event */ + if (dhd->pub.hang_was_sent == 1) { + DHD_ERROR(("%s: HANG was sent up earlier\n", __FUNCTION__)); + return -1; + } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 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 + DHD_OS_WAKE_LOCK(&dhd->pub); - DHD_ERROR(("%s: Enter, net[%p]\n", __FUNCTION__, net)); /* Update FW path if it was changed */ if (strlen(firmware_path) != 0) { if (firmware_path[strlen(firmware_path)-1] == '\n') firmware_path[strlen(firmware_path)-1] = '\0'; + bzero(fw_path, MOD_PARAM_PATHLEN); strncpy(fw_path, firmware_path, sizeof(fw_path)-1); - fw_path[sizeof(fw_path)-1] = '\0'; -#if defined(SUPPORT_MULTIPLE_REVISION) - ret = concate_revision(dhd->pub.bus, fw_path, MOD_PARAM_PATHLEN); - if (ret != 0) { - DHD_ERROR(("%s: fail to concatnate revison \n", __FUNCTION__)); - goto exit; - } -#endif firmware_path[0] = '\0'; } +#ifdef CUSTOMER_HW4 /* Update NVRAM path if it was changed */ if (!dhd_download_fw_on_driverload && (strlen(nvram_path) != 0)) { if (nvram_path[strlen(nvram_path)-1] == '\n') nvram_path[strlen(nvram_path)-1] = '\0'; - strcpy(nv_path, nvram_path); - nvram_path[0] = '\0'; + bzero(nv_path, MOD_PARAM_PATHLEN); + strncpy(nv_path, nvram_path, sizeof(nv_path)-1); + } +#endif /* CUSTOMER_HW4 */ + +#if defined(CUSTOMER_HW4) && defined(SUPPORT_MULTIPLE_REVISION) + /* dhd_open() can be call several times when loading failed */ + if (strlen(firmware_path) != 0) { + ret = concate_revision(dhd->pub.bus, fw_path, MOD_PARAM_PATHLEN, + nv_path, MOD_PARAM_PATHLEN); + if (ret != 0) { + DHD_ERROR(("%s: fail to concatnate revison \n", __FUNCTION__)); + goto exit; + } } +#endif /* CUSTOMER_HW4 && SUPPORT_MULTIPLE_REVISION */ dhd->pub.dongle_trap_occured = 0; dhd->pub.hang_was_sent = 0; @@ -2854,52 +3161,34 @@ dhd_open(struct net_device *net) if (!dhd_download_fw_on_driverload) { ret = wl_android_wifi_on(net); if (ret != 0) { - DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + DHD_ERROR(("%s : wl_android_wifi_on failed (%d)\n", + __FUNCTION__, ret)); ret = -1; goto exit; } - } else { + } #ifdef SUPPORT_DEEP_SLEEP + else { /* Flags to indicate if we distingish * power off policy when user set the memu * "Keep Wi-Fi on during sleep" to "Never" */ - if (sleep_never) { + if (trigger_deep_sleep) { dhd_deepsleep(net, 0); - sleep_never = 0; + trigger_deep_sleep = 0; } -#endif /* SUPPORT_DEEP_SLEEP */ } +#endif /* SUPPORT_DEEP_SLEEP */ #endif if (dhd->pub.busstate != DHD_BUS_DATA) { -#if defined(CUSTOMER_HW4) -#define WAIT_DHDBUS_READY 5 - /* Delay ifup until insmod completed in case of module type */ - if (dhd_download_fw_on_driverload) { - uint retry = 0; - - do { - OSL_DELAY(100*1000); - } while ((dhd->pub.busstate != DHD_BUS_DATA) && - (retry++ < WAIT_DHDBUS_READY)); - - if (dhd->pub.busstate != DHD_BUS_DATA) { - DHD_ERROR(("%s: call dev open before insmod complete!\n", - __FUNCTION__)); - ret = -1; - goto exit; - } + /* try to bring up bus */ + if ((ret = dhd_bus_start(&dhd->pub)) != 0) { + DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); + ret = -1; + goto exit; } - else -#endif /* CUSTOMER_HW4 */ - /* try to bring up bus */ - if ((ret = dhd_bus_start(&dhd->pub)) != 0) { - DHD_ERROR(("%s: failed with code %d\n", __FUNCTION__, ret)); - ret = -1; - goto exit; - } } @@ -2937,6 +3226,11 @@ exit: dhd_stop(net); DHD_OS_WAKE_UNLOCK(&dhd->pub); + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 1 + mutex_unlock(&_dhd_sdio_mutex_lock_); +#endif + return ret; } @@ -2949,6 +3243,15 @@ int dhd_do_driver_init(struct net_device *net) return -EINVAL; } +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 && 1 +#ifdef MULTIPLE_SUPPLICANT + if (mutex_is_locked(&_dhd_sdio_mutex_lock_) != 0) { + DHD_ERROR(("%s : dhdsdio_probe is already running!\n", __FUNCTION__)); + return 0; + } +#endif +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ + /* && defined(OEM_ANDROID) && defined(BCMSDIO) */ dhd = *(dhd_info_t **)netdev_priv(net); /* If driver is already initialized, do nothing @@ -2957,7 +3260,7 @@ int dhd_do_driver_init(struct net_device *net) DHD_TRACE(("Driver already Inititalized. Nothing to do")); return 0; } - DHD_ERROR(("%s: call dhd_open\n", __FUNCTION__)); + if (dhd_open(net) < 0) { DHD_ERROR(("Driver Init Failed \n")); return -1; @@ -3007,7 +3310,7 @@ dhd_add_if(dhd_info_t *dhd, int ifidx, void *handle, char *name, } } else if ((ifp = MALLOC(dhd->pub.osh, sizeof(dhd_if_t))) == NULL) { - DHD_ERROR(("%s: OOM - dhd_if_t\n", __FUNCTION__)); + DHD_ERROR(("%s: OOM - dhd_if_t(%d)\n", __FUNCTION__, sizeof(dhd_if_t))); return -ENOMEM; } @@ -3095,20 +3398,21 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* updates firmware nvram path if it was provided as module parameters */ if (strlen(firmware_path) != 0) { + bzero(fw_path, MOD_PARAM_PATHLEN); strncpy(fw_path, firmware_path, sizeof(fw_path) - 1); - fw_path[sizeof(fw_path) - 1] = '\0'; } if (strlen(nvram_path) != 0) { + bzero(nv_path, MOD_PARAM_PATHLEN); strncpy(nv_path, nvram_path, sizeof(nv_path) -1); - nv_path[sizeof(nv_path) -1] = '\0'; } -#if defined(SUPPORT_MULTIPLE_REVISION) +#if defined(CUSTOMER_HW4) && defined(SUPPORT_MULTIPLE_REVISION) if (strlen(fw_path) != 0 && - concate_revision(bus, fw_path, MOD_PARAM_PATHLEN) != 0) { + concate_revision(bus, fw_path, MOD_PARAM_PATHLEN, + nv_path, MOD_PARAM_PATHLEN) != 0) { DHD_ERROR(("%s: fail to concatnate revison \n", __FUNCTION__)); goto fail; } -#endif +#endif /* CUSTOMER_HW4 && SUPPORT_MULTIPLE_REVISION */ /* Allocate etherdev, including space for private structure */ if (!(net = alloc_etherdev(sizeof(dhd)))) { @@ -3118,10 +3422,18 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd_state |= DHD_ATTACH_STATE_NET_ALLOC; /* Allocate primary dhd_info */ - if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { - DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__)); - goto fail; +#if defined(CONFIG_DHD_USE_STATIC_BUF) + dhd = (void *)dhd_os_prealloc(osh, DHD_PREALLOC_DHD_INFO, sizeof(dhd_info_t)); + if (!dhd) { + DHD_INFO(("%s: OOM - Pre-alloc dhd_info\n", __FUNCTION__)); +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + if (!(dhd = MALLOC(osh, sizeof(dhd_info_t)))) { + DHD_ERROR(("%s: OOM - alloc dhd_info\n", __FUNCTION__)); + goto fail; + } +#if defined(CONFIG_DHD_USE_STATIC_BUF) } +#endif /* CONFIG_DHD_USE_STATIC_BUF */ memset(dhd, 0, sizeof(dhd_info_t)); #ifdef DHDTHREAD @@ -3185,20 +3497,33 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) spin_lock_init(&dhd->sdlock); spin_lock_init(&dhd->txqlock); spin_lock_init(&dhd->dhd_lock); +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) + spin_lock_init(&dhd->rxf_lock); +#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ +#ifdef DHDTCPACK_SUPPRESS + spin_lock_init(&dhd->tcpack_lock); +#endif /* DHDTCPACK_SUPPRESS */ /* Initialize Wakelock stuff */ spin_lock_init(&dhd->wakelock_spinlock); dhd->wakelock_counter = 0; + dhd->wakelock_wd_counter = 0; dhd->wakelock_rx_timeout_enable = 0; dhd->wakelock_ctrl_timeout_enable = 0; #ifdef CONFIG_HAS_WAKELOCK - wake_lock_init(&dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); - wake_lock_init(&dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); - wake_lock_init(&dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) - wake_lock_init(&dhd->pub.pno_wakelock, WAKE_LOCK_SUSPEND, "pno_wake_lock"); -#endif -#endif + dhd->wl_wifi = MALLOC(osh, sizeof(struct wake_lock)); + dhd->wl_rxwake = MALLOC(osh, sizeof(struct wake_lock)); + dhd->wl_ctrlwake = MALLOC(osh, sizeof(struct wake_lock)); + dhd->wl_wdwake = MALLOC(osh, sizeof(struct wake_lock)); + if (!dhd->wl_wifi || !dhd->wl_rxwake || !dhd->wl_ctrlwake || !dhd->wl_wdwake) { + DHD_ERROR(("%s: mem alloc for wake lock failed\n", __FUNCTION__)); + goto fail; + } + wake_lock_init(dhd->wl_wifi, WAKE_LOCK_SUSPEND, "wlan_wake"); + wake_lock_init(dhd->wl_rxwake, WAKE_LOCK_SUSPEND, "wlan_rx_wake"); + wake_lock_init(dhd->wl_ctrlwake, WAKE_LOCK_SUSPEND, "wlan_ctrl_wake"); + wake_lock_init(dhd->wl_wdwake, WAKE_LOCK_SUSPEND, "wlan_wd_wake"); +#endif /* CONFIG_HAS_WAKELOCK */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) && 1 mutex_init(&dhd->dhd_net_if_mutex); mutex_init(&dhd->dhd_suspend_mutex); @@ -3249,13 +3574,10 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd->threads_only = FALSE; } - if (dhd_dpc_prio >= 0) { + if (dhd_watchdog_prio >= 0) { /* Initialize watchdog thread */ -#ifdef USE_KTHREAD_API - PROC_START2(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread"); -#else - PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0); -#endif + PROC_START(dhd_watchdog_thread, dhd, &dhd->thr_wdt_ctl, 0, "dhd_watchdog_thread"); + } else { dhd->thr_wdt_ctl.thr_pid = -1; } @@ -3263,16 +3585,17 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) /* Set up the bottom half handler */ if (dhd_dpc_prio >= 0) { /* Initialize DPC thread */ -#ifdef USE_KTHREAD_API - PROC_START2(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc"); -#else - PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0); -#endif + PROC_START(dhd_dpc_thread, dhd, &dhd->thr_dpc_ctl, 0, "dhd_dpc"); } else { /* use tasklet for dpc */ tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); dhd->thr_dpc_ctl.thr_pid = -1; } +#ifdef RXFRAME_THREAD + bzero(&dhd->pub.skbbuf[0], sizeof(void *) * MAXSKBPEND); + /* Initialize RXF thread */ + PROC_START(dhd_rxf_thread, dhd, &dhd->thr_rxf_ctl, 0, "dhd_rxf"); +#endif #else /* Set up the bottom half handler */ tasklet_init(&dhd->tasklet, dhd_dpc, (ulong)dhd); @@ -3280,18 +3603,16 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) #endif /* DHDTHREAD */ if (dhd_sysioc) { -#ifdef USE_KTHREAD_API - PROC_START2(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc"); -#else - PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0); -#endif + PROC_START(_dhd_sysioc_thread, dhd, &dhd->thr_sysioc_ctl, 0, "dhd_sysioc"); } else { dhd->thr_sysioc_ctl.thr_pid = -1; } dhd_state |= DHD_ATTACH_STATE_THREADS_CREATED; + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) && (1) INIT_WORK(&dhd->work_hang, dhd_hang_process); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ + /* * Save the dhd_info into the priv */ @@ -3307,13 +3628,18 @@ dhd_attach(osl_t *osh, struct dhd_bus *bus, uint bus_hdrlen) dhd->early_suspend.resume = dhd_late_resume; register_early_suspend(&dhd->early_suspend); dhd_state |= DHD_ATTACH_STATE_EARLYSUSPEND_DONE; -#endif +#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ #ifdef ARP_OFFLOAD_SUPPORT dhd->pend_ipaddr = 0; register_inetaddr_notifier(&dhd_notifier); #endif /* ARP_OFFLOAD_SUPPORT */ +#ifdef DHDTCPACK_SUPPRESS + dhd->pub.tcp_ack_info_cnt = 0; + bzero(dhd->pub.tcp_ack_info_tbl, sizeof(struct tcp_ack_info)*MAXTCPSTREAMS); +#endif /* DHDTCPACK_SUPPRESS */ + dhd_state |= DHD_ATTACH_STATE_DONE; dhd->dhd_state = dhd_state; return &dhd->pub; @@ -3351,13 +3677,31 @@ dhd_bus_start(dhd_pub_t *dhdp) /* try to download image and nvram to the dongle */ if ((dhd->pub.busstate == DHD_BUS_DOWN) && - (fw_path != NULL) && (fw_path[0] != '\0') && - (nv_path != NULL) && (nv_path[0] != '\0')) { + (fw_path[0] != '\0') && + (nv_path[0] != '\0')) { +#ifdef SHOW_NVRAM_TYPE + { /* Show nvram type in the kernel log */ + int i; + for (i = 0; nv_path[i] != '\0'; ++i) { + if (nv_path[i] == '.') { + ++i; + break; + } + } + DHD_ERROR(("%s: nvram_type = [%s]\n", __FUNCTION__, &nv_path[i])); + } +#endif /* SHOW_NVRAM_TYPE */ /* wake lock moved to dhdsdio_download_firmware */ if (!(dhd_bus_download_firmware(dhd->pub.bus, dhd->pub.osh, - fw_path, nv_path))) { - DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware or nvram path is wrong\n", - __FUNCTION__)); + fw_path, nv_path))) { +#ifdef CUSTOMER_HW4 + DHD_ERROR(("%s: dhdsdio_probe_download failed. " + "firmware or nvram wrong\n", + __FUNCTION__)); +#else + DHD_ERROR(("%s: dhdsdio_probe_download failed. firmware = %s nvram = %s\n", + __FUNCTION__, fw_path, nv_path)); +#endif /* CUSTOMER_HW4 */ #ifdef DHDTHREAD if (dhd->threads_only) dhd_os_sdunlock(dhdp); @@ -3402,6 +3746,7 @@ dhd_bus_start(dhd_pub_t *dhdp) if (dhd->threads_only) dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -3422,6 +3767,7 @@ dhd_bus_start(dhd_pub_t *dhdp) if (dhd->threads_only) dhd_os_sdunlock(dhdp); #endif /* DHDTHREAD */ + DHD_OS_WD_WAKE_UNLOCK(&dhd->pub); return -ENODEV; } @@ -3478,7 +3824,7 @@ dhd_bus_start(dhd_pub_t *dhdp) #ifdef ARP_OFFLOAD_SUPPORT if (dhd->pend_ipaddr) { #ifdef AOE_IP_ALIAS_SUPPORT - aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE); + aoe_update_host_ipv4_table(&dhd->pub, dhd->pend_ipaddr, TRUE, 0); #endif /* AOE_IP_ALIAS_SUPPORT */ dhd->pend_ipaddr = 0; } @@ -3500,7 +3846,6 @@ bool dhd_is_concurrent_mode(dhd_pub_t *dhd) else return FALSE; } - #if !defined(AP) && defined(WLP2P) /* From Android JerryBean release, the concurrent mode is enabled by default and the firmware * name would be fw_bcmdhd.bin. So we need to determine whether P2P is enabled in the STA @@ -3550,7 +3895,7 @@ dhd_get_concurrent_capabilites(dhd_pub_t *dhd) ret = DHD_FLAG_CONCURR_SINGLE_CHAN_MODE; if (mchan_supported) ret |= DHD_FLAG_CONCURR_MULTI_CHAN_MODE; -#if defined(WL_ENABLE_P2P_IF) +#if defined(WL_ENABLE_P2P_IF) || defined(CUSTOMER_HW4) /* For customer_hw4, although ICS, * we still support concurrent mode */ @@ -3570,26 +3915,35 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) int ret = 0; char eventmask[WL_EVENTING_MASK_LEN]; char iovbuf[WL_EVENTING_MASK_LEN + 12]; /* Room for "event_msgs" + '\0' + bitvec */ - -#if !defined(WL_CFG80211) - uint up = 0; -#endif /* !defined(WL_CFG80211) */ + uint32 buf_key_b4_m4 = 1; +#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) + uint32 sup_wpa = 0; +#endif +#ifdef CUSTOM_AMPDU_BA_WSIZE + uint32 ampdu_ba_wsize = CUSTOM_AMPDU_BA_WSIZE; +#endif /* CUSTOM_AMPDU_BA_WSIZE */ + uint32 lpc = 1; uint power_mode = PM_FAST; uint32 dongle_align = DHD_SDALIGN; uint32 glom = CUSTOM_GLOM_SETTING; -#if defined(VSDB) || defined(ROAM_ENABLE) +#if (defined(CUSTOMER_HW4) || defined(BOARD_PANDA)) && (defined(VSDB) || \ + defined(ROAM_ENABLE)) uint bcn_timeout = 8; #else uint bcn_timeout = 4; -#endif -#ifdef ENABLE_BCN_LI_BCN_WAKEUP +#endif /* CUSTOMER_HW4 && (VSDB || ROAM_ENABLE) */ +#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP) uint32 bcn_li_bcn = 1; -#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ +#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */ uint retry_max = 3; #if defined(ARP_OFFLOAD_SUPPORT) int arpoe = 1; #endif +#if defined(CUSTOMER_HW4) + int scan_assoc_time = 80; +#else int scan_assoc_time = DHD_SCAN_ASSOC_ACTIVE_TIME; +#endif int scan_unassoc_time = DHD_SCAN_UNASSOC_ACTIVE_TIME; int scan_passive_time = DHD_SCAN_PASSIVE_TIME; char buf[WLC_IOCTL_SMLEN]; @@ -3599,10 +3953,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) uint roamvar = 0; int roam_trigger[2] = {CUSTOM_ROAM_TRIGGER_SETTING, WLC_BAND_ALL}; int roam_scan_period[2] = {10, WLC_BAND_ALL}; + int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; #ifdef ROAM_AP_ENV_DETECTION int roam_env_mode = AP_ENV_INDETERMINATE; #endif /* ROAM_AP_ENV_DETECTION */ - int roam_delta[2] = {CUSTOM_ROAM_DELTA_SETTING, WLC_BAND_ALL}; #ifdef FULL_ROAMING_SCAN_PERIOD_60_SEC int roam_fullscan_period = 60; #else /* FULL_ROAMING_SCAN_PERIOD_60_SEC */ @@ -3631,24 +3985,48 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) #ifdef OKC_SUPPORT uint32 okc = 1; #endif +#ifdef WLTDLS + uint32 tdls = 1; +#ifdef CUSTOMER_HW4 + uint32 tdls_idle_time = 10000; /* 10sec */ + uint32 tdls_auto_op = 1; + int32 tdls_rssi_high = -80; + int32 tdls_rssi_low = -85; +#endif +#endif /* WLTDLS */ + #ifdef DISABLE_11N uint32 nmode = 0; -#else -#ifdef AMPDU_HOSTREORDER - uint32 hostreorder = 1; -#endif #endif /* DISABLE_11N */ + +#ifdef DISABLE_11AC + uint32 vhtmode = 0; +#endif /* DISABLE_11AC */ + #if defined(VSDB) && defined(CUSTOMER_HW4) int interference_mode = 3; #endif +#ifdef USE_WL_TXBF + uint32 txbf = 1; +#endif /* USE_WL_TXBF */ +#ifdef USE_WL_FRAMEBURST + uint32 frameburst = 1; +#endif /* USE_WL_FRAMEBURST */ +#ifdef DHD_SET_FW_HIGHSPEED + uint32 ack_ratio = 250; + uint32 ack_ratio_depth = 64; +#endif /* DHD_SET_FW_HIGHSPEED */ #ifdef PROP_TXSTATUS #ifdef PROP_TXSTATUS_VSDB + /* In case the host does not support proptxstatus, hostreorder in dongle should be off */ + uint32 hostreorder = 0; dhd->wlfc_enabled = FALSE; /* enable WLFC only if the firmware is VSDB */ #else dhd->wlfc_enabled = TRUE; #endif /* PROP_TXSTATUS_VSDB */ #endif /* PROP_TXSTATUS */ + dhd->suspend_bcn_li_dtim = CUSTOM_SUSPEND_BCN_LI_DTIM; DHD_TRACE(("Enter %s\n", __FUNCTION__)); dhd->op_mode = 0; #ifdef GET_CUSTOM_MAC_ENABLE @@ -3679,6 +4057,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } #endif /* GET_CUSTOM_MAC_ENABLE */ + DHD_TRACE(("Firmware = %s\n", fw_path)); if ((!op_mode && strstr(fw_path, "_apsta") != NULL) || (op_mode == DHD_FLAG_HOSTAP_MODE)) { @@ -3717,7 +4096,6 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) DHD_ERROR(("%s mpc for HostAPD failed %d\n", __FUNCTION__, ret)); } #endif - } else { uint32 concurrent_mode = 0; @@ -3776,6 +4154,10 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) DHD_ERROR(("%s: country code setting failed\n", __FUNCTION__)); } +#ifdef DISABLE_11AC + bcm_mkiovar("vhtmode", (char *)&vhtmode, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +#endif /* Set Listen Interval */ bcm_mkiovar("assoc_listen", (char *)&listen_interval, 4, iovbuf, sizeof(iovbuf)); @@ -3787,7 +4169,7 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("roam_off", (char *)&roamvar, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); #endif /* ROAM_ENABLE || DISABLE_BUILTIN_ROAM */ -#ifdef ROAM_ENABLE +#if defined(ROAM_ENABLE) if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_ROAM_TRIGGER, roam_trigger, sizeof(roam_trigger), TRUE, 0)) < 0) DHD_ERROR(("%s: roam trigger set failed %d\n", __FUNCTION__, ret)); @@ -3806,8 +4188,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) 4, iovbuf, sizeof(iovbuf)); if (dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0) == BCME_OK) dhd->roam_env_detection = TRUE; - else + else { dhd->roam_env_detection = FALSE; + } } #endif /* ROAM_AP_ENV_DETECTION */ #endif /* ROAM_ENABLE */ @@ -3816,13 +4199,37 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) bcm_mkiovar("okc_enable", (char *)&okc, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); #endif +#ifdef WLTDLS + bcm_mkiovar("tdls_enable", (char *)&tdls, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +#ifdef CUSTOMER_HW4 + bcm_mkiovar("tdls_auto_op", (char *)&tdls_auto_op, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + + bcm_mkiovar("tdls_idle_time", (char *)&tdls_idle_time, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#ifdef CONFIG_CONTROL_PM + bcm_mkiovar("tdls_rssi_high", (char *)&tdls_rssi_high, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + + bcm_mkiovar("tdls_rssi_low", (char *)&tdls_rssi_low, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); +#endif +#endif /* WLTDLS */ + + /* Set lpc 1 */ + bcm_mkiovar("lpc", (char *)&lpc, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set lpc failed %d\n", __FUNCTION__, ret)); + } + +#if defined(CUSTOMER_HW4) && defined(CONFIG_CONTROL_PM) sec_control_pm(dhd, &power_mode); #else /* Set PowerSave mode */ dhd_wl_ioctl_cmd(dhd, WLC_SET_PM, (char *)&power_mode, sizeof(power_mode), TRUE, 0); -#endif +#endif /* CUSTOMER_HW4 && CONFIG_CONTROL_PM */ /* Match Host and Dongle rx alignment */ bcm_mkiovar("bus:txglomalign", (char *)&dongle_align, 4, iovbuf, sizeof(iovbuf)); @@ -3873,6 +4280,60 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) } } #endif /* defined(KEEP_ALIVE) */ +#ifdef USE_WL_TXBF + bcm_mkiovar("txbf", (char *)&txbf, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set txbf failed %d\n", __FUNCTION__, ret)); + } +#endif /* USE_WL_TXBF */ + +#ifdef USE_WL_FRAMEBURST +#if defined(CUSTOMER_HW4) + frameburst = sec_control_frameburst(); +#endif /* CUSTOMER_HW4 */ + /* Set frameburst to value */ + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_FAKEFRAG, (char *)&frameburst, + sizeof(frameburst), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set frameburst failed %d\n", __FUNCTION__, ret)); + } +#endif /* USE_WL_FRAMEBURST */ +#ifdef DHD_SET_FW_HIGHSPEED + /* Set ack_ratio */ + bcm_mkiovar("ack_ratio", (char *)&ack_ratio, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set ack_ratio failed %d\n", __FUNCTION__, ret)); + } + + /* Set ack_ratio_depth */ + bcm_mkiovar("ack_ratio_depth", (char *)&ack_ratio_depth, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set ack_ratio_depth failed %d\n", __FUNCTION__, ret)); + } +#endif /* DHD_SET_FW_HIGHSPEED */ +#ifdef CUSTOM_AMPDU_BA_WSIZE + /* Set ampdu ba wsize to 64 */ + bcm_mkiovar("ampdu_ba_wsize", (char *)&du_ba_wsize, 4, iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0)) < 0) { + DHD_ERROR(("%s Set ampdu_ba_wsize to %d failed %d\n", + __FUNCTION__, CUSTOM_AMPDU_BA_WSIZE, ret)); + } +#endif /* CUSTOM_AMPDU_BA_WSIZE */ +#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) + /* Read 4-way handshake requirements. */ + bcm_mkiovar("sup_wpa", (char *)&sup_wpa, 4, + iovbuf, sizeof(iovbuf)); + ret = dhd_wl_ioctl_cmd(dhd, WLC_GET_VAR, iovbuf, sizeof(iovbuf), FALSE, 0); + if (ret >= 0) + dhd->fw_4way_handshake = TRUE; + DHD_TRACE(("4-way handshake mode is: %d\n", dhd->fw_4way_handshake)); +#endif /* BCMSUP_4WAY_HANDSHAKE && WLAN_AKM_SUITE_FT_8021X */ + + bcm_mkiovar("buf_key_b4_m4", (char *)&buf_key_b4_m4, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); /* Read event_msgs mask */ bcm_mkiovar("event_msgs", eventmask, WL_EVENTING_MASK_LEN, iovbuf, sizeof(iovbuf)); @@ -3919,6 +4380,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) setbit(eventmask, WLC_E_ADDTS_IND); setbit(eventmask, WLC_E_DELTS_IND); #endif /* BCMCCX */ +#ifdef WLTDLS + setbit(eventmask, WLC_E_TDLS_PEER_EVENT); +#endif /* WLTDLS */ #ifdef WL_CFG80211 setbit(eventmask, WLC_E_ESCAN_RESULT); if (dhd->op_mode & DHD_FLAG_P2P_MODE) { @@ -3961,21 +4425,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd_arp_offload_enable(dhd, FALSE); dhd_arp_offload_set(dhd, 0); } + dhd_arp_enable = arpoe; #endif /* ARP_OFFLOAD_SUPPORT */ #ifdef PKT_FILTER_SUPPORT /* Setup default defintions for pktfilter , enable in suspend */ dhd->pktfilter_count = 5; - /* Setup filter to allow only unicast */ - dhd->pktfilter[0] = "100 0 0 0 0x01 0x00"; dhd->pktfilter[1] = NULL; dhd->pktfilter[2] = NULL; dhd->pktfilter[3] = NULL; /* Add filter to pass multicastDNS packet and NOT filter out as Broadcast */ dhd->pktfilter[4] = "104 0 0 0 0xFFFFFFFFFFFF 0x01005E0000FB"; -#ifdef CUSTOMER_HW4 -#ifdef GAN_LITE_NAT_KEEPALIVE_FILTER +#if defined(CUSTOMER_HW4) && defined(GAN_LITE_NAT_KEEPALIVE_FILTER) dhd->pktfilter_count = 4; /* Setup filter to block broadcast and NAT Keepalive packets */ dhd->pktfilter[0] = "100 0 0 0 0xffffff 0xffffff"; /* discard all broadcast packets */ @@ -3984,23 +4446,19 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) dhd->pktfilter[3] = NULL; #else /* Setup filter to allow only unicast */ -#if defined(BLOCK_IPV6_PACKET) +#if defined(BLOCK_IPV6_PACKET) && defined(CUSTOMER_HW4) dhd->pktfilter[0] = "100 0 0 0 " HEX_PREF_STR UNI_FILTER_STR ZERO_ADDR_STR ETHER_TYPE_STR IPV6_FILTER_STR " " HEX_PREF_STR ZERO_ADDR_STR ZERO_ADDR_STR ETHER_TYPE_STR ZERO_TYPE_STR; #else dhd->pktfilter[0] = "100 0 0 0 0x01 0x00"; -#endif /* BLOCK_IPV6_PACKET */ -#if defined(PASS_IPV4_SUSPEND) +#endif /* BLOCK_IPV6_PACKET && CUSTOMER_HW4 */ +#if defined(PASS_IPV4_SUSPEND) && defined(CUSTOMER_HW4) dhd->pktfilter_count = 5; dhd->pktfilter[4] = "104 0 0 0 0xFFFFFF 0x01005E"; -#endif -#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */ -#ifdef PASS_ARP_PACKET - dhd->pktfilter[dhd->pktfilter_count++] = "105 0 0 12 0xFFFF 0x0806"; -#endif -#endif /* CUSTOMER_HW4 */ +#endif /* PASS_IPV4_SUSPEND && CUSTOMER_HW4 */ +#endif /* GAN_LITE_NAT_KEEPALIVE_FILTER && CUSTOMER_HW4 */ #if defined(SOFTAP) if (ap_fw_loaded) { @@ -4014,30 +4472,21 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0)) < 0) DHD_ERROR(("%s wl nmode 0 failed %d\n", __FUNCTION__, ret)); #else -#ifdef AMPDU_HOSTREORDER +#if defined(PROP_TXSTATUS) && defined(PROP_TXSTATUS_VSDB) bcm_mkiovar("ampdu_hostreorder", (char *)&hostreorder, 4, buf, sizeof(buf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, buf, sizeof(buf), TRUE, 0); -#endif /* AMPDU_HOSTREORDER */ +#endif #endif /* DISABLE_11N */ -#if !defined(WL_CFG80211) - /* Force STA UP */ - if ((ret = dhd_wl_ioctl_cmd(dhd, WLC_UP, (char *)&up, sizeof(up), TRUE, 0)) < 0) { - DHD_ERROR(("%s Setting WL UP failed %d\n", __FUNCTION__, ret)); - goto done; - } -#endif - #if defined(VSDB) && defined(CUSTOMER_HW4) dhd_wl_ioctl_cmd(dhd, WLC_SET_INTERFERENCE_MODE, (int *)&interference_mode, sizeof(int), TRUE, 0); #endif -#ifdef ENABLE_BCN_LI_BCN_WAKEUP +#if defined(CUSTOMER_HW4) && defined(ENABLE_BCN_LI_BCN_WAKEUP) bcm_mkiovar("bcn_li_bcn", (char *)&bcn_li_bcn, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhd, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); -#endif /* ENABLE_BCN_LI_BCN_WAKEUP */ - +#endif /* CUSTOMER_HW4 && ENABLE_BCN_LI_BCN_WAKEUP */ /* query for 'ver' to get version info from firmware */ memset(buf, 0, sizeof(buf)); ptr = buf; @@ -4049,14 +4498,9 @@ dhd_preinit_ioctls(dhd_pub_t *dhd) /* Print fw version info */ DHD_ERROR(("Firmware version = %s\n", buf)); - dhd_set_version_info(dhd, buf); - - DHD_BLOG(buf, strlen(buf) + 1); - DHD_BLOG(dhd_version, strlen(dhd_version) + 1); - /* Check and adjust IOCTL response timeout for Manufactring firmware */ if (strstr(buf, MANUFACTRING_FW) != NULL) { - dhd_os_set_ioctl_resp_timeout(IOCTL_RESP_TIMEOUT * 10); + dhd_os_set_ioctl_resp_timeout(20000); DHD_ERROR(("%s : adjust IOCTL response time for Manufactring Firmware\n", __FUNCTION__)); } @@ -4120,7 +4564,7 @@ int dhd_change_mtu(dhd_pub_t *dhdp, int new_mtu, int ifidx) #ifdef ARP_OFFLOAD_SUPPORT /* add or remove AOE host ip(s) (up to 8 IPs on the interface) */ void -aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add) +aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add, int idx) { u32 ipv4_buf[MAX_IPV4_ENTRIES]; /* temp save for AOE host_ip table */ int i; @@ -4129,13 +4573,13 @@ aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add) bzero(ipv4_buf, sizeof(ipv4_buf)); /* display what we've got */ - ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf)); + ret = dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx); DHD_ARPOE(("%s: hostip table read from Dongle:\n", __FUNCTION__)); #ifdef AOE_DBG dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ #endif /* now we saved hoste_ip table, clr it in the dongle AOE */ - dhd_aoe_hostip_clr(dhd_pub); + dhd_aoe_hostip_clr(dhd_pub, idx); if (ret) { DHD_ERROR(("%s failed\n", __FUNCTION__)); @@ -4156,19 +4600,24 @@ aoe_update_host_ipv4_table(dhd_pub_t *dhd_pub, u32 ipa, bool add) if (ipv4_buf[i] != 0) { /* add back host_ip entries from our local cache */ - dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i]); + dhd_arp_offload_add_ip(dhd_pub, ipv4_buf[i], idx); DHD_ARPOE(("%s: added IP:%x to dongle arp_hostip[%d]\n\n", __FUNCTION__, ipv4_buf[i], i)); } } #ifdef AOE_DBG /* see the resulting hostip table */ - dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf)); + dhd_arp_get_arp_hostip_table(dhd_pub, ipv4_buf, sizeof(ipv4_buf), idx); DHD_ARPOE(("%s: read back arp_hostip table:\n", __FUNCTION__)); dhd_print_buf(ipv4_buf, 32, 4); /* max 8 IPs 4b each */ #endif } +/* + * Notification mechanism from kernel to our driver. This function is called by the Linux kernel + * whenever there is an event related to an IP address. + * ptr : kernel provided pointer to IP address that has changed + */ static int dhd_device_event(struct notifier_block *this, unsigned long event, void *ptr) @@ -4177,19 +4626,48 @@ static int dhd_device_event(struct notifier_block *this, dhd_info_t *dhd; dhd_pub_t *dhd_pub; + int idx; - if (!ifa) + if (!dhd_arp_enable) return NOTIFY_DONE; + if (!ifa || !(ifa->ifa_dev->dev)) + return NOTIFY_DONE; + +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) + /* Filter notifications meant for non Broadcom devices */ + if ((ifa->ifa_dev->dev->netdev_ops != &dhd_ops_pri) && + (ifa->ifa_dev->dev->netdev_ops != &dhd_ops_virt)) { +#ifdef WLP2P + if (!wl_cfgp2p_is_ifops(ifa->ifa_dev->dev->netdev_ops)) +#endif + return NOTIFY_DONE; + } +#endif /* LINUX_VERSION_CODE */ dhd = *(dhd_info_t **)netdev_priv(ifa->ifa_dev->dev); + if (!dhd) + return NOTIFY_DONE; + dhd_pub = &dhd->pub; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 31)) - if (ifa->ifa_dev->dev->netdev_ops == &dhd_ops_pri) { -#else - if (ifa->ifa_dev->dev) { -#endif - switch (event) { + if (dhd_pub->arp_version == 1) { + idx = 0; + } + else { + for (idx = 0; idx < DHD_MAX_IFS; idx++) { + if (dhd->iflist[idx] && dhd->iflist[idx]->net == ifa->ifa_dev->dev) + break; + } + if (idx < DHD_MAX_IFS) + DHD_TRACE(("ifidx : %p %s %d\n", dhd->iflist[idx]->net, + dhd->iflist[idx]->name, dhd->iflist[idx]->idx)); + else { + DHD_ERROR(("Cannot find ifidx for(%s) set to 0\n", ifa->ifa_label)); + idx = 0; + } + } + + switch (event) { case NETDEV_UP: DHD_ARPOE(("%s: [%s] Up IP: 0x%x\n", __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); @@ -4205,17 +4683,10 @@ static int dhd_device_event(struct notifier_block *this, } #ifdef AOE_IP_ALIAS_SUPPORT - if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) { - if (ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a) { - /* 0x3a = ':' */ - DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n", - __FUNCTION__)); - aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE); - } - else - aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE); - } -#endif + DHD_ARPOE(("%s:add aliased IP to AOE hostip cache\n", + __FUNCTION__)); + aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, TRUE, idx); +#endif /* AOE_IP_ALIAS_SUPPORT */ break; case NETDEV_DOWN: @@ -4223,20 +4694,12 @@ static int dhd_device_event(struct notifier_block *this, __FUNCTION__, ifa->ifa_label, ifa->ifa_address)); dhd->pend_ipaddr = 0; #ifdef AOE_IP_ALIAS_SUPPORT - if (!(dhd_pub->op_mode & DHD_FLAG_HOSTAP_MODE)) { - if (!(ifa->ifa_label[strlen(ifa->ifa_label)-2] == 0x3a)) { - /* 0x3a = ':' */ - DHD_ARPOE(("%s: primary interface is down," - " AOE clr all\n", __FUNCTION__)); - dhd_aoe_hostip_clr(&dhd->pub); - dhd_aoe_arp_clr(&dhd->pub); - } else - aoe_update_host_ipv4_table(dhd_pub, - ifa->ifa_address, FALSE); - } + DHD_ARPOE(("%s:interface is down, AOE clr all for this if\n", + __FUNCTION__)); + aoe_update_host_ipv4_table(dhd_pub, ifa->ifa_address, FALSE, idx); #else - dhd_aoe_hostip_clr(&dhd->pub); - dhd_aoe_arp_clr(&dhd->pub); + dhd_aoe_hostip_clr(&dhd->pub, idx); + dhd_aoe_arp_clr(&dhd->pub, idx); #endif /* AOE_IP_ALIAS_SUPPORT */ break; @@ -4244,7 +4707,6 @@ static int dhd_device_event(struct notifier_block *this, DHD_ARPOE(("%s: do noting for [%s] Event: %lu\n", __func__, ifa->ifa_label, event)); break; - } } return NOTIFY_DONE; } @@ -4258,7 +4720,7 @@ dhd_net_attach(dhd_pub_t *dhdp, int ifidx) int err = 0; uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x11, 0x22, 0x33 }; - DHD_ERROR(("%s: ifidx %d\n", __FUNCTION__, ifidx)); + DHD_TRACE(("%s: ifidx %d\n", __FUNCTION__, ifidx)); ASSERT(dhd && dhd->iflist[ifidx]); @@ -4431,7 +4893,7 @@ void dhd_detach(dhd_pub_t *dhdp) if (dhd->early_suspend.suspend) unregister_early_suspend(&dhd->early_suspend); } -#endif /* defined(CONFIG_HAS_EARLYSUSPEND) */ +#endif /* CONFIG_HAS_EARLYSUSPEND && DHD_USE_EARLYSUSPEND */ #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) cancel_work_sync(&dhd->work_hang); @@ -4501,11 +4963,15 @@ void dhd_detach(dhd_pub_t *dhdp) if (dhd->thr_dpc_ctl.thr_pid >= 0) { PROC_STOP(&dhd->thr_dpc_ctl); } +#ifdef RXFRAME_THREAD + if (dhd->thr_rxf_ctl.thr_pid >= 0) { + PROC_STOP(&dhd->thr_rxf_ctl); + } +#endif else #endif /* DHDTHREAD */ tasklet_kill(&dhd->tasklet); } - #ifdef WL_CFG80211 if (dhd->dhd_state & DHD_ATTACH_STATE_CFG80211) { wl_cfg80211_detach(NULL); @@ -4520,16 +4986,32 @@ void dhd_detach(dhd_pub_t *dhdp) /* && defined(CONFIG_PM_SLEEP) */ if (dhd->dhd_state & DHD_ATTACH_STATE_WAKELOCKS_INIT) { + printk("wd wakelock count:%d\n", dhd->wakelock_wd_counter); #ifdef CONFIG_HAS_WAKELOCK dhd->wakelock_counter = 0; + dhd->wakelock_wd_counter = 0; dhd->wakelock_rx_timeout_enable = 0; dhd->wakelock_ctrl_timeout_enable = 0; - wake_lock_destroy(&dhd->wl_wifi); - wake_lock_destroy(&dhd->wl_rxwake); - wake_lock_destroy(&dhd->wl_ctrlwake); -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) - wake_lock_destroy(&dhdp->pno_wakelock); -#endif + if (dhd->wl_wifi) { + wake_lock_destroy(dhd->wl_wifi); + MFREE(dhd->pub.osh, dhd->wl_wifi, sizeof(struct wake_lock)); + dhd->wl_wifi = NULL; + } + if (dhd->wl_rxwake) { + wake_lock_destroy(dhd->wl_rxwake); + MFREE(dhd->pub.osh, dhd->wl_rxwake, sizeof(struct wake_lock)); + dhd->wl_rxwake = NULL; + } + if (dhd->wl_ctrlwake) { + wake_lock_destroy(dhd->wl_ctrlwake); + MFREE(dhd->pub.osh, dhd->wl_ctrlwake, sizeof(struct wake_lock)); + dhd->wl_ctrlwake = NULL; + } + if (dhd->wl_wdwake) { + wake_lock_destroy(dhd->wl_wdwake); + MFREE(dhd->pub.osh, dhd->wl_wdwake, sizeof(struct wake_lock)); + dhd->wl_wdwake = NULL; + } #endif /* CONFIG_HAS_WAKELOCK */ } } @@ -4559,8 +5041,19 @@ dhd_free(dhd_pub_t *dhdp) } } dhd = (dhd_info_t *)dhdp->info; - if (dhd) - MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); +#if defined(CONFIG_DHD_USE_STATIC_BUF) + /* If pointer is allocated by dhd_os_prealloc then avoid MFREE */ + if (dhd != (dhd_info_t *)dhd_os_prealloc(NULL, DHD_PREALLOC_DHD_INFO, 0)) { +#endif /* CONFIG_DHD_USE_STATIC_BUF */ + if (dhd) + MFREE(dhd->pub.osh, dhd, sizeof(*dhd)); +#if defined(CONFIG_DHD_USE_STATIC_BUF) + } + else { + if (dhd) + dhd = NULL; + } +#endif /* CONFIG_DHD_USE_STATIC_BUF */ } } @@ -4581,6 +5074,10 @@ dhd_module_cleanup(void) } +#if defined(CONFIG_WIFI_CONTROL_FUNC) +extern bool g_wifi_poweron; +#endif /* CONFIG_WIFI_CONTROL_FUNC */ + static int __init dhd_module_init(void) { @@ -4650,6 +5147,17 @@ dhd_module_init(void) #endif +#if defined(CONFIG_WIFI_CONTROL_FUNC) + /* If the wifi_set_power() is failed, + * we need to jump error handling routines. + */ + if (!g_wifi_poweron) { + printk("%s: wifi_set_power() failed\n", __FUNCTION__); + error = -ENODEV; + goto fail_1; + } +#endif /* defined(CONFIG_WIFI_CONTROL_FUNC) */ + #if 1 && (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) sema_init(&dhd_registration_sem, 0); #endif @@ -4788,18 +5296,23 @@ dhd_os_wd_timer(void *bus, uint wdtick) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); - if (!dhd) + if (!dhd) { + DHD_ERROR(("%s: dhd NULL\n", __FUNCTION__)); return; + } + if (wdtick) + DHD_OS_WD_WAKE_LOCK(pub); flags = dhd_os_spin_lock(pub); /* don't start the wd until fw is loaded */ if (pub->busstate == DHD_BUS_DOWN) { dhd_os_spin_unlock(pub, flags); + DHD_OS_WD_WAKE_UNLOCK(pub); return; } - /* totally stop the timer */ + /* Totally stop the timer */ if (!wdtick && dhd->wd_timer_valid == TRUE) { dhd->wd_timer_valid = FALSE; dhd_os_spin_unlock(pub, flags); @@ -4808,6 +5321,7 @@ dhd_os_wd_timer(void *bus, uint wdtick) #else del_timer(&dhd->timer); #endif /* DHDTHREAD */ + DHD_OS_WD_WAKE_UNLOCK(pub); return; } @@ -4932,6 +5446,48 @@ dhd_os_sdtxunlock(dhd_pub_t *pub) dhd_os_sdunlock(pub); } +#if defined(DHDTHREAD) && defined(RXFRAME_THREAD) +static void +dhd_os_rxflock(dhd_pub_t *pub) +{ + dhd_info_t *dhd; + + dhd = (dhd_info_t *)(pub->info); + spin_lock_bh(&dhd->rxf_lock); + +} + +static void +dhd_os_rxfunlock(dhd_pub_t *pub) +{ + dhd_info_t *dhd; + + dhd = (dhd_info_t *)(pub->info); + spin_unlock_bh(&dhd->rxf_lock); +} +#endif /* defined(DHDTHREAD) && defined(RXFRAME_THREAD) */ + +#ifdef DHDTCPACK_SUPPRESS +void +dhd_os_tcpacklock(dhd_pub_t *pub) +{ + dhd_info_t *dhd; + + dhd = (dhd_info_t *)(pub->info); + spin_lock_bh(&dhd->tcpack_lock); + +} + +void +dhd_os_tcpackunlock(dhd_pub_t *pub) +{ + dhd_info_t *dhd; + + dhd = (dhd_info_t *)(pub->info); + spin_unlock_bh(&dhd->tcpack_lock); +} +#endif /* DHDTCPACK_SUPPRESS */ + #if defined(CONFIG_DHD_USE_STATIC_BUF) uint8* dhd_os_prealloc(void *osh, int section, uint size) { @@ -5129,9 +5685,9 @@ void dhd_wait_for_event(dhd_pub_t *dhd, bool *lockvar) struct dhd_info *dhdinfo = dhd->info; #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) - int timeout = msecs_to_jiffies(2000); + int timeout = msecs_to_jiffies(IOCTL_RESP_TIMEOUT); #else - int timeout = 2 * HZ; + int timeout = (IOCTL_RESP_TIMEOUT / 1000) * HZ; #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) */ dhd_os_sdunlock(dhd); @@ -5197,19 +5753,16 @@ int net_os_set_suspend(struct net_device *dev, int val, int force) #else ret = dhd_suspend_resume_helper(dhd, val, force); #endif -#ifdef WL_CFG80211 - wl_cfg80211_update_power_mode(dev); -#endif } return ret; } -int net_os_set_dtim_skip(struct net_device *dev, int val) +int net_os_set_suspend_bcn_li_dtim(struct net_device *dev, int val) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); if (dhd) - dhd->pub.dtim_skip = val; + dhd->pub.suspend_bcn_li_dtim = val; return 0; } @@ -5236,10 +5789,10 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) filterp = "102 0 0 0 0xFFFFFF 0x01005E"; break; case DHD_MULTICAST6_FILTER_NUM: -#if defined(BLOCK_IPV6_PACKET) +#if defined(BLOCK_IPV6_PACKET) && defined(CUSTOMER_HW4) /* customer want to use NO IPV6 packets only */ return ret; -#endif +#endif /* BLOCK_IPV6_PACKET && CUSTOMER_HW4 */ filterp = "103 0 0 0 0xFFFF 0x3333"; break; default: @@ -5254,9 +5807,9 @@ int net_os_rxfilter_add_remove(struct net_device *dev, int add_remove, int num) #endif /* GAN_LITE_NAT_KEEPALIVE_FILTER */ } -int net_os_enable_packet_filter(struct net_device *dev, int val) +int dhd_os_enable_packet_filter(dhd_pub_t *dhdp, int val) + { - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); int ret = 0; /* Packet filtering is set only if we still in early-suspend and @@ -5264,26 +5817,35 @@ int net_os_enable_packet_filter(struct net_device *dev, int val) * We can always turn it OFF in case of early-suspend, but we turn it * back ON only if suspend_disable_flag was not set */ - if (dhd && dhd->pub.up) { - if (dhd->pub.in_suspend) { - if (!val || (val && !dhd->pub.suspend_disable_flag)) { - dhd_enable_packet_filter(val, &dhd->pub); - } + if (dhdp && dhdp->up) { + if (dhdp->in_suspend) { + if (!val || (val && !dhdp->suspend_disable_flag)) + dhd_enable_packet_filter(val, dhdp); } } return ret; } + +/* function to enable/disable packet for Network device */ +int net_os_enable_packet_filter(struct net_device *dev, int val) +{ + dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); + + return dhd_os_enable_packet_filter(&dhd->pub, val); +} #endif /* PKT_FILTER_SUPPORT */ int dhd_dev_init_ioctl(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); -#if defined(USE_STAMAC_4SOFTAP) + +#if defined(CUSTOMER_HW4) && defined(USE_STAMAC_4SOFTAP) /* Writing STA's MAC ID to the Dongle for SOFTAP */ if (_dhd_set_mac_address(dhd, 0, &dhd->pub.mac) == 0) DHD_INFO(("dhd_bus_start: MAC ID is overwritten\n")); -#endif +#endif /* CUSTOMER_HW4 && USE_STAMAC_4SOFTAP */ + return dhd_preinit_ioctls(&dhd->pub); } @@ -5354,12 +5916,20 @@ static void dhd_hang_process(struct work_struct *work) int dhd_os_send_hang_message(dhd_pub_t *dhdp) { int ret = 0; + DHD_ERROR(("%s : Enter \n",__FUNCTION__)); + if (dhdp) { if (!dhdp->hang_was_sent) { dhdp->hang_was_sent = 1; - schedule_work(&dhdp->info->work_hang); + ret = schedule_work(&dhdp->info->work_hang); + if(!ret) + DHD_ERROR(("%s : schedule_task fail \n",__FUNCTION__)); + else + DHD_ERROR(("%s : schedule_task success \n",__FUNCTION__)); } } + else + DHD_ERROR(("%s : dhdp is null \n",__FUNCTION__)); return ret; } @@ -5376,7 +5946,7 @@ int net_os_send_hang_message(struct net_device *dev) #endif return ret; } -#endif /* (OEM_ANDROID) */ +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27) && OEM_ANDROID */ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) { @@ -5388,6 +5958,7 @@ void dhd_bus_country_set(struct net_device *dev, wl_country_t *cspec) #endif } } + void dhd_bus_band_set(struct net_device *dev, uint band) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -5398,7 +5969,6 @@ void dhd_bus_band_set(struct net_device *dev, uint band) } } - void dhd_net_if_lock(struct net_device *dev) { dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); @@ -5470,7 +6040,7 @@ dhd_get_pend_8021x_cnt(dhd_info_t *dhd) return (atomic_read(&dhd->pend_8021x_cnt)); } -#define MAX_WAIT_FOR_8021X_TX 25 +#define MAX_WAIT_FOR_8021X_TX 50 int dhd_wait_pend8021x(struct net_device *dev) @@ -5490,7 +6060,10 @@ dhd_wait_pend8021x(struct net_device *dev) pend = dhd_get_pend_8021x_cnt(dhd); } if (ntimes == 0) + { + atomic_set(&dhd->pend_8021x_cnt, 0); DHD_ERROR(("%s: TIMEOUT\n", __FUNCTION__)); + } return pend; } @@ -5543,10 +6116,10 @@ int dhd_os_wake_lock_timeout(dhd_pub_t *pub) dhd->wakelock_rx_timeout_enable : dhd->wakelock_ctrl_timeout_enable; #ifdef CONFIG_HAS_WAKELOCK if (dhd->wakelock_rx_timeout_enable) - wake_lock_timeout(&dhd->wl_rxwake, + wake_lock_timeout(dhd->wl_rxwake, msecs_to_jiffies(dhd->wakelock_rx_timeout_enable)); if (dhd->wakelock_ctrl_timeout_enable) - wake_lock_timeout(&dhd->wl_ctrlwake, + wake_lock_timeout(dhd->wl_ctrlwake, msecs_to_jiffies(dhd->wakelock_ctrl_timeout_enable)); #endif dhd->wakelock_rx_timeout_enable = 0; @@ -5566,22 +6139,6 @@ int net_os_wake_lock_timeout(struct net_device *dev) return ret; } -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) -int net_os_wake_lock_timeout_for_pno(struct net_device *dev, int sec) -{ - dhd_info_t *dhd = *(dhd_info_t **)netdev_priv(dev); - int ret = 0; - unsigned long flags; - - if (dhd) { - spin_lock_irqsave(&dhd->wakelock_spinlock, flags); - wake_lock_timeout(&dhd->pub.pno_wakelock, HZ * sec); - spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); - } - return ret; -} -#endif - int dhd_os_wake_lock_rx_timeout_enable(dhd_pub_t *pub, int val) { dhd_info_t *dhd = (dhd_info_t *)(pub->info); @@ -5640,11 +6197,11 @@ int dhd_os_wake_lock(dhd_pub_t *pub) spin_lock_irqsave(&dhd->wakelock_spinlock, flags); #ifdef CONFIG_HAS_WAKELOCK if (!dhd->wakelock_counter) - wake_lock(&dhd->wl_wifi); -#elif defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) - /* SLP_wakelock_alternative_code */ - pm_stay_awake(pm_dev); -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ + wake_lock(dhd->wl_wifi); +#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) + if (pm_dev) + pm_stay_awake(pm_dev); +#endif dhd->wakelock_counter++; ret = dhd->wakelock_counter; spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); @@ -5675,11 +6232,11 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) dhd->wakelock_counter--; #ifdef CONFIG_HAS_WAKELOCK if (!dhd->wakelock_counter) - wake_unlock(&dhd->wl_wifi); -#elif defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) - /* SLP_wakelock_alternative_code */ - pm_relax(pm_dev); -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ + wake_unlock(dhd->wl_wifi); +#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) + if (pm_dev) + pm_relax(pm_dev); +#endif ret = dhd->wakelock_counter; } spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); @@ -5689,30 +6246,23 @@ int dhd_os_wake_unlock(dhd_pub_t *pub) int dhd_os_check_wakelock(void *dhdp) { -#ifdef CONFIG_HAS_WAKELOCK +#if defined(CONFIG_HAS_WAKELOCK) || (1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, \ + 36))) dhd_pub_t *pub = (dhd_pub_t *)dhdp; dhd_info_t *dhd; if (!pub) return 0; dhd = (dhd_info_t *)(pub->info); +#endif /* CONFIG_HAS_WAKELOCK || BCMSDIO */ - if (dhd && wake_lock_active(&dhd->wl_wifi)) +#ifdef CONFIG_HAS_WAKELOCK + if (dhd && wake_lock_active(dhd->wl_wifi)) return 1; -#elif defined(CUSTOMER_HW4) && defined(CONFIG_PM_SLEEP) && defined(PLATFORM_SLP) - /* SLP_wakelock_alternative_code */ - dhd_pub_t *pub = (dhd_pub_t *)dhdp; - dhd_info_t *dhd; - - if (!pub) - return 0; - dhd = (dhd_info_t *)(pub->info); - - DHD_ERROR(("%s : wakelock_count = %d\n", __func__, dhd->wakelock_counter)); - - if (dhd && (dhd->wakelock_counter > 0)) +#elif 1 && (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 36)) + if (dhd && (dhd->wakelock_counter > 0) && pm_dev) return 1; -#endif /* CUSTOMER_HW4 && CONFIG_PM_SLEEP && PLATFORM_SLP */ +#endif return 0; } int net_os_wake_unlock(struct net_device *dev) @@ -5725,31 +6275,58 @@ int net_os_wake_unlock(struct net_device *dev) return ret; } -int dhd_os_check_if_up(void *dhdp) +int dhd_os_wd_wake_lock(dhd_pub_t *pub) { - dhd_pub_t *pub = (dhd_pub_t *)dhdp; + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + unsigned long flags; + int ret = 0; - if (!pub) - return 0; - return pub->up; + if (dhd) { + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); +#ifdef CONFIG_HAS_WAKELOCK + /* if wakelock_wd_counter was never used : lock it at once */ + if (!dhd->wakelock_wd_counter) { + if (dhd->wl_wdwake) + wake_lock(dhd->wl_wdwake); + else { + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + return 0; + } + } +#endif + dhd->wakelock_wd_counter++; + ret = dhd->wakelock_wd_counter; + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + } + return ret; } -/* function to collect firmware, chip id and chip version info */ -void dhd_set_version_info(dhd_pub_t *dhdp, char *fw) +int dhd_os_wd_wake_unlock(dhd_pub_t *pub) { - int i; - - i = snprintf(info_string, sizeof(info_string), - " Driver: %s\n Firmware: %s ", EPI_VERSION_STR, fw); - - if (!dhdp) - return; + dhd_info_t *dhd = (dhd_info_t *)(pub->info); + unsigned long flags; + int ret = 0; - i = snprintf(&info_string[i], sizeof(info_string) - i, - "\n Chip: %x Rev %x Pkg %x", dhd_bus_chip_id(dhdp), - dhd_bus_chiprev_id(dhdp), dhd_bus_chippkg_id(dhdp)); + if (dhd) { + spin_lock_irqsave(&dhd->wakelock_spinlock, flags); + if (dhd->wakelock_wd_counter) { + dhd->wakelock_wd_counter = 0; +#ifdef CONFIG_HAS_WAKELOCK + wake_unlock(dhd->wl_wdwake); +#endif + } + spin_unlock_irqrestore(&dhd->wakelock_spinlock, flags); + } + return ret; } +int dhd_os_check_if_up(void *dhdp) +{ + dhd_pub_t *pub = (dhd_pub_t *)dhdp; + if (!pub) + return 0; + return pub->up; +} int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) { int ifidx; @@ -5762,6 +6339,9 @@ int dhd_ioctl_entry_local(struct net_device *net, wl_ioctl_t *ioc, int cmd) } dhd = *(dhd_info_t **)netdev_priv(net); + if (!dhd) + return -EINVAL; + ifidx = dhd_net2idx(dhd, net); if (ifidx == DHD_BAD_IF) { DHD_ERROR(("%s bad ifidx\n", __FUNCTION__)); @@ -5785,7 +6365,7 @@ bool dhd_os_check_hang(dhd_pub_t *dhdp, int ifidx, int ret) } #if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP) -#define MAX_TRY_CNT 5 /* Number of tries to disable deepsleep */ +#define MAX_TRY_CNT 5 /* Number of tries to disable deepsleep */ int dhd_deepsleep(struct net_device *dev, int flag) { char iovbuf[20]; @@ -5799,62 +6379,67 @@ int dhd_deepsleep(struct net_device *dev, int flag) dhdp = &dhd->pub; switch (flag) { - case 1 : /* Deepsleep on */ - DHD_ERROR(("[WiFi] Deepsleep On\n")); - /* give some time to _dhd_sysioc_thread() before deepsleep */ - msleep(200); + case 1 : /* Deepsleep on */ + DHD_ERROR(("[WiFi] Deepsleep On\n")); + /* give some time to _dhd_sysioc_thread() before deepsleep */ + msleep(200); #ifdef PKT_FILTER_SUPPORT /* disable pkt filter */ dhd_enable_packet_filter(0, dhdp); #endif /* PKT_FILTER_SUPPORT */ - /* Disable MPC */ - powervar = 0; - memset(iovbuf, 0, sizeof(iovbuf)); - bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - - /* Enable Deepsleep */ - powervar = 1; - memset(iovbuf, 0, sizeof(iovbuf)); - bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - break; - - case 0: /* Deepsleep Off */ - DHD_ERROR(("[WiFi] Deepsleep Off\n")); - - /* Disable Deepsleep */ - for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) { + /* Disable MPC */ powervar = 0; memset(iovbuf, 0, sizeof(iovbuf)); - bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); + bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + /* Enable Deepsleep */ + powervar = 1; memset(iovbuf, 0, sizeof(iovbuf)); bcm_mkiovar("deepsleep", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); - if ((ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf, sizeof(iovbuf), - FALSE, 0)) < 0) { - DHD_ERROR(("the error of dhd deepsleep status ret value :%d\n", - ret)); - } else { - if (!(*(int *)iovbuf)) { - DHD_ERROR(("deepsleep mode is 0, ok , count : %d\n", cnt)); - break; + dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + break; + + case 0: /* Deepsleep Off */ + DHD_ERROR(("[WiFi] Deepsleep Off\n")); + + /* Disable Deepsleep */ + for (cnt = 0; cnt < MAX_TRY_CNT; cnt++) { + powervar = 0; + memset(iovbuf, 0, sizeof(iovbuf)); + bcm_mkiovar("deepsleep", (char *)&powervar, 4, + iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, + sizeof(iovbuf), TRUE, 0); + + + memset(iovbuf, 0, sizeof(iovbuf)); + bcm_mkiovar("deepsleep", (char *)&powervar, 4, + iovbuf, sizeof(iovbuf)); + if ((ret = dhd_wl_ioctl_cmd(dhdp, WLC_GET_VAR, iovbuf, + sizeof(iovbuf), FALSE, 0)) < 0) { + DHD_ERROR(("the error of dhd deepsleep status" + " ret value :%d\n", ret)); + } else { + if (!(*(int *)iovbuf)) { + DHD_ERROR(("deepsleep mode is 0," + " count: %d\n", cnt)); + break; + } } } - } - /* Enable MPC */ - powervar = 1; - memset(iovbuf, 0, sizeof(iovbuf)); - bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); - dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); - break; + /* Enable MPC */ + powervar = 1; + memset(iovbuf, 0, sizeof(iovbuf)); + bcm_mkiovar("mpc", (char *)&powervar, 4, iovbuf, sizeof(iovbuf)); + dhd_wl_ioctl_cmd(dhdp, WLC_SET_VAR, iovbuf, sizeof(iovbuf), TRUE, 0); + break; } return 0; } -#endif /* SUPPORT_DEEP_SLEEP */ +#endif /* WL_CFG80211 && SUPPORT_DEEP_SLEEP */ #ifdef PROP_TXSTATUS extern int dhd_wlfc_interface_entry_update(void* state, ewlfc_mac_entry_action_t action, uint8 ifid, @@ -5864,34 +6449,23 @@ extern int dhd_wlfc_FIFOcreditmap_update(void* state, uint8* credits); int dhd_wlfc_interface_event(struct dhd_info *dhd, ewlfc_mac_entry_action_t action, uint8 ifid, uint8 iftype, uint8* ea) { - int ret = BCME_OK; + if (dhd->pub.wlfc_state == NULL) + return BCME_OK; - dhd_os_wlfc_block(&dhd->pub); - if (dhd->pub.wlfc_state != NULL) - ret = dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); - dhd_os_wlfc_unblock(&dhd->pub); - return ret; + return dhd_wlfc_interface_entry_update(dhd->pub.wlfc_state, action, ifid, iftype, ea); } int dhd_wlfc_FIFOcreditmap_event(struct dhd_info *dhd, uint8* event_data) { - int ret = BCME_OK; + if (dhd->pub.wlfc_state == NULL) + return BCME_OK; - dhd_os_wlfc_block(&dhd->pub); - if (dhd->pub.wlfc_state != NULL) - ret = dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); - dhd_os_wlfc_unblock(&dhd->pub); - return ret; + return dhd_wlfc_FIFOcreditmap_update(dhd->pub.wlfc_state, event_data); } int dhd_wlfc_event(struct dhd_info *dhd) { - int ret; - - dhd_os_wlfc_block(&dhd->pub); - ret = dhd_wlfc_enable(&dhd->pub); - dhd_os_wlfc_unblock(&dhd->pub); - return ret; + return dhd_wlfc_enable(&dhd->pub); } #endif /* PROP_TXSTATUS */ diff --git a/drivers/net/wireless/bcmdhd/dhd_proto.h b/drivers/net/wireless/bcmdhd/dhd_proto.h index 09d5468..21dfe23 100644 --- a/drivers/net/wireless/bcmdhd/dhd_proto.h +++ b/drivers/net/wireless/bcmdhd/dhd_proto.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_proto.h 343390 2012-07-06 22:34:19Z $ + * $Id: dhd_proto.h 364579 2012-10-24 17:56:37Z $ */ #ifndef _dhd_proto_h_ @@ -54,10 +54,6 @@ extern int dhd_prot_init(dhd_pub_t *dhdp); /* Stop protocol: sync w/dongle state. */ extern void dhd_prot_stop(dhd_pub_t *dhdp); -#ifdef PROP_TXSTATUS -extern int dhd_wlfc_init(dhd_pub_t *dhd); -extern void dhd_wlfc_deinit(dhd_pub_t *dhd); -#endif /* PROP_TXSTATUS */ /* Add any protocol-specific data header. * Caller must reserve prot_hdrlen prepend space. @@ -88,9 +84,10 @@ extern int dhd_ioctl(dhd_pub_t * dhd_pub, dhd_ioctl_t *ioc, void * buf, uint buf extern int dhd_preinit_ioctls(dhd_pub_t *dhd); #ifdef PROP_TXSTATUS -extern int dhd_wlfc_enque_sendq(void* state, int prec, void* p); -extern int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, void* commit_ctx); -extern void dhd_wlfc_cleanup(dhd_pub_t *dhd); +extern int dhd_wlfc_commit_packets(void* state, f_commitpkt_t fcommit, + void* commit_ctx, void *pktbuf); +extern void dhd_wlfc_cleanup(dhd_pub_t *dhd, ifpkt_cb_t fn, int arg); +extern bool ifpkt_fn(void* p, int ifid); #endif /* PROP_TXSTATUS */ extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, @@ -104,8 +101,6 @@ extern int dhd_process_pkt_reorder_info(dhd_pub_t *dhd, uchar *reorder_info_buf, #define DHD_PROTOCOL "bdc" #elif defined(CDC) #define DHD_PROTOCOL "cdc" -#elif defined(RNDIS) -#define DHD_PROTOCOL "rndis" #else #define DHD_PROTOCOL "unknown" #endif /* proto */ diff --git a/drivers/net/wireless/bcmdhd/dhd_sdio.c b/drivers/net/wireless/bcmdhd/dhd_sdio.c index 422ad03..138e8e5 100644 --- a/drivers/net/wireless/bcmdhd/dhd_sdio.c +++ b/drivers/net/wireless/bcmdhd/dhd_sdio.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sdio.c 357859 2012-09-20 06:34:26Z $ + * $Id: dhd_sdio.c 394690 2013-04-03 09:18:44Z $ */ #include <typedefs.h> @@ -79,10 +79,13 @@ #define PRIOMASK 7 #define TXRETRIES 2 /* # of retries for tx frames */ - +#ifndef DHD_RXBOUND #define DHD_RXBOUND 50 /* Default for max rx frames in one scheduling */ +#endif +#ifndef DHD_TXBOUND #define DHD_TXBOUND 20 /* Default for max tx frames in one scheduling */ +#endif #define DHD_TXMINMAX 1 /* Max tx frames if rx still pending */ @@ -155,7 +158,9 @@ extern void bcmsdh_set_irq(int flag); #endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ #ifdef PROP_TXSTATUS extern void dhd_wlfc_txcomplete(dhd_pub_t *dhd, void *txp, bool success); +extern void dhd_wlfc_trigger_pktcommit(dhd_pub_t *dhd); #endif + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) DEFINE_MUTEX(_dhd_sdio_mutex_lock_); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ @@ -183,14 +188,16 @@ typedef struct dhd_console { #define MIN_RSRC_SR 0x3 #define CORE_CAPEXT_ADDR (SI_ENUM_BASE + 0x64c) #define CORE_CAPEXT_SR_SUPPORTED_MASK (1 << 1) -#define RCTL_MACPHY_DISABLE_MASK (1 << 26) -#define RCTL_LOGIC_DISABLE_MASK (1 << 27) +#define RCTL_MACPHY_DISABLE_MASK (1 << 26) +#define RCTL_LOGIC_DISABLE_MASK (1 << 27) #define OOB_WAKEUP_ENAB(bus) ((bus)->_oobwakeup) #define GPIO_DEV_SRSTATE 16 /* Host gpio17 mapped to device gpio0 SR state */ #define GPIO_DEV_SRSTATE_TIMEOUT 320000 /* 320ms */ #define GPIO_DEV_WAKEUP 17 /* Host gpio17 mapped to device gpio1 wakeup */ #define CC_CHIPCTRL2_GPIO1_WAKEUP (1 << 0) +#define OVERFLOW_BLKSZ512_WM 48 +#define OVERFLOW_BLKSZ512_MES 80 #define CC_PMUCC3 (0x3) /* Private data for SDIO bus interaction */ @@ -304,6 +311,13 @@ typedef struct dhd_bus { uint pktgen_ptick; /* Burst counter for printing */ uint pktgen_sent; /* Number of test packets generated */ uint pktgen_rcvd; /* Number of test packets received */ + uint pktgen_prev_time; /* Time at which previous stats where printed */ + uint pktgen_prev_sent; /* Number of test packets generated when + * previous stats were printed + */ + uint pktgen_prev_rcvd; /* Number of test packets received when + * previous stats were printed + */ uint pktgen_fail; /* Number of failed send attempts */ uint16 pktgen_len; /* Length of next packet to send */ #define PKTGEN_RCV_IDLE (0) @@ -391,7 +405,11 @@ uint dhd_txminmax = DHD_TXMINMAX; #define DONGLE_MIN_MEMSIZE (128 *1024) int dhd_dongle_memsize; +#ifndef REPEAT_READFRAME static bool dhd_doflow; +#else +extern bool dhd_doflow; +#endif /* REPEAT_READFRAME */ static bool dhd_alignctl; static bool sd1idle; @@ -399,13 +417,17 @@ static bool sd1idle; static bool retrydata; #define RETRYCHAN(chan) (((chan) == SDPCM_EVENT_CHANNEL) || retrydata) -#if defined(SDIO_CRC_ERROR_FIX) +#ifdef BCMSPI +/* At a watermark around 8 the spid hits underflow error. */ +static const uint watermark = 32; +static const uint mesbusyctrl = 0; +#elif defined(SDIO_CRC_ERROR_FIX) static uint watermark = 48; static uint mesbusyctrl = 80; #else static const uint watermark = 8; static const uint mesbusyctrl = 0; -#endif +#endif /* BCMSPI */ static const uint firstread = DHD_FIRSTREAD; #define HDATLEN (firstread - (SDPCM_HDRLEN)) @@ -443,7 +465,6 @@ static const uint max_roundup = 512; /* Try doing readahead */ static bool dhd_readahead; - /* To check if there's window offered */ #define DATAOK(bus) \ (((uint8)(bus->tx_max - bus->tx_seq) > 1) && \ @@ -538,7 +559,7 @@ do { \ \ R_SDREG(intstatuserr, &bus->regs->intstatus, retries); \ printf("dstatussw = 0x%x, dstatushw = 0x%x, intstatus = 0x%x\n", \ - dstatussw, dstatushw, intstatuserr); \ + dstatussw, dstatushw, intstatuserr); \ \ bus->nextlen = 0; \ *finished = TRUE; \ @@ -561,7 +582,7 @@ do { \ #ifdef SDTEST static void dhdsdio_testrcv(dhd_bus_t *bus, void *pkt, uint seq); -static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint8 count); +static void dhdsdio_sdtest_set(dhd_bus_t *bus, uint count); #endif #ifdef DHD_DEBUG @@ -591,7 +612,7 @@ static int dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, void *pkt, bcmsdh_cmplt_fn_t complete, void *handle); #ifdef BCMSDIOH_TXGLOM -static void dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, uint len); +static void dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, void *pkt, uint len); static void dhd_bcmsdh_glom_clear(dhd_bus_t *bus); #endif @@ -613,6 +634,39 @@ extern uint32 dhd_get_htsf(void *dhd, int ifidx); #endif /* WLMEDIA_HTSF */ static void +dhd_overflow_war(struct dhd_bus *bus) +{ + int err; + uint8 devctl, wm, mes; + + /* See .ppt in PR for these recommended values */ + if (bus->blocksize == 512) { + wm = OVERFLOW_BLKSZ512_WM; + mes = OVERFLOW_BLKSZ512_MES; + } else { + mes = bus->blocksize/4; + wm = bus->blocksize/4; + } + + + /* Update watermark */ + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, wm, &err); + + devctl = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); + devctl |= SBSDIO_DEVCTL_F2WM_ENAB; + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); + + /* Update MES */ + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, + (mes | SBSDIO_MESBUSYCTRL_ENAB), &err); + + DHD_INFO(("Apply overflow WAR: 0x%02x 0x%02x 0x%02x\n", + bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err), + bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, &err), + bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, &err))); +} + +static void dhd_dongle_setmemsize(struct dhd_bus *bus, int mem_size) { int32 min_size = DONGLE_MIN_MEMSIZE; @@ -693,7 +747,7 @@ static bool dhdsdio_sr_cap(dhd_bus_t *bus) { bool cap = FALSE; - uint32 min = 0, core_capext, addr, data; + uint32 core_capext, addr, data; if (bus->sih->chip == BCM4324_CHIP_ID) { addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); data = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_data); @@ -712,9 +766,7 @@ dhdsdio_sr_cap(dhd_bus_t *bus) if (bus->sih->chip == BCM4324_CHIP_ID) { /* FIX: Should change to query SR control register instead */ - min = bcmsdh_reg_read(bus->sdh, MIN_RSRC_ADDR, 4); - if (min == MIN_RSRC_SR) - cap = TRUE; + cap = TRUE; } else if (bus->sih->chip == BCM4335_CHIP_ID) { uint32 enabval = 0; addr = SI_ENUM_BASE + OFFSETOF(chipcregs_t, chipcontrol_addr); @@ -807,7 +859,12 @@ dhdsdio_clk_kso_init(dhd_bus_t *bus) } #define KSO_DBG(x) +#define KSO_WAIT_US 50 +#if defined(CUSTOMER_HW4) #define MAX_KSO_ATTEMPTS 64 +#else +#define MAX_KSO_ATTEMPTS (PMU_MAX_TRANSITION_DLY/KSO_WAIT_US) +#endif /* CUSTOMER_HW4 */ static int dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) { @@ -826,9 +883,8 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) bmask = cmp_val; msleep(3); - } else { - /* Put device to sleep, turn off KSO */ + /* Put device to sleep, turn off KSO */ cmp_val = 0; bmask = SBSDIO_FUNC1_SLEEPCSR_KSO_MASK; } @@ -839,17 +895,15 @@ dhdsdio_clk_kso_enab(dhd_bus_t *bus, bool on) break; KSO_DBG(("%s> KSO wr/rd retry:%d, ERR:%x \n", __FUNCTION__, try_cnt, err)); - OSL_DELAY(50); + OSL_DELAY(KSO_WAIT_US); bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_SLEEPCSR, wr_val, &err); - } while (try_cnt++ < MAX_KSO_ATTEMPTS); - if (try_cnt > 1) { + if (try_cnt > 2) KSO_DBG(("%s> op:%s, try_cnt:%d, rd_val:%x, ERR:%x \n", __FUNCTION__, (on ? "KSO_SET" : "KSO_CLR"), try_cnt, rd_val, err)); - } if (try_cnt > MAX_KSO_ATTEMPTS) { DHD_ERROR(("%s> op:%s, ERROR: try_cnt:%d, rd_val:%x, ERR:%x \n", @@ -1061,6 +1115,8 @@ dhdsdio_clk_devsleep_iovar(dhd_bus_t *bus, bool on) bus->kso = on ? FALSE : TRUE; else { DHD_ERROR(("%s: Sleep request failed: on:%d err:%d\n", __FUNCTION__, on, err)); + if (!on && retry > 2) + bus->kso = TRUE; } return err; @@ -1078,9 +1134,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); -#if defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) - pendok = FALSE; -#endif /* defined(OOB_INTR_ONLY) || defined(BCMSPI_ANDROID) */ clkctl = 0; sdh = bus->sdh; @@ -1119,12 +1172,6 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) ht_avail_error = 0; } - if (pendok && - ((bus->sih->buscoretype == PCMCIA_CORE_ID) && (bus->sih->buscorerev == 9))) { - uint32 dummy, retries; - R_SDREG(dummy, &bus->regs->clockctlstatus, retries); - BCM_REFERENCE(dummy); - } /* Check current status */ clkctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); @@ -1133,6 +1180,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) return BCME_ERROR; } +#if !defined(OOB_INTR_ONLY) /* Go to pending and await interrupt if appropriate */ if (!SBSDIO_CLKAV(clkctl, bus->alp_only) && pendok) { /* Allow only clock-available interrupt */ @@ -1148,11 +1196,15 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) DHD_INFO(("CLKCTL: set PENDING\n")); bus->clkstate = CLK_PENDING; return BCME_OK; - } else if (bus->clkstate == CLK_PENDING) { - /* Cancel CA-only interrupt filter */ - devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); - devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); + } else +#endif /* !defined (OOB_INTR_ONLY) */ + { + if (bus->clkstate == CLK_PENDING) { + /* Cancel CA-only interrupt filter */ + devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); + devctl &= ~SBSDIO_DEVCTL_CA_INT_ONLY; + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, devctl, &err); + } } /* Otherwise, wait here (polling) for HT Avail */ @@ -1196,6 +1248,7 @@ dhdsdio_htclk(dhd_bus_t *bus, bool on, bool pendok) #endif /* DHD_USE_IDLECOUNT */ } else { clkreq = 0; + if (bus->clkstate == CLK_PENDING) { /* Cancel CA-only interrupt filter */ devctl = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_DEVICE_CTL, &err); @@ -1484,16 +1537,15 @@ dhdsdio_bussleep(dhd_bus_t *bus, bool sleep) return err; } -#if defined(CUSTOMER_HW4) && defined(DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS) -int -dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) +int dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) { int func_blk_size = function_num; int bcmerr = 0; int result; - bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size, sizeof(int), &result, - sizeof(int), 0); + bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size, + sizeof(int), &result, sizeof(int), IOV_GET); if (bcmerr != BCME_OK) { DHD_ERROR(("%s: Get F%d Block size error\n", __FUNCTION__, function_num)); @@ -1501,14 +1553,11 @@ dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) } if (result != block_size) { - - DHD_ERROR(("%s: F%d Block size set from %d to %d\n", __FUNCTION__, - function_num, result, block_size)); - + DHD_TRACE_HW4(("%s: F%d Block size set from %d to %d\n", + __FUNCTION__, function_num, result, block_size)); func_blk_size = function_num << 16 | block_size; - bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", &func_blk_size, sizeof(int32), - &result, sizeof(int32), 1); - + bcmerr = dhd_bus_iovar_op(dhd, "sd_blocksize", NULL, + 0, &func_blk_size, sizeof(int32), IOV_SET); if (bcmerr != BCME_OK) { DHD_ERROR(("%s: Set F2 Block size error\n", __FUNCTION__)); return BCME_ERROR; @@ -1516,9 +1565,8 @@ dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size) } return BCME_OK; - } -#endif /* CUSTOMER_HW4 && DYNAMIC_F2_BLKSIZE_OF_PROPTXSTATUS */ +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ #if defined(OOB_INTR_ONLY) void @@ -1551,6 +1599,236 @@ dhd_enable_oob_intr(struct dhd_bus *bus, bool enable) } #endif /* defined(OOB_INTR_ONLY) */ + +#ifdef DHDTCPACK_SUPPRESS +extern bool dhd_use_tcpack_suppress; + +/* Please be sure this function is called under dhd_os_tcpacklock() */ +void dhd_onoff_tcpack_sup(void *pub, bool on) +{ + dhd_pub_t *dhdp = (dhd_pub_t *)pub; + + if (dhd_use_tcpack_suppress != on) { + + DHD_ERROR(("dhd_onoff_tcpack_sup: %d -> %d\n", dhd_use_tcpack_suppress, on)); + dhd_use_tcpack_suppress = on; + dhdp->tcp_ack_info_cnt = 0; + bzero(dhdp->tcp_ack_info_tbl, sizeof(struct tcp_ack_info)*MAXTCPSTREAMS); + + } else + DHD_ERROR(("dhd_onoff_tcpack_sup: alread %d\n", on)); + + return; +} + +inline void dhd_tcpack_check_xmit(dhd_pub_t *dhdp, void *pkt) +{ + uint8 i; + tcp_ack_info_t *tcp_ack_info = NULL; + int tbl_cnt; + + dhd_os_tcpacklock(dhdp); + tbl_cnt = dhdp->tcp_ack_info_cnt; + for (i = 0; i < tbl_cnt; i++) { + tcp_ack_info = &dhdp->tcp_ack_info_tbl[i]; + if (tcp_ack_info->p_tcpackinqueue == pkt) { + /* This pkt is being transmitted so remove the tcp_ack_info of it. + * compact the array unless the last element, + * then the pkt's array is removed. + */ + if (i < tbl_cnt-1) { + memmove(&dhdp->tcp_ack_info_tbl[i], + &dhdp->tcp_ack_info_tbl[i+1], + sizeof(struct tcp_ack_info)*(tbl_cnt - (i+1))); + } + bzero(&dhdp->tcp_ack_info_tbl[tbl_cnt-1], sizeof(struct tcp_ack_info)); + if (--dhdp->tcp_ack_info_cnt < 0) { + DHD_ERROR(("dhdsdio_sendfromq:(ERROR) tcp_ack_info_cnt %d" + " Stop using tcpack_suppress\n", dhdp->tcp_ack_info_cnt)); + dhd_onoff_tcpack_sup(dhdp, FALSE); + } + break; + } + } + dhd_os_tcpackunlock(dhdp); +} + +bool +dhd_tcpack_suppress(dhd_pub_t *dhdp, void *pkt) +{ + uint8 *eh_header; + uint16 eh_type; + uint8 *ip_header; + uint8 *tcp_header; + uint32 ip_hdr_len; + uint32 cur_framelen; + uint8 bdc_hdr_len = BDC_HEADER_LEN; + uint8 wlfc_hdr_len = 0; + uint8 *data = PKTDATA(dhdp->osh, pkt); + cur_framelen = PKTLEN(dhdp->osh, pkt); + +#ifdef PROP_TXSTATUS + /* In this case, BDC header is not pushed in dhd_sendpkt() */ + if (dhdp->wlfc_state) { + bdc_hdr_len = 0; + wlfc_hdr_len = 8; + } +#endif + if (cur_framelen < bdc_hdr_len + ETHER_HDR_LEN) { + DHD_TRACE(("dhd_tcpack_suppress: Too short packet length %d\n", cur_framelen)); + return FALSE; + } + + /* Get rid of BDC header */ + eh_header = data + bdc_hdr_len; + cur_framelen -= bdc_hdr_len; + eh_type = eh_header[12] << 8 | eh_header[13]; + + if (eh_type != ETHER_TYPE_IP) { + DHD_TRACE(("dhd_tcpack_suppress: Not a IP packet 0x%x\n", eh_type)); + return FALSE; + } + + DHD_TRACE(("dhd_tcpack_suppress: IP pkt! 0x%x\n", eh_type)); + + ip_header = eh_header + ETHER_HDR_LEN; + cur_framelen -= ETHER_HDR_LEN; + ip_hdr_len = 4 * (ip_header[0] & 0x0f); + + if ((ip_header[0] & 0xf0) != 0x40) { + DHD_TRACE(("dhd_tcpack_suppress: Not IPv4!\n")); + return FALSE; + } + + if (cur_framelen < ip_hdr_len) { + DHD_ERROR(("dhd_tcpack_suppress: IP packet length %d wrong!\n", cur_framelen)); + return FALSE; + } + + /* not tcp */ + if (ip_header[9] != 0x06) { + DHD_TRACE(("dhd_tcpack_suppress: Not a TCP packet 0x%x\n", ip_header[9])); + return FALSE; + } + + DHD_TRACE(("dhd_tcpack_suppress: TCP pkt!\n")); + + tcp_header = ip_header + ip_hdr_len; + + /* is it an ack ? */ + if (tcp_header[13] == 0x10) { +#if defined(DHD_DEBUG) + uint32 tcp_seq_num = tcp_header[4] << 24 | tcp_header[5] << 16 | + tcp_header[6] << 8 | tcp_header[7]; +#endif + uint32 tcp_ack_num = tcp_header[8] << 24 | tcp_header[9] << 16 | + tcp_header[10] << 8 | tcp_header[11]; + uint16 ip_tcp_ttllen = (ip_header[3] & 0xff) + (ip_header[2] << 8); + uint32 tcp_hdr_len = 4*((tcp_header[12] & 0xf0) >> 4); + DHD_TRACE(("dhd_tcpack_suppress: TCP ACK seq %ud ack %ud\n", + tcp_seq_num, tcp_ack_num)); + + + /* zero length ? */ + if (ip_tcp_ttllen == ip_hdr_len + tcp_hdr_len) { + int i; + tcp_ack_info_t *tcp_ack_info = NULL; + DHD_TRACE(("dhd_tcpack_suppress: TCP ACK zero length\n")); + /* Look for tcp_ack_info that has the same + * ip src/dst addrs and tcp src/dst ports + */ + dhd_os_tcpacklock(dhdp); + for (i = 0; i < dhdp->tcp_ack_info_cnt; i++) { + if (dhdp->tcp_ack_info_tbl[i].p_tcpackinqueue && + !memcmp(&ip_header[12], dhdp->tcp_ack_info_tbl[i].ipaddrs, 8) && + !memcmp(tcp_header, dhdp->tcp_ack_info_tbl[i].tcpports, 4)) { + tcp_ack_info = &dhdp->tcp_ack_info_tbl[i]; + break; + } + } + + if (i == dhdp->tcp_ack_info_cnt && i < MAXTCPSTREAMS) + tcp_ack_info = &dhdp->tcp_ack_info_tbl[dhdp->tcp_ack_info_cnt++]; + + if (!tcp_ack_info) { + DHD_TRACE(("dhd_tcpack_suppress: No empty tcp ack info" + "%d %d %d %d, %d %d %d %d\n", + tcp_header[0], tcp_header[1], tcp_header[2], tcp_header[3], + dhdp->tcp_ack_info_tbl[i].tcpports[0], + dhdp->tcp_ack_info_tbl[i].tcpports[1], + dhdp->tcp_ack_info_tbl[i].tcpports[2], + dhdp->tcp_ack_info_tbl[i].tcpports[3])); + dhd_os_tcpackunlock(dhdp); + return FALSE; + } + + if (tcp_ack_info->p_tcpackinqueue) { + if (tcp_ack_num > tcp_ack_info->tcpack_number) { + void *prevpkt = tcp_ack_info->p_tcpackinqueue; + uint8 pushed_len = SDPCM_HDRLEN + + (BDC_HEADER_LEN - bdc_hdr_len) + wlfc_hdr_len; +#ifdef PROP_TXSTATUS + /* In case the prev pkt is delayenqueued + * but not delayedequeued yet, it may not have + * any additional header yet. + */ + if (dhdp->wlfc_state && (PKTLEN(dhdp->osh, prevpkt) == + tcp_ack_info->ip_tcp_ttllen + ETHER_HDR_LEN)) + pushed_len = 0; +#endif + if ((ip_tcp_ttllen == tcp_ack_info->ip_tcp_ttllen) && + (PKTLEN(dhdp->osh, pkt) == + PKTLEN(dhdp->osh, prevpkt) - pushed_len)) { + bcopy(PKTDATA(dhdp->osh, pkt), + PKTDATA(dhdp->osh, prevpkt) + pushed_len, + PKTLEN(dhdp->osh, pkt)); + PKTFREE(dhdp->osh, pkt, FALSE); + DHD_TRACE(("dhd_tcpack_suppress: pkt 0x%p" + " TCP ACK replace %ud -> %ud\n", prevpkt, + tcp_ack_info->tcpack_number, tcp_ack_num)); + tcp_ack_info->tcpack_number = tcp_ack_num; + dhd_os_tcpackunlock(dhdp); + return TRUE; + } else + DHD_TRACE(("dhd_tcpack_suppress: len mismatch" + " %d(%d) %d(%d)\n", + PKTLEN(dhdp->osh, pkt), ip_tcp_ttllen, + PKTLEN(dhdp->osh, prevpkt), + tcp_ack_info->ip_tcp_ttllen)); + } else { +#ifdef TCPACK_TEST + void *prevpkt = tcp_ack_info->p_tcpackinqueue; +#endif + DHD_TRACE(("dhd_tcpack_suppress: TCP ACK number reverse" + " prev %ud (0x%p) new %ud (0x%p)\n", + tcp_ack_info->tcpack_number, + tcp_ack_info->p_tcpackinqueue, + tcp_ack_num, pkt)); +#ifdef TCPACK_TEST + if (PKTLEN(dhdp->osh, pkt) == PKTLEN(dhdp->osh, prevpkt)) { + PKTFREE(dhdp->osh, pkt, FALSE); + dhd_os_tcpackunlock(dhdp); + return TRUE; + } +#endif + } + } else { + tcp_ack_info->p_tcpackinqueue = pkt; + tcp_ack_info->tcpack_number = tcp_ack_num; + tcp_ack_info->ip_tcp_ttllen = ip_tcp_ttllen; + bcopy(&ip_header[12], tcp_ack_info->ipaddrs, 8); + bcopy(tcp_header, tcp_ack_info->tcpports, 4); + } + dhd_os_tcpackunlock(dhdp); + } else + DHD_TRACE(("dhd_tcpack_suppress: TCP ACK with DATA len %d\n", + ip_tcp_ttllen - ip_hdr_len - tcp_hdr_len)); + } + return FALSE; +} +#endif /* DHDTCPACK_SUPPRESS */ + + /* Writes a HW/SW header into the packet and sends it. */ /* Assumes: (a) header space already there, (b) caller holds lock */ static int @@ -1562,6 +1840,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on uint16 len, pad1 = 0; uint32 swheader; uint retries = 0; + uint32 real_pad = 0; bcmsdh_info_t *sdh; void *new; int i; @@ -1574,12 +1853,17 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on htsfts_t *htsf_ts; #endif - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); sdh = bus->sdh; osh = bus->dhd->osh; +#ifdef DHDTCPACK_SUPPRESS + if (dhd_use_tcpack_suppress) { + dhd_tcpack_check_xmit(bus->dhd, pkt); + } +#endif /* DHDTCPACK_SUPPRESS */ + if (bus->dhd->dongle_reset) { ret = BCME_NOTREADY; goto done; @@ -1599,7 +1883,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on #endif /* WLMEDIA_HTSF */ /* Add alignment padding, allocate new packet if needed */ - if (!((uintptr)frame & 1) && (pad1 = ((uintptr)frame % DHD_SDALIGN))) { + if ((pad1 = ((uintptr)frame % DHD_SDALIGN))) { if (PKTHEADROOM(osh, pkt) < pad1) { DHD_INFO(("%s: insufficient headroom %d for %d pad1\n", __FUNCTION__, (int)PKTHEADROOM(osh, pkt), pad1)); @@ -1649,8 +1933,13 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on htol32_ua_store(0, frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN + sizeof(swheader)); if (queue_only) { - if (forcealign && (len & (ALIGNMENT - 1))) - len = ROUNDUP(len, ALIGNMENT); + uint8 alignment = ALIGNMENT; +#if defined(BCMLXSDMMC) && defined(CUSTOMER_HW4) + if (bus->glom_mode == SDPCM_TXGLOM_MDESC) + alignment = DHD_SDALIGN; +#endif /* defined(BCMLXSDMMC) && defined(CUSTOMER_HW4) */ + if (forcealign && (len & (alignment - 1))) + len = ROUNDUP(len, alignment); /* Hardware extention tag */ /* 2byte frame length, 1byte-, 1byte frame flag, * 2byte-hdrlength, 2byte padlenght @@ -1659,8 +1948,19 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on hwheader2 = (len - act_len) << 16; htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); + real_pad = len - act_len; + if (PKTTAILROOM(osh, pkt) < real_pad) { + DHD_INFO(("%s 1: insufficient tailroom %d for %d real_pad\n", + __FUNCTION__, (int)PKTTAILROOM(osh, pkt), real_pad)); + if (PKTPADTAILROOM(osh, pkt, real_pad)) { + DHD_ERROR(("padding error size %d\n", real_pad)); + } + } +#ifdef BCMLXSDMMC + PKTSETLEN(osh, pkt, len); +#endif /* BCMLXSDMMC */ /* Post the frame pointer to sdio glom array */ - dhd_bcmsdh_glom_post(bus, frame, len); + dhd_bcmsdh_glom_post(bus, frame, pkt, len); /* Save the pkt pointer in bus glom array */ bus->glom_pkt_arr[bus->glom_cnt] = pkt; bus->glom_total_len += len; @@ -1692,9 +1992,20 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on hwheader2 = (len - act_len) << 16; htol32_ua_store(hwheader1, frame + SDPCM_FRAMETAG_LEN); htol32_ua_store(hwheader2, frame + SDPCM_FRAMETAG_LEN + 4); - + real_pad = len - act_len; + if (PKTTAILROOM(osh, pkt) < real_pad) { + DHD_INFO(("%s 2: insufficient tailroom %d" + " for %d real_pad\n", + __FUNCTION__, (int)PKTTAILROOM(osh, pkt), real_pad)); + if (PKTPADTAILROOM(osh, pkt, real_pad)) { + DHD_ERROR(("padding error size %d\n", real_pad)); + } + } +#ifdef BCMLXSDMMC + PKTSETLEN(osh, pkt, len); +#endif /* BCMLXSDMMC */ /* Post the frame pointer to sdio glom array */ - dhd_bcmsdh_glom_post(bus, frame, len); + dhd_bcmsdh_glom_post(bus, frame, pkt, len); /* Save the pkt pointer in bus glom array */ bus->glom_pkt_arr[bus->glom_cnt] = pkt; bus->glom_cnt++; @@ -1708,6 +2019,7 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on } else #endif /* BCMSDIOH_TXGLOM */ { + uint32 act_len = len; /* Software tag: channel, sequence number, data offset */ swheader = ((chan << SDPCM_CHANNEL_SHIFT) & SDPCM_CHANNEL_MASK) | bus->tx_seq | (((pad1 + SDPCM_HDRLEN) << SDPCM_DOFFSET_SHIFT) & SDPCM_DOFFSET_MASK); @@ -1752,8 +2064,15 @@ dhdsdio_txpkt(dhd_bus_t *bus, void *pkt, uint chan, bool free_pkt, bool queue_on DHD_ERROR(("%s: sending unrounded %d-byte packet\n", __FUNCTION__, len)); #endif } + real_pad = len - act_len; + if (PKTTAILROOM(osh, pkt) < real_pad) { + DHD_INFO(("%s 3: insufficient tailroom %d for %d real_pad\n", + __FUNCTION__, (int)PKTTAILROOM(osh, pkt), real_pad)); + if (PKTPADTAILROOM(osh, pkt, real_pad)) { + DHD_ERROR(("padding error size %d\n", real_pad)); + } + } } - do { ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, frame, len, pkt, NULL, NULL); @@ -1816,13 +2135,20 @@ done: #ifdef BCMSDIOH_TXGLOM uint32 doff; if (bus->glom_enable) { +#ifdef BCMLXSDMMC + uint32 pad2 = 0; +#endif /* BCMLXSDMMC */ pkt = bus->glom_pkt_arr[bus->glom_cnt - pkt_cnt]; frame = (uint8*)PKTDATA(osh, pkt); doff = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + SDPCM_HWEXT_LEN); doff = (doff & SDPCM_DOFFSET_MASK) >> SDPCM_DOFFSET_SHIFT; +#ifdef BCMLXSDMMC + pad2 = ltoh32_ua(frame + SDPCM_FRAMETAG_LEN + 4) >> 16; + PKTSETLEN(osh, pkt, PKTLEN(osh, pkt) - pad2); +#endif /* BCMLXSDMMC */ PKTPULL(osh, pkt, doff); } else -#endif +#endif /* BCMSDIOH_TXGLOM */ { PKTPULL(osh, pkt, SDPCM_HDRLEN + pad1); } @@ -1833,7 +2159,13 @@ done: dhd_os_sdlock(bus->dhd); } else { #endif /* PROP_TXSTATUS */ +#ifdef SDTEST + if (chan != SDPCM_TEST_CHANNEL) { + dhd_txcomplete(bus->dhd, pkt, ret != 0); + } +#else /* SDTEST */ dhd_txcomplete(bus->dhd, pkt, ret != 0); +#endif /* SDTEST */ if (free_pkt) PKTFREE(osh, pkt, TRUE); @@ -1956,8 +2288,6 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) } else ret = BCME_OK; - dhd_os_sdunlock_txq(bus->dhd); - if ((pktq_len(&bus->txq) >= FCHI) && dhd_doflow) dhd_txflowcontrol(bus->dhd, ALL_INTERFACES, ON); @@ -1965,6 +2295,8 @@ dhd_bus_txdata(struct dhd_bus *bus, void *pkt) if (pktq_plen(&bus->txq, prec) > qcount[prec]) qcount[prec] = pktq_plen(&bus->txq, prec); #endif + dhd_os_sdunlock_txq(bus->dhd); + /* Schedule DPC if needed to send queued packet(s) */ if (dhd_deferred_tx && !bus->dpc_sched) { bus->dpc_sched = TRUE; @@ -2018,6 +2350,7 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) uint cnt = 0; uint datalen; uint8 tx_prec_map; + uint8 txpktqlen = 0; #ifdef BCMSDIOH_TXGLOM uint i; uint8 glom_cnt; @@ -2034,31 +2367,35 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) } tx_prec_map = ~bus->flowcontrol; - /* Send frames until the limit or some other event */ for (cnt = 0; (cnt < maxframes) && DATAOK(bus); cnt++) { #ifdef BCMSDIOH_TXGLOM if (bus->glom_enable) { + void *pkttable[SDPCM_MAXGLOM_SIZE]; + dhd_os_sdlock_txq(bus->dhd); glom_cnt = MIN(DATABUFCNT(bus), bus->glomsize); glom_cnt = MIN(glom_cnt, pktq_mlen(&bus->txq, tx_prec_map)); glom_cnt = MIN(glom_cnt, maxframes-cnt); /* Limiting the size to 2pkts in case of copy */ if (bus->glom_mode == SDPCM_TXGLOM_CPY) - glom_cnt = MIN(glom_cnt, 5); + glom_cnt = MIN(glom_cnt, 10); + + for (i = 0; i < glom_cnt; i++) + pkttable[i] = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out); + + txpktqlen = pktq_len(&bus->txq); + dhd_os_sdunlock_txq(bus->dhd); if (glom_cnt == 0) break; datalen = 0; for (i = 0; i < glom_cnt; i++) { - dhd_os_sdlock_txq(bus->dhd); - if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { + if ((pkt = pkttable[i]) == NULL) { /* This case should not happen */ DHD_ERROR(("No pkts in the queue for glomming\n")); - dhd_os_sdunlock_txq(bus->dhd); break; } - dhd_os_sdunlock_txq(bus->dhd); datalen += (PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN); #ifndef SDTEST @@ -2081,9 +2418,11 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) { dhd_os_sdlock_txq(bus->dhd); if ((pkt = pktq_mdeq(&bus->txq, tx_prec_map, &prec_out)) == NULL) { + txpktqlen = pktq_len(&bus->txq); dhd_os_sdunlock_txq(bus->dhd); break; } + txpktqlen = pktq_len(&bus->txq); dhd_os_sdunlock_txq(bus->dhd); datalen = PKTLEN(bus->dhd->osh, pkt) - SDPCM_HDRLEN; @@ -2118,12 +2457,68 @@ dhdsdio_sendfromq(dhd_bus_t *bus, uint maxframes) /* Deflow-control stack if needed */ if (dhd_doflow && dhd->up && (dhd->busstate == DHD_BUS_DATA) && - dhd->txoff && (pktq_len(&bus->txq) < FCLOW)) + dhd->txoff && (txpktqlen < FCLOW)) dhd_txflowcontrol(dhd, ALL_INTERFACES, OFF); return cnt; } +static void +dhdsdio_sendpendctl(dhd_bus_t *bus) +{ + bcmsdh_info_t *sdh = bus->sdh; + int ret, i; + uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; + +#ifdef BCMSDIOH_TXGLOM + if (bus->glom_enable) + frame_seq += SDPCM_HWEXT_LEN; +#endif + + if (*frame_seq != bus->tx_seq) { + DHD_INFO(("%s IOCTL frame seq lag detected!" + " frm_seq:%d != bus->tx_seq:%d, corrected\n", + __FUNCTION__, *frame_seq, bus->tx_seq)); + *frame_seq = bus->tx_seq; + } + + ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, + (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, + NULL, NULL, NULL); + ASSERT(ret != BCME_PENDING); + if (ret == BCME_NODEVICE) { + DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__)); + } else if (ret < 0) { + /* On failure, abort the command and terminate the frame */ + DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", + __FUNCTION__, ret)); + bus->tx_sderrs++; + + bcmsdh_abort(sdh, SDIO_FUNC_2); + + bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, + SFC_WF_TERM, NULL); + bus->f1regdata++; + + for (i = 0; i < 3; i++) { + uint8 hi, lo; + hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, + SBSDIO_FUNC1_WFRAMEBCHI, NULL); + lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, + SBSDIO_FUNC1_WFRAMEBCLO, NULL); + bus->f1regdata += 2; + if ((hi == 0) && (lo == 0)) + break; + } + } + if (ret == 0) { + bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; + } + + bus->ctrl_frame_stat = FALSE; + dhd_wait_event_wakeup(bus->dhd); +} + int dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) { @@ -2235,9 +2630,18 @@ dhd_bus_txctl(struct dhd_bus *bus, uchar *msg, uint msglen) ret = 0; } else { bus->dhd->txcnt_timeout++; - if (!bus->dhd->hang_was_sent) + if (!bus->dhd->hang_was_sent) { +#ifdef CUSTOMER_HW4 + uint32 status, retry = 0; + R_SDREG(status, &bus->regs->intstatus, retry); + DHD_TRACE_HW4(("%s: txcnt_timeout, INT status=0x%08X\n", + __FUNCTION__, status)); + DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n", + __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); +#endif /* CUSTOMER_HW4 */ DHD_ERROR(("%s: ctrl_frame_stat == TRUE txcnt_timeout=%d\n", __FUNCTION__, bus->dhd->txcnt_timeout)); + } ret = -1; bus->ctrl_frame_stat = FALSE; goto done; @@ -2309,7 +2713,7 @@ done: else bus->dhd->tx_ctlpkts++; - if (bus->dhd->txcnt_timeout >= MAX_CNTL_TIMEOUT) + if (bus->dhd->txcnt_timeout >= MAX_CNTL_TX_TIMEOUT) return -ETIMEDOUT; return ret ? -EIO : 0; @@ -2338,7 +2742,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) if (rxlen) { DHD_CTL(("%s: resumed on rxctl frame, got %d expected %d\n", - __FUNCTION__, rxlen, msglen)); + __FUNCTION__, rxlen, msglen)); } else if (timeleft == 0) { #ifdef DHD_DEBUG uint32 status, retry = 0; @@ -2367,8 +2771,10 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) #endif /* DHD_DEBUG */ } if (timeleft == 0) { - bus->dhd->rxcnt_timeout++; - DHD_ERROR(("%s: rxcnt_timeout=%d\n", __FUNCTION__, bus->dhd->rxcnt_timeout)); + if (rxlen == 0) + bus->dhd->rxcnt_timeout++; + DHD_ERROR(("%s: rxcnt_timeout=%d, rxlen=%d\n", __FUNCTION__, + bus->dhd->rxcnt_timeout, rxlen)); } else bus->dhd->rxcnt_timeout = 0; @@ -2378,7 +2784,7 @@ dhd_bus_rxctl(struct dhd_bus *bus, uchar *msg, uint msglen) else bus->dhd->rx_ctlerrs++; - if (bus->dhd->rxcnt_timeout >= MAX_CNTL_TIMEOUT) + if (bus->dhd->rxcnt_timeout >= MAX_CNTL_RX_TIMEOUT) return -ETIMEDOUT; if (bus->dhd->dongle_trap_occured) @@ -2646,12 +3052,15 @@ dhdsdio_pktgen_set(dhd_bus_t *bus, uint8 *arg) bus->pktgen_stop = pktgen.stop; bus->pktgen_tick = bus->pktgen_ptick = 0; + bus->pktgen_prev_time = jiffies; bus->pktgen_len = MAX(bus->pktgen_len, bus->pktgen_minlen); bus->pktgen_len = MIN(bus->pktgen_len, bus->pktgen_maxlen); /* Clear counts for a new pktgen (mode change, or was stopped) */ - if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) - bus->pktgen_sent = bus->pktgen_rcvd = bus->pktgen_fail = 0; + if (bus->pktgen_count && (!oldcnt || oldmode != bus->pktgen_mode)) { + bus->pktgen_sent = bus->pktgen_prev_sent = bus->pktgen_rcvd = 0; + bus->pktgen_prev_rcvd = bus->pktgen_fail = 0; + } return 0; } @@ -2886,6 +3295,9 @@ dhdsdio_checkdied(dhd_bus_t *bus, char *data, uint size) DHD_TRACE(("%s: Enter\n", __FUNCTION__)); + if (DHD_NOCHECKDIED_ON()) + return 0; + if (data == NULL) { /* * Called after a rx ctrl timeout. "data" is NULL. @@ -3113,7 +3525,8 @@ dhd_serialconsole(dhd_bus_t *bus, bool set, bool enable, int *bcmerror) uart_enab = CC_PLL_CHIPCTRL_SERIAL_ENAB; } else if (bus->sih->chip == BCM4334_CHIP_ID || - bus->sih->chip == BCM43341_CHIP_ID) { + bus->sih->chip == BCM43341_CHIP_ID || + 0) { if (enable) { /* Moved to PMU chipcontrol 1 from 4330 */ int_val &= ~gpio_sel; @@ -3309,6 +3722,16 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch DHD_INFO(("%s: Request to %s %d bytes at address 0x%08x\n", __FUNCTION__, (set ? "write" : "read"), size, address)); + /* check if CR4 */ + if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { + /* if address is 0, store the reset instruction to be written in 0 */ + + if (address == 0) { + bus->resetinstr = *(((uint32*)params) + 2); + } + /* Add start of RAM address to the address given by user */ + address += bus->dongle_ram_base; + } else { /* If we know about SOCRAM, check for a fit */ if ((bus->orig_ramsize) && ((address > bus->orig_ramsize) || (address + size > bus->orig_ramsize))) @@ -3350,6 +3773,7 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch break; } } + } /* Generate the actual data pointer */ data = set ? (uint8*)params + 2 * sizeof(int): (uint8*)arg; @@ -3604,13 +4028,14 @@ dhdsdio_doiovar(dhd_bus_t *bus, const bcm_iovar_t *vi, uint32 actionid, const ch case IOV_SVAL(IOV_MESBUSYCTRL): mesbusyctrl = (uint)int_val; mesbusyctrl = (mesbusyctrl > SBSDIO_MESBUSYCTRL_MASK) - ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; + ? SBSDIO_MESBUSYCTRL_MASK : mesbusyctrl; DHD_ERROR(("Setting mesbusyctrl as 0x%x.\n", mesbusyctrl)); bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, ((uint8)mesbusyctrl | 0x80), NULL); break; #endif /* SDIO_CRC_ERROR_FIX */ + case IOV_GVAL(IOV_DONGLEISOLATION): int_val = bus->dhd->dongle_isolation; bcopy(&int_val, arg, val_size); @@ -3840,6 +4265,8 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) int bcmerror = 0; int foundcr4 = 0; + if (!bus->sih) + return BCME_ERROR; /* To enter download state, disable ARM and reset SOCRAM. * To exit download state, simply reset ARM (default is RAM boot). */ @@ -3851,45 +4278,47 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { foundcr4 = 1; } else { - DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } + DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } } if (!foundcr4) { - si_core_disable(bus->sih, 0); - if (bcmsdh_regfail(bus->sdh)) { - bcmerror = BCME_SDIO_ERROR; - goto fail; - } - - if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - - si_core_reset(bus->sih, 0, 0); - if (bcmsdh_regfail(bus->sdh)) { - DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", __FUNCTION__)); - bcmerror = BCME_SDIO_ERROR; - goto fail; - } + si_core_disable(bus->sih, 0); + if (bcmsdh_regfail(bus->sdh)) { + bcmerror = BCME_SDIO_ERROR; + goto fail; + } - /* Disable remap for download */ - if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih)) - dhdsdio_devram_remap(bus, FALSE); + if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { + DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } - /* Clear the top bit of memory */ - if (bus->ramsize) { - uint32 zeros = 0; - if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, (uint8*)&zeros, 4) < 0) { + si_core_reset(bus->sih, 0, 0); + if (bcmsdh_regfail(bus->sdh)) { + DHD_ERROR(("%s: Failure trying reset SOCRAM core?\n", + __FUNCTION__)); bcmerror = BCME_SDIO_ERROR; goto fail; } - } - } else { + + /* Disable remap for download */ + if (REMAP_ENAB(bus) && si_socdevram_remap_isenb(bus->sih)) + dhdsdio_devram_remap(bus, FALSE); + + /* Clear the top bit of memory */ + if (bus->ramsize) { + uint32 zeros = 0; + if (dhdsdio_membytes(bus, TRUE, bus->ramsize - 4, + (uint8*)&zeros, 4) < 0) { + bcmerror = BCME_SDIO_ERROR; + goto fail; + } + } + } else { /* For CR4, * Halt ARM * Remove ARM reset @@ -3903,42 +4332,44 @@ dhdsdio_download_state(dhd_bus_t *bus, bool enter) } } else { if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { - if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } + if (!(si_setcore(bus->sih, SOCRAM_CORE_ID, 0))) { + DHD_ERROR(("%s: Failed to find SOCRAM core!\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } - if (!si_iscoreup(bus->sih)) { - DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } + if (!si_iscoreup(bus->sih)) { + DHD_ERROR(("%s: SOCRAM core is down after reset?\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } - if ((bcmerror = dhdsdio_write_vars(bus))) { - DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__)); - goto fail; - } - /* Enable remap before ARM reset but after vars. - * No backplane access in remap mode - */ - if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) - dhdsdio_devram_remap(bus, TRUE); + if ((bcmerror = dhdsdio_write_vars(bus))) { + DHD_ERROR(("%s: could not write vars to RAM\n", __FUNCTION__)); + goto fail; + } - if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && - !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { - DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } - W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); + /* Enable remap before ARM reset but after vars. + * No backplane access in remap mode + */ + if (REMAP_ENAB(bus) && !si_socdevram_remap_isenb(bus->sih)) + dhdsdio_devram_remap(bus, TRUE); - if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && - !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { - DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); - bcmerror = BCME_ERROR; - goto fail; - } + if (!si_setcore(bus->sih, PCMCIA_CORE_ID, 0) && + !si_setcore(bus->sih, SDIOD_CORE_ID, 0)) { + DHD_ERROR(("%s: Can't change back to SDIO core?\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } + W_SDREG(0xFFFFFFFF, &bus->regs->intstatus, retries); + + + if (!(si_setcore(bus->sih, ARM7S_CORE_ID, 0)) && + !(si_setcore(bus->sih, ARMCM3_CORE_ID, 0))) { + DHD_ERROR(("%s: Failed to find ARM core!\n", __FUNCTION__)); + bcmerror = BCME_ERROR; + goto fail; + } } else { /* cr4 has no socram, but tcm's */ /* write vars */ @@ -4055,6 +4486,9 @@ dhd_bus_iovar_op(dhd_pub_t *dhdp, const char *name, } else { DHD_INFO(("%s: noted %s update, value now %d\n", __FUNCTION__, "sd_blocksize", bus->blocksize)); + + if (bus->sih->chip == BCM4335_CHIP_ID) + dhd_overflow_war(bus); } } bus->roundup = MIN(max_roundup, bus->blocksize); @@ -4114,10 +4548,12 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) dhd_os_sdlock(bus->dhd); if ((bus->dhd->busstate == DHD_BUS_DOWN) || bus->dhd->hang_was_sent) { + /* if Firmware already hangs disbale any interrupt */ bus->dhd->busstate = DHD_BUS_DOWN; bus->hostintmask = 0; bcmsdh_intr_disable(bus->sdh); } else { + BUS_WAKE(bus); if (KSO_ENAB(bus)) { @@ -4132,33 +4568,34 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) if (KSO_ENAB(bus)) { - /* Enable clock for device interrupts */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + /* Enable clock for device interrupts */ + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); - /* Disable and clear interrupts at the chip level also */ - W_SDREG(0, &bus->regs->hostintmask, retries); - local_hostintmask = bus->hostintmask; - bus->hostintmask = 0; + /* Disable and clear interrupts at the chip level also */ + W_SDREG(0, &bus->regs->hostintmask, retries); + local_hostintmask = bus->hostintmask; + bus->hostintmask = 0; - /* Force clocks on backplane to be sure F2 interrupt propagates */ - saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); - if (!err) { - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, - (saveclk | SBSDIO_FORCE_HT), &err); - } - if (err) { - DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", __FUNCTION__, err)); - } + /* Force clocks on backplane to be sure F2 interrupt propagates */ + saveclk = bcmsdh_cfg_read(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, &err); + if (!err) { + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_CHIPCLKCSR, + (saveclk | SBSDIO_FORCE_HT), &err); + } + if (err) { + DHD_ERROR(("%s: Failed to force clock for F2: err %d\n", + __FUNCTION__, err)); + } - /* Turn off the bus (F2), free any pending packets */ - DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); - bcmsdh_intr_disable(bus->sdh); + /* Turn off the bus (F2), free any pending packets */ + DHD_INTR(("%s: disable SDIO interrupts\n", __FUNCTION__)); + bcmsdh_intr_disable(bus->sdh); #ifndef BCMSPI - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); -#endif + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_0, SDIOD_CCCR_IOEN, SDIO_FUNC_ENABLE_1, NULL); +#endif /* !BCMSPI */ - /* Clear any pending interrupts now that F2 is disabled */ - W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); + /* Clear any pending interrupts now that F2 is disabled */ + W_SDREG(local_hostintmask, &bus->regs->intstatus, retries); } /* Turn off the backplane clock (only) */ @@ -4185,6 +4622,8 @@ dhd_bus_stop(struct dhd_bus *bus, bool enforce_mutex) bus->rxskip = FALSE; bus->tx_seq = bus->rx_seq = 0; + bus->tx_max = 4; + if (enforce_mutex) dhd_os_sdunlock(bus->dhd); } @@ -4327,8 +4766,10 @@ dhd_bus_init(dhd_pub_t *dhdp, bool enforce_mutex) mesbusyctrl = watermark = bus->blocksize / 4; } #endif /* SDIO_CRC_ERROR_FIX */ - - bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, (uint8)watermark, &err); + if (bus->sih->chip != BCM4335_CHIP_ID) { + bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_WATERMARK, + (uint8)watermark, &err); + } #ifdef SDIO_CRC_ERROR_FIX bcmsdh_cfg_write(bus->sdh, SDIO_FUNC_1, SBSDIO_FUNC1_MESBUSYCTRL, (uint8)mesbusyctrl|0x80, &err); @@ -4401,12 +4842,21 @@ dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx) } bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, SFC_RF_TERM, &err); + if (err) { + DHD_ERROR(("%s: SBSDIO_FUNC1_FRAMECTRL cmd err\n", __FUNCTION__)); + goto fail; + } bus->f1regdata++; /* Wait until the packet has been flushed (device/FIFO stable) */ for (lastrbc = retries = 0xffff; retries > 0; retries--) { hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCHI, NULL); - lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, NULL); + lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_RFRAMEBCLO, &err); + if (err) { + DHD_ERROR(("%s: SBSDIO_FUNC1_RFAMEBCLO cmd err\n", __FUNCTION__)); + goto fail; + } + bus->f1regdata += 2; if ((hi == 0) && (lo == 0)) @@ -4437,6 +4887,7 @@ dhdsdio_rxfail(dhd_bus_t *bus, bool abort, bool rtx) /* Clear partial in any case */ bus->nextlen = 0; +fail: /* If we can't reach the device, signal failure */ if (err || bcmsdh_regfail(sdh)) bus->dhd->busstate = DHD_BUS_DOWN; @@ -4542,11 +4993,6 @@ done: dhd_os_ioctl_resp_wake(bus->dhd); } -#ifdef CUSTOMER_HW4 -int pkt_free; -int caller; -void *free_ptr; -#endif static uint8 dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) { @@ -4569,9 +5015,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) int ifidx = 0; bool usechain = bus->use_rxchain; -#ifdef CUSTOMER_HW4 - pkt_free = 0; -#endif /* If packets, issue read(s) and send up packet chain */ /* Return sequence numbers consumed? */ @@ -4889,11 +5332,6 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) reorder_info_len = sizeof(reorder_info_buf); if (PKTLEN(osh, pfirst) == 0) { -#ifdef CUSTOMER_HW4 - pkt_free = 1; - caller = 1; - free_ptr = pfirst; -#endif PKTFREE(bus->dhd->osh, pfirst, FALSE); continue; } else if (dhd_prot_hdrpull(bus->dhd, &ifidx, pfirst, reorder_info_buf, @@ -4986,7 +5424,12 @@ dhdsdio_rxglom(dhd_bus_t *bus, uint8 rxseq) /* Return TRUE if there may be more frames to read */ static uint +#ifdef REPEAT_READFRAME +dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished, bool tx_enable) +#else dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) +#endif + { osl_t *osh = bus->dhd->osh; bcmsdh_info_t *sdh = bus->sdh; @@ -5018,9 +5461,6 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) bool sdtest = FALSE; /* To limit message spew from test mode */ #endif -#ifdef CUSTOMER_HW4 - pkt_free = 0; -#endif DHD_TRACE(("%s: Enter\n", __FUNCTION__)); bus->readframes = TRUE; @@ -5043,7 +5483,6 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) /* Not finished unless we encounter no more frames indication */ *finished = FALSE; - #ifdef BCMSPI /* Get pktlen from gSPI device F0 reg. */ if (bus->bus == SPI_BUS) { @@ -5082,8 +5521,19 @@ dhdsdio_readframes(dhd_bus_t *bus, uint maxframes, bool *finished) rxseq++, rxleft--) { #ifdef DHDTHREAD + + if ( +#ifdef REPEAT_READFRAME + tx_enable && +#endif + TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) + dhdsdio_sendpendctl(bus); /* tx more to improve rx performance */ - if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && + else if ( +#ifdef REPEAT_READFRAME + tx_enable && +#endif + (bus->clkstate == CLK_AVAIL) && !bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && DATAOK(bus)) { dhdsdio_sendfromq(bus, dhd_txbound); } @@ -5665,11 +6115,6 @@ deliver: if (PKTLEN(osh, pkt) == 0) { dhd_os_sdlock_rxq(bus->dhd); -#ifdef CUSTOMER_HW4 - pkt_free = 1; - caller = 0; - free_ptr = pkt; -#endif PKTFREE(bus->dhd->osh, pkt, FALSE); dhd_os_sdunlock_rxq(bus->dhd); continue; @@ -5692,7 +6137,6 @@ deliver: else pkt_count = 1; - /* Unlock during rx call */ dhd_os_sdunlock(bus->dhd); dhd_rx_frame(bus->dhd, ifidx, pkt, pkt_count, chan); @@ -5803,7 +6247,7 @@ dhdsdio_hostmail(dhd_bus_t *bus) #ifdef DHD_DEBUG /* At least print a message if FW halted */ if (hmb_data & HMB_DATA_FWHALT) { - DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED\n")); + DHD_ERROR(("INTERNAL ERROR: FIRMWARE HALTED : set BUS DOWN\n")); dhdsdio_checkdied(bus, NULL, 0); bus->dhd->busstate = DHD_BUS_DOWN; } @@ -5823,6 +6267,10 @@ dhdsdio_hostmail(dhd_bus_t *bus) return intstatus; } +#ifdef REPEAT_READFRAME +extern uint dhd_dpcpoll; +#endif + static bool dhdsdio_dpc(dhd_bus_t *bus) { @@ -5900,7 +6348,6 @@ dhdsdio_dpc(dhd_bus_t *bus) } BUS_WAKE(bus); - /* Make sure backplane clock is on */ dhdsdio_clkctl(bus, CLK_AVAIL, TRUE); if (bus->clkstate != CLK_AVAIL) @@ -5931,6 +6378,7 @@ dhdsdio_dpc(dhd_bus_t *bus) intstatus |= newstatus; bus->intstatus = 0; + /* Handle flow-control change: read new state in case our ack * crossed another change interrupt. If change still set, assume * FC ON for safety, let next loop through do the debounce. @@ -5985,7 +6433,11 @@ dhdsdio_dpc(dhd_bus_t *bus) /* On frame indication, read available frames */ if (PKT_AVAILABLE(bus, intstatus)) { +#ifdef REPEAT_READFRAME + framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone, true); +#else framecnt = dhdsdio_readframes(bus, rxlimit, &rxdone); +#endif if (rxdone || bus->rxskip) intstatus &= ~FRAME_AVAIL_MASK(bus); rxlimit -= MIN(framecnt, rxlimit); @@ -6025,54 +6477,13 @@ clkwait: } #endif /* defined(OOB_INTR_ONLY) && !defined(HW_OOB) */ - if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) { - int ret, i; - - uint8* frame_seq = bus->ctrl_frame_buf + SDPCM_FRAMETAG_LEN; - - if (*frame_seq != bus->tx_seq) { - DHD_INFO(("%s IOCTL frame seq lag detected!" - " frm_seq:%d != bus->tx_seq:%d, corrected\n", - __FUNCTION__, *frame_seq, bus->tx_seq)); - *frame_seq = bus->tx_seq; - } - - ret = dhd_bcmsdh_send_buf(bus, bcmsdh_cur_sbwad(sdh), SDIO_FUNC_2, F2SYNC, - (uint8 *)bus->ctrl_frame_buf, (uint32)bus->ctrl_frame_len, - NULL, NULL, NULL); - ASSERT(ret != BCME_PENDING); - if (ret == BCME_NODEVICE) { - DHD_ERROR(("%s: Device asleep already\n", __FUNCTION__)); - } else if (ret < 0) { - /* On failure, abort the command and terminate the frame */ - DHD_INFO(("%s: sdio error %d, abort command and terminate frame.\n", - __FUNCTION__, ret)); - bus->tx_sderrs++; - - bcmsdh_abort(sdh, SDIO_FUNC_2); - - bcmsdh_cfg_write(sdh, SDIO_FUNC_1, SBSDIO_FUNC1_FRAMECTRL, - SFC_WF_TERM, NULL); - bus->f1regdata++; +#ifdef PROP_TXSTATUS + dhd_wlfc_trigger_pktcommit(bus->dhd); +#endif - for (i = 0; i < 3; i++) { - uint8 hi, lo; - hi = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCHI, NULL); - lo = bcmsdh_cfg_read(sdh, SDIO_FUNC_1, - SBSDIO_FUNC1_WFRAMEBCLO, NULL); - bus->f1regdata += 2; - if ((hi == 0) && (lo == 0)) - break; - } - } - if (ret == 0) { - bus->tx_seq = (bus->tx_seq + 1) % SDPCM_SEQUENCE_WRAP; - } - bus->ctrl_frame_stat = FALSE; - dhd_wait_event_wakeup(bus->dhd); - } + if (TXCTLOK(bus) && bus->ctrl_frame_stat && (bus->clkstate == CLK_AVAIL)) + dhdsdio_sendpendctl(bus); /* Send queued frames (limit 1 if rx may still be pending) */ else if ((bus->clkstate == CLK_AVAIL) && !bus->fcstate && pktq_mlen(&bus->txq, ~bus->flowcontrol) && txlimit && DATAOK(bus)) { @@ -6081,11 +6492,8 @@ clkwait: txlimit -= framecnt; } /* Resched the DPC if ctrl cmd is pending on bus credit */ - if (bus->ctrl_frame_stat) { - DHD_TRACE_HW4(("%s : tx_max : %d, tx_seq : %d, clkstate : %d \n", - __FUNCTION__, bus->tx_max, bus->tx_seq, bus->clkstate)); + if (bus->ctrl_frame_stat) resched = TRUE; - } /* Resched if events or tx frames are pending, else await next interrupt */ /* On failed register access, all bets are off: no resched or interrupts */ @@ -6118,6 +6526,12 @@ clkwait: } exit: +#ifdef REPEAT_READFRAME + if (!resched && dhd_dpcpoll) { + resched = dhdsdio_readframes(bus, dhd_rxbound, &rxdone, true); + } +#endif + dhd_os_sdunlock(bus->dhd); return resched; } @@ -6185,7 +6599,6 @@ dhdsdio_isr(void *arg) while (dhdsdio_dpc(bus)); DHD_OS_WAKE_UNLOCK(bus->dhd); #else - bus->dpc_sched = TRUE; dhd_sched_dpc(bus->dhd); @@ -6209,7 +6622,7 @@ dhdsdio_pktgen_init(dhd_bus_t *bus) /* Default to per-watchdog burst with 10s print time */ bus->pktgen_freq = 1; - bus->pktgen_print = dhd_watchdog_ms ? (10000/dhd_watchdog_ms):0; + bus->pktgen_print = dhd_watchdog_ms ? (10000 / dhd_watchdog_ms) : 0; bus->pktgen_count = (dhd_pktgen * dhd_watchdog_ms + 999) / 1000; /* Default to echo mode */ @@ -6226,19 +6639,37 @@ dhdsdio_pktgen(dhd_bus_t *bus) uint fillbyte; osl_t *osh = bus->dhd->osh; uint16 len; + ulong time_lapse; + uint sent_pkts; + uint rcvd_pkts; /* Display current count if appropriate */ if (bus->pktgen_print && (++bus->pktgen_ptick >= bus->pktgen_print)) { bus->pktgen_ptick = 0; - printf("%s: send attempts %d rcvd %d\n", - __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd); + printf("%s: send attempts %d, rcvd %d, errors %d\n", + __FUNCTION__, bus->pktgen_sent, bus->pktgen_rcvd, bus->pktgen_fail); + + /* Print throughput stats only for constant length packet runs */ + if (bus->pktgen_minlen == bus->pktgen_maxlen) { + time_lapse = jiffies - bus->pktgen_prev_time; + bus->pktgen_prev_time = jiffies; + sent_pkts = bus->pktgen_sent - bus->pktgen_prev_sent; + bus->pktgen_prev_sent = bus->pktgen_sent; + rcvd_pkts = bus->pktgen_rcvd - bus->pktgen_prev_rcvd; + bus->pktgen_prev_rcvd = bus->pktgen_rcvd; + + printf("%s: Tx Throughput %d kbps, Rx Throughput %d kbps\n", + __FUNCTION__, + (sent_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8, + (rcvd_pkts * bus->pktgen_len / jiffies_to_msecs(time_lapse)) * 8); + } } /* For recv mode, just make sure dongle has started sending */ if (bus->pktgen_mode == DHD_PKTGEN_RECV) { if (bus->pktgen_rcv_state == PKTGEN_RCV_IDLE) { bus->pktgen_rcv_state = PKTGEN_RCV_ONGOING; - dhdsdio_sdtest_set(bus, (uint8)bus->pktgen_total); + dhdsdio_sdtest_set(bus, bus->pktgen_total); } return; } @@ -6252,7 +6683,11 @@ dhdsdio_pktgen(dhd_bus_t *bus) } /* Allocate an appropriate-sized packet */ - len = bus->pktgen_len; + if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) { + len = SDPCM_TEST_PKT_CNT_FLD_LEN; + } else { + len = bus->pktgen_len; + } if (!(pkt = PKTGET(osh, (len + SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN), TRUE))) {; DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__)); @@ -6275,7 +6710,7 @@ dhdsdio_pktgen(dhd_bus_t *bus) case DHD_PKTGEN_RXBURST: *data++ = SDPCM_TEST_BURST; - *data++ = (uint8)bus->pktgen_count; + *data++ = (uint8)bus->pktgen_count; /* Just for backward compatability */ break; default: @@ -6286,12 +6721,23 @@ dhdsdio_pktgen(dhd_bus_t *bus) } /* Write test header length field */ - *data++ = (len >> 0); - *data++ = (len >> 8); + *data++ = (bus->pktgen_len >> 0); + *data++ = (bus->pktgen_len >> 8); - /* Then fill in the remainder -- N/A for burst, but who cares... */ - for (fillbyte = 0; fillbyte < len; fillbyte++) - *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent); + /* Write frame count in a 4 byte field adjucent to SDPCM test header for + * burst mode + */ + if (bus->pktgen_mode == DHD_PKTGEN_RXBURST) { + *data++ = (uint8)(bus->pktgen_count >> 0); + *data++ = (uint8)(bus->pktgen_count >> 8); + *data++ = (uint8)(bus->pktgen_count >> 16); + *data++ = (uint8)(bus->pktgen_count >> 24); + } else { + + /* Then fill in the remainder -- N/A for burst */ + for (fillbyte = 0; fillbyte < len; fillbyte++) + *data++ = SDPCM_TEST_FILL(fillbyte, (uint8)bus->pktgen_sent); + } #ifdef DHD_DEBUG if (DHD_BYTES_ON() && DHD_DATA_ON()) { @@ -6319,25 +6765,31 @@ dhdsdio_pktgen(dhd_bus_t *bus) } static void -dhdsdio_sdtest_set(dhd_bus_t *bus, uint8 count) +dhdsdio_sdtest_set(dhd_bus_t *bus, uint count) { void *pkt; uint8 *data; osl_t *osh = bus->dhd->osh; /* Allocate the packet */ - if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + DHD_SDALIGN, TRUE))) { + if (!(pkt = PKTGET(osh, SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + + SDPCM_TEST_PKT_CNT_FLD_LEN + DHD_SDALIGN, TRUE))) { DHD_ERROR(("%s: PKTGET failed!\n", __FUNCTION__)); return; } - PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN), DHD_SDALIGN); + PKTALIGN(osh, pkt, (SDPCM_HDRLEN + SDPCM_TEST_HDRLEN + + SDPCM_TEST_PKT_CNT_FLD_LEN), DHD_SDALIGN); data = (uint8*)PKTDATA(osh, pkt) + SDPCM_HDRLEN; /* Fill in the test header */ *data++ = SDPCM_TEST_SEND; - *data++ = count; + *data++ = (count > 0)?TRUE:FALSE; *data++ = (bus->pktgen_maxlen >> 0); *data++ = (bus->pktgen_maxlen >> 8); + *data++ = (uint8)(count >> 0); + *data++ = (uint8)(count >> 8); + *data++ = (uint8)(count >> 16); + *data++ = (uint8)(count >> 24); /* Send it */ if (dhdsdio_txpkt(bus, pkt, SDPCM_TEST_CHANNEL, TRUE, FALSE)) @@ -6505,7 +6957,7 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) if (!bus->dpc_sched) { uint32 devpend; devpend = bcmsdh_cfg_read_word(bus->sdh, SDIO_FUNC_0, - SPID_STATUS_REG, NULL); + SPID_STATUS_REG, NULL); intstatus = devpend & STATUS_F2_PKT_AVAILABLE; } #endif /* !BCMSPI */ @@ -6548,7 +7000,10 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) /* Generate packets if configured */ if (bus->pktgen_count && (++bus->pktgen_tick >= bus->pktgen_freq)) { /* Make sure backplane clock is on */ - dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); + if (SLPAUTO_ENAB(bus)) + dhdsdio_bussleep(bus, FALSE); + else + dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); bus->pktgen_tick = 0; dhdsdio_pktgen(bus); } @@ -6563,7 +7018,6 @@ dhd_bus_watchdog(dhd_pub_t *dhdp) if (bus->idlecount >= bus->idletime) { DHD_TIMER(("%s: DHD Idle state!!\n", __FUNCTION__)); - if (SLPAUTO_ENAB(bus)) { if (dhdsdio_bussleep(bus, TRUE) != BCME_BUSY) dhd_os_wd_timer(bus->dhd, 0); @@ -6708,16 +7162,24 @@ dhdsdio_chipmatch(uint16 chipid) return TRUE; if (chipid == BCM4314_CHIP_ID) return TRUE; - if (chipid == BCM4334_CHIP_ID) + if (chipid == BCM43242_CHIP_ID) return TRUE; if (chipid == BCM43341_CHIP_ID) return TRUE; + if (chipid == BCM43143_CHIP_ID) + return TRUE; + if (chipid == BCM43342_CHIP_ID) + return TRUE; + if (chipid == BCM4334_CHIP_ID) + return TRUE; if (chipid == BCM43239_CHIP_ID) return TRUE; if (chipid == BCM4324_CHIP_ID) return TRUE; if (chipid == BCM4335_CHIP_ID) return TRUE; + if (chipid == BCM4350_CHIP_ID) + return TRUE; return FALSE; } @@ -6732,7 +7194,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, #endif /* GET_CUSTOM_MAC_ENABLE */ #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__)); } @@ -6758,7 +7219,11 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, sd1idle = TRUE; dhd_readahead = TRUE; retrydata = FALSE; +#ifndef REPEAT_READFRAME dhd_doflow = FALSE; +#else + dhd_doflow = TRUE; +#endif /* REPEAT_READFRAME */ dhd_dongle_memsize = 0; dhd_txminmax = DHD_TXMINMAX; @@ -6899,7 +7364,6 @@ dhdsdio_probe(uint16 venid, uint16 devid, uint16 bus_no, uint16 slot, if (dhd_download_fw_on_driverload) { if ((ret = dhd_bus_start(bus->dhd)) != 0) { DHD_ERROR(("%s: dhd_bus_start failed\n", __FUNCTION__)); - if (ret == BCME_NOTUP) goto fail; } } @@ -6933,6 +7397,284 @@ forcereturn: return NULL; } +#ifdef REGON_BP_HANG_FIX +static int dhd_sdio_backplane_reset(struct dhd_bus *bus) +{ + uint32 temp = 0; + DHD_ERROR(("Resetting the backplane to avoid failure in firmware download..\n")); + + temp = bcmsdh_reg_read(bus->sdh, 0x180021e0, 4); + DHD_INFO(("SDIO Clk Control Reg = %x\n", temp)); + + /* Force HT req from PMU */ + bcmsdh_reg_write(bus->sdh, 0x18000644, 4, 0x6000005); + + /* Increase the clock stretch duration. */ + bcmsdh_reg_write(bus->sdh, 0x18000630, 4, 0xC8FFC8); + + /* Setting ALP clock request in SDIOD clock control status register */ + bcmsdh_reg_write(bus->sdh, 0x180021e0, 4, 0x41); + + /* Allowing clock from SR engine to SR memory */ + bcmsdh_reg_write(bus->sdh, 0x18004400, 4, 0xf92f1); + /* Disabling SR Engine before SR binary download. */ + bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x0); + + /* Enabling clock from backplane to SR memory */ + bcmsdh_reg_write(bus->sdh, 0x18004400, 4, 0xf9af1); + + /* Initializing SR memory address register in SOCRAM */ + bcmsdh_reg_write(bus->sdh, 0x18004408, 4, 0x0); + + /* Downloading the SR binary */ + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xc0002000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1051f080); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1050f080); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1050f080); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x80008000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x1050f080); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000004); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000604); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00001604); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00001404); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a08c80); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010001); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00011404); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x04a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xf8000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x04a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00002000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xf8000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00011604); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010604); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010004); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000004); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010001); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010004); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00010000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x14a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x30a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000008); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x04a00000); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0x00000008); + bcmsdh_reg_write(bus->sdh, 0x1800440c, 4, 0xfc000000); + /* SR Binary Download complete */ + + /* Allowing clock from SR engine to SR memory */ + bcmsdh_reg_write(bus->sdh, 0x18004400, 4, 0xf92f1); + + /* Turning ON SR Engine to initiate backplane reset Repeated ?? Maharana */ + bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x0); + bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x2); + bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x37); + bcmsdh_reg_write(bus->sdh, 0x18000650, 4, 0x3); + temp = bcmsdh_reg_read(bus->sdh, 0x18000654, 4); + DHD_INFO(("0x18000654 = %x\n", temp)); + bcmsdh_reg_write(bus->sdh, 0x18000654, 4, 0x800037); + OSL_DELAY(100000); + /* Rolling back the original values for clock stretch and PMU timers */ + bcmsdh_reg_write(bus->sdh, 0x18000644, 4, 0x0); + bcmsdh_reg_write(bus->sdh, 0x18000630, 4, 0xC800C8); + /* Removing ALP clock request in SDIOD clock control status register */ + bcmsdh_reg_write(bus->sdh, 0x180021e0, 4, 0x40); + OSL_DELAY(10000); + return TRUE; +} + +static int dhdsdio_sdio_hang_war(struct dhd_bus *bus) +{ + uint32 temp = 0, temp2 = 0, counter = 0, BT_pwr_up = 0, BT_ready = 0; + /* Removing reset of D11 Core */ + bcmsdh_reg_write(bus->sdh, 0x18101408, 4, 0x3); + bcmsdh_reg_write(bus->sdh, 0x18101800, 4, 0x0); + bcmsdh_reg_write(bus->sdh, 0x18101408, 4, 0x1); + /* Reading CLB XTAL BT cntrl register */ + bcmsdh_reg_write(bus->sdh, 0x180013D8, 2, 0xD1); + bcmsdh_reg_write(bus->sdh, 0x180013DA, 2, 0x12); + bcmsdh_reg_write(bus->sdh, 0x180013D8, 2, 0x2D0); + /* Read if BT is powered up */ + temp = bcmsdh_reg_read(bus->sdh, 0x180013DA, 2); + /* Read BT_ready from WLAN wireless register */ + temp2 = bcmsdh_reg_read(bus->sdh, 0x1800002C, 4); + /* + Check if the BT is powered up and ready. The duration between BT being powered up + and BT becoming ready is the problematic window for WLAN. If we move ahead at this + time then we may encounter a corrupted backplane later. So we wait for BT to be ready + and then proceed after checking the health of the backplane. If the backplane shows + indications of failure then we have to do a full reset of the backplane using SR engine + and then proceed. + */ + (temp & 0xF0) ? (BT_pwr_up = 1):(BT_pwr_up = 0); + (temp2 & (1<<17)) ? (BT_ready = 1):(BT_ready = 0); + DHD_ERROR(("WARNING: Checking if BT is ready BT_pwr_up = %x" + "BT_ready = %x \n", BT_pwr_up, BT_ready)); + while (BT_pwr_up && !BT_ready) + { + OSL_DELAY(1000); + bcmsdh_reg_write(bus->sdh, 0x180013D8, 2, 0x2D0); + temp = bcmsdh_reg_read(bus->sdh, 0x180013DA, 2); + temp2 = bcmsdh_reg_read(bus->sdh, 0x1800002C, 4); + (temp & 0xF0) ? (BT_pwr_up = 1):(BT_pwr_up = 0); + (temp2 & (1<<17)) ? (BT_ready = 1):(BT_ready = 0); + counter++; + if (counter == 5000) + { + DHD_ERROR(("WARNING: Going ahead after 5 secs with" + "risk of failure because BT ready is not yet set\n")); + break; + } + } + DHD_ERROR(("\nWARNING: WL Proceeding BT_pwr_up = %x BT_ready = %x" + "\n", BT_pwr_up, BT_ready)); + counter = 0; + OSL_DELAY(10000); + /* + Get the information of who accessed the crucial backplane entities + by reading read and write access registers + */ + DHD_TRACE(("%d: Read Value @ 0x18104808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18104808, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810480C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810480C, 4))); + DHD_TRACE(("%d: Read Value @ 0x18106808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18106808, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810680C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810680C, 4))); + DHD_TRACE(("%d: Read Value @ 0x18107808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18107808, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810780C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810780C, 4))); + DHD_TRACE(("%d: Read Value @ 0x18108808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18108808, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810880C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810880C, 4))); + DHD_TRACE(("%d: Read Value @ 0x18109808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18109808, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810980C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810980C, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810C808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c808, 4))); + DHD_TRACE(("%d: Read Value @ 0x1810C80C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c80C, 4))); + counter = 0; + while ((bcmsdh_reg_read(bus->sdh, 0x18104808, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810480C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x18106808, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810680C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810780C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810780C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810880C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810880C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810980C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810980C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810C80C, 4) == 5) || + (bcmsdh_reg_read(bus->sdh, 0x1810C80C, 4) == 5)) + { + if (++counter > 10) + { + DHD_ERROR(("Unable to recover the backkplane corruption" + "..Tried %d times.. Exiting\n", counter)); + break; + } + OSL_DELAY(10000); + dhd_sdio_backplane_reset(bus); + /* + Get the information of who accessed the crucial backplane + entities by reading read and write access registers + */ + DHD_ERROR(("%d: Read Value @ 0x18104808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18104808, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810480C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810480C, 4))); + DHD_ERROR(("%d: Read Value @ 0x18106808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18106808, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810680C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810680C, 4))); + DHD_ERROR(("%d: Read Value @ 0x18107808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18107808, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810780C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810780C, 4))); + DHD_ERROR(("%d: Read Value @ 0x18108808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18108808, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810880C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810880C, 4))); + DHD_ERROR(("%d: Read Value @ 0x18109808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x18109808, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810980C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810980C, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810C808 = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c808, 4))); + DHD_ERROR(("%d: Read Value @ 0x1810C80C = %x." + "\n", __LINE__, bcmsdh_reg_read(bus->sdh, 0x1810c80C, 4))); + } + /* Set the WL ready to indicate BT that we are done with backplane reset */ + DHD_ERROR(("Setting up AXI_OK\n")); + bcmsdh_reg_write(bus->sdh, 0x18000658, 4, 0x3); + temp = bcmsdh_reg_read(bus->sdh, 0x1800065c, 4); + temp |= 0x80000000; + bcmsdh_reg_write(bus->sdh, 0x1800065c, 4, temp); + return TRUE; +} +#endif /* REGON_BP_HANG_FIX */ static bool dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, uint16 devid) @@ -7031,6 +7773,12 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, goto fail; } +#ifdef REGON_BP_HANG_FIX + /* WAR - for 43241 B0-B1-B2. B3 onwards do not need this */ + if (((uint16)bus->sih->chip == BCM4324_CHIP_ID) && (bus->sih->chiprev < 3)) + dhdsdio_sdio_hang_war(bus); +#endif /* REGON_BP_HANG_FIX */ + bcmsdh_chipinfo(sdh, bus->sih->chip, bus->sih->chiprev); if (!dhdsdio_chipmatch((uint16)bus->sih->chip)) { @@ -7062,10 +7810,10 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, } if (!si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { - if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { - DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__)); - goto fail; - } + if (!(bus->orig_ramsize = si_socram_size(bus->sih))) { + DHD_ERROR(("%s: failed to find SOCRAM memory!\n", __FUNCTION__)); + goto fail; + } } else { /* cr4 has a different way to find the RAM size from TCM's */ if (!(bus->orig_ramsize = si_tcm_size(bus->sih))) { @@ -7073,14 +7821,28 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, goto fail; } /* also populate base address */ - bus->dongle_ram_base = CR4_RAM_BASE; + switch ((uint16)bus->sih->chip) { + case BCM4335_CHIP_ID: + bus->dongle_ram_base = CR4_4335_RAM_BASE; + break; + case BCM4350_CHIP_ID: + bus->dongle_ram_base = CR4_4350_RAM_BASE; + break; + case BCM4360_CHIP_ID: + bus->dongle_ram_base = CR4_4360_RAM_BASE; + break; + default: + bus->dongle_ram_base = 0; + DHD_ERROR(("%s: WARNING: Using default ram base at 0x%x\n", + __FUNCTION__, bus->dongle_ram_base)); + } } bus->ramsize = bus->orig_ramsize; if (dhd_dongle_memsize) dhd_dongle_setmemsize(bus, dhd_dongle_memsize); - DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d)\n", - bus->ramsize, bus->orig_ramsize)); + DHD_ERROR(("DHD: dongle ram size is set to %d(orig %d) at 0x%x\n", + bus->ramsize, bus->orig_ramsize, bus->dongle_ram_base)); bus->srmemsize = si_socram_srmem_size(bus->sih); } @@ -7123,7 +7885,7 @@ dhdsdio_probe_attach(struct dhd_bus *bus, osl_t *osh, void *sdh, void *regsva, #ifdef BCMSDIOH_TXGLOM /* Setting default Glom mode */ - bus->glom_mode = SDPCM_TXGLOM_CPY; + bus->glom_mode = bcmsdh_set_mode(bus->sdh, SDPCM_DEFGLOM_MODE); /* Setting default Glom size */ bus->glomsize = SDPCM_DEFGLOM_SIZE; #endif @@ -7233,6 +7995,9 @@ dhdsdio_probe_init(dhd_bus_t *bus, osl_t *osh, void *sdh) } else { DHD_INFO(("%s: Initial value for %s is %d\n", __FUNCTION__, "sd_blocksize", bus->blocksize)); + + if (bus->sih->chip == BCM4335_CHIP_ID) + dhd_overflow_war(bus); } bus->roundup = MIN(max_roundup, bus->blocksize); @@ -7372,10 +8137,10 @@ dhdsdio_release_dongle(dhd_bus_t *bus, osl_t *osh, bool dongle_isolation, bool r return; if (bus->sih) { +#if !defined(BCMLXSDMMC) if (bus->dhd) { dhdsdio_clkctl(bus, CLK_AVAIL, FALSE); } -#if !defined(BCMLXSDMMC) if (KSO_ENAB(bus) && (dongle_isolation == FALSE)) si_watchdog(bus->sih, 4); #endif /* !defined(BCMLXSDMMC) */ @@ -7397,8 +8162,9 @@ dhdsdio_disconnect(void *ptr) { dhd_bus_t *bus = (dhd_bus_t *)ptr; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) + DHD_TRACE(("%s: Enter\n", __FUNCTION__)); +#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__)); } @@ -7408,7 +8174,6 @@ dhdsdio_disconnect(void *ptr) mutex_lock(&_dhd_sdio_mutex_lock_); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ - DHD_TRACE(("%s: Enter\n", __FUNCTION__)); if (bus) { ASSERT(bus->dhd); @@ -7420,6 +8185,7 @@ dhdsdio_disconnect(void *ptr) DHD_ERROR(("%s : the lock is released.\n", __FUNCTION__)); #endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) */ + DHD_TRACE(("%s: Disconnected\n", __FUNCTION__)); } @@ -7475,6 +8241,17 @@ dhdsdio_download_code_array(struct dhd_bus *bus) /* Download image */ while ((offset + MEMBLOCK) < sizeof(dlarray)) { + /* check if CR4 */ + if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { + /* if address is 0, store the reset instruction to be written in 0 */ + + if (offset == 0) { + bus->resetinstr = *(((uint32*)dlarray)); + /* Add start of RAM address to the address given by user */ + offset += bus->dongle_ram_base; + } + } + bcmerror = dhdsdio_membytes(bus, TRUE, offset, (uint8 *) (dlarray + offset), MEMBLOCK); if (bcmerror) { @@ -7572,6 +8349,17 @@ dhdsdio_download_code_file(struct dhd_bus *bus, char *pfw_path) bcmerror = BCME_ERROR; goto err; } + /* check if CR4 */ + if (si_setcore(bus->sih, ARMCR4_CORE_ID, 0)) { + /* if address is 0, store the reset instruction to be written in 0 */ + + if (offset == 0) { + bus->resetinstr = *(((uint32*)memptr)); + /* Add start of RAM address to the address given by user */ + offset += bus->dongle_ram_base; + } + } + bcmerror = dhdsdio_membytes(bus, TRUE, offset, memptr, len); if (bcmerror) { DHD_ERROR(("%s: error %d on writing %d membytes at 0x%08x\n", @@ -7721,6 +8509,7 @@ _dhdsdio_download_firmware(struct dhd_bus *bus) dlok = TRUE; } } + #ifdef BCMEMBEDIMAGE if (embed) { if (dhdsdio_download_code_array(bus)) { @@ -7791,9 +8580,9 @@ dhd_bcmsdh_send_buf(dhd_bus_t *bus, uint32 addr, uint fn, uint flags, uint8 *buf #ifdef BCMSDIOH_TXGLOM static void -dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, uint len) +dhd_bcmsdh_glom_post(dhd_bus_t *bus, uint8 *frame, void *pkt, uint len) { - bcmsdh_glom_post(bus->sdh, frame, len); + bcmsdh_glom_post(bus->sdh, frame, pkt, len); } static void @@ -7947,23 +8736,6 @@ uint dhd_bus_chip_id(dhd_pub_t *dhdp) return bus->sih->chip; } - -/* Get Chip Rev ID version */ -uint dhd_bus_chiprev_id(dhd_pub_t *dhdp) -{ - dhd_bus_t *bus = dhdp->bus; - - return bus->sih->chiprev; -} - -/* Get Chip Pkg ID version */ -uint dhd_bus_chippkg_id(dhd_pub_t *dhdp) -{ - dhd_bus_t *bus = dhdp->bus; - - return bus->sih->chippkg; -} - int dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint size) { @@ -7972,7 +8744,7 @@ dhd_bus_membytes(dhd_pub_t *dhdp, bool set, uint32 address, uint8 *data, uint si bus = dhdp->bus; return dhdsdio_membytes(bus, set, address, data, size); } -#if defined(SUPPORT_MULTIPLE_REVISION) +#if defined(CUSTOMER_HW4) && defined(SUPPORT_MULTIPLE_REVISION) static int concate_revision_bcm4334(dhd_bus_t *bus, char *path, int path_len) { @@ -7982,7 +8754,7 @@ concate_revision_bcm4334(dhd_bus_t *bus, char *path, int path_len) uint chipver; uint32 unique_id; uint8 data[4]; - char chipver_tag[4] = "_b0"; + char chipver_tag[4] = "_b?"; DHD_TRACE(("%s: BCM4334 Multiple Revision Check\n", __FUNCTION__)); if (bus->sih->chip != BCM4334_CHIP_ID) { @@ -7999,14 +8771,12 @@ concate_revision_bcm4334(dhd_bus_t *bus, char *path, int path_len) DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); if (chipver == 1) { DHD_ERROR(("----- CHIP bcm4334_B0 -----\n")); - chipver_tag[2] = '0'; strcpy(chipver_tag, "_b0"); } else if (chipver == 2) { DHD_ERROR(("----- CHIP bcm4334_B1 -----\n")); - chipver_tag[2] = '1'; + strcpy(chipver_tag, "_b1"); } else if (chipver == 3) { DHD_ERROR(("----- CHIP bcm4334_B2 -----\n")); - chipver_tag[2] = '2'; strcpy(chipver_tag, "_b2"); } else { @@ -8019,18 +8789,49 @@ concate_revision_bcm4334(dhd_bus_t *bus, char *path, int path_len) return 0; } -int -concate_revision(dhd_bus_t *bus, char *path, int path_len) +static int +concate_revision_bcm4335 + (dhd_bus_t *bus, char *fw_path, int fw_path_len, char *nv_path, int nv_path_len) { + uint chipver; + char chipver_tag[4] = {0, }; + + DHD_TRACE(("%s: BCM4335 Multiple Revision Check\n", __FUNCTION__)); + if (bus->sih->chip != BCM4335_CHIP_ID) { + DHD_ERROR(("%s:Chip is not BCM4335\n", __FUNCTION__)); + return -1; + } + chipver = bus->sih->chiprev; + DHD_ERROR(("CHIP VER = [0x%x]\n", chipver)); + if (chipver == 0x0) { + DHD_ERROR(("----- CHIP bcm4335_A0 -----\n")); + strcpy(chipver_tag, "_a0"); + } else if (chipver == 0x1) { + DHD_ERROR(("----- CHIP bcm4335_B0 -----\n")); + } + strcat(fw_path, chipver_tag); + strcat(nv_path, chipver_tag); + + return 0; + +} +int +concate_revision(dhd_bus_t *bus, char *fw_path, int fw_path_len, char *nv_path, int nv_path_len) +{ if (!bus || !bus->sih) { DHD_ERROR(("%s:Bus is Invalid\n", __FUNCTION__)); return -1; } - if (bus->sih->chip == BCM4334_CHIP_ID) { - return concate_revision_bcm4334(bus, path, path_len); + switch (bus->sih->chip) { + case BCM4334_CHIP_ID: + return concate_revision_bcm4334(bus, fw_path, fw_path_len); + case BCM4335_CHIP_ID: + return concate_revision_bcm4335(bus, fw_path, fw_path_len, + nv_path, nv_path_len); } + DHD_ERROR(("REVISION SPECIFIC feature is not required\n")); - return -1; + return 0; } -#endif /* MULTIPLE_REVISION */ +#endif /* CUSTOMER_HW4 && SUPPORT_MULTIPLE_REVISION */ diff --git a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h index fdad958..933a78a 100755 --- a/drivers/net/wireless/bcmdhd/dhd_sec_feature.h +++ b/drivers/net/wireless/bcmdhd/dhd_sec_feature.h @@ -1,17 +1,14 @@ -/* - * Header file describing the internal (inter-module) DHD interfaces. - * - * Provides type definitions and function prototypes used to link the - * DHD OS, bus, and protocol modules. +/* + * Customer HW 4 dependant file * * Copyright (C) 1999-2012, Broadcom Corporation - * + * * Unless you and Broadcom execute a separate written software license * agreement governing use of this software, this software is licensed to you * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -19,105 +16,133 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhd_sec_feature.h 309548 2012-01-20 01:13:08Z $ + * $Id: dhd_sec_feature.h$ */ +#ifndef _dhd_sec_feature_h_ +#define _dhd_sec_feature_h_ + /* PROJECTS */ #if defined(CONFIG_MACH_SAMSUNG_ESPRESSO)\ || defined(CONFIG_MACH_SAMSUNG_ESPRESSO_10) #define READ_MACADDR #define HW_OOB -#endif +#endif /* CONFIG_MACH_SAMSUNG_ESPRESSO && CONFIG_MACH_SAMSUNG_ESPRESSO_10 */ /* Q1 also uses this feature */ #if defined(CONFIG_MACH_U1) || defined(CONFIG_MACH_TRATS) #ifdef CONFIG_MACH_Q1_BD #define HW_OOB -#endif +#endif /* CONFIG_MACH_Q1_BD */ #define USE_CID_CHECK #define WRITE_MACADDR -#endif +#endif /* CONFIG_MACH_U1 || CONFIG_MACH_TRATS */ #ifdef CONFIG_ARCH_MSM7X30 #define HW_OOB #define READ_MACADDR -#endif +#endif /* CONFIG_ARCH_MSM7X30 */ -#if defined CONFIG_MACH_GC1 || defined CONFIG_MACH_U1_NA_SPR +#if defined(CONFIG_MACH_GC1) || defined(CONFIG_MACH_U1_NA_SPR) || defined(CONFIG_MACH_V1) #undef USE_CID_CHECK #define READ_MACADDR -#endif +#endif /* CONFIG_MACH_GC1 || CONFIG_MACH_U1_NA_SPR || CONFIG_MACH_V1 */ #ifdef CONFIG_MACH_P10 #define READ_MACADDR -#endif +#endif /* CONFIG_MACH_P10 */ #ifdef CONFIG_ARCH_MSM8960 #undef WIFI_TURNOFF_DELAY #define WIFI_TURNOFF_DELAY 200 -#endif +#endif /* CONFIG_ARCH_MSM8960 */ + +#ifdef CONFIG_MACH_JF +#undef CUSTOM_TXGLOM_SIZE +#define CUSTOM_TXGLOM_SIZE 32 +#define DHD_TXBOUND 32 +#endif /* CONFIG_MACH_JF */ + +#if defined(CONFIG_BCM4335) || defined (CONFIG_BCM4335_MODULE) +#define POWERUP_MAX_RETRY 5 /* Due to late start-up of FPGA in JF project */ +#endif /* CONFIG_BCM4335 || CONFIG_BCM4335_MODULE */ /* REGION CODE */ +#ifndef CONFIG_WLAN_REGION_CODE +#define CONFIG_WLAN_REGION_CODE 100 +#endif /* CONFIG_WLAN_REGION_CODE */ -//#if (WLAN_REGION_CODE >= 100) && (WLAN_REGION_CODE < 200) /*EUR*/ -//#if (WLAN_REGION_CODE == 101) /*EUR ORG*/ +#if (CONFIG_WLAN_REGION_CODE >= 100) && (CONFIG_WLAN_REGION_CODE < 200) /* EUR */ +#if (CONFIG_WLAN_REGION_CODE == 101) /* EUR ORG */ /* GAN LITE NAT KEEPALIVE FILTER */ -//#define GAN_LITE_NAT_KEEPALIVE_FILTER -//#endif -//#endif +#define GAN_LITE_NAT_KEEPALIVE_FILTER +#endif /* CONFIG_WLAN_REGION_CODE == 101 */ +#endif /* CONFIG_WLAN_REGION_CODE >= 100 && CONFIG_WLAN_REGION_CODE < 200 */ -#if (WLAN_REGION_CODE >= 200) && (WLAN_REGION_CODE < 300) /* KOR */ +#if (CONFIG_WLAN_REGION_CODE >= 200) && (CONFIG_WLAN_REGION_CODE < 300) /* KOR */ #undef USE_INITIAL_2G_SCAN_ORG #ifndef ROAM_ENABLE #define ROAM_ENABLE -#endif +#endif /* ROAM_ENABLE */ #ifndef ROAM_API #define ROAM_API -#endif +#endif /* ROAM_API */ #ifndef ROAM_CHANNEL_CACHE #define ROAM_CHANNEL_CACHE -#endif +#endif /* ROAM_CHANNEL_CACHE */ #ifndef OKC_SUPPORT #define OKC_SUPPORT -#endif +#endif /* OKC_SUPPORT */ #ifndef ROAM_AP_ENV_DETECTION #define ROAM_AP_ENV_DETECTION -#endif +#endif /* ROAM_AP_ENV_DETECTION */ #undef WRITE_MACADDR #undef READ_MACADDR -#ifdef CONFIG_BCM4334 +#if defined(CONFIG_BCM4334) || defined(CONFIG_BCM4335) \ + || defined(CONFIG_BCM4334_MODULE) || defined(CONFIG_BCM4335_MODULE) #define READ_MACADDR #else #define RDWR_MACADDR -#endif +#endif /* CONFIG_BCM4334 || CONFIG_BCM4335 */ -#if (WLAN_REGION_CODE == 201) /* SKT */ -#endif +#if (CONFIG_WLAN_REGION_CODE == 201) /* SKT */ +#endif /* CONFIG_WLAN_REGION_CODE == 201 */ -#if (WLAN_REGION_CODE == 202) /* KTT */ +#if (CONFIG_WLAN_REGION_CODE == 202) /* KTT */ #define VLAN_MODE_OFF -#define KEEP_ALIVE_PACKET_PERIOD_30_SEC +#define CUSTOM_KEEP_ALIVE_SETTING 30000 /* JBP type KOR KTT only. do not correct here */ #define FULL_ROAMING_SCAN_PERIOD_60_SEC -#endif +#endif /* CONFIG_WLAN_REGION_CODE == 202 */ -#if (WLAN_REGION_CODE == 203) /* LGT */ -#endif -#endif +#if (CONFIG_WLAN_REGION_CODE == 203) /* LGT */ +#endif /* CONFIG_WLAN_REGION_CODE == 203 */ +#endif /* CONFIG_WLAN_REGION_CODE >= 200 && CONFIG_WLAN_REGION_CODE < 300 */ -#if (WLAN_REGION_CODE >= 300) && (WLAN_REGION_CODE < 400) /* CHN */ +#if (CONFIG_WLAN_REGION_CODE >= 300) && (CONFIG_WLAN_REGION_CODE < 400) /* CHN */ +#ifndef BCMWAPI_WPI #define BCMWAPI_WPI +#endif +#ifndef BCMWAPI_WAI #define BCMWAPI_WAI #endif +#endif /* CONFIG_WLAN_REGION_CODE >= 300 && CONFIG_WLAN_REGION_CODE < 400 */ + +#if (CONFIG_WLAN_REGION_CODE >= 400) && (CONFIG_WLAN_REGION_CODE < 500) /* JPN */ +#define DISABLE_11AC +#endif /* CONFIG_WLAN_REGION_CODE >= 400 && CONFIG_WLAN_REGION_CODE < 500 */ -#if !defined(READ_MACADDR) && !defined(WRITE_MACADDR) && !defined(RDWR_KORICS_MACADDR) && !defined(RDWR_MACADDR) +#if !defined(READ_MACADDR) && !defined(WRITE_MACADDR) \ + && !defined(RDWR_KORICS_MACADDR) && !defined(RDWR_MACADDR) #define GET_MAC_FROM_OTP -#endif +#define SHOW_NVRAM_TYPE +#endif /* !READ_MACADDR && !WRITE_MACADDR && !RDWR_KORICS_MACADDR && !RDWR_MACADDR */ +#endif /* _dhd_sec_feature_h_ */ diff --git a/drivers/net/wireless/bcmdhd/dhd_wlfc.h b/drivers/net/wireless/bcmdhd/dhd_wlfc.h index 4087351..0eaaa0f 100644 --- a/drivers/net/wireless/bcmdhd/dhd_wlfc.h +++ b/drivers/net/wireless/bcmdhd/dhd_wlfc.h @@ -18,7 +18,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. -* $Id: dhd_wlfc.h 341930 2012-06-29 04:51:25Z $ +* $Id: dhd_wlfc.h 381116 2013-01-25 06:08:41Z $ * */ #ifndef __wlfc_host_driver_definitions_h__ @@ -27,9 +27,10 @@ /* 16 bits will provide an absolute max of 65536 slots */ #define WLFC_HANGER_MAXITEMS 1024 -#define WLFC_HANGER_ITEM_STATE_FREE 1 -#define WLFC_HANGER_ITEM_STATE_INUSE 2 +#define WLFC_HANGER_ITEM_STATE_FREE 1 +#define WLFC_HANGER_ITEM_STATE_INUSE 2 #define WLFC_HANGER_ITEM_STATE_INUSE_SUPPRESSED 3 + #define WLFC_PKTID_HSLOT_MASK 0xffff /* allow 16 bits only */ #define WLFC_PKTID_HSLOT_SHIFT 8 @@ -84,6 +85,7 @@ typedef struct wlfc_hanger { uint32 failed_to_push; uint32 failed_to_pop; uint32 failed_slotfind; + uint32 slot_pos; wlfc_hanger_item_t items[1]; } wlfc_hanger_t; @@ -97,13 +99,9 @@ typedef struct wlfc_hanger { #define WLFC_PSQ_LEN 2048 -#define WLFC_SENDQ_LEN 256 - - #define WLFC_FLOWCONTROL_HIWATER (2048 - 256) #define WLFC_FLOWCONTROL_LOWATER 256 - typedef struct wlfc_mac_descriptor { uint8 occupied; uint8 interface_id; @@ -127,9 +125,15 @@ typedef struct wlfc_mac_descriptor { /* 1= send on next opportunity */ uint8 send_tim_signal; uint8 mac_handle; + /* Number of packets in transit for this entry. */ uint transit_count; + /* Numbe of suppression to wait before evict from delayQ */ uint suppr_transit_count; + /* Used when a new suppress is detected to track the number of + * packets getting suppressed + */ uint suppress_count; + /* flag. TRUE when in suppress state */ uint8 suppressed; #ifdef PROP_TXSTATUS_DEBUG @@ -153,7 +157,6 @@ typedef struct athost_wl_stat_counters { uint32 tlv_parse_failed; uint32 rollback; uint32 rollback_failed; - uint32 sendq_full_error; uint32 delayq_full_error; uint32 credit_request_failed; uint32 packet_request_failed; @@ -178,7 +181,7 @@ typedef struct athost_wl_stat_counters { uint32 dhd_hdrpulls; uint32 generic_error; /* an extra one for bc/mc traffic */ - uint32 sendq_pkts[AC_COUNT + 1]; + uint32 send_pkts[AC_COUNT + 1]; #ifdef PROP_TXSTATUS_DEBUG /* all pkt2bus -> txstatus latency accumulated */ uint32 latency_sample_count; @@ -237,8 +240,6 @@ typedef struct athost_wl_status_info { /* Credit borrow counts for each FIFO from each of the other FIFOs */ int credits_borrowed[AC_COUNT + 2][AC_COUNT + 2]; - struct pktq SENDQ; - /* packet hanger and MAC->handle lookup table */ void* hanger; struct { diff --git a/drivers/net/wireless/bcmdhd/hndpmu.c b/drivers/net/wireless/bcmdhd/hndpmu.c index ad9a9ca..92a56db 100644 --- a/drivers/net/wireless/bcmdhd/hndpmu.c +++ b/drivers/net/wireless/bcmdhd/hndpmu.c @@ -22,7 +22,16 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndpmu.c 357871 2012-09-20 07:17:35Z $ + * $Id: hndpmu.c 367414 2012-11-08 00:40:54Z $ + */ + +/* + * Note: this file contains PLL/FLL related functions. A chip can contain multiple PLLs/FLLs. + * However, in the context of this file the baseband ('BB') PLL/FLL is referred to. + * + * Throughout this code, the prefixes 'pmu0_', 'pmu1_' and 'pmu2_' are used. + * They refer to different revisions of the PMU (which is at revision 18 @ Apr 25, 2012) + * pmu2_ marks the transition from PLL to ADFLL (Digital Frequency Locked Loop) */ #include <bcm_cfg.h> @@ -116,7 +125,6 @@ static const sdiod_drive_str_t sdiod_drive_strength_tab6_1v8[] = { {1, 0x1}, {0, 0x0} }; - #define SDIOD_DRVSTR_KEY(chip, pmu) (((chip) << 16) | (pmu)) void diff --git a/drivers/net/wireless/bcmdhd/include/Makefile b/drivers/net/wireless/bcmdhd/include/Makefile index eca939f..bcc1267 100755..100644 --- a/drivers/net/wireless/bcmdhd/include/Makefile +++ b/drivers/net/wireless/bcmdhd/include/Makefile @@ -10,10 +10,10 @@ # # Copyright 2005, Broadcom, Inc. # -# $Id: Makefile 241686 2011-02-19 00:22:45Z prakashd $ +# $Id: Makefile 347587 2012-07-27 09:13:31Z prakashd $ # -SRCBASE := .. +export SRCBASE:=.. TARGETS := epivers.h @@ -23,11 +23,11 @@ endif all release: epivers compvers -# Generate epivers.h for native branch version +# Generate epivers.h for native branch url epivers: bash epivers.sh -# Generate epivers.h for native branch version +# Generate component versions based on component url compvers: @if [ -s "compvers.sh" ]; then \ echo "Generating component versions, if any"; \ diff --git a/drivers/net/wireless/bcmdhd/include/bcmdefs.h b/drivers/net/wireless/bcmdhd/include/bcmdefs.h index a35ed72..0462f81 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdefs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdefs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdefs.h 316830 2012-02-23 20:29:22Z $ + * $Id: bcmdefs.h 366265 2012-11-01 20:08:27Z $ */ #ifndef _bcmdefs_h_ @@ -54,8 +54,13 @@ #define BCMNMIATTACHDATA(_data) _data #define CONST const #ifndef BCMFASTPATH +#if defined(__ARM_ARCH_7A__) +#define BCMFASTPATH __attribute__ ((__section__ (".text.fastpath"))) +#define BCMFASTPATH_HOST __attribute__ ((__section__ (".text.fastpath_host"))) +#else #define BCMFASTPATH #define BCMFASTPATH_HOST +#endif #endif @@ -177,9 +182,9 @@ typedef struct { #if defined(BCM_RPC_NOCOPY) || defined(BCM_RCP_TXNOCOPY) -#define BCMEXTRAHDROOM 220 +#define BCMEXTRAHDROOM 260 #else -#define BCMEXTRAHDROOM 172 +#define BCMEXTRAHDROOM 204 #endif diff --git a/drivers/net/wireless/bcmdhd/include/bcmdevs.h b/drivers/net/wireless/bcmdhd/include/bcmdevs.h index c7e06ff..50e693a 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmdevs.h +++ b/drivers/net/wireless/bcmdhd/include/bcmdevs.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmdevs.h 329854 2012-04-27 01:42:28Z $ + * $Id: bcmdevs.h 368924 2012-11-15 08:12:59Z $ */ #ifndef _BCMDEVS_H @@ -63,6 +63,12 @@ #define BCM_DNGL_BL_PID_43239 0xbd1b #define BCM_DNGL_BL_PID_4324 0xbd1c #define BCM_DNGL_BL_PID_4360 0xbd1d +#define BCM_DNGL_BL_PID_43143 0xbd1e +#define BCM_DNGL_BL_PID_43242 0xbd1f +#define BCM_DNGL_BL_PID_43342 0xbd21 +#define BCM_DNGL_BL_PID_4335 0xbd20 +#define BCM_DNGL_BL_PID_4350 0xbd23 +#define BCM_DNGL_BL_PID_43341 0xbd22 #define BCM_DNGL_BDC_PID 0x0bdc #define BCM_DNGL_JTAG_PID 0x4a44 @@ -146,28 +152,42 @@ #define BCM43131_D11N2G_ID 0x43aa #define BCM4314_D11N2G_ID 0x4364 #define BCM43142_D11N2G_ID 0x4365 +#define BCM43143_D11N2G_ID 0x4366 #define BCM4334_D11N_ID 0x4380 #define BCM4334_D11N2G_ID 0x4381 #define BCM4334_D11N5G_ID 0x4382 +#define BCM43342_D11N_ID 0x4383 +#define BCM43342_D11N2G_ID 0x4384 +#define BCM43342_D11N5G_ID 0x4385 #define BCM43341_D11N_ID 0x4386 #define BCM43341_D11N2G_ID 0x4387 #define BCM43341_D11N5G_ID 0x4388 #define BCM4360_D11AC_ID 0x43a0 #define BCM4360_D11AC2G_ID 0x43a1 #define BCM4360_D11AC5G_ID 0x43a2 +#define BCM4335_D11AC_ID 0x43ae +#define BCM4335_D11AC2G_ID 0x43af +#define BCM4335_D11AC5G_ID 0x43b0 +#define BCM4352_D11AC_ID 0x43b1 +#define BCM4352_D11AC2G_ID 0x43b2 +#define BCM4352_D11AC5G_ID 0x43b3 #define BCM943228HMB_SSID_VEN1 0x0607 #define BCM94313HMGBL_SSID_VEN1 0x0608 #define BCM94313HMG_SSID_VEN1 0x0609 +#define BCM943142HM_SSID_VEN1 0x0611 +#define BCM43143_D11N2G_ID 0x4366 + +#define BCM43242_D11N_ID 0x4367 +#define BCM43242_D11N2G_ID 0x4368 +#define BCM43242_D11N5G_ID 0x4369 + +#define BCM4350_D11AC_ID 0x43a3 +#define BCM4350_D11AC2G_ID 0x43a4 +#define BCM4350_D11AC5G_ID 0x43a5 -#define BCM4335_D11AC_ID 0x43ae -#define BCM4335_D11AC2G_ID 0x43af -#define BCM4335_D11AC5G_ID 0x43b0 -#define BCM4352_D11AC_ID 0x43b1 -#define BCM4352_D11AC2G_ID 0x43b2 -#define BCM4352_D11AC5G_ID 0x43b3 #define BCMGPRS_UART_ID 0x4333 #define BCMGPRS2_UART_ID 0x4344 @@ -205,6 +225,8 @@ #define BCM47XX_GIGETH_ID 0x471f #define BCM4712_MIPS_ID 0x4720 #define BCM4716_DEVICE_ID 0x4722 +#define BCM47XX_USB30H_ID 0x472a +#define BCM47XX_USB30D_ID 0x472b #define BCM47XX_SMBUS_EMU_ID 0x47fe #define BCM47XX_XOR_EMU_ID 0x47ff #define EPI41210_DEVICE_ID 0xa0fa @@ -260,21 +282,27 @@ #define BCM6362_CHIP_ID 0x6362 #define BCM4314_CHIP_ID 0x4314 #define BCM43142_CHIP_ID 43142 +#define BCM43143_CHIP_ID 43143 #define BCM4324_CHIP_ID 0x4324 #define BCM43242_CHIP_ID 43242 +#define BCM43243_CHIP_ID 43243 #define BCM4334_CHIP_ID 0x4334 +#define BCM4335_CHIP_ID 0x4335 #define BCM4360_CHIP_ID 0x4360 #define BCM4352_CHIP_ID 0x4352 #define BCM43526_CHIP_ID 0xAA06 #define BCM43341_CHIP_ID 43341 #define BCM43342_CHIP_ID 43342 - #define BCM4335_CHIP_ID 0x4335 +#define BCM4350_CHIP_ID 0x4350 #define BCM4342_CHIP_ID 4342 #define BCM4402_CHIP_ID 0x4402 #define BCM4704_CHIP_ID 0x4704 #define BCM4706_CHIP_ID 0x5300 +#define BCM4707_CHIP_ID 53010 +#define BCM53018_CHIP_ID 53018 +#define BCM4707_CHIP(chipid) (((chipid) == BCM4707_CHIP_ID) || ((chipid) == BCM53018_CHIP_ID)) #define BCM4710_CHIP_ID 0x4710 #define BCM4712_CHIP_ID 0x4712 #define BCM4716_CHIP_ID 0x4716 @@ -336,27 +364,38 @@ #define BCM4314SDIO_FPBGA_PKG_ID (8 | 4) #define BCM4314DEV_PKG_ID (8 | 6) +#define BCM4707_PKG_ID 1 +#define BCM4708_PKG_ID 2 +#define BCM4709_PKG_ID 0 + #define PCIXX21_FLASHMEDIA0_ID 0x8033 #define PCIXX21_SDIOH0_ID 0x8034 +#define BCM4335_WLCSP_PKG_ID (0x0) +#define BCM4335_FCBGA_PKG_ID (0x1) +#define BCM4335_WLBGA_PKG_ID (0x2) +#define BCM4335_FCBGAD_PKG_ID (0x3) +#define BCM4335_PKG_MASK (0x3) + #define BFL_BTC2WIRE 0x00000001 #define BFL_BTCOEX 0x00000001 #define BFL_PACTRL 0x00000002 #define BFL_AIRLINEMODE 0x00000004 #define BFL_ADCDIV 0x00000008 -#define BFL_RFPLL 0x00000008 +#define BFL_DIS_256QAM 0x00000008 #define BFL_ENETROBO 0x00000010 #define BFL_NOPLLDOWN 0x00000020 #define BFL_CCKHIPWR 0x00000040 #define BFL_ENETADM 0x00000080 #define BFL_ENETVLAN 0x00000100 -#define BFL_UNUSED 0x00000200 +#define BFL_LTECOEX 0x00000200 #define BFL_NOPCI 0x00000400 #define BFL_FEM 0x00000800 #define BFL_EXTLNA 0x00001000 #define BFL_HGPA 0x00002000 -#define BFL_BTC2WIRE_ALTGPIO 0x00004000 +#define BFL_BTC2WIRE_ALTGPIO 0x00004000 + #define BFL_ALTIQ 0x00008000 #define BFL_NOPA 0x00010000 #define BFL_RSSIINV 0x00020000 @@ -365,6 +404,7 @@ #define BFL_PHASESHIFT 0x00100000 #define BFL_BUCKBOOST 0x00200000 #define BFL_FEM_BT 0x00400000 +#define BFL_RXCHAIN_OFF_BT 0x00400000 #define BFL_NOCBUCK 0x00800000 #define BFL_CCKFAVOREVM 0x01000000 #define BFL_PALDO 0x02000000 @@ -373,6 +413,7 @@ #define BFL_UCPWRCTL_MININDX 0x08000000 #define BFL_EXTLNA_5GHz 0x10000000 #define BFL_TRSW_1by2 0x20000000 +#define BFL_GAINBOOSTA01 0x20000000 #define BFL_LO_TRSW_R_5GHz 0x40000000 #define BFL_ELNA_GAINDEF 0x80000000 #define BFL_EXTLNA_TX 0x20000000 @@ -405,7 +446,8 @@ #define BFL2_ANAPACTRL_2G 0x00100000 #define BFL2_ANAPACTRL_5G 0x00200000 #define BFL2_ELNACTRL_TRSW_2G 0x00400000 -#define BFL2_BT_SHARE_ANT0 0x00800000 +#define BFL2_BT_SHARE_ANT0 0x00800000 +#define BFL2_BT_SHARE_BM_BIT0 0x00800000 #define BFL2_TEMPSENSE_HIGHER 0x01000000 #define BFL2_BTC3WIREONLY 0x02000000 #define BFL2_PWR_NOMINAL 0x04000000 @@ -413,7 +455,31 @@ #define BFL2_4313_RADIOREG 0x10000000 +#define BFL2_DYNAMIC_VMID 0x10000000 + #define BFL2_SDR_EN 0x20000000 +#define BFL2_DYNAMIC_VMID 0x10000000 +#define BFL2_BT_SHARE_BM_BIT1 0x40000000 + + +#define BFL_SROM11_BTCOEX 0x00000001 +#define BFL_SROM11_WLAN_BT_SH_XTL 0x00000002 +#define BFL_SROM11_EXTLNA 0x00001000 +#define BFL_SROM11_EXTLNA_5GHz 0x10000000 +#define BFL_SROM11_GAINBOOSTA01 0x20000000 +#define BFL2_SROM11_APLL_WAR 0x00000002 +#define BFL2_SROM11_ANAPACTRL_2G 0x00100000 +#define BFL2_SROM11_ANAPACTRL_5G 0x00200000 + + +#define BFL3_FEMCTRL_SUB 0x00000007 +#define BFL3_RCAL_WAR 0x00000008 +#define BFL3_TXGAINTBLID 0x00000070 +#define BFL3_TXGAINTBLID_SHIFT 0x4 +#define BFL3_TSSI_DIV_WAR 0x00000080 +#define BFL3_TSSI_DIV_WAR_SHIFT 0x7 +#define BFL3_FEMTBL_FROM_NVRAM 0x00000100 +#define BFL3_FEMTBL_FROM_NVRAM_SHIFT 0x8 #define BOARD_GPIO_BTC3W_IN 0x850 @@ -457,6 +523,9 @@ #define BCM943341WLABGS_SSID 0x062d +#define BCM943342FCAGBI_SSID 0x0641 + + #define GPIO_NUMPINS 32 @@ -470,6 +539,12 @@ #define RDL_RAM_BASE_4328 0x80000000 #define RDL_RAM_SIZE_4322 0x60000 #define RDL_RAM_BASE_4322 0x60000000 +#define RDL_RAM_SIZE_4360 0xA0000 +#define RDL_RAM_BASE_4360 0x60000000 +#define RDL_RAM_SIZE_43242 0x90000 +#define RDL_RAM_BASE_43242 0x60000000 +#define RDL_RAM_SIZE_43143 0x70000 +#define RDL_RAM_BASE_43143 0x60000000 #define MUXENAB_UART 0x00000001 diff --git a/drivers/net/wireless/bcmdhd/include/bcmnvram.h b/drivers/net/wireless/bcmdhd/include/bcmnvram.h index ce0e035..ba22bec 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmnvram.h +++ b/drivers/net/wireless/bcmdhd/include/bcmnvram.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmnvram.h 320632 2012-03-12 19:22:42Z $ + * $Id: bcmnvram.h 364705 2012-10-25 00:42:42Z $ */ #ifndef _bcmnvram_h_ @@ -51,6 +51,7 @@ extern char *nvram_default_get(const char *name); extern int nvram_init(void *sih); +extern int nvram_deinit(void *sih); extern int nvram_append(void *si, char *vars, uint varsz); @@ -80,7 +81,7 @@ nvram_safe_get(const char *name) static INLINE int -nvram_match(char *name, char *match) +nvram_match(const char *name, const char *match) { const char *value = nvram_get(name); return (value && !strcmp(value, match)); @@ -88,7 +89,7 @@ nvram_match(char *name, char *match) static INLINE int -nvram_invmatch(char *name, char *invmatch) +nvram_invmatch(const char *name, const char *invmatch) { const char *value = nvram_get(name); return (value && strcmp(value, invmatch)); @@ -109,6 +110,8 @@ extern int nvram_getall(char *nvram_buf, int count); uint8 nvram_calc_crc(struct nvram_header * nvh); +extern int nvram_space; + #endif @@ -120,6 +123,13 @@ uint8 nvram_calc_crc(struct nvram_header * nvh); #define NVRAM_VERSION 1 #define NVRAM_HEADER_SIZE 20 #define NVRAM_SPACE 0x8000 +#define DEF_NVRAM_SPACE 0x8000 +#ifdef MAX_NVRAM_SPACE +#undef MAX_NVRAM_SPACE +#endif +#define MAX_NVRAM_SPACE NVRAM_SPACE +#define ROM_ENVRAM_SPACE 0x1000 +#define NVRAM_LZMA_MAGIC 0x4c5a4d41 #define NVRAM_MAX_VALUE_LEN 255 #define NVRAM_MAX_PARAM_LEN 64 diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h index 29657d7..cbea8c5 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdbus.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdbus.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdbus.h 347614 2012-07-27 10:24:51Z $ + * $Id: bcmsdbus.h 387188 2013-02-24 09:20:24Z $ */ #ifndef _sdio_api_h_ @@ -48,12 +48,27 @@ #ifdef BCMSDIOH_TXGLOM /* Max number of glommed pkts */ -#define SDPCM_MAXGLOM_SIZE 10 -#define SDPCM_DEFGLOM_SIZE 3 +#ifdef CUSTOM_MAX_TXGLOM_SIZE +#define SDPCM_MAXGLOM_SIZE CUSTOM_MAX_TXGLOM_SIZE +#else +#define SDPCM_MAXGLOM_SIZE 16 +#endif /* CUSTOM_MAX_TXGLOM_SIZE */ #define SDPCM_TXGLOM_CPY 0 /* SDIO 2.0 should use copy mode */ #define SDPCM_TXGLOM_MDESC 1 /* SDIO 3.0 should use multi-desc mode */ + +#ifdef BCMSDIOH_TXGLOM_HIGHSPEED +#define SDPCM_DEFGLOM_MODE SDPCM_TXGLOM_MDESC +#ifdef CUSTOM_TXGLOM_SIZE +#define SDPCM_DEFGLOM_SIZE CUSTOM_TXGLOM_SIZE +#else +#define SDPCM_DEFGLOM_SIZE 10 #endif +#else +#define SDPCM_DEFGLOM_MODE SDPCM_TXGLOM_CPY +#define SDPCM_DEFGLOM_SIZE 3 +#endif /* BCMSDIOH_TXGLOM_HIGHSPEED */ +#endif /* BCMSDIOH_TXGLOM */ typedef int SDIOH_API_RC; @@ -96,12 +111,12 @@ extern SDIOH_API_RC sdioh_request_buffer(sdioh_info_t *si, uint pio_dma, uint fi void *pkt); #ifdef BCMSDIOH_TXGLOM -extern void sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, uint len); +extern void sdioh_glom_post(sdioh_info_t *sd, uint8 *frame, void *pkt, uint len); extern void sdioh_glom_clear(sdioh_info_t *sd); extern uint sdioh_set_mode(sdioh_info_t *sd, uint mode); extern bool sdioh_glom_enabled(void); #else -#define sdioh_glom_post(a, b, c) +#define sdioh_glom_post(a, b, c, d) #define sdioh_glom_clear(a) #define sdioh_set_mode(a) (0) #define sdioh_glom_enabled() (FALSE) diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh.h b/drivers/net/wireless/bcmdhd/include/bcmsdh.h index 3348e84..e882d5e 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh.h @@ -23,7 +23,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh.h 347614 2012-07-27 10:24:51Z $ + * $Id: bcmsdh.h 365575 2012-10-30 05:25:07Z $ */ /** @@ -48,6 +48,8 @@ extern const uint bcmsdh_msglevel; typedef struct bcmsdh_info bcmsdh_info_t; typedef void (*bcmsdh_cb_fn_t)(void *); +extern struct device *pm_dev; + /* Attach and build an interface to the underlying SD host driver. * - Allocates resources (structs, arrays, mem, OS handles, etc) needed by bcmsdh. * - Returns the bcmsdh handle and virtual address base for register access. @@ -145,7 +147,7 @@ extern int bcmsdh_recv_buf(void *sdh, uint32 addr, uint fn, uint flags, uint8 *buf, uint nbytes, void *pkt, bcmsdh_cmplt_fn_t complete_fn, void *handle); -extern void bcmsdh_glom_post(void *sdh, uint8 *frame, uint len); +extern void bcmsdh_glom_post(void *sdh, uint8 *frame, void *pkt, uint len); extern void bcmsdh_glom_clear(void *sdh); extern uint bcmsdh_set_mode(void *sdh, uint mode); extern bool bcmsdh_glom_enabled(void); diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h index 25cd55b..bd85de3 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h @@ -21,21 +21,19 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdh_sdmmc.h 355594 2012-09-07 10:22:02Z $ + * $Id: bcmsdh_sdmmc.h 393684 2013-03-28 11:03:49Z $ */ #ifndef __BCMSDH_SDMMC_H__ #define __BCMSDH_SDMMC_H__ -#define sd_err(x) do {printf x;} while (0) +#define sd_err(x) #define sd_trace(x) #define sd_info(x) #define sd_debug(x) #define sd_data(x) #define sd_ctrl(x) -#define sd_trace_hw4 sd_trace - #define sd_sync_dma(sd, read, nbytes) #define sd_init_dma(sd) #define sd_ack_intr(sd) @@ -61,10 +59,21 @@ extern void sdioh_sdmmc_osfree(sdioh_info_t *sd); /* private bus modes */ #define SDIOH_MODE_SD4 2 -#define CLIENT_INTR 0x100 /* Get rid of this! */ +#define CLIENT_INTR 0x100 /* Get rid of this! */ + +#ifdef BCMSDIOH_TXGLOM +/* Setting the MAX limit to 10 */ +#define SDIOH_MAXGLOM_SIZE 16 + +typedef struct glom_buf { + void *glom_pkt_head; + void *glom_pkt_tail; + uint32 count; /* Total number of pkts queued */ +} glom_buf_t; +#endif struct sdioh_info { - osl_t *osh; /* osh handler */ + osl_t *osh; /* osh handler */ bool client_intr_enabled; /* interrupt connnected flag */ bool intr_handler_valid; /* client driver interrupt handler valid */ sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ @@ -72,22 +81,27 @@ struct sdioh_info { uint16 intmask; /* Current active interrupts */ void *sdos_info; /* Pointer to per-OS private data */ - uint irq; /* Client irq */ - int intrcount; /* Client interrupts */ + uint irq; /* Client irq */ + int intrcount; /* Client interrupts */ bool sd_use_dma; /* DMA on CMD53 */ - bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ + bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ /* Must be on for sd_multiblock to be effective */ bool use_client_ints; /* If this is false, make sure to restore */ int sd_mode; /* SD1/SD4/SPI */ int client_block_size[SDIOD_MAX_IOFUNCS]; /* Blocksize */ uint8 num_funcs; /* Supported funcs on client */ uint32 com_cis_ptr; - uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; + uint32 func_cis_ptr[SDIOD_MAX_IOFUNCS]; #define SDIOH_SDMMC_MAX_SG_ENTRIES 32 struct scatterlist sg_list[SDIOH_SDMMC_MAX_SG_ENTRIES]; bool use_rxchain; + +#ifdef BCMSDIOH_TXGLOM + glom_buf_t glom_info; /* pkt information used for glomming */ + uint txglom_mode; /* Txglom mode: 0 - copy, 1 - multi-descriptor */ +#endif }; /************************************************************ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h index 80c0a3d..1fc37f9 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdpcm.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdpcm.h 291086 2011-10-21 01:17:24Z $ + * $Id: bcmsdpcm.h 364353 2012-10-23 20:31:46Z $ */ #ifndef _bcmsdpcm_h_ @@ -146,16 +146,23 @@ #define SDPCM_GLOMDESC(p) (((uint8 *)p)[1] & 0x80) /* For TEST_CHANNEL packets, define another 4-byte header */ -#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); - * Semantics of Ext byte depend on command. - * Len is current or requested frame length, not - * including test header; sent little-endian. - */ -#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ -#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ -#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ -#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count */ -#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off */ +#define SDPCM_TEST_HDRLEN 4 /* Generally: Cmd(1), Ext(1), Len(2); + * Semantics of Ext byte depend on command. + * Len is current or requested frame length, not + * including test header; sent little-endian. + */ +#define SDPCM_TEST_PKT_CNT_FLD_LEN 4 /* Packet count filed legth */ +#define SDPCM_TEST_DISCARD 0x01 /* Receiver discards. Ext is a pattern id. */ +#define SDPCM_TEST_ECHOREQ 0x02 /* Echo request. Ext is a pattern id. */ +#define SDPCM_TEST_ECHORSP 0x03 /* Echo response. Ext is a pattern id. */ +#define SDPCM_TEST_BURST 0x04 /* Receiver to send a burst. Ext is a frame count + * (Backward compatabilty) Set frame count in a + * 4 byte filed adjacent to the HDR + */ +#define SDPCM_TEST_SEND 0x05 /* Receiver sets send mode. Ext is boolean on/off + * Set frame count in a 4 byte filed adjacent to + * the HDR + */ /* Handy macro for filling in datagen packets with a pattern */ #define SDPCM_TEST_FILL(byteno, id) ((uint8)(id + byteno)) diff --git a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h index 896686c..2b5adf1 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsdstd.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsdstd.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsdstd.h 347614 2012-07-27 10:24:51Z $ + * $Id: bcmsdstd.h 343301 2012-07-06 13:07:32Z $ */ #ifndef _BCM_SD_STD_H #define _BCM_SD_STD_H diff --git a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h index d94e9e4..a3e9b49 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h +++ b/drivers/net/wireless/bcmdhd/include/bcmspibrcm.h @@ -1,168 +1,168 @@ -/*
- * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer
- *
- * Copyright (C) 1999-2012, Broadcom Corporation
- *
- * Unless you and Broadcom execute a separate written software license
- * agreement governing use of this software, this software is licensed to you
- * under the terms of the GNU General Public License version 2 (the "GPL"),
- * available at http://www.broadcom.com/licenses/GPLv2.php, with the
- * following added to such license:
- *
- * As a special exception, the copyright holders of this software give you
- * permission to link this software with independent modules, and to copy and
- * distribute the resulting executable under terms of your choice, provided that
- * you also meet, for each linked independent module, the terms and conditions of
- * the license of that module. An independent module is a module which is not
- * derived from this software. The special exception does not apply to any
- * modifications of the software.
- *
- * Notwithstanding the above, under no circumstances may you combine this
- * software in any way with any other Broadcom software provided under a license
- * other than the GPL, without Broadcom's express prior written consent.
- *
- * $Id: bcmspibrcm.h 354176 2012-08-30 07:34:33Z $
- */
-#ifndef _BCM_SPI_BRCM_H
-#define _BCM_SPI_BRCM_H
-
-#ifndef SPI_MAX_IOFUNCS
-/* Maximum number of I/O funcs */
-#define SPI_MAX_IOFUNCS 4
-#endif
-/* global msglevel for debug messages - bitvals come from sdiovar.h */
-
-#if defined(DHD_DEBUG)
-#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0)
-#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0)
-#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0)
-#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0)
-#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0)
-#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0)
-#else
-#define sd_err(x)
-#define sd_trace(x)
-#define sd_info(x)
-#define sd_debug(x)
-#define sd_data(x)
-#define sd_ctrl(x)
-#endif
-
-#define sd_log(x)
-
-#define SDIOH_ASSERT(exp) \
- do { if (!(exp)) \
- printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \
- } while (0)
-
-#define BLOCK_SIZE_F1 64
-#define BLOCK_SIZE_F2 2048
-#define BLOCK_SIZE_F3 2048
-
-/* internal return code */
-#define SUCCESS 0
-#undef ERROR
-#define ERROR 1
-#define ERROR_UF 2
-#define ERROR_OF 3
-
-/* private bus modes */
-#define SDIOH_MODE_SPI 0
-
-#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */
-#define USE_MULTIBLOCK 0x4
-
-struct sdioh_info {
- uint cfg_bar; /* pci cfg address for bar */
- uint32 caps; /* cached value of capabilities reg */
-#ifndef BCMSPI_ANDROID
- void *bar0; /* BAR0 for PCI Device */
-#endif /* !BCMSPI_ANDROID */
- osl_t *osh; /* osh handler */
- void *controller; /* Pointer to SPI Controller's private data struct */
-#ifndef BCMSPI_ANDROID
- uint lockcount; /* nest count of spi_lock() calls */
- bool client_intr_enabled; /* interrupt connnected flag */
- bool intr_handler_valid; /* client driver interrupt handler valid */
- sdioh_cb_fn_t intr_handler; /* registered interrupt handler */
- void *intr_handler_arg; /* argument to call interrupt handler */
-#endif /* !BCMSPI_ANDROID */
- bool initialized; /* card initialized */
- uint32 target_dev; /* Target device ID */
- uint32 intmask; /* Current active interrupts */
-#ifndef BCMSPI_ANDROID
- void *sdos_info; /* Pointer to per-OS private data */
-#endif /* !BCMSPI_ANDROID */
- uint32 controller_type; /* Host controller type */
- uint8 version; /* Host Controller Spec Compliance Version */
- uint irq; /* Client irq */
- uint32 intrcount; /* Client interrupts */
- uint32 local_intrcount; /* Controller interrupts */
- bool host_init_done; /* Controller initted */
- bool card_init_done; /* Client SDIO interface initted */
- bool polled_mode; /* polling for command completion */
-
- bool sd_use_dma; /* DMA on CMD53 */
- bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */
- /* Must be on for sd_multiblock to be effective */
- bool use_client_ints; /* If this is false, make sure to restore */
- /* polling hack in wl_linux.c:wl_timer() */
- int adapter_slot; /* Maybe dealing with multiple slots/controllers */
- int sd_mode; /* SD1/SD4/SPI */
- int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */
- uint32 data_xfer_count; /* Current transfer */
- uint16 card_rca; /* Current Address */
- uint8 num_funcs; /* Supported funcs on client */
- uint32 card_dstatus; /* 32bit device status */
- uint32 com_cis_ptr;
- uint32 func_cis_ptr[SPI_MAX_IOFUNCS];
- void *dma_buf;
- ulong dma_phys;
- int r_cnt; /* rx count */
- int t_cnt; /* tx_count */
- uint32 wordlen; /* host processor 16/32bits */
- uint32 prev_fun;
- uint32 chip;
- uint32 chiprev;
- bool resp_delay_all;
- bool dwordmode;
- bool resp_delay_new;
-
- struct spierrstats_t spierrstats;
-};
-
-/************************************************************
- * Internal interfaces: per-port references into bcmspibrcm.c
- */
-
-/* Global message bits */
-extern uint sd_msglevel;
-
-/**************************************************************
- * Internal interfaces: bcmspibrcm.c references to per-port code
- */
-
-/* Interrupt (de)registration routines */
-extern int spi_register_irq(sdioh_info_t *sd, uint irq);
-extern void spi_free_irq(uint irq, sdioh_info_t *sd);
-
-/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */
-extern void spi_lock(sdioh_info_t *sd);
-extern void spi_unlock(sdioh_info_t *sd);
-
-/* Allocate/init/free per-OS private data */
-extern int spi_osinit(sdioh_info_t *sd);
-extern void spi_osfree(sdioh_info_t *sd);
-
-#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */
-#define SPI_RW_FLAG_S 31
-#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */
-#define SPI_ACCESS_S 30
-#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */
-#define SPI_FUNCTION_S 28
-#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */
-#define SPI_REG_ADDR_S 11
-#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */
-#define SPI_LEN_S 0
-
-#endif /* _BCM_SPI_BRCM_H */
+/* + * SD-SPI Protocol Conversion - BCMSDH->gSPI Translation Layer + * + * Copyright (C) 1999-2012, Broadcom Corporation + * + * Unless you and Broadcom execute a separate written software license + * agreement governing use of this software, this software is licensed to you + * under the terms of the GNU General Public License version 2 (the "GPL"), + * available at http://www.broadcom.com/licenses/GPLv2.php, with the + * following added to such license: + * + * As a special exception, the copyright holders of this software give you + * permission to link this software with independent modules, and to copy and + * distribute the resulting executable under terms of your choice, provided that + * you also meet, for each linked independent module, the terms and conditions of + * the license of that module. An independent module is a module which is not + * derived from this software. The special exception does not apply to any + * modifications of the software. + * + * Notwithstanding the above, under no circumstances may you combine this + * software in any way with any other Broadcom software provided under a license + * other than the GPL, without Broadcom's express prior written consent. + * + * $Id: bcmspibrcm.h 358377 2012-09-23 11:30:22Z $ + */ +#ifndef _BCM_SPI_BRCM_H +#define _BCM_SPI_BRCM_H + +#ifndef SPI_MAX_IOFUNCS +/* Maximum number of I/O funcs */ +#define SPI_MAX_IOFUNCS 4 +#endif +/* global msglevel for debug messages - bitvals come from sdiovar.h */ + +#if defined(DHD_DEBUG) +#define sd_err(x) do { if (sd_msglevel & SDH_ERROR_VAL) printf x; } while (0) +#define sd_trace(x) do { if (sd_msglevel & SDH_TRACE_VAL) printf x; } while (0) +#define sd_info(x) do { if (sd_msglevel & SDH_INFO_VAL) printf x; } while (0) +#define sd_debug(x) do { if (sd_msglevel & SDH_DEBUG_VAL) printf x; } while (0) +#define sd_data(x) do { if (sd_msglevel & SDH_DATA_VAL) printf x; } while (0) +#define sd_ctrl(x) do { if (sd_msglevel & SDH_CTRL_VAL) printf x; } while (0) +#else +#define sd_err(x) +#define sd_trace(x) +#define sd_info(x) +#define sd_debug(x) +#define sd_data(x) +#define sd_ctrl(x) +#endif + +#define sd_log(x) + +#define SDIOH_ASSERT(exp) \ + do { if (!(exp)) \ + printf("!!!ASSERT fail: file %s lines %d", __FILE__, __LINE__); \ + } while (0) + +#define BLOCK_SIZE_F1 64 +#define BLOCK_SIZE_F2 2048 +#define BLOCK_SIZE_F3 2048 + +/* internal return code */ +#define SUCCESS 0 +#undef ERROR +#define ERROR 1 +#define ERROR_UF 2 +#define ERROR_OF 3 + +/* private bus modes */ +#define SDIOH_MODE_SPI 0 + +#define USE_BLOCKMODE 0x2 /* Block mode can be single block or multi */ +#define USE_MULTIBLOCK 0x4 + +struct sdioh_info { + uint cfg_bar; /* pci cfg address for bar */ + uint32 caps; /* cached value of capabilities reg */ +#ifndef BCMSPI_ANDROID + void *bar0; /* BAR0 for PCI Device */ +#endif /* !BCMSPI_ANDROID */ + osl_t *osh; /* osh handler */ + void *controller; /* Pointer to SPI Controller's private data struct */ +#ifndef BCMSPI_ANDROID + uint lockcount; /* nest count of spi_lock() calls */ + bool client_intr_enabled; /* interrupt connnected flag */ + bool intr_handler_valid; /* client driver interrupt handler valid */ + sdioh_cb_fn_t intr_handler; /* registered interrupt handler */ + void *intr_handler_arg; /* argument to call interrupt handler */ +#endif /* !BCMSPI_ANDROID */ + bool initialized; /* card initialized */ + uint32 target_dev; /* Target device ID */ + uint32 intmask; /* Current active interrupts */ +#ifndef BCMSPI_ANDROID + void *sdos_info; /* Pointer to per-OS private data */ +#endif /* !BCMSPI_ANDROID */ + uint32 controller_type; /* Host controller type */ + uint8 version; /* Host Controller Spec Compliance Version */ + uint irq; /* Client irq */ + uint32 intrcount; /* Client interrupts */ + uint32 local_intrcount; /* Controller interrupts */ + bool host_init_done; /* Controller initted */ + bool card_init_done; /* Client SDIO interface initted */ + bool polled_mode; /* polling for command completion */ + + bool sd_use_dma; /* DMA on CMD53 */ + bool sd_blockmode; /* sd_blockmode == FALSE => 64 Byte Cmd 53s. */ + /* Must be on for sd_multiblock to be effective */ + bool use_client_ints; /* If this is false, make sure to restore */ + /* polling hack in wl_linux.c:wl_timer() */ + int adapter_slot; /* Maybe dealing with multiple slots/controllers */ + int sd_mode; /* SD1/SD4/SPI */ + int client_block_size[SPI_MAX_IOFUNCS]; /* Blocksize */ + uint32 data_xfer_count; /* Current transfer */ + uint16 card_rca; /* Current Address */ + uint8 num_funcs; /* Supported funcs on client */ + uint32 card_dstatus; /* 32bit device status */ + uint32 com_cis_ptr; + uint32 func_cis_ptr[SPI_MAX_IOFUNCS]; + void *dma_buf; + ulong dma_phys; + int r_cnt; /* rx count */ + int t_cnt; /* tx_count */ + uint32 wordlen; /* host processor 16/32bits */ + uint32 prev_fun; + uint32 chip; + uint32 chiprev; + bool resp_delay_all; + bool dwordmode; + bool resp_delay_new; + + struct spierrstats_t spierrstats; +}; + +/************************************************************ + * Internal interfaces: per-port references into bcmspibrcm.c + */ + +/* Global message bits */ +extern uint sd_msglevel; + +/************************************************************** + * Internal interfaces: bcmspibrcm.c references to per-port code + */ + +/* Interrupt (de)registration routines */ +extern int spi_register_irq(sdioh_info_t *sd, uint irq); +extern void spi_free_irq(uint irq, sdioh_info_t *sd); + +/* OS-specific interrupt wrappers (atomic interrupt enable/disable) */ +extern void spi_lock(sdioh_info_t *sd); +extern void spi_unlock(sdioh_info_t *sd); + +/* Allocate/init/free per-OS private data */ +extern int spi_osinit(sdioh_info_t *sd); +extern void spi_osfree(sdioh_info_t *sd); + +#define SPI_RW_FLAG_M BITFIELD_MASK(1) /* Bit [31] - R/W Command Bit */ +#define SPI_RW_FLAG_S 31 +#define SPI_ACCESS_M BITFIELD_MASK(1) /* Bit [30] - Fixed/Incr Access */ +#define SPI_ACCESS_S 30 +#define SPI_FUNCTION_M BITFIELD_MASK(2) /* Bit [29:28] - Function Number */ +#define SPI_FUNCTION_S 28 +#define SPI_REG_ADDR_M BITFIELD_MASK(17) /* Bit [27:11] - Address */ +#define SPI_REG_ADDR_S 11 +#define SPI_LEN_M BITFIELD_MASK(11) /* Bit [10:0] - Packet length */ +#define SPI_LEN_S 0 + +#endif /* _BCM_SPI_BRCM_H */ diff --git a/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h b/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h index f5246a5..0347674 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsrom_fmt.h 327439 2012-04-13 17:44:48Z $ + * $Id: bcmsrom_fmt.h 361510 2012-10-09 00:15:04Z $ */ #ifndef _bcmsrom_fmt_h_ @@ -43,6 +43,7 @@ #define SROM3_SWRGN_OFF 28 /* s/w region offset in words */ #define SROM_SSID 2 +#define SROM_SVID 3 #define SROM_WL1LHMAXP 29 @@ -452,6 +453,7 @@ #define SROM11_THERMAL 87 #define SROM11_MPWR_RAWTS 88 #define SROM11_TS_SLP_OPT_CORRX 89 +#define SROM11_XTAL_FREQ 90 #define SROM11_PHYCAL_TEMPDELTA 92 #define SROM11_MPWR_1_AND_2 93 @@ -465,6 +467,16 @@ #define SROM11_TEMPSENSE_OPTION_MASK 0x3 #define SROM11_TEMPSENSE_OPTION_SHIFT 0 +#define SROM11_PDOFF_2G_40M_A0_MASK 0x000f +#define SROM11_PDOFF_2G_40M_A0_SHIFT 0 +#define SROM11_PDOFF_2G_40M_A1_MASK 0x00f0 +#define SROM11_PDOFF_2G_40M_A1_SHIFT 4 +#define SROM11_PDOFF_2G_40M_A2_MASK 0x0f00 +#define SROM11_PDOFF_2G_40M_A2_SHIFT 8 +#define SROM11_PDOFF_2G_40M_VALID_MASK 0x8000 +#define SROM11_PDOFF_2G_40M_VALID_SHIFT 15 + +#define SROM11_PDOFF_2G_40M 100 #define SROM11_PDOFF_40M_A0 101 #define SROM11_PDOFF_40M_A1 102 #define SROM11_PDOFF_40M_A2 103 @@ -533,25 +545,23 @@ #define SROM11_MCSBW405GLPO_1 179 #define SROM11_MCSBW805GLPO 180 #define SROM11_MCSBW805GLPO_1 181 -#define SROM11_MCSBW1605GLPO 182 -#define SROM11_MCSBW1605GLPO_1 183 +#define SROM11_RPCAL_2G 182 +#define SROM11_RPCAL_5GL 183 #define SROM11_MCSBW205GMPO 184 #define SROM11_MCSBW205GMPO_1 185 #define SROM11_MCSBW405GMPO 186 #define SROM11_MCSBW405GMPO_1 187 #define SROM11_MCSBW805GMPO 188 #define SROM11_MCSBW805GMPO_1 189 -#define SROM11_MCSBW1605GMPO 190 -#define SROM11_MCSBW1605GMPO_1 191 +#define SROM11_RPCAL_5GM 190 +#define SROM11_RPCAL_5GH 191 #define SROM11_MCSBW205GHPO 192 #define SROM11_MCSBW205GHPO_1 193 #define SROM11_MCSBW405GHPO 194 #define SROM11_MCSBW405GHPO_1 195 #define SROM11_MCSBW805GHPO 196 #define SROM11_MCSBW805GHPO_1 197 -#define SROM11_MCSBW1605GHPO 198 -#define SROM11_MCSBW1605GHPO_1 199 - +#define SROM11_RPCAL_5GU 198 #define SROM11_MCSLR5GLPO 200 #define SROM11_MCSLR5GMPO 201 #define SROM11_MCSLR5GHPO 202 diff --git a/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h b/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h index 040ae6a..cb49421 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h +++ b/drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmsrom_tbl.h 327694 2012-04-16 13:22:24Z $ + * $Id: bcmsrom_tbl.h 368874 2012-11-15 02:39:03Z $ */ #ifndef _bcmsrom_tbl_h_ @@ -65,7 +65,11 @@ typedef struct { */ static const sromvar_t pci_sromvars[] = { +#if defined(CABLECPE) + {"devid", 0xffffff00, SRFL_PRHEX, PCI_F0DEVID, 0xffff}, +#else {"devid", 0xffffff00, SRFL_PRHEX|SRFL_NOVAR, PCI_F0DEVID, 0xffff}, +#endif {"boardrev", 0x0000000e, SRFL_PRHEX, SROM_AABREV, SROM_BR_MASK}, {"boardrev", 0x000000f0, SRFL_PRHEX, SROM4_BREV, 0xffff}, {"boardrev", 0xffffff00, SRFL_PRHEX, SROM8_BREV, 0xffff}, @@ -87,7 +91,7 @@ static const sromvar_t pci_sromvars[] = { {"boardflags2", 0xffffff00, SRFL_PRHEX|SRFL_MORE, SROM8_BFL2, 0xffff}, {"", 0, 0, SROM8_BFL3, 0xffff}, {"boardtype", 0xfffffffc, SRFL_PRHEX, SROM_SSID, 0xffff}, - + {"subvid", 0xfffffffc, SRFL_PRHEX, SROM_SVID, 0xffff}, {"boardnum", 0x00000006, 0, SROM_MACLO_IL0, 0xffff}, {"boardnum", 0x00000008, 0, SROM3_MACLO, 0xffff}, {"boardnum", 0x00000010, 0, SROM4_MACLO, 0xffff}, @@ -446,8 +450,8 @@ static const sromvar_t pci_sromvars[] = { {"", 0x00000400, SRFL_PRHEX, SROM10_SWCTRLMAP_2G + 8, 0xffff}, /* sromrev 11 */ - {"boardflags3", 0xfffff800, SRFL_PRHEX|SRFL_MORE, SROM11_BFL3, 0xffff}, - {"", 0, 0, SROM11_BFL3, 0xffff}, + {"boardflags3", 0xfffff800, SRFL_PRHEX|SRFL_MORE, SROM11_BFL4, 0xffff}, + {"", 0, 0, SROM11_BFL5, 0xffff}, {"boardnum", 0xfffff800, 0, SROM11_MACLO, 0xffff}, {"macaddr", 0xfffff800, SRFL_ETHADDR, SROM11_MACHI, 0xffff}, {"ccode", 0xfffff800, SRFL_CCODE, SROM11_CCODE, 0xffff}, @@ -459,12 +463,12 @@ static const sromvar_t pci_sromvars[] = { {"leddc", 0xfffff800, SRFL_NOFFS|SRFL_LEDDC, SROM11_LEDDC, 0xffff}, {"aa2g", 0xfffff800, 0, SROM11_AA, 0x00ff}, {"aa5g", 0xfffff800, 0, SROM11_AA, 0xff00}, - {"agbg0", 0xfffff800, 0, SROM11_AGBG10, 0x00ff}, - {"agbg1", 0xfffff800, 0, SROM11_AGBG10, 0xff00}, - {"agbg2", 0xfffff800, 0, SROM11_AGBG2A0, 0x00ff}, - {"aga0", 0xfffff800, 0, SROM11_AGBG2A0, 0xff00}, - {"aga1", 0xfffff800, 0, SROM11_AGA21, 0x00ff}, - {"aga2", 0xfffff800, 0, SROM11_AGA21, 0xff00}, + {"agbg0", 0xfffff800, 0, SROM11_AGBG10, 0xff00}, + {"agbg1", 0xfffff800, 0, SROM11_AGBG10, 0x00ff}, + {"agbg2", 0xfffff800, 0, SROM11_AGBG2A0, 0xff00}, + {"aga0", 0xfffff800, 0, SROM11_AGBG2A0, 0x00ff}, + {"aga1", 0xfffff800, 0, SROM11_AGA21, 0xff00}, + {"aga2", 0xfffff800, 0, SROM11_AGA21, 0x00ff}, {"txchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_TXCHAIN_MASK}, {"rxchain", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_RXCHAIN_MASK}, {"antswitch", 0xfffff800, SRFL_NOFFS, SROM11_TXRXC, SROM4_SWITCH_MASK}, @@ -490,11 +494,17 @@ static const sromvar_t pci_sromvars[] = { {"tempsense_slope", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x00ff}, {"tempcorrx", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0xfc00}, {"tempsense_option", 0xfffff800, SRFL_PRHEX, SROM11_TS_SLP_OPT_CORRX, 0x0300}, + {"xtalfreq", 0xfffff800, 0, SROM11_XTAL_FREQ, 0xffff}, {"phycal_tempdelta", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x00ff}, {"temps_period", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0x0f00}, {"temps_hysteresis", 0xfffff800, 0, SROM11_PHYCAL_TEMPDELTA, 0xf000}, {"measpower1", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x007f}, {"measpower2", 0xfffff800, SRFL_PRHEX, SROM11_MPWR_1_AND_2, 0x3f80}, + + {"pdoffset2g40ma0", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x000f}, + {"pdoffset2g40ma1", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x00f0}, + {"pdoffset2g40ma2", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x0f00}, + {"pdoffset2g40mvalid", 0xfffff800, 0, SROM11_PDOFF_2G_40M, 0x8000}, {"pdoffset40ma0", 0xfffff800, 0, SROM11_PDOFF_40M_A0, 0xffff}, {"pdoffset40ma1", 0xfffff800, 0, SROM11_PDOFF_40M_A1, 0xffff}, {"pdoffset40ma2", 0xfffff800, 0, SROM11_PDOFF_40M_A2, 0xffff}, @@ -519,28 +529,22 @@ static const sromvar_t pci_sromvars[] = { {"", 0xfffff800, 0, SROM11_MCSBW405GLPO_1, 0xffff}, {"mcsbw805glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GLPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW805GLPO_1, 0xffff}, - {"mcsbw1605glpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GLPO, 0xffff}, - {"", 0xfffff800, 0, SROM11_MCSBW1605GLPO_1, 0xffff}, {"mcsbw205gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GMPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW205GMPO_1, 0xffff}, {"mcsbw405gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GMPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW405GMPO_1, 0xffff}, {"mcsbw805gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GMPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW805GMPO_1, 0xffff}, - {"mcsbw1605gmpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GMPO, 0xffff}, - {"", 0xfffff800, 0, SROM11_MCSBW1605GMPO_1, 0xffff}, {"mcsbw205ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW205GHPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW205GHPO_1, 0xffff}, {"mcsbw405ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW405GHPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW405GHPO_1, 0xffff}, {"mcsbw805ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW805GHPO, 0xffff}, {"", 0xfffff800, 0, SROM11_MCSBW805GHPO_1, 0xffff}, - {"mcsbw1605ghpo", 0xfffff800, SRFL_MORE, SROM11_MCSBW1605GHPO, 0xffff}, - {"", 0xfffff800, 0, SROM11_MCSBW1605GHPO_1, 0xffff}, {"mcslr5glpo", 0xfffff800, 0, SROM11_MCSLR5GLPO, 0xffff}, {"mcslr5gmpo", 0xfffff800, 0, SROM11_MCSLR5GMPO, 0xffff}, {"mcslr5ghpo", 0xfffff800, 0, SROM11_MCSLR5GHPO, 0xffff}, - {"sb20in40hrrpo", 0xfffff800, 0, SROM11_SB20IN40HRPO, 0xffff}, + {"sb20in40hrpo", 0xfffff800, 0, SROM11_SB20IN40HRPO, 0xffff}, {"sb20in80and160hr5glpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GLPO, 0xffff}, {"sb40and80hr5glpo", 0xfffff800, 0, SROM11_SB40AND80HR5GLPO, 0xffff}, {"sb20in80and160hr5gmpo", 0xfffff800, 0, SROM11_SB20IN80AND160HR5GMPO, 0xffff}, @@ -558,7 +562,6 @@ static const sromvar_t pci_sromvars[] = { {"dot11agduplrpo", 0xfffff800, 0, SROM11_DOT11AGDUPLRPO, 0xffff}, /* Misc */ - {"pcieingress_war", 0xfffff800, 0, SROM11_PCIEINGRESS_WAR, 0xf}, {"sar2g", 0xfffff800, 0, SROM11_SAR, 0x00ff}, {"sar5g", 0xfffff800, 0, SROM11_SAR, 0xff00}, @@ -593,6 +596,11 @@ static const sromvar_t pci_sromvars[] = { {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GM, 0xf800}, {"", 0xfffff800, SRFL_ARRAY, SROM11_RXGAINERR_5GH, 0xf800}, {"", 0xfffff800, 0, SROM11_RXGAINERR_5GU, 0xf800}, + {"rpcal2g", 0xfffff800, 0, SROM11_RPCAL_2G, 0xffff}, + {"rpcal5gb0", 0xfffff800, 0, SROM11_RPCAL_5GL, 0xffff}, + {"rpcal5gb1", 0xfffff800, 0, SROM11_RPCAL_5GM, 0xffff}, + {"rpcal5gb2", 0xfffff800, 0, SROM11_RPCAL_5GH, 0xffff}, + {"rpcal5gb3", 0xfffff800, 0, SROM11_RPCAL_5GU, 0xffff}, {NULL, 0, 0, 0, 0} }; @@ -786,7 +794,8 @@ static const cis_tuple_t cis_hnbuvars[] = { {HNBU_AA, 0xffffffff, 3, "1aa0 1aa1"}, /* backward compatibility */ {HNBU_AG, 0xffffffff, 5, "1ag0 1ag1 1ag2 1ag3"}, {HNBU_BOARDFLAGS, 0xffffffff, 13, "4boardflags 4boardflags2 4boardflags3"}, - {HNBU_LEDS, 0xffffffff, 5, "1ledbh0 1ledbh1 1ledbh2 1ledbh3"}, + {HNBU_LEDS, 0xffffffff, 13, "1ledbh0 1ledbh1 1ledbh2 1ledbh3 1ledbh4 1ledbh5 " + "1ledbh6 1ledbh7 1ledbh8 1ledbh9 1ledbh10 1ledbh11"}, {HNBU_CCODE, 0xffffffff, 4, "2ccode 1cctl"}, {HNBU_CCKPO, 0xffffffff, 3, "2cckpo"}, {HNBU_OFDMPO, 0xffffffff, 5, "4ofdmpo"}, @@ -869,8 +878,8 @@ static const cis_tuple_t cis_hnbuvars[] = { "2pdoffset80ma0 2pdoffset80ma1 2pdoffset80ma2"}, {HNBU_ACPPR_2GPO, 0xfffff800, 5, "2dot11agofdmhrbw202gpo 2ofdmlrbw202gpo"}, {HNBU_ACPPR_5GPO, 0xfffff800, 31, "4mcsbw805glpo 4mcsbw1605glpo 4mcsbw805gmpo " - "4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5rlpo 2mcslr5gmpo 2mcslr5ghpo"}, - {HNBU_ACPPR_SBPO, 0xfffff800, 33, "2sb20in40hrrpo 2sb20in80and160hr5glpo " + "4mcsbw1605gmpo 4mcsbw805ghpo 4mcsbw1605ghpo 2mcslr5glpo 2mcslr5gmpo 2mcslr5ghpo"}, + {HNBU_ACPPR_SBPO, 0xfffff800, 33, "2sb20in40hrpo 2sb20in80and160hr5glpo " "2sb40and80hr5glpo 2sb20in80and160hr5gmpo 2sb40and80hr5gmpo 2sb20in80and160hr5ghpo " "2sb40and80hr5ghpo 2sb20in40lrpo 2sb20in80and160lr5glpo 2sb40and80lr5glpo " "2sb20in80and160lr5gmpo 2sb40and80lr5gmpo 2sb20in80and160lr5ghpo 2sb40and80lr5ghpo " @@ -894,6 +903,10 @@ static const cis_tuple_t cis_hnbuvars[] = { "0rxgains5gelnagaina2 0rxgains2gtrelnabypa2 0rxgains2gtrisoa2 0rxgains2gelnagaina2 " "0rxgains5ghtrelnabypa2 0rxgains5ghtrisoa2 0rxgains5ghelnagaina2 0rxgains5gmtrelnabypa2 " "0rxgains5gmtrisoa2 0rxgains5gmelnagaina2"}, /* special case */ + {HNBU_TXDUTY, 0xfffff800, 9, "2tx_duty_cycle_ofdm_40_5g " + "2tx_duty_cycle_thresh_40_5g 2tx_duty_cycle_ofdm_80_5g 2tx_duty_cycle_thresh_80_5g"}, + {HNBU_PDOFF_2G, 0xfffff800, 3, "0pdoffset2g40ma0 0pdoffset2g40ma1 " + "0pdoffset2g40ma2 0pdoffset2g40mvalid"}, {0xFF, 0xffffffff, 0, ""} }; diff --git a/drivers/net/wireless/bcmdhd/include/bcmutils.h b/drivers/net/wireless/bcmdhd/include/bcmutils.h index cbbd7ef..1b21327 100644 --- a/drivers/net/wireless/bcmdhd/include/bcmutils.h +++ b/drivers/net/wireless/bcmdhd/include/bcmutils.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: bcmutils.h 354184 2012-08-30 08:08:08Z $ + * $Id: bcmutils.h 365744 2012-10-30 22:01:29Z $ */ #ifndef _bcmutils_h_ @@ -121,6 +121,8 @@ typedef struct { uint32 max_avail; uint32 max_used; uint32 queue_capacity; + uint32 rtsfail; + uint32 acked; } pktq_counters_t; #endif @@ -137,7 +139,9 @@ struct pktq { struct pktq_prec q[PKTQ_MAX_PREC]; #ifdef PKTQ_LOG - pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; + pktq_counters_t _prec_cnt[PKTQ_MAX_PREC]; + pktq_counters_t _prec_bytes[PKTQ_MAX_PREC]; + uint32 _logtime; #endif }; @@ -289,6 +293,7 @@ extern void *pktq_penq(struct pktq *pq, int prec, void *p); extern void *pktq_penq_head(struct pktq *pq, int prec, void *p); extern void *pktq_pdeq(struct pktq *pq, int prec); extern void *pktq_pdeq_prev(struct pktq *pq, int prec, void *prev_p); +extern void *pktq_pdeq_with_fn(struct pktq *pq, int prec, ifpkt_cb_t fn, int arg); extern void *pktq_pdeq_tail(struct pktq *pq, int prec); extern void pktq_pflush(osl_t *osh, struct pktq *pq, int prec, bool dir, @@ -335,7 +340,8 @@ extern uint pkttotlen(osl_t *osh, void *p); extern void *pktlast(osl_t *osh, void *p); extern uint pktsegcnt(osl_t *osh, void *p); extern uint pktsegcnt_war(osl_t *osh, void *p); -extern uint8 *pktoffset(osl_t *osh, void *p, uint offset); +extern uint8 *pktdataoffset(osl_t *osh, void *p, uint offset); +extern void *pktoffset(osl_t *osh, void *p, uint offset); #define PKTPRIO_VDSCP 0x100 @@ -568,6 +574,24 @@ extern int bcm_format_ssid(char* buf, const uchar ssid[], uint ssid_len); #define MAX(a, b) (((a) > (b)) ? (a) : (b)) #endif + +#ifndef LIMIT_TO_RANGE +#define LIMIT_TO_RANGE(x, min, max) \ + ((x) < (min) ? (min) : ((x) > (max) ? (max) : (x))) +#endif + + +#ifndef LIMIT_TO_MAX +#define LIMIT_TO_MAX(x, max) \ + (((x) > (max) ? (max) : (x))) +#endif + + +#ifndef LIMIT_TO_MIN +#define LIMIT_TO_MIN(x, min) \ + (((x) < (min) ? (min) : (x))) +#endif + #define CEIL(x, y) (((x) + ((y) - 1)) / (y)) #define ROUNDUP(x, y) ((((x) + ((y) - 1)) / (y)) * (y)) #define ISALIGNED(a, x) (((uintptr)(a) & ((x) - 1)) == 0) @@ -598,7 +622,7 @@ extern void *_bcmutils_dummy_fn; #ifndef setbit -#ifndef NBBY +#ifndef NBBY #define NBBY 8 #endif #define setbit(a, i) (((uint8 *)a)[(i) / NBBY] |= 1 << ((i) % NBBY)) @@ -607,6 +631,8 @@ extern void *_bcmutils_dummy_fn; #define isclr(a, i) ((((const uint8 *)a)[(i) / NBBY] & (1 << ((i) % NBBY))) == 0) #endif +#define isbitset(a, i) (((a) & (1 << (i))) != 0) + #define NBITS(type) (sizeof(type) * 8) #define NBITVAL(nbits) (1 << (nbits)) #define MAXBITVAL(nbits) ((1 << (nbits)) - 1) @@ -663,7 +689,8 @@ extern void *_bcmutils_dummy_fn; #else #define MACDBG "%02x:%02x:%02x" #define MAC2STRDBG(ea) (ea)[0], (ea)[4], (ea)[5] -#endif /* SIMPLE_MAC_PRINT */ +#endif + typedef struct bcm_bit_desc { uint32 bit; @@ -671,6 +698,13 @@ typedef struct bcm_bit_desc { } bcm_bit_desc_t; +typedef struct bcm_bit_desc_ex { + uint32 mask; + const bcm_bit_desc_t *bitfield; +} bcm_bit_desc_ex_t; + + + typedef struct bcm_tlv { uint8 id; uint8 len; @@ -716,6 +750,9 @@ extern uint32 hndcrc32(uint8 *p, uint nbytes, uint32 crc); #if defined(DHD_DEBUG) || defined(WLMSG_PRHDRS) || defined(WLMSG_PRPKT) || \ defined(WLMSG_ASSOC) + +extern int bcm_format_field(const bcm_bit_desc_ex_t *bd, uint32 field, char* buf, int len); + extern int bcm_format_flags(const bcm_bit_desc_t *bd, uint32 flags, char* buf, int len); #endif @@ -737,7 +774,7 @@ extern bcm_tlv_t *bcm_parse_ordered_tlvs(void *buf, int buflen, uint key); extern const char *bcmerrorstr(int bcmerror); -extern bcm_tlv_t *bcm_parse_tlvs(void *buf, int buflen, uint key); + typedef uint32 mbool; diff --git a/drivers/net/wireless/bcmdhd/include/dbus.h b/drivers/net/wireless/bcmdhd/include/dbus.h index c5ea223..9784e1f 100644 --- a/drivers/net/wireless/bcmdhd/include/dbus.h +++ b/drivers/net/wireless/bcmdhd/include/dbus.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dbus.h 323680 2012-03-26 17:52:31Z $ + * $Id: dbus.h 349214 2012-08-07 10:04:38Z $ */ #ifndef __DBUS_H__ @@ -33,7 +33,6 @@ #define DBUSTRACE(args) #define DBUSERR(args) #define DBUSINFO(args) -#define DBUSTRACE(args) #define DBUSDBGLOCK(args) enum { @@ -77,8 +76,8 @@ enum { #define DBUS_TX_RETRY_LIMIT 3 /* retries for failed txirb */ #define DBUS_TX_TIMEOUT_INTERVAL 250 /* timeout for txirb complete, in ms */ -#define DBUS_BUFFER_SIZE_TX 16000 -#define DBUS_BUFFER_SIZE_RX 5000 +#define DBUS_BUFFER_SIZE_TX 32000 +#define DBUS_BUFFER_SIZE_RX 24000 #define DBUS_BUFFER_SIZE_TX_NOAGG 2048 #define DBUS_BUFFER_SIZE_RX_NOAGG 2048 @@ -296,7 +295,6 @@ 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_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); diff --git a/drivers/net/wireless/bcmdhd/include/dhdioctl.h b/drivers/net/wireless/bcmdhd/include/dhdioctl.h index 11fff55..53bab2c 100644 --- a/drivers/net/wireless/bcmdhd/include/dhdioctl.h +++ b/drivers/net/wireless/bcmdhd/include/dhdioctl.h @@ -25,7 +25,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: dhdioctl.h 354894 2012-09-04 12:34:07Z $ + * $Id: dhdioctl.h 358413 2012-09-24 04:50:47Z $ */ #ifndef _dhdioctl_h_ @@ -93,7 +93,8 @@ enum { #define DHD_ARPOE_VAL 0x4000 #define DHD_REORDER_VAL 0x8000 #define DHD_WL_VAL 0x10000 -#define DHD_WL_VAL2 0x20000 +#define DHD_NOCHECKDIED_VAL 0x20000 /* UTF WAR */ +#define DHD_WL_VAL2 0x40000 #ifdef SDTEST /* For pktgen iovar */ diff --git a/drivers/net/wireless/bcmdhd/include/epivers.h b/drivers/net/wireless/bcmdhd/include/epivers.h index 60f9838..12470ad 100644 --- a/drivers/net/wireless/bcmdhd/include/epivers.h +++ b/drivers/net/wireless/bcmdhd/include/epivers.h @@ -28,28 +28,28 @@ #define EPI_MAJOR_VERSION 1 -#define EPI_MINOR_VERSION 28 +#define EPI_MINOR_VERSION 61 -#define EPI_RC_NUMBER 13 +#define EPI_RC_NUMBER 47 -#define EPI_INCREMENTAL_NUMBER 1 +#define EPI_INCREMENTAL_NUMBER 0 #define EPI_BUILD_NUMBER 0 -#define EPI_VERSION 1, 28, 13, 1 +#define EPI_VERSION 1, 61, 47, 0 -#define EPI_VERSION_NUM 0x011c0d01 +#define EPI_VERSION_NUM 0x013d2f00 -#define EPI_VERSION_DEV 1.28.13 +#define EPI_VERSION_DEV 1.61.47 /* Driver Version String, ASCII, 32 chars max */ #ifdef BCMINTERNAL -#define EPI_VERSION_STR "1.28.13.1 (r BCMINT)" +#define EPI_VERSION_STR "1.61.47 (r BCMINT)" #else #ifdef WLTEST -#define EPI_VERSION_STR "1.28.13.1 (r WLTEST)" +#define EPI_VERSION_STR "1.61.47 (r WLTEST)" #else -#define EPI_VERSION_STR "1.28.13.1 (r)" +#define EPI_VERSION_STR "1.61.47 (r)" #endif #endif /* BCMINTERNAL */ diff --git a/drivers/net/wireless/bcmdhd/include/hndsoc.h b/drivers/net/wireless/bcmdhd/include/hndsoc.h index 66640c3..f5c161b 100644 --- a/drivers/net/wireless/bcmdhd/include/hndsoc.h +++ b/drivers/net/wireless/bcmdhd/include/hndsoc.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: hndsoc.h 309193 2012-01-19 00:03:57Z $ + * $Id: hndsoc.h 365041 2012-10-26 09:10:35Z $ */ #ifndef _HNDSOC_H @@ -46,10 +46,8 @@ #define SI_WRAP_BASE 0x18100000 /* Wrapper space base */ #define SI_CORE_SIZE 0x1000 /* each core gets 4Kbytes for registers */ -#define SI_MAXCORES 16 /* Max cores (this is arbitrary, for software - * convenience and could be changed if we - * make any larger chips - */ + +#define SI_MAXCORES 32 /* NorthStar has more cores */ #define SI_FASTRAM 0x19000000 /* On-chip RAM on chips that also have DDR */ #define SI_FASTRAM_SWAPPED 0x19800000 @@ -59,6 +57,13 @@ #define SI_ARMCM3_ROM 0x1e000000 /* ARM Cortex-M3 ROM */ #define SI_FLASH1 0x1fc00000 /* MIPS Flash Region 1 */ #define SI_FLASH1_SZ 0x00400000 /* MIPS Size of Flash Region 1 */ +#define SI_FLASH_WINDOW 0x01000000 /* Flash XIP Window */ + +#define SI_NS_NANDFLASH 0x1c000000 /* NorthStar NAND flash base */ +#define SI_NS_NORFLASH 0x1e000000 /* NorthStar NOR flash base */ +#define SI_NS_ROM 0xfffd0000 /* NorthStar ROM */ +#define SI_NS_FLASH_WINDOW 0x02000000 /* Flash XIP Window */ + #define SI_ARM7S_ROM 0x20000000 /* ARM7TDMI-S ROM */ #define SI_ARMCR4_ROM 0x000f0000 /* ARM Cortex-R4 ROM */ #define SI_ARMCM3_SRAM2 0x60000000 /* ARM Cortex-M3 SRAM Region 2 */ @@ -147,7 +152,21 @@ */ #define CC_4706_CORE_ID 0x500 /* chipcommon core */ +#define NS_PCIEG2_CORE_ID 0x501 /* PCIE Gen 2 core */ +#define NS_DMA_CORE_ID 0x502 /* DMA core */ +#define NS_SDIO3_CORE_ID 0x503 /* SDIO3 core */ +#define NS_USB20_CORE_ID 0x504 /* USB2.0 core */ +#define NS_USB30_CORE_ID 0x505 /* USB3.0 core */ +#define NS_A9JTAG_CORE_ID 0x506 /* ARM Cortex A9 JTAG core */ +#define NS_DDR23_CORE_ID 0x507 /* Denali DDR2/DDR3 memory controller */ +#define NS_ROM_CORE_ID 0x508 /* ROM core */ +#define NS_NAND_CORE_ID 0x509 /* NAND flash controller core */ +#define NS_QSPI_CORE_ID 0x50a /* SPI flash controller core */ +#define NS_CCB_CORE_ID 0x50b /* ChipcommonB core */ #define SOCRAM_4706_CORE_ID 0x50e /* internal memory core */ +#define NS_SOCRAM_CORE_ID SOCRAM_4706_CORE_ID +#define ARMCA9_CORE_ID 0x510 /* ARM Cortex A9 core (ihost) */ +#define NS_IHOST_CORE_ID ARMCA9_CORE_ID /* ARM Cortex A9 core (ihost) */ #define GMAC_COMMON_4706_CORE_ID 0x5dc /* Gigabit MAC core */ #define GMAC_4706_CORE_ID 0x52d /* Gigabit MAC core */ #define AMEMC_CORE_ID 0x52e /* DDR1/2 memory controller core */ @@ -172,6 +191,7 @@ #define SOCI_SB 0 #define SOCI_AI 1 #define SOCI_UBUS 2 +#define SOCI_NAI 3 /* Common core control flags */ #define SICF_BIST_EN 0x8000 @@ -187,6 +207,14 @@ #define SISF_DMA64 0x1000 #define SISF_CORE_BITS 0x0fff +/* Norstar core status flags */ +#define SISF_NS_BOOTDEV_MASK 0x0003 /* ROM core */ +#define SISF_NS_BOOTDEV_NOR 0x0000 /* ROM core */ +#define SISF_NS_BOOTDEV_NAND 0x0001 /* ROM core */ +#define SISF_NS_BOOTDEV_ROM 0x0002 /* ROM core */ +#define SISF_NS_BOOTDEV_OFFLOAD 0x0003 /* ROM core */ +#define SISF_NS_SKUVEC_MASK 0x000c /* ROM core */ + /* A register that is common to all cores to * communicate w/PMU regarding clock control. */ @@ -232,4 +260,18 @@ #define BISZ_BSSEND_IDX 6 /* 6: bss end */ #define BISZ_SIZE 7 /* descriptor size in 32-bit integers */ +/* Boot/Kernel related defintion and functions */ +#define SOC_BOOTDEV_ROM 0x00000001 +#define SOC_BOOTDEV_PFLASH 0x00000002 +#define SOC_BOOTDEV_SFLASH 0x00000004 +#define SOC_BOOTDEV_NANDFLASH 0x00000008 + +#define SOC_KNLDEV_NORFLASH 0x00000002 +#define SOC_KNLDEV_NANDFLASH 0x00000004 + +#ifndef _LANGUAGE_ASSEMBLY +int soc_boot_dev(void *sih); +int soc_knl_dev(void *sih); +#endif /* _LANGUAGE_ASSEMBLY */ + #endif /* _HNDSOC_H */ diff --git a/drivers/net/wireless/bcmdhd/include/linux_osl.h b/drivers/net/wireless/bcmdhd/include/linux_osl.h index 5fd1dbd..7d6481f 100644 --- a/drivers/net/wireless/bcmdhd/include/linux_osl.h +++ b/drivers/net/wireless/bcmdhd/include/linux_osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.h 352246 2012-08-22 05:42:04Z $ + * $Id: linux_osl.h 388661 2013-03-04 05:50:45Z $ */ #ifndef _linux_osl_h_ @@ -92,7 +92,6 @@ extern struct pci_dev *osl_pci_device(osl_t *osh); typedef struct { bool pkttag; - uint pktalloced; bool mmbus; pktfree_cb_fn_t tx_fn; void *tx_ctx; @@ -139,7 +138,8 @@ extern void osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa); #define DMA_UNMAP(osh, pa, size, direction, p, dmah) \ osl_dma_unmap((osh), (pa), (size), (direction)) -extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction); +extern uint osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, + hnddma_seg_map_t *txp_dmah); extern void osl_dma_unmap(osl_t *osh, uint pa, uint size, int direction); @@ -165,8 +165,11 @@ extern int osl_error(int bcmerror); #include <linuxver.h> #include <linux/kernel.h> #include <linux/string.h> - +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 4, 29) #define OSL_SYSUPTIME() ((uint32)jiffies_to_msecs(jiffies)) +#else +#define OSL_SYSUPTIME() ((uint32)jiffies * (1000 / HZ)) +#endif #define printf(fmt, args...) printk(fmt , ## args) #include <linux/kernel.h> #include <linux/string.h> @@ -218,6 +221,9 @@ extern int osl_error(int bcmerror); #define OSL_UNCACHED(va) ((void *)va) #define OSL_CACHED(va) ((void *)va) + +#define OSL_CACHE_FLUSH(va, len) + #define OSL_PREF_RANGE_LD(va, sz) #define OSL_PREF_RANGE_ST(va, sz) @@ -260,14 +266,14 @@ extern int osl_error(int bcmerror); #define PKTDATA(osh, skb) (((struct sk_buff*)(skb))->data) #define PKTLEN(osh, skb) (((struct sk_buff*)(skb))->len) #define PKTHEADROOM(osh, skb) (PKTDATA(osh, skb)-(((struct sk_buff*)(skb))->head)) -#define PKTTAILROOM(osh, skb) ((((struct sk_buff*)(skb))->end)-(((struct sk_buff*)(skb))->tail)) +#define PKTTAILROOM(osh, skb) skb_tailroom((struct sk_buff*)(skb)) +#define PKTPADTAILROOM(osh, skb, padlen) skb_pad((struct sk_buff*)(skb), (padlen)) #define PKTNEXT(osh, skb) (((struct sk_buff*)(skb))->next) #define PKTSETNEXT(osh, skb, x) (((struct sk_buff*)(skb))->next = (struct sk_buff*)(x)) #define PKTSETLEN(osh, skb, len) __skb_trim((struct sk_buff*)(skb), (len)) #define PKTPUSH(osh, skb, bytes) skb_push((struct sk_buff*)(skb), (bytes)) #define PKTPULL(osh, skb, bytes) skb_pull((struct sk_buff*)(skb), (bytes)) #define PKTTAG(skb) ((void*)(((struct sk_buff*)(skb))->cb)) -#define PKTALLOCED(osh) ((osl_pubinfo_t *)(osh))->pktalloced #define PKTSETPOOL(osh, skb, x, y) do {} while (0) #define PKTPOOL(osh, skb) FALSE #define PKTSHRINK(osh, m) (m) @@ -286,6 +292,18 @@ typedef struct ctfpool { uint slow_allocs; } ctfpool_t; #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +#define FASTBUF (1 << 0) +#define CTFBUF (1 << 1) +#define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= FASTBUF) +#define PKTCLRFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~FASTBUF)) +#define PKTSETCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) |= CTFBUF) +#define PKTCLRCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) &= (~CTFBUF)) +#define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & FASTBUF) +#define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->pktc_flags) & CTFBUF) +#define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->pktc_flags) +#else #define FASTBUF (1 << 16) #define CTFBUF (1 << 17) #define PKTSETFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) |= FASTBUF) @@ -295,6 +313,7 @@ typedef struct ctfpool { #define PKTISFAST(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & FASTBUF) #define PKTISCTF(osh, skb) ((((struct sk_buff*)(skb))->mac_len) & CTFBUF) #define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->mac_len) +#endif #else #define FASTBUF (1 << 0) #define CTFBUF (1 << 1) @@ -307,8 +326,13 @@ typedef struct ctfpool { #define PKTFAST(osh, skb) (((struct sk_buff*)(skb))->__unused) #endif +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +#define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->ctfpool) +#define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->ctfpool)->head) +#else #define CTFPOOLPTR(osh, skb) (((struct sk_buff*)(skb))->sk) #define CTFPOOLHEAD(osh, skb) (((ctfpool_t *)((struct sk_buff*)(skb))->sk)->head) +#endif extern void *osl_ctfpool_add(osl_t *osh); extern void osl_ctfpool_replenish(osl_t *osh, uint thresh); @@ -320,20 +344,45 @@ extern void osl_ctfpool_stats(osl_t *osh, void *b); #ifdef HNDCTF #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 22) + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) +#define SKIPCT (1 << 2) +#define CHAINED (1 << 3) +#define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= SKIPCT) +#define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~SKIPCT)) +#define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->pktc_flags & SKIPCT) +#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags |= CHAINED) +#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->pktc_flags &= (~CHAINED)) +#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->pktc_flags & CHAINED) +#else #define SKIPCT (1 << 18) +#define CHAINED (1 << 19) #define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len |= SKIPCT) #define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~SKIPCT)) #define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->mac_len & SKIPCT) +#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len |= CHAINED) +#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->mac_len &= (~CHAINED)) +#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->mac_len & CHAINED) +#endif #else #define SKIPCT (1 << 2) +#define CHAINED (1 << 3) #define PKTSETSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused |= SKIPCT) #define PKTCLRSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~SKIPCT)) #define PKTSKIPCT(osh, skb) (((struct sk_buff*)(skb))->__unused & SKIPCT) +#define PKTSETCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused |= CHAINED) +#define PKTCLRCHAINED(osh, skb) (((struct sk_buff*)(skb))->__unused &= (~CHAINED)) +#define PKTISCHAINED(skb) (((struct sk_buff*)(skb))->__unused & CHAINED) #endif +typedef struct ctf_mark { + uint32 value; +} ctf_mark_t; +#define CTF_MARK(m) (m.value) #else #define PKTSETSKIPCT(osh, skb) #define PKTCLRSKIPCT(osh, skb) #define PKTSKIPCT(osh, skb) +#define CTF_MARK(m) 0 #endif extern void osl_pktfree(osl_t *osh, void *skb, bool send); @@ -357,8 +406,24 @@ extern struct sk_buff *osl_pkt_tonative(osl_t *osh, void *pkt); #define PKTSHARED(skb) (((struct sk_buff*)(skb))->cloned) +#ifdef CONFIG_NF_CONNTRACK_MARK +#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 0)) +#define PKTMARK(p) (((struct sk_buff *)(p))->mark) +#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->mark = (m) +#else +#define PKTMARK(p) (((struct sk_buff *)(p))->nfmark) +#define PKTSETMARK(p, m) ((struct sk_buff *)(p))->nfmark = (m) +#endif +#else +#define PKTMARK(p) 0 +#define PKTSETMARK(p, m) +#endif + +#define PKTALLOCED(osh) osl_pktalloced(osh) +extern uint osl_pktalloced(osl_t *osh); + #define DMA_MAP(osh, va, size, direction, p, dmah) \ - osl_dma_map((osh), (va), (size), (direction)) + osl_dma_map((osh), (va), (size), (direction), (p), (dmah)) #ifdef PKTC @@ -373,27 +438,47 @@ struct chain_node { #define CHAIN_NODE(skb) ((struct chain_node*)&(((struct sk_buff*)skb)->stamp)) #endif +#define PKTCSETATTR(s, f, p, b) ({CHAIN_NODE(s)->flags = (f); CHAIN_NODE(s)->pkts = (p); \ + CHAIN_NODE(s)->bytes = (b);}) +#define PKTCCLRATTR(s) ({CHAIN_NODE(s)->flags = CHAIN_NODE(s)->pkts = \ + CHAIN_NODE(s)->bytes = 0;}) +#define PKTCGETATTR(s) (CHAIN_NODE(s)->flags << 29 | CHAIN_NODE(s)->pkts << 20 | \ + CHAIN_NODE(s)->bytes) #define PKTCCNT(skb) (CHAIN_NODE(skb)->pkts) #define PKTCLEN(skb) (CHAIN_NODE(skb)->bytes) #define PKTCFLAGS(skb) (CHAIN_NODE(skb)->flags) -#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c) & ((1 << 9) - 1)) -#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l) & ((1 << 20) - 1)) +#define PKTCSETCNT(skb, c) (CHAIN_NODE(skb)->pkts = (c)) +#define PKTCINCRCNT(skb) (CHAIN_NODE(skb)->pkts++) +#define PKTCADDCNT(skb, c) (CHAIN_NODE(skb)->pkts += (c)) +#define PKTCSETLEN(skb, l) (CHAIN_NODE(skb)->bytes = (l)) +#define PKTCADDLEN(skb, l) (CHAIN_NODE(skb)->bytes += (l)) #define PKTCSETFLAG(skb, fb) (CHAIN_NODE(skb)->flags |= (fb)) #define PKTCCLRFLAG(skb, fb) (CHAIN_NODE(skb)->flags &= ~(fb)) #define PKTCLINK(skb) (CHAIN_NODE(skb)->link) #define PKTSETCLINK(skb, x) (CHAIN_NODE(skb)->link = (struct sk_buff*)(x)) -#define PKTISCHAINED(skb) (PKTCLINK(skb) != NULL) #define FOREACH_CHAINED_PKT(skb, nskb) \ for (; (skb) != NULL; (skb) = (nskb)) \ - if ((nskb) = PKTCLINK(skb), PKTSETCLINK((skb), NULL), 1) + if ((nskb) = (PKTISCHAINED(skb) ? PKTCLINK(skb) : NULL), \ + PKTSETCLINK((skb), NULL), 1) #define PKTCFREE(osh, skb, send) \ do { \ void *nskb; \ ASSERT((skb) != NULL); \ FOREACH_CHAINED_PKT((skb), nskb) { \ + PKTCLRCHAINED((osh), (skb)); \ + PKTCCLRATTR((skb)); \ PKTFREE((osh), (skb), (send)); \ } \ } while (0) +#define PKTCENQTAIL(h, t, p) \ +do { \ + if ((t) == NULL) { \ + (h) = (t) = (p); \ + } else { \ + PKTSETCLINK((t), (p)); \ + (t) = (p); \ + } \ +} while (0) #endif #else diff --git a/drivers/net/wireless/bcmdhd/include/linuxver.h b/drivers/net/wireless/bcmdhd/include/linuxver.h index 3c2a168..149b740 100644 --- a/drivers/net/wireless/bcmdhd/include/linuxver.h +++ b/drivers/net/wireless/bcmdhd/include/linuxver.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linuxver.h 353905 2012-08-29 07:33:08Z $ + * $Id: linuxver.h 367714 2012-11-09 03:26:01Z $ */ #ifndef _linuxver_h_ @@ -511,29 +511,28 @@ typedef struct { #endif -#define PROC_START(thread_func, owner, tsk_ctl, flags) \ +#ifdef USE_KTHREAD_API +#define PROC_START(thread_func, owner, tsk_ctl, flags, name) \ { \ sema_init(&((tsk_ctl)->sema), 0); \ init_completion(&((tsk_ctl)->completed)); \ (tsk_ctl)->parent = owner; \ (tsk_ctl)->terminated = FALSE; \ - (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ + (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \ + (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \ DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ - if ((tsk_ctl)->thr_pid > 0) \ - wait_for_completion(&((tsk_ctl)->completed)); \ - DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ } - -#ifdef USE_KTHREAD_API -#define PROC_START2(thread_func, owner, tsk_ctl, flags, name) \ +#else +#define PROC_START(thread_func, owner, tsk_ctl, flags, name) \ { \ sema_init(&((tsk_ctl)->sema), 0); \ init_completion(&((tsk_ctl)->completed)); \ (tsk_ctl)->parent = owner; \ (tsk_ctl)->terminated = FALSE; \ - (tsk_ctl)->p_task = kthread_run(thread_func, tsk_ctl, (char*)name); \ - (tsk_ctl)->thr_pid = (tsk_ctl)->p_task->pid; \ - DBG_THR(("%s thr:%lx created\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ + (tsk_ctl)->thr_pid = kernel_thread(thread_func, tsk_ctl, flags); \ + if ((tsk_ctl)->thr_pid > 0) \ + wait_for_completion(&((tsk_ctl)->completed)); \ + DBG_THR(("%s thr:%lx started\n", __FUNCTION__, (tsk_ctl)->thr_pid)); \ } #endif diff --git a/drivers/net/wireless/bcmdhd/include/osl.h b/drivers/net/wireless/bcmdhd/include/osl.h index ca171d8..b7173fd 100644 --- a/drivers/net/wireless/bcmdhd/include/osl.h +++ b/drivers/net/wireless/bcmdhd/include/osl.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: osl.h 320905 2012-03-13 15:33:25Z $ + * $Id: osl.h 346935 2012-07-25 00:24:55Z $ */ #ifndef _osl_h_ @@ -69,20 +69,30 @@ typedef void (*osl_wreg_fn_t)(void *ctx, volatile void *reg, unsigned int val, #endif #if !defined(PKTC) +#define PKTCGETATTR(s) (0) +#define PKTCSETATTR(skb, f, p, b) +#define PKTCCLRATTR(skb) #define PKTCCNT(skb) (0) #define PKTCLEN(skb) (0) #define PKTCFLAGS(skb) (0) #define PKTCSETCNT(skb, c) +#define PKTCINCRCNT(skb) +#define PKTCADDCNT(skb, c) #define PKTCSETLEN(skb, l) +#define PKTCADDLEN(skb, l) #define PKTCSETFLAG(skb, fb) #define PKTCCLRFLAG(skb, fb) -#define PKTCLINK(skb) PKTLINK(skb) -#define PKTSETCLINK(skb, x) PKTSETLINK((skb), (x)) -#define PKTISCHAINED(skb) FALSE +#define PKTCLINK(skb) NULL +#define PKTSETCLINK(skb, x) #define FOREACH_CHAINED_PKT(skb, nskb) \ for ((nskb) = NULL; (skb) != NULL; (skb) = (nskb)) #define PKTCFREE PKTFREE -#endif +#endif +#ifndef HNDCTF +#define PKTSETCHAINED(osh, skb) +#define PKTCLRCHAINED(osh, skb) +#define PKTISCHAINED(skb) (FALSE) +#endif #endif diff --git a/drivers/net/wireless/bcmdhd/include/pcicfg.h b/drivers/net/wireless/bcmdhd/include/pcicfg.h index 5f7df6a..0a984e8a 100644 --- a/drivers/net/wireless/bcmdhd/include/pcicfg.h +++ b/drivers/net/wireless/bcmdhd/include/pcicfg.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: pcicfg.h 309193 2012-01-19 00:03:57Z $ + * $Id: pcicfg.h 346935 2012-07-25 00:24:55Z $ */ #ifndef _h_pcicfg_ @@ -55,6 +55,7 @@ #define PCI_CFG_PIN 0x3d #define PCI_CFG_MINGNT 0x3e #define PCI_CFG_MAXLAT 0x3f +#define PCI_CFG_DEVCTRL 0xd8 #define PCI_BAR0_WIN 0x80 #define PCI_BAR1_WIN 0x84 #define PCI_SPROM_CONTROL 0x88 diff --git a/drivers/net/wireless/bcmdhd/include/proto/802.11.h b/drivers/net/wireless/bcmdhd/include/proto/802.11.h index 1632e7d..aca9316 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/802.11.h +++ b/drivers/net/wireless/bcmdhd/include/proto/802.11.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to 802.11 * - * $Id: 802.11.h 346820 2012-07-24 13:53:12Z $ + * $Id: 802.11.h 368403 2012-11-13 17:20:09Z $ */ #ifndef _802_11_H_ @@ -410,6 +410,36 @@ BWL_PRE_PACKED_STRUCT struct dot11y_action_ext_csa { struct dot11_csa_body b; } BWL_POST_PACKED_STRUCT; + +BWL_PRE_PACKED_STRUCT struct dot11_wide_bw_channel_switch { + uint8 id; + uint8 len; + uint8 channel_width; + uint8 center_frequency_segment_0; + uint8 center_frequency_segment_1; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_wide_bw_channel_switch dot11_wide_bw_chan_switch_ie_t; + +#define DOT11_WIDE_BW_SWITCH_IE_LEN 3 + + +BWL_PRE_PACKED_STRUCT struct dot11_channel_switch_wrapper { + uint8 id; + uint8 len; + dot11_wide_bw_chan_switch_ie_t wb_chan_switch_ie; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_channel_switch_wrapper dot11_chan_switch_wrapper_ie_t; + + +BWL_PRE_PACKED_STRUCT struct dot11_vht_transmit_power_envelope { + uint8 id; + uint8 len; + uint8 transmit_power_info; + uint8 local_max_transmit_power_20; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_vht_transmit_power_envelope dot11_vht_transmit_power_envelope_ie_t; + + BWL_PRE_PACKED_STRUCT struct dot11_obss_coex { uint8 id; uint8 len; @@ -469,7 +499,7 @@ typedef struct dot11_extcap dot11_extcap_t; #define DOT11_MEASURE_TYPE_NOISE 4 #define DOT11_MEASURE_TYPE_BEACON 5 #define DOT11_MEASURE_TYPE_FRAME 6 -#define DOT11_MEASURE_TYPE_STATS 7 +#define DOT11_MEASURE_TYPE_STAT 7 #define DOT11_MEASURE_TYPE_LCI 8 #define DOT11_MEASURE_TYPE_TXSTREAM 9 #define DOT11_MEASURE_TYPE_PAUSE 255 @@ -564,8 +594,8 @@ typedef struct dot11_ibss_dfs dot11_ibss_dfs_t; #define WME_OUI "\x00\x50\xf2" -#define WME_OUI_LEN 3 #define WME_OUI_TYPE 2 +#define WME_OUI_LEN 3 #define WME_TYPE 2 #define WME_SUBTYPE_IE 0 #define WME_SUBTYPE_PARAM_IE 1 @@ -1060,6 +1090,7 @@ typedef struct ti_ie ti_ie_t; #define DOT11_MNG_EXT_RATES_ID 50 #define DOT11_MNG_AP_CHREP_ID 51 #define DOT11_MNG_NBR_REP_ID 52 +#define DOT11_MNG_RCPI_ID 53 #define DOT11_MNG_MDIE_ID 54 #define DOT11_MNG_FTIE_ID 55 #define DOT11_MNG_FT_TI_ID 56 @@ -1067,12 +1098,20 @@ typedef struct ti_ie ti_ie_t; #define DOT11_MNG_EXT_CSA_ID 60 #define DOT11_MNG_HT_ADD 61 #define DOT11_MNG_EXT_CHANNEL_OFFSET 62 +#define DOT11_MNG_BSS_AVR_ACCESS_DELAY_ID 63 +#define DOT11_MNG_ANTENNA_ID 64 +#define DOT11_MNG_RSNI_ID 65 +#define DOT11_MNG_MEASUREMENT_PILOT_TX_ID 66 +#define DOT11_MNG_BSS_AVAL_ADMISSION_CAP_ID 67 +#define DOT11_MNG_BSS_AC_ACCESS_DELAY_ID 68 #define DOT11_MNG_WAPI_ID 68 #define DOT11_MNG_TIME_ADVERTISE_ID 69 #define DOT11_MNG_RRM_CAP_ID 70 +#define DOT11_MNG_MULTIPLE_BSSID_ID 71 #define DOT11_MNG_HT_BSS_COEXINFO_ID 72 #define DOT11_MNG_HT_BSS_CHANNEL_REPORT_ID 73 #define DOT11_MNG_HT_OBSS_ID 74 +#define DOT11_MNG_MMIE_ID 76 #define DOT11_MNG_CHANNEL_USAGE 97 #define DOT11_MNG_TIME_ZONE_ID 98 #define DOT11_MNG_LINK_IDENTIFIER_ID 101 @@ -1089,6 +1128,10 @@ typedef struct ti_ie ti_ie_t; #define DOT11_MNG_EXT_CAP_ID 127 #define DOT11_MNG_VHT_CAP_ID 191 #define DOT11_MNG_VHT_OPERATION_ID 192 +#define DOT11_MNG_WIDE_BW_CHANNEL_SWITCH_ID 194 +#define DOT11_MNG_VHT_TRANSMIT_POWER_ENVELOPE_ID 195 +#define DOT11_MNG_CHANNEL_SWITCH_WRAPPER_ID 196 + #define DOT11_MNG_WPA_ID 221 #define DOT11_MNG_PROPR_ID 221 @@ -1096,8 +1139,27 @@ typedef struct ti_ie ti_ie_t; #define DOT11_MNG_VS_ID 221 -#define DOT11_RATE_BASIC 0x80 -#define DOT11_RATE_MASK 0x7F + + + +#define DOT11_RATE_1M 2 +#define DOT11_RATE_2M 4 +#define DOT11_RATE_5M5 11 +#define DOT11_RATE_11M 22 +#define DOT11_RATE_6M 12 +#define DOT11_RATE_9M 18 +#define DOT11_RATE_12M 24 +#define DOT11_RATE_18M 36 +#define DOT11_RATE_24M 48 +#define DOT11_RATE_36M 72 +#define DOT11_RATE_48M 96 +#define DOT11_RATE_54M 108 +#define DOT11_RATE_MAX 108 + + +#define DOT11_RATE_BASIC 0x80 +#define DOT11_RATE_MASK 0x7F + #define DOT11_MNG_ERP_LEN 1 @@ -1128,6 +1190,8 @@ typedef struct ti_ie ti_ie_t; #define DOT11_EXT_CAP_SPSMP 6 +#define DOT11_EXT_CAP_PROXY_ARP 12 + #define DOT11_EXT_CAP_BSS_TRANSITION_MGMT 19 #define DOT11_EXT_CAP_IW 31 @@ -1153,7 +1217,7 @@ typedef struct ti_ie ti_ie_t; #define DOT11_ACTION_CAT_HT 7 #define DOT11_ACTION_CAT_SA_QUERY 8 #define DOT11_ACTION_CAT_PDPA 9 -#define DOT11_ACTION_CAT_BSSMGMT 10 +#define DOT11_ACTION_CAT_WNM 10 #define DOT11_ACTION_NOTIFICATION 17 #define DOT11_ACTION_CAT_VSP 126 #define DOT11_ACTION_CAT_VS 127 @@ -1411,6 +1475,8 @@ typedef struct dot11_ft_res dot11_ft_res_t; #define DOT11_RRM_CAP_LEN 5 +#define RCPI_IE_LEN 1 +#define RSNI_IE_LEN 1 BWL_PRE_PACKED_STRUCT struct dot11_rrm_cap_ie { uint8 cap[DOT11_RRM_CAP_LEN]; } BWL_POST_PACKED_STRUCT; @@ -1455,6 +1521,7 @@ BWL_PRE_PACKED_STRUCT struct dot11_rmreq { uint8 action; uint8 token; uint16 reps; + uint8 data[1]; } BWL_POST_PACKED_STRUCT; typedef struct dot11_rmreq dot11_rmreq_t; #define DOT11_RMREQ_LEN 5 @@ -1533,9 +1600,189 @@ typedef struct dot11_rmrep_bcn dot11_rmrep_bcn_t; #define DOT11_RMREP_BCN_FRM_BODY 1 -BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { +#define DOT11_RMREP_FRAME_COUNT_REPORT 1 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmreq_chanload { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint8 reg; + uint8 channel; + uint16 interval; + uint16 duration; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmreq_chanload dot11_rmreq_chanload_t; +#define DOT11_RMREQ_CHANLOAD_LEN 11 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_chanload { + uint8 reg; + uint8 channel; + uint32 starttime[2]; + uint16 duration; + uint8 channel_load; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_chanload dot11_rmrep_chanload_t; +#define DOT11_RMREP_CHANLOAD_LEN 13 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmreq_noise { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint8 reg; + uint8 channel; + uint16 interval; + uint16 duration; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmreq_noise dot11_rmreq_noise_t; +#define DOT11_RMREQ_NOISE_LEN 11 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_noise { + uint8 reg; + uint8 channel; + uint32 starttime[2]; + uint16 duration; + uint8 antid; + uint8 anpi; + uint8 ipi0_dens; + uint8 ipi1_dens; + uint8 ipi2_dens; + uint8 ipi3_dens; + uint8 ipi4_dens; + uint8 ipi5_dens; + uint8 ipi6_dens; + uint8 ipi7_dens; + uint8 ipi8_dens; + uint8 ipi9_dens; + uint8 ipi10_dens; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_noise dot11_rmrep_noise_t; +#define DOT11_RMREP_NOISE_LEN 25 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmreq_frame { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint8 reg; + uint8 channel; + uint16 interval; + uint16 duration; + uint8 req_type; + struct ether_addr ta; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmreq_frame dot11_rmreq_frame_t; +#define DOT11_RMREQ_FRAME_LEN 18 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frame { + uint8 reg; + uint8 channel; + uint32 starttime[2]; + uint16 duration; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_frame dot11_rmrep_frame_t; +#define DOT11_RMREP_FRAME_LEN 12 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_frmentry { + struct ether_addr ta; struct ether_addr bssid; - uint32 bssid_info; + uint8 phy_type; + uint8 avg_rcpi; + uint8 last_rsni; + uint8 last_rcpi; + uint8 ant_id; + uint16 frame_cnt; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_frmentry dot11_rmrep_frmentry_t; +#define DOT11_RMREP_FRMENTRY_LEN 19 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmreq_stat { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + struct ether_addr peer; + uint16 interval; + uint16 duration; + uint8 group_id; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmreq_stat dot11_rmreq_stat_t; +#define DOT11_RMREQ_STAT_LEN 16 + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_stat { + uint16 duration; + uint8 group_id; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_stat dot11_rmrep_stat_t; + + +BWL_PRE_PACKED_STRUCT struct dot11_rmreq_tx_stream { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint16 interval; + uint16 duration; + struct ether_addr peer; + uint8 traffic_id; + uint8 bin0_range; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmreq_tx_stream dot11_rmreq_tx_stream_t; + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_tx_stream { + uint32 starttime[2]; + uint16 duration; + struct ether_addr peer; + uint8 traffic_id; + uint8 reason; + uint32 txmsdu_cnt; + uint32 msdu_discarded_cnt; + uint32 msdufailed_cnt; + uint32 msduretry_cnt; + uint32 cfpolls_lost_cnt; + uint32 avrqueue_delay; + uint32 avrtx_delay; + uint8 bin0_range; + uint32 bin0; + uint32 bin1; + uint32 bin2; + uint32 bin3; + uint32 bin4; + uint32 bin5; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmrep_tx_stream dot11_rmrep_tx_stream_t; + + +BWL_PRE_PACKED_STRUCT struct dot11_rmreq_pause_time { + uint8 id; + uint8 len; + uint8 token; + uint8 mode; + uint8 type; + uint16 pause_time; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rmreq_pause_time dot11_rmreq_pause_time_t; + + +BWL_PRE_PACKED_STRUCT struct dot11_rmrep_nbr { + struct ether_addr bssid; + uint32 bssid_info; uint8 reg; uint8 channel; uint8 phytype; @@ -1545,6 +1792,15 @@ typedef struct dot11_rmrep_nbr dot11_rmrep_nbr_t; #define DOT11_RMREP_NBR_LEN 13 +BWL_PRE_PACKED_STRUCT struct dot11_rrmrep_nbr { + uint8 id; + uint8 len; + dot11_rmrep_nbr_t nbr_rrmrep; +} BWL_POST_PACKED_STRUCT; +typedef struct dot11_rrmrep_nbr dot11_rrmrep_nbr_t; +#define DOT11_RRMREP_NBR_LEN 15 + + #define DOT11_BSSTYPE_INFRASTRUCTURE 0 #define DOT11_BSSTYPE_INDEPENDENT 1 #define DOT11_BSSTYPE_ANY 2 @@ -1585,42 +1841,56 @@ typedef struct dot11_lmrep dot11_lmrep_t; -#define HT_SIG1_MCS_MASK 0x00007F -#define HT_SIG1_CBW 0x000080 -#define HT_SIG1_HT_LENGTH 0xFFFF00 +#define HT_SIG1_MCS_MASK 0x00007F +#define HT_SIG1_CBW 0x000080 +#define HT_SIG1_HT_LENGTH 0xFFFF00 -#define HT_SIG2_SMOOTHING 0x000001 -#define HT_SIG2_NOT_SOUNDING 0x000002 -#define HT_SIG2_RESERVED 0x000004 -#define HT_SIG2_AGGREGATION 0x000008 -#define HT_SIG2_STBC_MASK 0x000030 -#define HT_SIG2_STBC_SHIFT 4 -#define HT_SIG2_FEC_CODING 0x000040 -#define HT_SIG2_SHORT_GI 0x000080 -#define HT_SIG2_ESS_MASK 0x000300 -#define HT_SIG2_ESS_SHIFT 8 -#define HT_SIG2_CRC 0x03FC00 -#define HT_SIG2_TAIL 0x1C0000 +#define HT_SIG2_SMOOTHING 0x000001 +#define HT_SIG2_NOT_SOUNDING 0x000002 +#define HT_SIG2_RESERVED 0x000004 +#define HT_SIG2_AGGREGATION 0x000008 +#define HT_SIG2_STBC_MASK 0x000030 +#define HT_SIG2_STBC_SHIFT 4 +#define HT_SIG2_FEC_CODING 0x000040 +#define HT_SIG2_SHORT_GI 0x000080 +#define HT_SIG2_ESS_MASK 0x000300 +#define HT_SIG2_ESS_SHIFT 8 +#define HT_SIG2_CRC 0x03FC00 +#define HT_SIG2_TAIL 0x1C0000 -#define APHY_SLOT_TIME 9 -#define APHY_SIFS_TIME 16 -#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) -#define APHY_PREAMBLE_TIME 16 -#define APHY_SIGNAL_TIME 4 -#define APHY_SYMBOL_TIME 4 -#define APHY_SERVICE_NBITS 16 -#define APHY_TAIL_NBITS 6 -#define APHY_CWMIN 15 +#define HT_T_LEG_PREAMBLE 16 +#define HT_T_L_SIG 4 +#define HT_T_SIG 8 +#define HT_T_LTF1 4 +#define HT_T_GF_LTF1 8 +#define HT_T_LTFs 4 +#define HT_T_STF 4 +#define HT_T_GF_STF 8 +#define HT_T_SYML 4 +#define HT_N_SERVICE 16 +#define HT_N_TAIL 6 -#define BPHY_SLOT_TIME 20 -#define BPHY_SIFS_TIME 10 -#define BPHY_DIFS_TIME 50 -#define BPHY_PLCP_TIME 192 -#define BPHY_PLCP_SHORT_TIME 96 -#define BPHY_CWMIN 31 + +#define APHY_SLOT_TIME 9 +#define APHY_SIFS_TIME 16 +#define APHY_DIFS_TIME (APHY_SIFS_TIME + (2 * APHY_SLOT_TIME)) +#define APHY_PREAMBLE_TIME 16 +#define APHY_SIGNAL_TIME 4 +#define APHY_SYMBOL_TIME 4 +#define APHY_SERVICE_NBITS 16 +#define APHY_TAIL_NBITS 6 +#define APHY_CWMIN 15 + + +#define BPHY_SLOT_TIME 20 +#define BPHY_SIFS_TIME 10 +#define BPHY_DIFS_TIME 50 +#define BPHY_PLCP_TIME 192 +#define BPHY_PLCP_SHORT_TIME 96 +#define BPHY_CWMIN 31 #define DOT11_OFDM_SIGNAL_EXTENSION 6 @@ -1635,30 +1905,36 @@ typedef int vht_group_id_t; -#define VHT_SIGA1_CONST_MASK 0x800004 +#define VHT_SIGA1_CONST_MASK 0x800004 -#define VHT_SIGA1_20MHZ_VAL 0x000000 -#define VHT_SIGA1_40MHZ_VAL 0x000001 -#define VHT_SIGA1_80MHZ_VAL 0x000002 -#define VHT_SIGA1_160MHZ_VAL 0x000003 +#define VHT_SIGA1_BW_MASK 0x000003 +#define VHT_SIGA1_20MHZ_VAL 0x000000 +#define VHT_SIGA1_40MHZ_VAL 0x000001 +#define VHT_SIGA1_80MHZ_VAL 0x000002 +#define VHT_SIGA1_160MHZ_VAL 0x000003 -#define VHT_SIGA1_STBC 0x000008 +#define VHT_SIGA1_STBC 0x000008 -#define VHT_SIGA1_GID_MAX_GID 0x3f -#define VHT_SIGA1_GID_SHIFT 4 -#define VHT_SIGA1_GID_TO_AP 0x00 -#define VHT_SIGA1_GID_NOT_TO_AP 0x3f +#define VHT_SIGA1_GID_MASK 0x0003f0 +#define VHT_SIGA1_GID_SHIFT 4 +#define VHT_SIGA1_GID_TO_AP 0x00 +#define VHT_SIGA1_GID_NOT_TO_AP 0x3f +#define VHT_SIGA1_GID_MAX_GID 0x3f -#define VHT_SIGA1_NSTS_SHIFT 10 #define VHT_SIGA1_NSTS_SHIFT_MASK_USER0 0x001C00 +#define VHT_SIGA1_NSTS_SHIFT 10 -#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 +#define VHT_SIGA1_PARTIAL_AID_MASK 0x3fe000 +#define VHT_SIGA1_PARTIAL_AID_SHIFT 13 + +#define VHT_SIGA1_TXOP_PS_NOT_ALLOWED 0x400000 #define VHT_SIGA2_GI_NONE 0x000000 #define VHT_SIGA2_GI_SHORT 0x000001 #define VHT_SIGA2_GI_W_MOD10 0x000002 #define VHT_SIGA2_CODING_LDPC 0x000004 +#define VHT_SIGA2_LDPC_EXTRA_OFDM_SYM 0x000008 #define VHT_SIGA2_BEAMFORM_ENABLE 0x000100 #define VHT_SIGA2_MCS_SHIFT 4 @@ -1666,8 +1942,17 @@ typedef int vht_group_id_t; #define VHT_SIGA2_TAIL_MASK 0xfc0000 #define VHT_SIGA2_TAIL_VALUE 0x000000 -#define VHT_SIGA2_SVC_BITS 16 -#define VHT_SIGA2_TAIL_BITS 6 + +#define VHT_T_LEG_PREAMBLE 16 +#define VHT_T_L_SIG 4 +#define VHT_T_SIG_A 8 +#define VHT_T_LTF 4 +#define VHT_T_STF 4 +#define VHT_T_SIG_B 4 +#define VHT_T_SYML 4 + +#define VHT_N_SERVICE 16 +#define VHT_N_TAIL 6 @@ -1693,6 +1978,9 @@ typedef struct d11cnt { +#define BRCM_SYSCAP_WET_TUNNEL 0x0100 + + #define BRCM_OUI "\x00\x10\x18" @@ -1722,6 +2010,7 @@ typedef struct brcm_ie brcm_ie_t; #define BRF1_RX_LARGE_AGG 0x10 #define BRF1_RFAWARE_DCS 0x20 #define BRF1_SOFTAP 0x40 +#define BRF1_DWDS 0x80 BWL_PRE_PACKED_STRUCT struct vndr_ie { @@ -1952,6 +2241,8 @@ typedef struct dot11_obss_ie dot11_obss_ie_t; + + BWL_PRE_PACKED_STRUCT struct vht_cap_ie { uint32 vht_cap_info; @@ -1962,23 +2253,22 @@ BWL_PRE_PACKED_STRUCT struct vht_cap_ie { } BWL_POST_PACKED_STRUCT; typedef struct vht_cap_ie vht_cap_ie_t; + #define VHT_CAP_IE_LEN 12 -#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 + +#define VHT_CAP_INFO_MAX_MPDU_LEN_MASK 0x00000003 #define VHT_CAP_INFO_SUPP_CHAN_WIDTH_MASK 0x0000000c #define VHT_CAP_INFO_LDPC 0x00000010 #define VHT_CAP_INFO_SGI_80MHZ 0x00000020 - #define VHT_CAP_INFO_SGI_160MHZ 0x00000040 #define VHT_CAP_INFO_TX_STBC 0x00000080 - #define VHT_CAP_INFO_RX_STBC_MASK 0x00000700 #define VHT_CAP_INFO_RX_STBC_SHIFT 8 #define VHT_CAP_INFO_SU_BEAMFMR 0x00000800 #define VHT_CAP_INFO_SU_BEAMFMEE 0x00001000 #define VHT_CAP_INFO_NUM_BMFMR_ANT_MASK 0x0000e000 #define VHT_CAP_INFO_NUM_BMFMR_ANT_SHIFT 13 - #define VHT_CAP_INFO_NUM_SOUNDING_DIM_MASK 0x00070000 #define VHT_CAP_INFO_NUM_SOUNDING_DIM_SHIFT 16 #define VHT_CAP_INFO_MU_BEAMFMR 0x00080000 @@ -1987,39 +2277,75 @@ typedef struct vht_cap_ie vht_cap_ie_t; #define VHT_CAP_INFO_HTCVHT 0x00400000 #define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_MASK 0x03800000 #define VHT_CAP_INFO_AMPDU_MAXLEN_EXP_SHIFT 23 - #define VHT_CAP_INFO_LINK_ADAPT_CAP_MASK 0x0c000000 #define VHT_CAP_INFO_LINK_ADAPT_CAP_SHIFT 26 -#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff -#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 +#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_MASK 0x1fff +#define VHT_CAP_SUPP_MCS_RX_HIGHEST_RATE_SHIFT 0 + +#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff +#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 + +#define VHT_CAP_MCS_MAP_0_7 0 +#define VHT_CAP_MCS_MAP_0_8 1 +#define VHT_CAP_MCS_MAP_0_9 2 +#define VHT_CAP_MCS_MAP_NONE 3 +#define VHT_CAP_MCS_MAP_S 2 +#define VHT_CAP_MCS_MAP_M 0x3 + +#define VHT_CAP_MCS_MAP_NONE_ALL 0xffff + +#define VHT_CAP_MCS_MAP_0_9_NSS3 \ + ((VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(1)) | \ + (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(2)) | \ + (VHT_CAP_MCS_MAP_0_9 << VHT_MCS_MAP_GET_SS_IDX(3))) -#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_MASK 0x1fff -#define VHT_CAP_SUPP_MCS_TX_HIGHEST_RATE_SHIFT 0 +#define VHT_CAP_MCS_MAP_NSS_MAX 8 -#define VHT_CAP_MCS_MAP_0_7 0 -#define VHT_CAP_MCS_MAP_0_8 1 -#define VHT_CAP_MCS_MAP_0_9 2 -#define VHT_CAP_MCS_MAP_NONE 3 -#define VHT_CAP_MCS_MAP_NSS_MAX 8 +#define VHT_CAP_MCS_MAP_CREATE(mcsmap, nss, mcs) \ + do { \ + int i; \ + for (i = 1; i <= nss; i++) { \ + VHT_MCS_MAP_SET_MCS_PER_SS(i, mcs, mcsmap); \ + } \ + } while (0) + + +#define VHT_MCS_CODE_TO_MCS_MAP(mcs_code) \ + ((mcs_code == VHT_CAP_MCS_MAP_0_7) ? 0xff : \ + (mcs_code == VHT_CAP_MCS_MAP_0_8) ? 0x1ff : \ + (mcs_code == VHT_CAP_MCS_MAP_0_9) ? 0x3ff : 0) + + +#define VHT_MCS_MAP_TO_MCS_CODE(mcs_map) \ + ((mcs_map == 0xff) ? VHT_CAP_MCS_MAP_0_7 : \ + (mcs_map == 0x1ff) ? VHT_CAP_MCS_MAP_0_8 : \ + (mcs_map == 0x3ff) ? VHT_CAP_MCS_MAP_0_9 : VHT_CAP_MCS_MAP_NONE) typedef enum vht_cap_chan_width { - VHT_CAP_CHAN_WIDTH_20_40 = 0x00, - VHT_CAP_CHAN_WIDTH_80 = 0x04, - VHT_CAP_CHAN_WIDTH_160 = 0x08 + VHT_CAP_CHAN_WIDTH_SUPPORT_MANDATORY = 0x00, + VHT_CAP_CHAN_WIDTH_SUPPORT_160 = 0x04, + VHT_CAP_CHAN_WIDTH_SUPPORT_160_8080 = 0x08 } vht_cap_chan_width_t; typedef enum vht_cap_max_mpdu_len { - VHT_CAP_MPDU_MAX_4K = 0x00, - VHT_CAP_MPDU_MAX_8K = 0x01, - VHT_CAP_MPDU_MAX_11K = 0x02 + VHT_CAP_MPDU_MAX_4K = 0x00, + VHT_CAP_MPDU_MAX_8K = 0x01, + VHT_CAP_MPDU_MAX_11K = 0x02 } vht_cap_max_mpdu_len_t; +#define VHT_MPDU_LIMIT_4K 3895 +#define VHT_MPDU_LIMIT_8K 7991 +#define VHT_MPDU_LIMIT_11K 11454 + + + + BWL_PRE_PACKED_STRUCT struct vht_op_ie { uint8 chan_width; uint8 chan1; @@ -2028,6 +2354,7 @@ BWL_PRE_PACKED_STRUCT struct vht_op_ie { } BWL_POST_PACKED_STRUCT; typedef struct vht_op_ie vht_op_ie_t; + #define VHT_OP_IE_LEN 5 typedef enum vht_op_chan_width { @@ -2038,16 +2365,31 @@ typedef enum vht_op_chan_width { } vht_op_chan_width_t; -#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1)*2) +#define BRCM_VHT_FEATURES_OUITYPE 0x4 +BWL_PRE_PACKED_STRUCT struct vht_features_ie_hdr { + uint8 oui[3]; + uint8 type; + uint8 rate_mask; +} BWL_POST_PACKED_STRUCT; +typedef struct vht_features_ie_hdr vht_features_ie_hdr_t; + + +#define VHT_MCS_MAP_GET_SS_IDX(nss) (((nss)-1) * VHT_CAP_MCS_MAP_S) #define VHT_MCS_MAP_GET_MCS_PER_SS(nss, mcsMap) \ - (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & 0x3) + (((mcsMap) >> VHT_MCS_MAP_GET_SS_IDX(nss)) & VHT_CAP_MCS_MAP_M) #define VHT_MCS_MAP_SET_MCS_PER_SS(nss, numMcs, mcsMap) \ - ((mcsMap) |= (((numMcs) & 0x3) << VHT_MCS_MAP_GET_SS_IDX(nss))) + do { \ + (mcsMap) &= (~(VHT_CAP_MCS_MAP_M << VHT_MCS_MAP_GET_SS_IDX(nss))); \ + (mcsMap) |= (((numMcs) & VHT_CAP_MCS_MAP_M) << VHT_MCS_MAP_GET_SS_IDX(nss)); \ + } while (0) +#define VHT_MCS_SS_SUPPORTED(nss, mcsMap) \ + (VHT_MCS_MAP_GET_MCS_PER_SS((nss), (mcsMap)) != VHT_CAP_MCS_MAP_NONE) + #define WPA_OUI "\x00\x50\xF2" -#define WPA_OUI_LEN 3 #define WPA_OUI_TYPE 1 +#define WPA_OUI_LEN 3 #define WPA_VERSION 1 #define WPA2_OUI "\x00\x0F\xAC" #define WPA2_OUI_LEN 3 @@ -2075,6 +2417,8 @@ typedef enum vht_op_chan_width { #define WFA_OUI_TYPE_TPC 8 #ifdef WLTDLS +#define WFA_OUI_TYPE_TPQ 4 +#define WFA_OUI_TYPE_TPS 5 #define WFA_OUI_TYPE_WFD 10 #endif @@ -2110,6 +2454,7 @@ typedef enum vht_op_chan_width { #define AES_KEY_SIZE 16 #define AES_MIC_SIZE 8 #define BIP_KEY_SIZE 16 +#define BIP_MIC_SIZE 8 #define WCN_OUI "\x00\x50\xf2" @@ -2158,7 +2503,6 @@ BWL_PRE_PACKED_STRUCT struct dot11_timeout_ie { typedef struct dot11_timeout_ie dot11_timeout_ie_t; - BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { uint8 id; uint8 len; @@ -2169,6 +2513,16 @@ BWL_PRE_PACKED_STRUCT struct dot11_gtk_ie { } BWL_POST_PACKED_STRUCT; typedef struct dot11_gtk_ie dot11_gtk_ie_t; + +BWL_PRE_PACKED_STRUCT struct mmic_ie { + uint8 id; + uint8 len; + uint16 key_id; + uint8 ipn[6]; + uint8 mic[BIP_MIC_SIZE]; +} BWL_POST_PACKED_STRUCT; +typedef struct mmic_ie mmic_ie_t; + #define BSSID_INVALID "\x00\x00\x00\x00\x00\x00" #define BSSID_BROADCAST "\xFF\xFF\xFF\xFF\xFF\xFF" diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h index 312074d..243a975 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmevent.h @@ -23,7 +23,7 @@ * * Dependencies: proto/bcmeth.h * - * $Id: bcmevent.h 326276 2012-04-06 23:16:42Z $ + * $Id: bcmevent.h 369617 2012-11-19 16:45:34Z $ * */ @@ -188,8 +188,23 @@ typedef BWL_PRE_PACKED_STRUCT struct bcm_event { #define WLC_E_AUTH_REQ 91 #define WLC_E_TDLS_PEER_EVENT 92 #define WLC_E_SPEEDY_RECREATE_FAIL 93 -#define WLC_E_LAST 94 - +#define WLC_E_NATIVE 94 +#define WLC_E_PKTDELAY_IND 95 +#define WLC_E_AWDL_AW 96 +#define WLC_E_AWDL_ROLE 97 +#define WLC_E_AWDL_EVENT 98 +#ifdef WLNIC +#define WLC_E_NIC_AF_TXS 99 +#define WLC_E_NIC_NIC_REPORT 100 +#endif +#define WLC_E_BEACON_FRAME_RX 101 +#define WLC_E_SERVICE_FOUND 102 +#define WLC_E_GAS_FRAGMENT_RX 103 +#define WLC_E_GAS_COMPLETE 104 +#define WLC_E_P2PO_ADD_DEVICE 105 +#define WLC_E_P2PO_DEL_DEVICE 106 +#define WLC_E_IBSS_COALESCE 107 +#define WLC_E_LAST 108 typedef struct { @@ -216,8 +231,8 @@ extern const int bcmevent_names_size; #define WLC_E_STATUS_SUPPRESS 12 #define WLC_E_STATUS_NOCHANS 13 #ifdef BCMCCX -#define WLC_E_STATUS_CCXFASTRM 14 -#endif +#define WLC_E_STATUS_CCXFASTRM 14 +#endif #define WLC_E_STATUS_CS_ABORT 15 #define WLC_E_STATUS_ERROR 16 @@ -251,20 +266,20 @@ extern const int bcmevent_names_size; #define WLC_E_PRUNE_NO_COMMON_RATES 9 #define WLC_E_PRUNE_BASIC_RATES 10 #ifdef BCMCCX -#define WLC_E_PRUNE_CCXFAST_PREVAP 11 -#endif +#define WLC_E_PRUNE_CCXFAST_PREVAP 11 +#endif #define WLC_E_PRUNE_CIPHER_NA 12 #define WLC_E_PRUNE_KNOWN_STA 13 #ifdef BCMCCX -#define WLC_E_PRUNE_CCXFAST_DROAM 14 -#endif +#define WLC_E_PRUNE_CCXFAST_DROAM 14 +#endif #define WLC_E_PRUNE_WDS_PEER 15 #define WLC_E_PRUNE_QBSS_LOAD 16 #define WLC_E_PRUNE_HOME_AP 17 #ifdef BCMCCX -#define WLC_E_PRUNE_AP_BLOCKED 18 -#define WLC_E_PRUNE_NO_DIAG_SUPPORT 19 -#endif +#define WLC_E_PRUNE_AP_BLOCKED 18 +#define WLC_E_PRUNE_NO_DIAG_SUPPORT 19 +#endif #define WLC_E_SUP_OTHER 0 @@ -321,6 +336,7 @@ typedef struct wl_event_data_if { #define WLC_E_IF_ROLE_BTA_ACCEPTOR 6 #endif +#define WLC_E_IF_FLAGS_BSSCFG_NOIF 0x1 #define WLC_E_LINK_BCN_LOSS 1 #define WLC_E_LINK_DISASSOC 2 @@ -337,6 +353,27 @@ typedef struct wl_event_data_if { #define WLC_E_TDLS_PEER_DISCONNECTED 2 +typedef BWL_PRE_PACKED_STRUCT struct wl_event_gas { + uint16 channel; + uint8 dialog_token; + uint8 fragment_id; + uint16 status_code; + uint16 data_len; + uint8 data[1]; +} BWL_POST_PACKED_STRUCT wl_event_gas_t; + + +typedef BWL_PRE_PACKED_STRUCT struct wl_event_sd { + uint8 protocol; + uint16 channel; + uint8 dialog_token; + uint8 fragment_id; + uint16 status_code; + uint16 data_len; + uint8 data[1]; +} BWL_POST_PACKED_STRUCT wl_event_sd_t; + + #include <packed_section_end.h> #endif diff --git a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h index d5c3b76..02ddd37 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/bcmip.h +++ b/drivers/net/wireless/bcmdhd/include/proto/bcmip.h @@ -21,7 +21,7 @@ * * Fundamental constants relating to IP Protocol * - * $Id: bcmip.h 290206 2011-10-17 19:13:51Z $ + * $Id: bcmip.h 346935 2012-07-25 00:24:55Z $ */ #ifndef _bcmip_h_ @@ -52,15 +52,16 @@ #define IP_PROT_ICMP6 0x3a -#define IPV4_VER_HL_OFFSET 0 -#define IPV4_TOS_OFFSET 1 -#define IPV4_PKTLEN_OFFSET 2 -#define IPV4_PKTFLAG_OFFSET 6 -#define IPV4_PROT_OFFSET 9 -#define IPV4_CHKSUM_OFFSET 10 -#define IPV4_SRC_IP_OFFSET 12 -#define IPV4_DEST_IP_OFFSET 16 -#define IPV4_OPTIONS_OFFSET 20 +#define IPV4_VER_HL_OFFSET 0 +#define IPV4_TOS_OFFSET 1 +#define IPV4_PKTLEN_OFFSET 2 +#define IPV4_PKTFLAG_OFFSET 6 +#define IPV4_PROT_OFFSET 9 +#define IPV4_CHKSUM_OFFSET 10 +#define IPV4_SRC_IP_OFFSET 12 +#define IPV4_DEST_IP_OFFSET 16 +#define IPV4_OPTIONS_OFFSET 20 +#define IPV4_MIN_HEADER_LEN 20 #define IPV4_VER_MASK 0xf0 @@ -204,6 +205,8 @@ ipv6_exthdr_len(uint8 *h, uint8 *proto) return len; } +#define IPV4_ISMULTI(a) (((a) & 0xf0000000) == 0xe0000000) + #include <packed_section_end.h> diff --git a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h index e455185..7b9b2e2 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/ethernet.h +++ b/drivers/net/wireless/bcmdhd/include/proto/ethernet.h @@ -21,10 +21,10 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: ethernet.h 309193 2012-01-19 00:03:57Z $ + * $Id: ethernet.h 354714 2012-09-03 03:12:21Z $ */ -#ifndef _NET_ETHERNET_H_ +#ifndef _NET_ETHERNET_H_ #define _NET_ETHERNET_H_ #ifndef _TYPEDEFS_H_ @@ -67,6 +67,11 @@ #define ETHER_TYPE_IPV6 0x86dd #define ETHER_TYPE_BRCM 0x886c #define ETHER_TYPE_802_1X 0x888e +#ifdef PLC +#define ETHER_TYPE_88E1 0x88e1 +#define ETHER_TYPE_8912 0x8912 +#define ETHER_TYPE_GIGLED 0xffff +#endif #define ETHER_TYPE_802_1X_PREAUTH 0x88c7 #define ETHER_TYPE_WAI 0x88b4 #define ETHER_TYPE_89_0D 0x890d @@ -94,7 +99,7 @@ ((uint8 *)ea)[5] = ((mgrp_ip) >> 0) & 0xff; \ } -#ifndef __INCif_etherh +#ifndef __INCif_etherh BWL_PRE_PACKED_STRUCT struct ether_header { uint8 ether_dhost[ETHER_ADDR_LEN]; @@ -122,19 +127,26 @@ BWL_PRE_PACKED_STRUCT struct ether_addr { -#define ether_cmp(a, b) (!(((short*)(a))[0] == ((short*)(b))[0]) | \ - !(((short*)(a))[1] == ((short*)(b))[1]) | \ - !(((short*)(a))[2] == ((short*)(b))[2])) +#define eacmp(a, b) ((((uint16 *)(a))[0] ^ ((uint16 *)(b))[0]) | \ + (((uint16 *)(a))[1] ^ ((uint16 *)(b))[1]) | \ + (((uint16 *)(a))[2] ^ ((uint16 *)(b))[2])) + +#define ether_cmp(a, b) eacmp(a, b) -#define ether_copy(s, d) { \ - ((short*)(d))[0] = ((const short*)(s))[0]; \ - ((short*)(d))[1] = ((const short*)(s))[1]; \ - ((short*)(d))[2] = ((const short*)(s))[2]; } +#define eacopy(s, d) \ +do { \ + ((uint16 *)(d))[0] = ((const uint16 *)(s))[0]; \ + ((uint16 *)(d))[1] = ((const uint16 *)(s))[1]; \ + ((uint16 *)(d))[2] = ((const uint16 *)(s))[2]; \ +} while (0) + +#define ether_copy(s, d) eacopy(s, d) static const struct ether_addr ether_bcast = {{255, 255, 255, 255, 255, 255}}; static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; +static const struct ether_addr ether_ipv6_mcast = {{0x33, 0x33, 0x00, 0x00, 0x00, 0x01}}; #define ETHER_ISBCAST(ea) ((((uint8 *)(ea))[0] & \ ((uint8 *)(ea))[1] & \ @@ -149,6 +161,11 @@ static const struct ether_addr ether_null = {{0, 0, 0, 0, 0, 0}}; ((uint8 *)(ea))[4] | \ ((uint8 *)(ea))[5]) == 0) +#define ETHER_ISNULLDEST(da) ((((const uint16 *)(da))[0] | \ + ((const uint16 *)(da))[1] | \ + ((const uint16 *)(da))[2]) == 0) +#define ETHER_ISNULLSRC(sa) ETHER_ISNULLDEST(sa) + #define ETHER_MOVE_HDR(d, s) \ do { \ struct ether_header t; \ @@ -156,6 +173,8 @@ do { \ *(struct ether_header *)(d) = t; \ } while (0) +#define ETHER_ISUCAST(ea) ((((uint8 *)(ea))[0] & 0x01) == 0) + #include <packed_section_end.h> diff --git a/drivers/net/wireless/bcmdhd/include/proto/p2p.h b/drivers/net/wireless/bcmdhd/include/proto/p2p.h index 2b6fef6..8f7652f 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/p2p.h +++ b/drivers/net/wireless/bcmdhd/include/proto/p2p.h @@ -21,7 +21,7 @@ * * Fundamental types and constants relating to WFA P2P (aka WiFi Direct) * - * $Id: p2p.h 357863 2012-09-20 06:40:47Z $ + * $Id: p2p.h 356416 2012-09-12 16:40:42Z $ */ #ifndef _P2P_H_ @@ -376,7 +376,8 @@ typedef struct wifi_p2p_pub_act_frame wifi_p2p_pub_act_frame_t; #define P2P_PAF_DEVDIS_RSP 6 #define P2P_PAF_PROVDIS_REQ 7 #define P2P_PAF_PROVDIS_RSP 8 -#define P2P_PAF_SUBTYPE_INVALID 255 /* Invalid Subtype */ +#define P2P_PAF_SUBTYPE_INVALID 255 + #define P2P_TYPE_MNREQ P2P_PAF_GON_REQ #define P2P_TYPE_MNRSP P2P_PAF_GON_RSP diff --git a/drivers/net/wireless/bcmdhd/include/proto/vlan.h b/drivers/net/wireless/bcmdhd/include/proto/vlan.h index 9c94985..2eb4832 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/vlan.h +++ b/drivers/net/wireless/bcmdhd/include/proto/vlan.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: vlan.h 241182 2011-02-17 21:50:03Z $ + * $Id: vlan.h 346935 2012-07-25 00:24:55Z $ */ #ifndef _vlan_h_ @@ -40,11 +40,19 @@ #define VLAN_PRI_MASK 7 +#define VLAN_TPID_OFFSET 12 +#define VLAN_TCI_OFFSET 14 + #define VLAN_TAG_LEN 4 #define VLAN_TAG_OFFSET (2 * ETHER_ADDR_LEN) #define VLAN_TPID 0x8100 +struct vlan_header { + uint16 vlan_type; + uint16 vlan_tag; +}; + struct ethervlan_header { uint8 ether_dhost[ETHER_ADDR_LEN]; uint8 ether_shost[ETHER_ADDR_LEN]; diff --git a/drivers/net/wireless/bcmdhd/include/proto/wpa.h b/drivers/net/wireless/bcmdhd/include/proto/wpa.h index 47bc354..7ebeeda 100644 --- a/drivers/net/wireless/bcmdhd/include/proto/wpa.h +++ b/drivers/net/wireless/bcmdhd/include/proto/wpa.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wpa.h 261155 2011-05-23 23:51:32Z $ + * $Id: wpa.h 369547 2012-11-19 08:57:31Z $ */ #ifndef _proto_wpa_h_ @@ -34,7 +34,11 @@ #include <packed_section_start.h> +#ifdef CUSTOMER_HW4 #include <dhd_sec_feature.h> +#endif + + #define DOT11_RC_INVALID_WPA_IE 13 @@ -116,9 +120,9 @@ typedef BWL_PRE_PACKED_STRUCT struct #define WPA_CIPHER_BIP 6 #define WPA_CIPHER_TPK 7 #ifdef BCMCCX -#define WPA_CIPHER_CKIP 8 -#define WPA_CIPHER_CKIP_MMH 9 -#define WPA_CIPHER_WEP_MMH 10 +#define WPA_CIPHER_CKIP 8 +#define WPA_CIPHER_CKIP_MMH 9 +#define WPA_CIPHER_WEP_MMH 10 #define IS_CCX_CIPHER(cipher) ((cipher) == WPA_CIPHER_CKIP || \ (cipher) == WPA_CIPHER_CKIP_MMH || \ @@ -170,10 +174,8 @@ typedef BWL_PRE_PACKED_STRUCT struct #define RSN_CAP_2_REPLAY_CNTRS 1 #define RSN_CAP_4_REPLAY_CNTRS 2 #define RSN_CAP_16_REPLAY_CNTRS 3 -#ifdef MFP #define RSN_CAP_MFPR 0x0040 #define RSN_CAP_MFPC 0x0080 -#endif #define WPA_CAP_4_REPLAY_CNTRS RSN_CAP_4_REPLAY_CNTRS diff --git a/drivers/net/wireless/bcmdhd/include/sbchipc.h b/drivers/net/wireless/bcmdhd/include/sbchipc.h index 5feb743..463c8af 100644 --- a/drivers/net/wireless/bcmdhd/include/sbchipc.h +++ b/drivers/net/wireless/bcmdhd/include/sbchipc.h @@ -5,7 +5,7 @@ * JTAG, 0/1/2 UARTs, clock frequency control, a watchdog interrupt timer, * GPIO interface, extbus, and support for serial and parallel flashes. * - * $Id: sbchipc.h 347614 2012-07-27 10:24:51Z $ + * $Id: sbchipc.h 368270 2012-11-12 23:46:50Z $ * * Copyright (C) 1999-2012, Broadcom Corporation * @@ -289,10 +289,10 @@ typedef volatile struct { uint32 pllcontrol_data; uint32 pmustrapopt; uint32 pmu_xtalfreq; - uint32 retention_ctl; + uint32 retention_ctl; uint32 PAD[3]; - uint32 retention_grpidx; - uint32 retention_grpctl; + uint32 retention_grpidx; + uint32 retention_grpctl; uint32 PAD[94]; uint16 sromotp[512]; #ifdef NFLASH_SUPPORT @@ -358,16 +358,58 @@ typedef volatile struct { uint32 nand_cache_data; uint32 nand_ctrl_config; uint32 nand_ctrl_status; -#endif - uint32 gci_corecaps0; - uint32 gci_corecaps1; - uint32 gci_corecaps2; - uint32 gci_corectrl; - uint32 gci_corestat; - uint32 PAD[11]; - uint32 gci_indirect_addr; - uint32 PAD[111]; - uint32 gci_chipctrl; +#endif + uint32 gci_corecaps0; + uint32 gci_corecaps1; + uint32 gci_corecaps2; + uint32 gci_corectrl; + uint32 gci_corestat; + uint32 gci_intstat; + uint32 gci_intmask; + uint32 gci_wakemask; + uint32 gci_levelintstat; + uint32 gci_eventintstat; + uint32 PAD[6]; + uint32 gci_indirect_addr; + uint32 gci_gpioctl; + uint32 PAD; + uint32 gci_gpiomask; + uint32 PAD; + uint32 gci_miscctl; + uint32 PAD[2]; + uint32 gci_input[32]; + uint32 gci_event[32]; + uint32 gci_output[4]; + uint32 gci_control_0; + uint32 gci_control_1; + uint32 gci_level_polreg; + uint32 gci_levelintmask; + uint32 gci_eventintmask; + uint32 PAD[3]; + uint32 gci_inbandlevelintmask; + uint32 gci_inbandeventintmask; + uint32 PAD[2]; + uint32 gci_seciauxtx; + uint32 gci_seciauxrx; + uint32 gci_secitx_datatag; + uint32 gci_secirx_datatag; + uint32 gci_secitx_datamask; + uint32 gci_seciusef0tx_reg; + uint32 gci_secif0tx_offset; + uint32 gci_secif0rx_offset; + uint32 gci_secif1tx_offset; + uint32 PAD[3]; + uint32 gci_uartescval; + uint32 PAD[3]; + uint32 gci_secibauddiv; + uint32 gci_secifcr; + uint32 gci_secilcr; + uint32 gci_secimcr; + uint32 PAD[2]; + uint32 gci_baudadj; + uint32 PAD; + uint32 gci_chipctrl; + uint32 gci_chipsts; } chipcregs_t; #endif @@ -473,9 +515,12 @@ typedef volatile struct { #define CC_CAP2_GSIO 0x00000002 -#define CC_CAP_EXT_SECI_PRESENT 0x00000001 +#define CC_CAP_EXT_SECI_PRESENT 0x00000001 +#define CC_CAP_EXT_GCI_PRESENT 0x00000004 +#define GCI_WL_CHN_INFO_MASK (0xFF00) + #define PLL_NONE 0x00000000 #define PLL_TYPE1 0x00010000 #define PLL_TYPE2 0x00020000 @@ -491,6 +536,28 @@ typedef volatile struct { #define ALP_CLOCK 20000000 +#ifdef CFG_SIM +#define NS_ALP_CLOCK 84922 +#define NS_SLOW_ALP_CLOCK 84922 +#define NS_CPU_CLOCK 534500 +#define NS_SLOW_CPU_CLOCK 534500 +#define NS_SI_CLOCK 271750 +#define NS_SLOW_SI_CLOCK 271750 +#define NS_FAST_MEM_CLOCK 271750 +#define NS_MEM_CLOCK 271750 +#define NS_SLOW_MEM_CLOCK 271750 +#else +#define NS_ALP_CLOCK 125000000 +#define NS_SLOW_ALP_CLOCK 100000000 +#define NS_CPU_CLOCK 1000000000 +#define NS_SLOW_CPU_CLOCK 800000000 +#define NS_SI_CLOCK 250000000 +#define NS_SLOW_SI_CLOCK 200000000 +#define NS_FAST_MEM_CLOCK 800000000 +#define NS_MEM_CLOCK 533000000 +#define NS_SLOW_MEM_CLOCK 400000000 +#endif + #define HT_CLOCK 80000000 @@ -808,6 +875,33 @@ typedef volatile struct { #define PCTL_LPO_SEL 0x00000001 +#define PMU_RCTL_CLK_DIV_SHIFT 0 +#define PMU_RCTL_CHAIN_LEN_SHIFT 12 +#define PMU_RCTL_MACPHY_DISABLE_SHIFT 26 +#define PMU_RCTL_MACPHY_DISABLE_MASK (1 << 26) +#define PMU_RCTL_LOGIC_DISABLE_SHIFT 27 +#define PMU_RCTL_LOGIC_DISABLE_MASK (1 << 27) +#define PMU_RCTL_MEMSLP_LOG_SHIFT 28 +#define PMU_RCTL_MEMSLP_LOG_MASK (1 << 28) +#define PMU_RCTL_MEMRETSLP_LOG_SHIFT 29 +#define PMU_RCTL_MEMRETSLP_LOG_MASK (1 << 29) + + +#define PMU_RCTLGRP_CHAIN_LEN_SHIFT 0 +#define PMU_RCTLGRP_RMODE_ENABLE_SHIFT 14 +#define PMU_RCTLGRP_RMODE_ENABLE_MASK (1 << 14) +#define PMU_RCTLGRP_DFT_ENABLE_SHIFT 15 +#define PMU_RCTLGRP_DFT_ENABLE_MASK (1 << 15) +#define PMU_RCTLGRP_NSRST_DISABLE_SHIFT 16 +#define PMU_RCTLGRP_NSRST_DISABLE_MASK (1 << 16) + +#define PMU4334_RCTLGRP_CHAIN_LEN_GRP0 338 +#define PMU4334_RCTLGRP_CHAIN_LEN_GRP1 315 + +#define PMU43341_RCTLGRP_CHAIN_LEN_GRP0 366 +#define PMU43341_RCTLGRP_CHAIN_LEN_GRP1 330 + + #define CSTRETCH_HT 0xffff0000 #define CSTRETCH_ALP 0x0000ffff @@ -874,6 +968,8 @@ typedef volatile struct { #define SFLASH_AT 0x200 #define NFLASH 0x300 #define PFLASH 0x700 +#define QSPIFLASH_ST 0x800 +#define QSPIFLASH_AT 0x900 #define CC_CFG_EN 0x0001 @@ -1726,9 +1822,36 @@ typedef volatile struct { #define CST43239_CHIPMODE_GSPI(cs) (((cs) & (1 << 0)) == (1 << 0)) -#define RES4324_OTP_PU 10 + +#define RES4324_LPLDO_PU 0 +#define RES4324_RESET_PULLDN_DIS 1 +#define RES4324_PMU_BG_PU 2 +#define RES4324_HSIC_LDO_PU 3 +#define RES4324_CBUCK_LPOM_PU 4 +#define RES4324_CBUCK_PFM_PU 5 +#define RES4324_CLDO_PU 6 +#define RES4324_LPLDO2_LVM 7 +#define RES4324_LNLDO1_PU 8 +#define RES4324_LNLDO2_PU 9 +#define RES4324_LDO3P3_PU 10 +#define RES4324_OTP_PU 11 +#define RES4324_XTAL_PU 12 +#define RES4324_BBPLL_PU 13 +#define RES4324_LQ_AVAIL 14 +#define RES4324_WL_CORE_READY 17 +#define RES4324_ILP_REQ 18 +#define RES4324_ALP_AVAIL 19 +#define RES4324_PALDO_PU 20 +#define RES4324_RADIO_PU 21 +#define RES4324_SR_CLK_STABLE 22 +#define RES4324_SR_SAVE_RESTORE 23 +#define RES4324_SR_PHY_PWRSW 24 +#define RES4324_SR_PHY_PIC 25 +#define RES4324_SR_SUBCORE_PWRSW 26 +#define RES4324_SR_SUBCORE_PIC 27 +#define RES4324_SR_MEM_PM0 28 #define RES4324_HT_AVAIL 29 -#define RES4324_MACPHY_CLKAVAIL 30 +#define RES4324_MACPHY_CLKAVAIL 30 #define CST4324_SPROM_MASK 0x00000080 @@ -1740,6 +1863,9 @@ typedef volatile struct { #define CST4324_CHIPMODE_USB20D(cs) (((cs) & CST4324_CHIPMODE_MASK) == 0x6) +#define CST43242_SFLASH_MASK 0x00000008 + + #define RES4331_REGULATOR 0 #define RES4331_ILP_REQUEST 1 #define RES4331_XTAL_PU 2 @@ -1974,6 +2100,42 @@ typedef volatile struct { #define PMU_VREG0_DISABLE_PULLD_BT_SHIFT 2 #define PMU_VREG0_DISABLE_PULLD_WL_SHIFT 3 +#define PMU_VREG4_ADDR 4 + +#define PMU_VREG4_CLDO_PWM_SHIFT 4 +#define PMU_VREG4_CLDO_PWM_MASK 0x7 + +#define PMU_VREG4_LPLDO1_SHIFT 15 +#define PMU_VREG4_LPLDO1_MASK 0x7 +#define PMU_VREG4_LPLDO1_1p20V 0 +#define PMU_VREG4_LPLDO1_1p15V 1 +#define PMU_VREG4_LPLDO1_1p10V 2 +#define PMU_VREG4_LPLDO1_1p25V 3 +#define PMU_VREG4_LPLDO1_1p05V 4 +#define PMU_VREG4_LPLDO1_1p00V 5 +#define PMU_VREG4_LPLDO1_0p95V 6 +#define PMU_VREG4_LPLDO1_0p90V 7 + +#define PMU_VREG4_LPLDO2_LVM_SHIFT 18 +#define PMU_VREG4_LPLDO2_LVM_MASK 0x7 +#define PMU_VREG4_LPLDO2_HVM_SHIFT 21 +#define PMU_VREG4_LPLDO2_HVM_MASK 0x7 +#define PMU_VREG4_LPLDO2_LVM_HVM_MASK 0x3f +#define PMU_VREG4_LPLDO2_1p00V 0 +#define PMU_VREG4_LPLDO2_1p15V 1 +#define PMU_VREG4_LPLDO2_1p20V 2 +#define PMU_VREG4_LPLDO2_1p10V 3 +#define PMU_VREG4_LPLDO2_0p90V 4 + +#define PMU_VREG4_HSICLDO_BYPASS_SHIFT 27 +#define PMU_VREG4_HSICLDO_BYPASS_MASK 0x1 + +#define PMU_VREG5_ADDR 5 +#define PMU_VREG5_HSICAVDD_PD_SHIFT 6 +#define PMU_VREG5_HSICAVDD_PD_MASK 0x1 +#define PMU_VREG5_HSICDVDD_PD_SHIFT 11 +#define PMU_VREG5_HSICDVDD_PD_MASK 0x1 + #define RES4334_LPLDO_PU 0 #define RES4334_RESET_PULLDN_DIS 1 @@ -2029,14 +2191,80 @@ typedef volatile struct { #define PCTL_4334_GPIO3_ENAB (1 << 3) +#define CCTRL4334_PMU_WAKEUP_GPIO1 (1 << 0) +#define CCTRL4334_PMU_WAKEUP_HSIC (1 << 1) +#define CCTRL4334_PMU_WAKEUP_AOS (1 << 2) +#define CCTRL4334_HSIC_WAKE_MODE (1 << 3) +#define CCTRL4334_HSIC_INBAND_GPIO1 (1 << 4) #define CCTRL4334_HSIC_LDO_PU (1 << 23) +#define CCTRL4334_BLOCK_EXTRNL_WAKE (1 << 4) +#define CCTRL4334_SAVERESTORE_FIX (1 << 5) + + +#define CCTRL43341_BLOCK_EXTRNL_WAKE (1 << 13) +#define CCTRL43341_SAVERESTORE_FIX (1 << 14) +#define CCTRL43341_BT_ISO_SEL (1 << 16) + + +#define CCTRL1_4334_GPIO_SEL (1 << 0) +#define CCTRL1_4334_ERCX_SEL (1 << 1) +#define CCTRL1_4334_SDIO_HOST_WAKE (1 << 2) +#define CCTRL1_4334_JTAG_DISABLE (1 << 3) +#define CCTRL1_4334_UART_ON_4_5 (1 << 28) + + #define CCTRL1_4324_GPIO_SEL (1 << 0) #define CCTRL1_4324_SDIO_HOST_WAKE (1 << 2) +#define CST43143_REMAP_TO_ROM (3 << 0) +#define CST43143_SDIO_EN (1 << 2) +#define CST43143_SDIO_ISO (1 << 3) +#define CST43143_USB_CPU_LESS (1 << 4) +#define CST43143_CBUCK_MODE (3 << 6) +#define CST43143_POK_CBUCK (1 << 8) +#define CST43143_PMU_OVRSPIKE (1 << 9) +#define CST43143_PMU_OVRTEMP (0xF << 10) +#define CST43143_SR_FLL_CAL_DONE (1 << 14) +#define CST43143_USB_PLL_LOCKDET (1 << 15) +#define CST43143_PMU_PLL_LOCKDET (1 << 16) +#define CST43143_CHIPMODE_SDIOD(cs) (((cs) & CST43143_SDIO_EN) != 0) + + + +#define CCTRL_43143_SECI (1<<0) +#define CCTRL_43143_BT_LEGACY (1<<1) +#define CCTRL_43143_I2S_MODE (1<<2) +#define CCTRL_43143_I2S_MASTER (1<<3) +#define CCTRL_43143_I2S_FULL (1<<4) +#define CCTRL_43143_GSIO (1<<5) +#define CCTRL_43143_RF_SWCTRL_MASK (7<<6) +#define CCTRL_43143_RF_SWCTRL_0 (1<<6) +#define CCTRL_43143_RF_SWCTRL_1 (2<<6) +#define CCTRL_43143_RF_SWCTRL_2 (4<<6) +#define CCTRL_43143_RF_XSWCTRL (1<<9) +#define CCTRL_43143_HOST_WAKE0 (1<<11) +#define CCTRL_43143_HOST_WAKE1 (1<<12) + + +#define RES43143_EXT_SWITCHER_PWM 0 +#define RES43143_XTAL_PU 1 +#define RES43143_ILP_REQUEST 2 +#define RES43143_ALP_AVAIL 3 +#define RES43143_WL_CORE_READY 4 +#define RES43143_BBPLL_PWRSW_PU 5 +#define RES43143_HT_AVAIL 6 +#define RES43143_RADIO_PU 7 +#define RES43143_MACPHY_CLK_AVAIL 8 +#define RES43143_OTP_PU 9 +#define RES43143_LQ_AVAIL 10 + +#define PMU43143_XTAL_CORE_SIZE_MASK 0x3F + + #define RES4313_BB_PU_RSRC 0 #define RES4313_ILP_REQ_RSRC 1 #define RES4313_XTAL_PU_RSRC 2 @@ -2137,11 +2365,19 @@ typedef volatile struct { #define FLSTRCF4706_1ST_MADDR_SEG_256MB 0x00000070 +#define CCTRL4360_I2C_MODE (1 << 0) +#define CCTRL4360_UART_MODE (1 << 1) #define CCTRL4360_SECI_MODE (1 << 2) #define CCTRL4360_BTSWCTRL_MODE (1 << 3) +#define CCTRL4360_DISCRETE_FEMCTRL_MODE (1 << 4) +#define CCTRL4360_DIGITAL_PACTRL_MODE (1 << 5) +#define CCTRL4360_BTSWCTRL_AND_DIGPA_PRESENT (1 << 6) +#define CCTRL4360_EXTRA_GPIO_MODE (1 << 7) #define CCTRL4360_EXTRA_FEMCTRL_MODE (1 << 8) #define CCTRL4360_BT_LGCY_MODE (1 << 9) #define CCTRL4360_CORE2FEMCTRL4_ON (1 << 21) +#define CCTRL4360_SECI_ON_GPIO01 (1 << 24) + #define RES4360_REGULATOR 0 @@ -2211,19 +2447,144 @@ typedef volatile struct { #define CST4335_RES_INIT_MODE_SHIFT 7 #define CST4335_RES_INIT_MODE_MASK 0x00000180 #define CST4335_CHIPMODE_MASK 0xF -#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) -#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) -#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) -#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) - - -#define CCTRL1_4335_GPIO_SEL (1 << 0) -#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) - - -#define CR4_RAM_BASE (0x180000) - - +#define CST4335_CHIPMODE_SDIOD(cs) (((cs) & (1 << 0)) != 0) +#define CST4335_CHIPMODE_GSPI(cs) (((cs) & (1 << 1)) != 0) +#define CST4335_CHIPMODE_USB20D(cs) (((cs) & (1 << 2)) != 0) +#define CST4335_CHIPMODE_PCIE(cs) (((cs) & (1 << 3)) != 0) + + +#define CCTRL1_4335_GPIO_SEL (1 << 0) +#define CCTRL1_4335_SDIO_HOST_WAKE (1 << 2) + +#define CR4_4335_RAM_BASE (0x180000) +#define CR4_4350_RAM_BASE (0x180000) +#define CR4_4360_RAM_BASE (0x0) + + + + + +#define CST4350_SDIO_MODE 0x00000001 +#define CST4350_HSIC20D_MODE 0x00000002 +#define CST4350_BP_ON_HSIC_CLK 0x00000004 +#define CST4350_PCIE_MODE 0x00000008 +#define CST4350_USB20D_MODE 0x00000010 +#define CST4350_USB30D_MODE 0x00000020 +#define CST4350_SPROM_PRESENT 0x00000040 +#define CST4350_RSRC_INIT_MODE_0 0x00000080 +#define CST4350_RSRC_INIT_MODE_1 0x00000100 +#define CST4350_SEL0_SDIO 0x00000200 +#define CST4350_SEL1_SDIO 0x00000400 +#define CST4350_SDIO_PAD_MODE 0x00000800 +#define CST4350_BBPLL_LOCKED 0x00001000 +#define CST4350_USBPLL_LOCKED 0x00002000 +#define CST4350_LINE_STATE 0x0000C000 +#define CST4350_SERDES_PIPE_PLLLOCK 0x00010000 +#define CST4350_BT_READY 0x00020000 +#define CST4350_SFLASH_PRESENT 0x00040000 +#define CST4350_CPULESS_ENABLE 0x00080000 +#define CST4350_STRAP_HOST_IFC_1 0x00100000 +#define CST4350_STRAP_HOST_IFC_2 0x00200000 +#define CST4350_STRAP_HOST_IFC_3 0x00400000 +#define CST4350_RAW_SPROM_PRESENT 0x00800000 +#define CST4350_APP_CLK_SWITCH_SEL_RDBACK 0x01000000 +#define CST4350_RAW_RSRC_INIT_MODE_0 0x02000000 +#define CST4350_SDIO_PAD_VDDIO 0x04000000 +#define CST4350_GSPI_MODE 0x08000000 +#define CST4350_PACKAGE_OPTION 0xF0000000 + + +#define CST4350_HOST_IFC_MASK 0x00700000 +#define CST4350_HOST_IFC_SHIFT 20 + + +#define CST4350_IFC_MODE_SDIOD 0x0 +#define CST4350_IFC_MODE_HSIC20D 0x1 +#define CST4350_IFC_MODE_HSIC30D 0x2 +#define CST4350_IFC_MODE_PCIE 0x3 +#define CST4350_IFC_MODE_USB20D 0x4 +#define CST4350_IFC_MODE_USB30D 0x5 +#define CST4350_IFC_MODE_USB30D_WL 0x6 +#define CST4350_IFC_MODE_USB30D_BT 0x7 + +#define CST4350_IFC_MODE(cs) ((cs & CST4350_HOST_IFC_MASK) >> CST4350_HOST_IFC_SHIFT) + +#define CST4350_CHIPMODE_SDIOD(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_SDIOD)) +#define CST4350_CHIPMODE_USB20D(cs) ((CST4350_IFC_MODE(cs)) == (CST4350_IFC_MODE_USB20D)) +#define CST4350_CHIPMODE_HSIC20D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC20D)) +#define CST4350_CHIPMODE_HSIC30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_HSIC30D)) +#define CST4350_CHIPMODE_USB30D(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D)) +#define CST4350_CHIPMODE_USB30D_WL(cs) (CST4350_IFC_MODE(cs) == (CST4350_IFC_MODE_USB30D_WL)) + + +#define RES4350_LPLDO_PU 0 +#define RES4350_PMU_BG_PU 1 +#define RES4350_PMU_SLEEP 2 +#define RES4350_RSVD_3 3 +#define RES4350_CBUCK_LPOM_PU 4 +#define RES4350_CBUCK_PFM_PU 5 +#define RES4350_COLD_START_WAIT 6 +#define RES4350_RSVD_7 7 +#define RES4350_LNLDO_PU 8 +#define RES4350_XTALLDO_PU 9 +#define RES4350_LDO3P3_PU 10 +#define RES4350_OTP_PU 11 +#define RES4350_XTAL_PU 12 +#define RES4350_SR_CLK_START 13 +#define RES4350_LQ_AVAIL 14 +#define RES4350_LQ_START 15 +#define RES4350_RSVD_16 16 +#define RES4350_WL_CORE_RDY 17 +#define RES4350_ILP_REQ 18 +#define RES4350_ALP_AVAIL 19 +#define RES4350_MINI_PMU 20 +#define RES4350_RADIO_PU 21 +#define RES4350_SR_CLK_STABLE 22 +#define RES4350_SR_SAVE_RESTORE 23 +#define RES4350_SR_PHY_PWRSW 24 +#define RES4350_SR_VDDM_PWRSW 25 +#define RES4350_SR_SUBCORE_PWRSW 26 +#define RES4350_SR_SLEEP 27 +#define RES4350_HT_START 28 +#define RES4350_HT_AVAIL 29 +#define RES4350_MACPHY_CLKAVAIL 30 + +#define MUXENAB4350_UART_MASK (0x0000000f) + + +#define CC4350_FNSEL_HWDEF (0) +#define CC4350_FNSEL_SAMEASPIN (1) +#define CC4350_FNSEL_UART (2) +#define CC4350_FNSEL_SFLASH (3) +#define CC4350_FNSEL_SPROM (4) +#define CC4350_FNSEL_I2C (5) +#define CC4350_FNSEL_MISC0 (6) +#define CC4350_FNSEL_GCI (7) +#define CC4350_FNSEL_MISC1 (8) +#define CC4350_FNSEL_MISC2 (9) +#define CC4350_FNSEL_PWDOG (10) +#define CC4350_FNSEL_IND (12) +#define CC4350_FNSEL_PDN (13) +#define CC4350_FNSEL_PUP (14) +#define CC4350_FNSEL_TRISTATE (15) + + +#define CC4350_PIN_GPIO_00 (0) +#define CC4350_PIN_GPIO_01 (1) +#define CC4350_PIN_GPIO_02 (2) +#define CC4350_PIN_GPIO_03 (3) +#define CC4350_PIN_GPIO_04 (4) +#define CC4350_PIN_GPIO_05 (5) +#define CC4350_PIN_GPIO_06 (6) +#define CC4350_PIN_GPIO_07 (7) +#define CC4350_PIN_GPIO_08 (8) +#define CC4350_PIN_GPIO_09 (9) +#define CC4350_PIN_GPIO_10 (10) +#define CC4350_PIN_GPIO_11 (11) +#define CC4350_PIN_GPIO_12 (12) +#define CC4350_PIN_GPIO_13 (13) +#define CC4350_PIN_GPIO_14 (14) +#define CC4350_PIN_GPIO_15 (15) #define CC_GCI_CHIPCTRL_00 (0) diff --git a/drivers/net/wireless/bcmdhd/include/sbhnddma.h b/drivers/net/wireless/bcmdhd/include/sbhnddma.h index da1f1a1..0b44602 100644 --- a/drivers/net/wireless/bcmdhd/include/sbhnddma.h +++ b/drivers/net/wireless/bcmdhd/include/sbhnddma.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbhnddma.h 309193 2012-01-19 00:03:57Z $ + * $Id: sbhnddma.h 348178 2012-07-31 22:27:41Z $ */ #ifndef _sbhnddma_h_ @@ -233,11 +233,17 @@ typedef volatile struct { #define D64RINGALIGN_BITS 13 #define D64MAXRINGSZ (1 << D64RINGALIGN_BITS) -#define D64RINGALIGN (1 << D64RINGALIGN_BITS) +#define D64RINGBOUNDARY (1 << D64RINGALIGN_BITS) #define D64MAXDD (D64MAXRINGSZ / sizeof (dma64dd_t)) +#define D64MAXDD_LARGE ((1 << 16) / sizeof (dma64dd_t)) + + +#define D64RINGBOUNDARY_LARGE (1 << 16) + + #define D64_XC_XE 0x00000001 #define D64_XC_SE 0x00000002 #define D64_XC_LE 0x00000004 @@ -258,7 +264,7 @@ typedef volatile struct { #define D64_XP_LD_MASK 0x00001fff -#define D64_XS0_CD_MASK 0x00001fff +#define D64_XS0_CD_MASK (di->d64_xs0_cd_mask) #define D64_XS0_XS_MASK 0xf0000000 #define D64_XS0_XS_SHIFT 28 #define D64_XS0_XS_DISABLED 0x00000000 @@ -267,7 +273,7 @@ typedef volatile struct { #define D64_XS0_XS_STOPPED 0x30000000 #define D64_XS0_XS_SUSP 0x40000000 -#define D64_XS1_AD_MASK 0x00001fff +#define D64_XS1_AD_MASK (di->d64_xs1_ad_mask) #define D64_XS1_XE_MASK 0xf0000000 #define D64_XS1_XE_SHIFT 28 #define D64_XS1_XE_NOERR 0x00000000 @@ -306,7 +312,7 @@ typedef volatile struct { #define D64_RP_LD_MASK 0x00001fff -#define D64_RS0_CD_MASK 0x00001fff +#define D64_RS0_CD_MASK (di->d64_rs0_cd_mask) #define D64_RS0_RS_MASK 0xf0000000 #define D64_RS0_RS_SHIFT 28 #define D64_RS0_RS_DISABLED 0x00000000 diff --git a/drivers/net/wireless/bcmdhd/include/sbsdio.h b/drivers/net/wireless/bcmdhd/include/sbsdio.h index 0e9ad7d..30a891e 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdio.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdio.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsdio.h 308945 2012-01-18 02:15:27Z $ + * $Id: sbsdio.h 369545 2012-11-19 08:38:45Z $ */ #ifndef _SBSDIO_H @@ -101,6 +101,7 @@ * => busy signal is asserted between data blocks. */ #define SBSDIO_MESBUSYCTRL_MASK 0x7f +#define SBSDIO_MESBUSYCTRL_ENAB 0x80 /* Enable busy capability for MES access */ /* SBSDIO_DEVICE_CTL */ #define SBSDIO_DEVCTL_SETBUSY 0x01 /* 1: device will assert busy signal when @@ -116,12 +117,9 @@ * external pads in tri-state; requires * sdio bus power cycle to clear (rev 9) */ -#define SBSDIO_DEVCTL_SB_RST_CTL 0x30 /* Force SD->SB reset mapping (rev 11) */ -#define SBSDIO_DEVCTL_RST_CORECTL 0x00 /* Determined by CoreControl bit */ -#define SBSDIO_DEVCTL_RST_BPRESET 0x10 /* Force backplane reset */ -#define SBSDIO_DEVCTL_RST_NOBPRESET 0x20 /* Force no backplane reset */ #define SBSDIO_DEVCTL_EN_F2_BLK_WATERMARK 0x10 /* Enable function 2 tx for each block */ - +#define SBSDIO_DEVCTL_F2WM_ENAB 0x10 /* Enable F2 Watermark */ +#define SBSDIO_DEVCTL_NONDAT_PADS_ISO 0x20 /* Isolate sdio clk and cmd (non-data) */ /* SBSDIO_FUNC1_CHIPCLKCSR */ #define SBSDIO_FORCE_ALP 0x01 /* Force ALP request to backplane */ diff --git a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h index 10c7401..66ff3fe 100644 --- a/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h +++ b/drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sbsdpcmdev.h 347614 2012-07-27 10:24:51Z $ + * $Id: sbsdpcmdev.h 336848 2012-06-05 11:28:07Z $ */ #ifndef _sbsdpcmdev_h_ diff --git a/drivers/net/wireless/bcmdhd/include/sdioh.h b/drivers/net/wireless/bcmdhd/include/sdioh.h index 5517a71..7597901 100644 --- a/drivers/net/wireless/bcmdhd/include/sdioh.h +++ b/drivers/net/wireless/bcmdhd/include/sdioh.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: sdioh.h 347633 2012-07-27 11:02:02Z $ + * $Id: sdioh.h 345499 2012-07-18 06:59:05Z $ */ #ifndef _SDIOH_H @@ -90,8 +90,8 @@ #define SD3_PresetVal_SDR104 0x06c #define SD3_PresetVal_DDR50 0x06e /* SDIO3.0 Revx specific Registers */ -#define SD3_Tuning_Info_Register 0x0EC -#define SD3_WL_BT_reset_register 0x0F0 +#define SD3_Tuning_Info_Register 0x0EC +#define SD3_WL_BT_reset_register 0x0F0 /* preset value indices */ diff --git a/drivers/net/wireless/bcmdhd/include/siutils.h b/drivers/net/wireless/bcmdhd/include/siutils.h index a797b3d..4a5be1a 100644 --- a/drivers/net/wireless/bcmdhd/include/siutils.h +++ b/drivers/net/wireless/bcmdhd/include/siutils.h @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.h 347614 2012-07-27 10:24:51Z $ + * $Id: siutils.h 364853 2012-10-25 18:54:06Z $ */ #ifndef _siutils_h_ @@ -159,6 +159,7 @@ extern void si_setosh(si_t *sih, osl_t *osh); extern uint si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val); extern void *si_coreregs(si_t *sih); extern uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val); +extern uint si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val); extern uint32 si_core_cflags(si_t *sih, uint32 mask, uint32 val); extern void si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val); extern uint32 si_core_sflags(si_t *sih, uint32 mask, uint32 val); @@ -247,6 +248,8 @@ static INLINE void * si_eci_init(si_t *sih) {return NULL;} #define si_seci_upd(sih, a) do {} while (0) static INLINE void * si_seci_init(si_t *sih, uint8 use_seci) {return NULL;} #define si_seci_down(sih) do {} while (0) +#define si_gci(sih) 0 +static INLINE void * si_gci_init(si_t *sih) {return NULL;} extern bool si_is_otp_disabled(si_t *sih); @@ -282,6 +285,8 @@ extern char *si_coded_devpathvar(si_t *sih, char *varname, int var_len, const ch extern uint8 si_pcieclkreq(si_t *sih, uint32 mask, uint32 val); extern uint32 si_pcielcreg(si_t *sih, uint32 mask, uint32 val); +extern uint8 si_pcieltrenable(si_t *sih, uint32 mask, uint32 val); +extern void si_pcie_set_error_injection(si_t *sih, uint32 mode); extern void si_war42780_clkreq(si_t *sih, bool clkreq); extern void si_pci_down(si_t *sih); extern void si_pci_up(si_t *sih); @@ -305,6 +310,7 @@ extern void si_btc_enable_chipcontrol(si_t *sih); extern void si_btcombo_p250_4313_war(si_t *sih); extern void si_btcombo_43228_war(si_t *sih); extern void si_clk_pmu_htavail_set(si_t *sih, bool set_clear); +extern void si_pmu_synth_pwrsw_4313_war(si_t *sih); extern uint si_pll_reset(si_t *sih); @@ -316,6 +322,8 @@ extern uint32 si_pciereg(si_t *sih, uint32 offset, uint32 mask, uint32 val, uint extern uint32 si_pcieserdesreg(si_t *sih, uint32 mdioslave, uint32 offset, uint32 mask, uint32 val); extern void si_pcie_set_request_size(si_t *sih, uint16 size); extern uint16 si_pcie_get_request_size(si_t *sih); +extern void si_pcie_set_maxpayload_size(si_t *sih, uint16 size); +extern uint16 si_pcie_get_maxpayload_size(si_t *sih); extern uint16 si_pcie_get_ssid(si_t *sih); extern uint32 si_pcie_get_bar0(si_t *sih); extern int si_pcie_configspace_cache(si_t *sih); @@ -329,4 +337,11 @@ extern uint32 si_tcm_size(si_t *sih); extern int si_set_sromctl(si_t *sih, uint32 value); extern uint32 si_get_sromctl(si_t *sih); + +extern uint32 si_gci_direct(si_t *sih, uint offset, uint32 mask, uint32 val); +extern void si_gci_reset(si_t *sih); +extern void si_gci_set_functionsel(si_t *sih, uint32 pin, uint8 fnsel); +extern uint8 si_gci_get_chipctrlreg_idx(uint32 pin, uint32 *regidx, uint32 *pos); +extern uint32 si_gci_chipcontrol(si_t *sih, uint reg, uint32 mask, uint32 val); + #endif diff --git a/drivers/net/wireless/bcmdhd/include/spid.h b/drivers/net/wireless/bcmdhd/include/spid.h index 6d2d403..bfe24ff 100644 --- a/drivers/net/wireless/bcmdhd/include/spid.h +++ b/drivers/net/wireless/bcmdhd/include/spid.h @@ -8,7 +8,7 @@ * under the terms of the GNU General Public License version 2 (the "GPL"), * available at http://www.broadcom.com/licenses/GPLv2.php, with the * following added to such license: - * + * * As a special exception, the copyright holders of this software give you * permission to link this software with independent modules, and to copy and * distribute the resulting executable under terms of your choice, provided that @@ -16,12 +16,12 @@ * the license of that module. An independent module is a module which is not * derived from this software. The special exception does not apply to any * modifications of the software. - * + * * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: spid.h 354172 2012-08-30 07:19:26Z $ + * $Id: spid.h 358377 2012-09-23 11:30:22Z $ */ #ifndef _SPI_H diff --git a/drivers/net/wireless/bcmdhd/include/trxhdr.h b/drivers/net/wireless/bcmdhd/include/trxhdr.h index bf92a56..da4763c 100644 --- a/drivers/net/wireless/bcmdhd/include/trxhdr.h +++ b/drivers/net/wireless/bcmdhd/include/trxhdr.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: trxhdr.h 260898 2011-05-20 23:11:12Z $ + * $Id: trxhdr.h 349211 2012-08-07 09:45:24Z $ */ #ifndef _TRX_HDR_H @@ -30,23 +30,62 @@ #include <typedefs.h> #define TRX_MAGIC 0x30524448 /* "HDR0" */ -#define TRX_VERSION 1 /* Version 1 */ #define TRX_MAX_LEN 0x3B0000 /* Max length */ #define TRX_NO_HEADER 1 /* Do not write TRX header */ #define TRX_GZ_FILES 0x2 /* Contains up to TRX_MAX_OFFSET individual gzip files */ #define TRX_EMBED_UCODE 0x8 /* Trx contains embedded ucode image */ #define TRX_ROMSIM_IMAGE 0x10 /* Trx contains ROM simulation image */ #define TRX_UNCOMP_IMAGE 0x20 /* Trx contains uncompressed rtecdc.bin image */ -#define TRX_MAX_OFFSET 3 /* Max number of individual files */ +#define TRX_BOOTLOADER 0x40 /* the image is a bootloader */ +#define TRX_V1 1 +#define TRX_V1_MAX_OFFSETS 3 /* V1: Max number of individual files */ + +#ifndef BCMTRXV2 +#define TRX_VERSION TRX_V1 /* Version 1 */ +#define TRX_MAX_OFFSET TRX_V1_MAX_OFFSETS +#endif + +/* BMAC Host driver/application like bcmdl need to support both Ver 1 as well as + * Ver 2 of trx header. To make it generic, trx_header is structure is modified + * as below where size of "offsets" field will vary as per the TRX version. + * Currently, BMAC host driver and bcmdl are modified to support TRXV2 as well. + * To make sure, other applications like "dhdl" which are yet to be enhanced to support + * TRXV2 are not broken, new macro and structure defintion take effect only when BCMTRXV2 + * is defined. + */ struct trx_header { uint32 magic; /* "HDR0" */ uint32 len; /* Length of file including header */ uint32 crc32; /* 32-bit CRC from flag_version to end of file */ uint32 flag_version; /* 0:15 flags, 16:31 version */ +#ifndef BCMTRXV2 uint32 offsets[TRX_MAX_OFFSET]; /* Offsets of partitions from start of header */ +#else + uint32 offsets[1]; /* Offsets of partitions from start of header */ +#endif }; +#ifdef BCMTRXV2 +#define TRX_VERSION TRX_V2 /* Version 2 */ +#define TRX_MAX_OFFSET TRX_V2_MAX_OFFSETS + +#define TRX_V2 2 +/* V2: Max number of individual files + * To support SDR signature + Config data region + */ +#define TRX_V2_MAX_OFFSETS 5 +#define SIZEOF_TRXHDR_V1 (sizeof(struct trx_header)+(TRX_V1_MAX_OFFSETS-1)*sizeof(uint32)) +#define SIZEOF_TRXHDR_V2 (sizeof(struct trx_header)+(TRX_V2_MAX_OFFSETS-1)*sizeof(uint32)) +#define TRX_VER(trx) (trx->flag_version>>16) +#define ISTRX_V1(trx) (TRX_VER(trx) == TRX_V1) +#define ISTRX_V2(trx) (TRX_VER(trx) == TRX_V2) +/* For V2, return size of V2 size: others, return V1 size */ +#define SIZEOF_TRX(trx) (ISTRX_V2(trx) ? SIZEOF_TRXHDR_V2: SIZEOF_TRXHDR_V1) +#else +#define SIZEOF_TRX(trx) (sizeof(struct trx_header)) +#endif /* BCMTRXV2 */ + /* Compatibility */ typedef struct trx_header TRXHDR, *PTRXHDR; diff --git a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h index 1c8cc01..dfa8db0 100644 --- a/drivers/net/wireless/bcmdhd/include/wlfc_proto.h +++ b/drivers/net/wireless/bcmdhd/include/wlfc_proto.h @@ -18,7 +18,7 @@ * Notwithstanding the above, under no circumstances may you combine this * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. -* $Id: wlfc_proto.h 347585 2012-07-27 09:02:53Z $ +* $Id: wlfc_proto.h 358262 2012-09-21 21:39:29Z $ * */ #ifndef __wlfc_proto_definitions_h__ @@ -62,12 +62,6 @@ | 13 | 3 | (count, handle, prec_bmp)| One time request for packet to a specific | | | | MAC destination. --------------------------------------------------------------------------- - | 15 | 1 | interface ID | NIC period start - --------------------------------------------------------------------------- - | 16 | 1 | interface ID | NIC period end - --------------------------------------------------------------------------- - | 17 | 3 | (ifid, txs) | Action frame tx status - --------------------------------------------------------------------------- | 255 | N/A | N/A | FILLER - This is a special type | | | | that has no length or value. | | | | Typically used for padding. @@ -82,7 +76,7 @@ #define WLFC_CTL_TYPE_MACDESC_ADD 6 #define WLFC_CTL_TYPE_MACDESC_DEL 7 -#define WLFC_CTL_TYPE_RSSI 8 +#define WLFC_CTL_TYPE_RSSI 8 #define WLFC_CTL_TYPE_INTERFACE_OPEN 9 #define WLFC_CTL_TYPE_INTERFACE_CLOSE 10 @@ -93,10 +87,9 @@ #define WLFC_CTL_TYPE_MAC_REQUEST_PACKET 13 #define WLFC_CTL_TYPE_HOST_REORDER_RXPKTS 14 -#define WLFC_CTL_TYPE_NIC_PRD_START 15 -#define WLFC_CTL_TYPE_NIC_PRD_END 16 -#define WLFC_CTL_TYPE_AF_TXS 17 -#define WLFC_CTL_TYPE_TRANS_ID 18 +#define WLFC_CTL_TYPE_TRANS_ID 18 +#define WLFC_CTL_TYPE_COMP_TXSTATUS 19 + #define WLFC_CTL_TYPE_FILLER 255 @@ -117,10 +110,6 @@ #define WLFC_CTL_VALUE_LEN_REQUEST_CREDIT 3 /* credit, MAC-handle, prec_bitmap */ #define WLFC_CTL_VALUE_LEN_REQUEST_PACKET 3 /* credit, MAC-handle, prec_bitmap */ -#define WLFC_CTL_VALUE_LEN_NIC_PRD_START 1 -#define WLFC_CTL_VALUE_LEN_NIC_PRD_END 1 -#define WLFC_CTL_VALUE_LEN_AF_TXS 3 - #define WLFC_PKTID_GEN_MASK 0x80000000 #define WLFC_PKTID_GEN_SHIFT 31 @@ -226,7 +215,8 @@ #define WLHOST_REORDERDATA_CURIDX_VALID 0x04 #define WLHOST_REORDERDATA_EXPIDX_VALID 0x08 #define WLHOST_REORDERDATA_NEW_HOLE 0x10 + /* transaction id data len byte 0: rsvd, byte 1: seqnumber, byte 2-5 will be used for timestampe */ -#define WLFC_CTL_TRANS_ID_LEN 6 +#define WLFC_CTL_TRANS_ID_LEN 6 #endif /* __wlfc_proto_definitions_h__ */ diff --git a/drivers/net/wireless/bcmdhd/include/wlioctl.h b/drivers/net/wireless/bcmdhd/include/wlioctl.h index 33811a1..09ba05c 100644 --- a/drivers/net/wireless/bcmdhd/include/wlioctl.h +++ b/drivers/net/wireless/bcmdhd/include/wlioctl.h @@ -24,7 +24,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wlioctl.h 357627 2012-09-19 12:42:22Z $ + * $Id: wlioctl.h 384900 2013-02-13 14:23:02Z $ */ #ifndef _wlioctl_h_ @@ -43,7 +43,9 @@ #include <bcmcdc.h> #endif /* LINUX_POSTMOGRIFY_REMOVAL */ +#ifdef CUSTOMER_HW4 #include <dhd_sec_feature.h> +#endif /* CUSTOMER_HW4 */ /* LINUX_POSTMOGRIFY_REMOVAL: undefined during compile phase, so its * a no-op for most cases. For hybrid and other open source releases, @@ -211,8 +213,8 @@ typedef struct wl_bss_info { uint32 nbss_cap; /* 802.11N+AC BSS Capabilities */ uint8 ctl_ch; /* 802.11N BSS control channel number */ uint8 padding1[3]; /* explicit struct alignment padding */ - uint16 vht_rxmcsmap; /* VHT rx mcs map */ - uint16 vht_txmcsmap; /* VHT tx mcs map */ + uint16 vht_rxmcsmap; /* VHT rx mcs map (802.11ac VHT_CAP_MCS_MAP_*) */ + uint16 vht_txmcsmap; /* VHT tx mcs map (802.11ac VHT_CAP_MCS_MAP_*) */ uint8 flags; /* flags */ uint8 vht_cap; /* BSS is vht capable */ uint8 reserved[2]; /* Reserved for expansion of BSS properties */ @@ -306,7 +308,7 @@ typedef struct wl_clm_dload_info wl_clm_dload_info_t; typedef struct wlc_ssid { uint32 SSID_len; - uchar SSID[32]; + uchar SSID[DOT11_MAX_SSID_LEN]; } wlc_ssid_t; #ifndef LINUX_POSTMOGRIFY_REMOVAL @@ -360,6 +362,7 @@ typedef struct wl_extdscan_params { #define WL_SCANFLAGS_PASSIVE 0x01 /* force passive scan */ #define WL_SCANFLAGS_RESERVED 0x02 /* Reserved */ #define WL_SCANFLAGS_PROHIBITED 0x04 /* allow scanning prohibited channels */ +#define WL_SCANFLAGS_OFFCHAN 0x08 /* allow scanning/reporting off-channel APs */ #define WL_SCAN_PARAMS_SSID_MAX 10 @@ -505,6 +508,7 @@ typedef struct wl_rateset_args { uint32 count; /* # rates in this set */ uint8 rates[WL_MAXRATES_IN_SET]; /* rates in 500kbps units w/hi bit set if basic */ uint8 mcs[MCSSET_LEN]; /* supported mcs index bit map */ + uint16 vht_mcs[VHT_CAP_MCS_MAP_NSS_MAX]; /* supported mcs index bit map per nss */ } wl_rateset_args_t; /* uint32 list */ @@ -518,6 +522,10 @@ typedef struct wl_uint32_list { /* used for association with a specific BSSID and chanspec list */ typedef struct wl_assoc_params { struct ether_addr bssid; /* 00:00:00:00:00:00: broadcast scan */ + uint16 bssid_cnt; /* 0: use chanspec_num, and the single bssid, + * otherwise count of chanspecs in chanspec_list + * AND paired bssids following chanspec_list + */ int32 chanspec_num; /* 0: all available channels, * otherwise count of chanspecs in chanspec_list */ @@ -606,6 +614,7 @@ typedef struct wl_extjoin_params { #define WL_RSPEC_BW_MASK 0x00070000 /* bandwidth mask */ #define WL_RSPEC_BW_SHIFT 16 /* bandwidth shift */ #define WL_RSPEC_STBC 0x00100000 /* STBC encoding, Nsts = 2 x Nss */ +#define WL_RSPEC_TXBF 0x00200000 /* bit indicates TXBF mode */ #define WL_RSPEC_LDPC 0x00400000 /* bit indicates adv coding in use */ #define WL_RSPEC_SGI 0x00800000 /* Short GI mode */ #define WL_RSPEC_ENCODING_MASK 0x03000000 /* Encoding of Rate/MCS field */ @@ -881,18 +890,19 @@ typedef enum sup_auth_status { #define CRYPTO_ALGO_AES_CCM 4 #define CRYPTO_ALGO_AES_OCB_MSDU 5 #define CRYPTO_ALGO_AES_OCB_MPDU 6 -#if !defined(BCMCCX) +#if !defined(BCMCCX) && !defined(BCMEXTCCX) #define CRYPTO_ALGO_NALG 7 #else #define CRYPTO_ALGO_CKIP 7 #define CRYPTO_ALGO_CKIP_MMH 8 #define CRYPTO_ALGO_WEP_MMH 9 #define CRYPTO_ALGO_NALG 10 -#endif +#endif /* !BCMCCX && !BCMEXTCCX */ #ifdef BCMWAPI_WPI #define CRYPTO_ALGO_SMS4 11 #endif /* BCMWAPI_WPI */ #define CRYPTO_ALGO_PMK 12 /* for 802.1x supp to set PMK before 4-way */ +#define CRYPTO_ALGO_BIP 13 /* 802.11w BIP (aes cmac) */ #define WSEC_GEN_MIC_ERROR 0x0001 #define WSEC_GEN_REPLAY 0x0002 @@ -903,13 +913,13 @@ typedef enum sup_auth_status { #define WL_SOFT_KEY (1 << 0) /* Indicates this key is using soft encrypt */ #define WL_PRIMARY_KEY (1 << 1) /* Indicates this key is the primary (ie tx) key */ -#if defined(BCMCCX) +#if defined(BCMCCX) || defined(BCMEXTCCX) #define WL_CKIP_KP (1 << 4) /* CMIC */ #define WL_CKIP_MMH (1 << 5) /* CKIP */ #else #define WL_KF_RES_4 (1 << 4) /* Reserved for backward compat */ #define WL_KF_RES_5 (1 << 5) /* Reserved for backward compat */ -#endif +#endif /* BCMCCX || BCMEXTCCX */ #define WL_IBSS_PEER_GROUP_KEY (1 << 6) /* Indicates a group key for a IBSS PEER */ typedef struct wl_wsec_key { @@ -990,21 +1000,19 @@ typedef struct { #define WSEC_SMS4_ENABLED(wsec) ((wsec) & SMS4_ENABLED) #endif /* BCMWAPI_WAI */ -#ifdef MFP #define MFP_CAPABLE 0x0200 #define MFP_REQUIRED 0x0400 #define MFP_SHA256 0x0800 /* a special configuration for STA for WIFI test tool */ -#endif /* MFP */ /* WPA authentication mode bitvec */ #define WPA_AUTH_DISABLED 0x0000 /* Legacy (i.e., non-WPA) */ #define WPA_AUTH_NONE 0x0001 /* none (IBSS) */ #define WPA_AUTH_UNSPECIFIED 0x0002 /* over 802.1x */ #define WPA_AUTH_PSK 0x0004 /* Pre-shared key */ -#if defined(BCMCCX) +#if defined(BCMCCX) || defined(BCMEXTCCX) #define WPA_AUTH_CCKM 0x0008 /* CCKM */ #define WPA2_AUTH_CCKM 0x0010 /* CCKM2 */ -#endif +#endif /* BCMCCX || BCMEXTCCX */ /* #define WPA_AUTH_8021X 0x0020 */ /* 802.1x, reserved */ #define WPA2_AUTH_UNSPECIFIED 0x0040 /* over 802.1x */ #define WPA2_AUTH_PSK 0x0080 /* Pre-shared key */ @@ -1022,6 +1030,7 @@ typedef struct { #define WPA_AUTH_PFN_ANY 0xffffffff /* for PFN, match only ssid */ /* pmkid */ +/* Due to pmkid_info driver IOVar/dhd implementation, leave this as 16 for now. */ #define MAXPMKID 16 typedef struct _pmkid { @@ -1119,6 +1128,32 @@ typedef struct wme_tx_params_s wme_tx_params_t; #define WL_WME_TX_PARAMS_IO_BYTES (sizeof(wme_tx_params_t) * AC_COUNT) +typedef struct wl_plc_nodelist { + uint count; /* Number of nodes */ + struct _node { + struct ether_addr ea; /* Node ether address */ + uint32 node_type; /* Node type */ + uint32 cost; /* PLC affinity */ + } node[1]; +} wl_plc_nodelist_t; + +typedef struct wl_plc_params { + uint32 cmd; /* Command */ + bool plc_failover; /* PLC failover control/status */ + struct ether_addr node_ea; /* Node ether address */ + uint32 cost; /* Link cost or mac cost */ +} wl_plc_params_t; + +#define PLC_CMD_FAILOVER 1 +#define PLC_CMD_MAC_COST 2 +#define PLC_CMD_LINK_COST 3 +#define PLC_CMD_NODE_LIST 4 + +#define NODE_TYPE_UNKNOWN 0 /* Unknown link */ +#define NODE_TYPE_WIFI_ONLY 1 /* Pure Wireless STA node */ +#define NODE_TYPE_PLC_ONLY 2 /* Pure PLC only node */ +#define NODE_TYPE_WIFI_PLC 3 /* WiFi PLC capable node */ + /* defines used by poweridx iovar - it controls power in a-band */ /* current gain setting is maintained */ #define WL_PWRIDX_PCL_OFF -2 /* turn off PCL. */ @@ -1264,7 +1299,7 @@ typedef struct { /* Get MAC rate histogram response */ typedef struct { - uint32 rate[WLC_MAXRATE + 1]; /* Rates */ + uint32 rate[DOT11_RATE_MAX + 1]; /* Rates */ uint32 mcs[WL_RATESET_SZ_HT_MCS * WL_TX_CHAINS_MAX]; /* MCS counts */ uint32 vht[WL_RATESET_SZ_VHT_MCS][WL_TX_CHAINS_MAX]; /* VHT counts */ uint32 tsf_timer[2][2]; /* Start and End time for 8bytes value */ @@ -1322,6 +1357,7 @@ typedef struct wlc_rev_info { uint phyrev; /* phy revision */ uint anarev; /* anacore rev */ uint chippkg; /* chip package info */ + uint nvramrev; /* nvram revision number */ } wlc_rev_info_t; #define WL_REV_INFO_LEGACY_LENGTH 48 @@ -1655,7 +1691,9 @@ typedef struct wlc_iov_trx_s { #define WLC_NVRAM_SET 265 #define WLC_NVRAM_DUMP 266 #define WLC_REBOOT 267 +#endif /* LINUX_POSTMOGRIFY_REMOVAL */ #define WLC_SET_WSEC_PMK 268 +#ifndef LINUX_POSTMOGRIFY_REMOVAL #define WLC_GET_AUTH_MODE 269 #define WLC_SET_AUTH_MODE 270 #define WLC_GET_WAKEENTRY 271 @@ -1776,15 +1814,12 @@ typedef struct { /* WLC_GET_AUTH, WLC_SET_AUTH values */ #define WL_AUTH_OPEN_SYSTEM 0 /* d11 open authentication */ #define WL_AUTH_SHARED_KEY 1 /* d11 shared authentication */ -#ifdef BCM4330_CHIP +#ifndef CONFIG_BCM4334 #define WL_AUTH_OPEN_SHARED 2 /* try open, then shared if open failed w/rc 13 */ #else -/* BCM4334(Phoenex branch) value changed to 3 */ -#define WL_AUTH_OPEN_SHARED 3 /* try open, then shared if open failed w/rc 13 */ +#define WL_AUTH_OPEN_SHARED 3 /* BCM4334(Phoenix branch) value changed to 3 */ #endif -#ifdef USE_WEP_AUTH_SHARED_OPEN -#define WL_AUTH_SHARED_OPEN 4 /* try shared, then open if shared failed w/rc 13 */ -#endif /* USE_WEP_AUTH_SHARED_OPEN */ + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ /* Bit masks for radio disabled status - returned by WL_GET_RADIO */ @@ -1805,6 +1840,16 @@ typedef struct { #define WL_PHY_PAVARS_LEN 32 /* Phy type, Band range, chain, a1[0], b0[0], b1[0] ... */ #define WL_PHY_PAVAR_VER 1 /* pavars version */ +#define WL_PHY_PAVARS2_NUM 3 /* a1, b0, b1 */ +typedef struct wl_pavars2 { + uint16 ver; /* version of this struct */ + uint16 len; /* len of this structure */ + uint16 inuse; /* driver return 1 for a1,b0,b1 in current band range */ + uint16 phy_type; /* phy type */ + uint16 bandrange; + uint16 chain; + uint16 inpa[WL_PHY_PAVARS2_NUM]; /* phy pavars for one band range */ +} wl_pavars2_t; typedef struct wl_po { uint16 phy_type; /* Phy type */ @@ -1856,6 +1901,12 @@ typedef struct wl_po { #define WL_CHAN_FREQ_RANGE_5GM 2 #define WL_CHAN_FREQ_RANGE_5GH 3 +#define WL_CHAN_FREQ_RANGE_5GLL_5BAND 4 +#define WL_CHAN_FREQ_RANGE_5GLH_5BAND 5 +#define WL_CHAN_FREQ_RANGE_5GML_5BAND 6 +#define WL_CHAN_FREQ_RANGE_5GMH_5BAND 7 +#define WL_CHAN_FREQ_RANGE_5GH_5BAND 8 + #define WL_CHAN_FREQ_RANGE_5G_BAND0 1 #define WL_CHAN_FREQ_RANGE_5G_BAND1 2 #define WL_CHAN_FREQ_RANGE_5G_BAND2 3 @@ -1982,10 +2033,6 @@ typedef struct wl_po { /* when sgi_tx==WLC_SGI_ALL, bypass rate selection, enable sgi for all mcs */ #define WLC_SGI_ALL 0x02 -#define DHD_SCAN_ACTIVE_TIME 40 /* ms : Embedded default Active setting from DHD */ -#define DHD_SCAN_UNASSOC_ACTIVE_TIME 80 /* ms : def. Unassoc Active setting from DHD */ -#define DHD_SCAN_PASSIVE_TIME 130 /* ms: Embedded default Passive setting from DHD */ - #define LISTEN_INTERVAL 10 /* interference mitigation options */ #define INTERFERE_OVRRIDE_OFF -1 /* interference override off */ @@ -2060,6 +2107,8 @@ typedef struct wl_samplecollect_args { uint8 module_sel1; uint8 module_sel2; uint16 nsamps; + int bitStart; + uint32 gpioCapMask; } wl_samplecollect_args_t; #define WL_SAMPLEDATA_HEADER_TYPE 1 @@ -2079,6 +2128,117 @@ typedef struct wl_sampledata { uint32 flag; /* bit def */ } wl_sampledata_t; +/* WL_OTA START */ + +#define WL_OTA_ARG_PARSE_BLK_SIZE 1200 +#define WL_OTA_TEST_MAX_NUM_RATE 30 +#define WL_OTA_TEST_MAX_NUM_SEQ 100 + +/* OTA Test Status */ +enum { + WL_OTA_TEST_IDLE, /* Default Idle state */ + WL_OTA_TEST_ACTIVE, /* Test Running */ + WL_OTA_TEST_SUCCESS, /* Successfully Finished Test */ + WL_OTA_TEST_FAIL /* Test Failed in the Middle */ +}; +/* OTA SYNC Status */ +enum { + WL_OTA_SYNC_IDLE, /* Idle state */ + WL_OTA_SYNC_ACTIVE, /* Waiting for Sync */ + WL_OTA_SYNC_FAIL /* Sync pkt not recieved */ +}; + +/* Various error states dut can get stuck during test */ +enum { + WL_OTA_SKIP_TEST_CAL_FAIL = 1, /* Phy calibration failed */ + WL_OTA_SKIP_TEST_SYNCH_FAIL, /* Sync Packet not recieved */ + WL_OTA_SKIP_TEST_FILE_DWNLD_FAIL, /* Cmd flow file download failed */ + WL_OTA_SKIP_TEST_NO_TEST_FOUND, /* No test found in Flow file */ + WL_OTA_SKIP_TEST_WL_NOT_UP, /* WL UP failed */ + WL_OTA_SKIP_TEST_UNKNOWN_CALL /* Unintentional scheduling on ota test */ +}; + +/* Differentiator for ota_tx and ota_rx */ +enum { + WL_OTA_TEST_TX, /* ota_tx */ + WL_OTA_TEST_RX /* ota_rx */ +}; + +/* Catch 3 modes of operation: 20Mhz, 40Mhz, 20 in 40 Mhz */ +enum { + WL_OTA_TEST_BW_20_IN_40MHZ, /* 20 in 40 operation */ + WL_OTA_TEST_BW_20MHZ, /* 20 Mhz operation */ + WL_OTA_TEST_BW_40MHZ /* full 40Mhz operation */ +}; +typedef struct ota_rate_info { + uint8 rate_cnt; /* Total number of rates */ + uint8 rate_val_mbps[WL_OTA_TEST_MAX_NUM_RATE]; /* array of rates from 1mbps to 130mbps */ + /* for legacy rates : ratein mbps * 2 */ + /* for HT rates : mcs index */ +} ota_rate_info_t; + +typedef struct ota_power_info { + int8 pwr_ctrl_on; /* power control on/off */ + int8 start_pwr; /* starting power/index */ + int8 delta_pwr; /* delta power/index */ + int8 end_pwr; /* end power/index */ +} ota_power_info_t; + +typedef struct ota_packetengine { + uint16 delay; /* Inter-packet delay */ + /* for ota_tx, delay is tx ifs in micro seconds */ + /* for ota_rx, delay is wait time in milliseconds */ + uint16 nframes; /* Number of frames */ + uint16 length; /* Packet length */ +} ota_packetengine_t; + +/* Test info vector */ +typedef struct wl_ota_test_args { + uint8 cur_test; /* test phase */ + uint8 chan; /* channel */ + uint8 bw; /* bandwidth */ + char control_band; /* control band */ + uint8 stf_mode; /* stf mode */ + ota_rate_info_t rt_info; /* Rate info */ + ota_packetengine_t pkteng; /* packeteng info */ + uint8 txant; /* tx antenna */ + uint8 rxant; /* rx antenna */ + ota_power_info_t pwr_info; /* power sweep info */ + uint8 wait_for_sync; /* wait for sync or not */ +} wl_ota_test_args_t; + +typedef struct wl_ota_test_vector { + wl_ota_test_args_t test_arg[WL_OTA_TEST_MAX_NUM_SEQ]; /* Test argument struct */ + uint16 test_cnt; /* Total no of test */ + bool file_dwnld_valid; /* File successfully downloaded */ + uint8 sync_timeout; /* sync packet timeout */ + int8 sync_fail_action; /* sync fail action */ + struct ether_addr sync_mac; /* macaddress for sync pkt */ + struct ether_addr tx_mac; /* macaddress for tx */ + struct ether_addr rx_mac; /* macaddress for rx */ + int8 loop_test; /* dbg feature to loop the test */ +} wl_ota_test_vector_t; + + +/* struct copied back form dongle to host to query the status */ +typedef struct wl_ota_test_status { + int16 cur_test_cnt; /* test phase */ + int8 skip_test_reason; /* skip test reasoin */ + wl_ota_test_args_t test_arg; /* cur test arg details */ + uint16 test_cnt; /* total no of test downloaded */ + bool file_dwnld_valid; /* file successfully downloaded ? */ + uint8 sync_timeout; /* sync timeout */ + int8 sync_fail_action; /* sync fail action */ + struct ether_addr sync_mac; /* macaddress for sync pkt */ + struct ether_addr tx_mac; /* tx mac address */ + struct ether_addr rx_mac; /* rx mac address */ + uint8 test_stage; /* check the test status */ + int8 loop_test; /* Debug feature to puts test enfine in a loop */ + uint8 sync_status; /* sync status */ +} wl_ota_test_status_t; + +/* WL_OTA END */ + /* wl_radar_args_t */ typedef struct { int npulses; /* required number of pulses at n * t_int */ @@ -2258,168 +2418,168 @@ typedef struct { typedef struct txppr { /* start of 20MHz tx power limits */ - uint8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ - uint8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ - - uint8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ - uint8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ - - uint8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ - uint8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ - uint8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ - - uint8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ - uint8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ - uint8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ - uint8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ - uint8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ - uint8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ - uint8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ - uint8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + int8 b20_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ + int8 b20_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ + + int8 b20_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b20_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ + int8 b20_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b20_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ + + int8 b20_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b20_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ + int8 b20_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b20_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ + int8 b20_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ + + int8 b20_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ + int8 b20_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ + int8 b20_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ + int8 b20_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ + int8 b20_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ + int8 b20_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ + int8 b20_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ + int8 b20_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ /* start of 40MHz tx power limits */ - uint8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ - uint8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ - - uint8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ - uint8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ - - uint8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ - uint8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ - uint8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ - - uint8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ - uint8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ - uint8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ - uint8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ - uint8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ - uint8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ - uint8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ - uint8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + int8 b40_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ + int8 b40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ + + int8 b40_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ + int8 b40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ + + int8 b40_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ + int8 b40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ + int8 b40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ + + int8 b40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ + int8 b40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ + int8 b40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ + int8 b40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ + int8 b40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ + int8 b40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ + int8 b40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ + int8 b40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ /* start of 20in40MHz tx power limits */ - uint8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ - uint8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ - - uint8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ - uint8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ - - uint8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ - uint8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ - uint8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ - uint8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ - - uint8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ - uint8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ - uint8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ - uint8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ - uint8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ - uint8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ - uint8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ - uint8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + int8 b20in40_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20in40_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ + int8 b20in40_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ + + int8 b20in40_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20in40_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b20in40_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ + int8 b20in40_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b20in40_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ + + int8 b20in40_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20in40_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* 20 in 40 MHz Legacy OFDM CDD */ + int8 b20in40_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ + int8 b20in40_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b20in40_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ + int8 b20in40_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ + + int8 b20in40_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ + int8 b20in40_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ + int8 b20in40_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ + int8 b20in40_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ + int8 b20in40_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ + int8 b20in40_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ + int8 b20in40_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ + int8 b20in40_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ /* start of 80MHz tx power limits */ - uint8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ - uint8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ - - uint8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ - uint8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ - - uint8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ - uint8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ - uint8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ - - uint8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ - uint8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ - uint8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ - uint8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ - uint8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ - uint8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ - uint8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ - uint8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + int8 b80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ + int8 b80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ + + int8 b80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ + int8 b80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ + + int8 b80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ + int8 b80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ + int8 b80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ + + int8 b80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ + int8 b80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ + int8 b80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ + int8 b80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ + int8 b80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ + int8 b80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ + int8 b80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ + int8 b80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ /* start of 20in80MHz tx power limits */ - uint8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ - uint8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ - - uint8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ - uint8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ - - uint8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ - uint8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ - uint8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ - - uint8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ - uint8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ - uint8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ - uint8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ - uint8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ - uint8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ - uint8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ - uint8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + int8 b20in80_1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ + int8 b20in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ + + int8 b20in80_1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b20in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ + int8 b20in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b20in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ + + int8 b20in80_1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b20in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b20in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ + int8 b20in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b20in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ + int8 b20in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ + + int8 b20in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ + int8 b20in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ + int8 b20in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ + int8 b20in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ + int8 b20in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ + int8 b20in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ + int8 b20in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ + int8 b20in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ /* start of 40in80MHz tx power limits */ - uint8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ - uint8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ - - uint8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ - uint8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ - uint8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ - - uint8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ - uint8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ - uint8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ - uint8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ - uint8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ - uint8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ - - uint8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ - uint8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ - uint8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ - uint8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ - uint8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ - uint8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ - uint8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ - uint8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ - - uint8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ + int8 b40in80_dummy1x1dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b40in80_1x1ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM transmission */ + int8 b40in80_1x1mcs0[WL_NUM_RATES_MCS_1STREAM]; /* SISO MCS 0-7 */ + + int8 b40in80_dummy1x2dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b40in80_1x2cdd_ofdm[WL_NUM_RATES_OFDM]; /* Legacy OFDM CDD transmission */ + int8 b40in80_1x2cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* CDD MCS 0-7 */ + int8 b40in80_2x2stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b40in80_2x2sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* MCS 8-15 */ + + int8 b40in80_dummy1x3dsss[WL_NUM_RATES_CCK]; /* Legacy CCK/DSSS */ + int8 b40in80_1x3cdd_ofdm[WL_NUM_RATES_OFDM]; /* MHz Legacy OFDM CDD */ + int8 b40in80_1x3cdd_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* 1 Nsts to 3 Tx Chain */ + int8 b40in80_2x3stbc_mcs0[WL_NUM_RATES_MCS_1STREAM]; /* STBC MCS 0-7 */ + int8 b40in80_2x3sdm_mcs8[WL_NUM_RATES_MCS_1STREAM]; /* 2 Nsts to 3 Tx Chain */ + int8 b40in80_3x3sdm_mcs16[WL_NUM_RATES_MCS_1STREAM]; /* 3 Nsts to 3 Tx Chain */ + + int8 b40in80_1x1vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1 */ + int8 b40in80_1x2cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD1 */ + int8 b40in80_2x2stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC */ + int8 b40in80_2x2sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2 */ + int8 b40in80_1x3cdd_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_CDD2 */ + int8 b40in80_2x3stbc_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS1_STBC_SPEXP1 */ + int8 b40in80_2x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS2_SPEXP1 */ + int8 b40in80_3x3sdm_vht[WL_NUM_RATES_EXTRA_VHT]; /* VHT8_9SS3 */ + + int8 mcs32; /* C_CHECK - THIS NEEDS TO BE REMOVED THROUGHOUT THE CODE */ } txppr_t; /* 20MHz */ @@ -2601,45 +2761,35 @@ typedef struct txppr { #define WL_TX_POWER_MCS20_SISO_FIRST_SSN WL_TX_POWER_MCS20_SISO_FIRST #define WL_TX_POWER_MCS40_SISO_FIRST_SSN WL_TX_POWER_MCS40_SISO_FIRST -/* tx_power_t.flags bits */ -#define WL_TX_POWER_F_ENABLED 1 -#define WL_TX_POWER_F_HW 2 -#define WL_TX_POWER_F_MIMO 4 -#define WL_TX_POWER_F_SISO 8 -#define WL_TX_POWER_F_HT 0x10 - typedef struct { uint16 ver; /* version of this struct */ uint16 len; /* length in bytes of this structure */ uint32 flags; chanspec_t chanspec; /* txpwr report for this channel */ chanspec_t local_chanspec; /* channel on which we are associated */ - uint8 ppr[WL_TX_POWER_RATES]; /* Latest target power */ + uint32 buflen; /* ppr buffer length */ + uint8 pprbuf[1]; /* Latest target power buffer buffer */ } wl_txppr_t; #define WL_TXPPR_VERSION 0 #define WL_TXPPR_LENGTH (sizeof(wl_txppr_t)) -#define TX_POWER_T_VERSION 43 +#define TX_POWER_T_VERSION 44 /* Defines used with channel_bandwidth for curpower */ #define WL_BW_20MHZ 0 #define WL_BW_40MHZ 1 #define WL_BW_80MHZ 2 +#define WL_BW_160MHZ 3 /* tx_power_t.flags bits */ -#ifdef PPR_API -#define WL_TX_POWER2_F_ENABLED 1 -#define WL_TX_POWER2_F_HW 2 -#define WL_TX_POWER2_F_MIMO 4 -#define WL_TX_POWER2_F_SISO 8 -#define WL_TX_POWER2_F_HT 0x10 -#else +/* use for defined PPR_API */ #define WL_TX_POWER_F_ENABLED 1 #define WL_TX_POWER_F_HW 2 #define WL_TX_POWER_F_MIMO 4 #define WL_TX_POWER_F_SISO 8 #define WL_TX_POWER_F_HT 0x10 -#endif +#define WL_TX_POWER_F_VHT 0x20 + typedef struct { uint32 flags; chanspec_t chanspec; /* txpwr report for this channel */ @@ -2649,9 +2799,7 @@ typedef struct { int8 antgain[2]; /* Ant gain for each band - from SROM */ uint8 rf_cores; /* count of RF Cores being reported */ uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ - uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain - * without adjustment - */ + uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ uint8 tx_power_max[4]; /* Maximum target power among all rates */ uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ @@ -2665,11 +2813,10 @@ typedef struct { int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ uint8 version; /* Version of the data format wlu <--> driver */ uint8 display_core; /* Displayed curpower core */ -#ifdef PPR_API -} tx_power_new_t; -#else + int8 target_offsets[4]; /* Target power offsets for current rate per core */ + uint32 last_tx_ratespec; /* Ratespec for last transmition */ + int8 SARLIMIT[MAX_STREAMS_SUPPORTED]; } tx_power_t; -#endif typedef struct tx_inst_power { uint8 txpwr_est_Pout[2]; /* Latest estimate for 2.4 and 5 Ghz */ @@ -2813,6 +2960,11 @@ typedef struct wl_txchain_pwr_offsets { #define WL_TBTT_VAL 0x00010000 #define WL_NIC_VAL 0x00020000 #define WL_PWRSEL_VAL 0x00040000 +#define WL_TRF_MGMT_VAL 0x00080000 +#define WL_L2FILTER_VAL 0x00100000 +#define WL_TSO_VAL 0x00200000 +#define WL_MQ_VAL 0x00400000 + /* use top-bit for WL_TIME_STAMP_VAL because this is a modifier * rather than a message-type of its own */ @@ -2845,7 +2997,9 @@ typedef struct wl_txchain_pwr_offsets { #define WL_LED_ASSOC_WITH_SEC 20 /* when connected with security */ /* keep on for 300 sec */ #define WL_LED_START_OFF 21 /* off upon boot, could be turned on later */ -#define WL_LED_NUMBEHAVIOR 22 +#define WL_LED_W6 22 /* off upon boot, could be turned on later */ +#define WL_LED_WI7 23 /* off upon boot, could be turned on later */ +#define WL_LED_NUMBEHAVIOR 24 /* led behavior numeric value format */ #define WL_LED_BEH_MASK 0x7f /* behavior mask */ @@ -2903,7 +3057,7 @@ typedef struct wl_txchain_pwr_offsets { * * 4. BAND RSSI - 2 octets * offset 0: band types - * offset 1: +ve RSSI boost balue in dB + * offset 1: +ve RSSI boost value in dB */ /* join preference types */ @@ -3167,6 +3321,12 @@ typedef struct { uint32 pstatxbcmc; /* count of bcmc frames transmitted on all psta */ uint32 cso_passthrough; /* hw cso required but passthrough */ + uint32 chained; /* number of frames chained */ + uint32 chainedsz1; /* number of chain size 1 frames */ + uint32 unchained; /* number of frames not chained */ + uint32 maxchainsz; /* max chain size so far */ + uint32 currchainsz; /* current chain size */ + uint32 cso_normal; /* hw cso hdr for normal process */ } wl_cnt_t; #ifndef LINUX_POSTMOGRIFY_REMOVAL @@ -3607,13 +3767,14 @@ struct tslist { #ifdef WLTDLS /* different ops for manual end point */ -#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ -#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ -#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ +#define TDLS_MANUAL_EP_CREATE 1 /* create manual dpt endpoint */ +#define TDLS_MANUAL_EP_MODIFY 2 /* modify manual dpt endpoint */ +#define TDLS_MANUAL_EP_DELETE 3 /* delete manual dpt endpoint */ #define TDLS_MANUAL_EP_PM 4 /* put dpt endpoint in PM mode */ #define TDLS_MANUAL_EP_WAKE 5 /* wake up dpt endpoint from PM */ #define TDLS_MANUAL_EP_DISCOVERY 6 /* discover if endpoint is TDLS capable */ #define TDLS_MANUAL_EP_CHSW 7 /* channel switch */ +#define TDLS_MANUAL_EP_WFD_TPQ 8 /* WiFi-Display Tunneled Probe reQuest */ /* structure for tdls iovars */ typedef struct tdls_iovar { @@ -3624,14 +3785,16 @@ typedef struct tdls_iovar { } tdls_iovar_t; /* modes */ -#define TDLS_WFD_IE_TX 0 -#define TDLS_WFD_IE_RX 1 -#define TDLS_WFD_IE_SIZE 255 +#define TDLS_WFD_IE_TX 0 +#define TDLS_WFD_IE_RX 1 +#define TDLS_WFD_PROBE_IE_TX 2 +#define TDLS_WFD_PROBE_IE_RX 3 +#define TDLS_WFD_IE_SIZE 512 /* structure for tdls wfd ie */ typedef struct tdls_wfd_ie_iovar { struct ether_addr ea; /* Station address */ uint8 mode; - uint8 length; + uint16 length; uint8 data[TDLS_WFD_IE_SIZE]; } tdls_wfd_ie_iovar_t; #endif /* WLTDLS */ @@ -3701,11 +3864,11 @@ typedef struct wme_max_bandwidth { /* Software feature flag defines used by wlfeatureflag */ #ifdef WLAFTERBURNER -#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ -#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ +#define WL_SWFL_ABBFL 0x0001 /* Allow Afterburner on systems w/o hardware BFL */ +#define WL_SWFL_ABENCORE 0x0002 /* Allow AB on non-4318E chips */ #endif /* WLAFTERBURNER */ #define WL_SWFL_NOHWRADIO 0x0004 -#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ +#define WL_SWFL_FLOWCONTROL 0x0008 /* Enable backpressure to OS stack */ #define WL_SWFL_WLBSSSORT 0x0010 /* Per-port supports sorting of BSS */ #define WL_LIFETIME_MAX 0xFFFF /* Max value in ms */ @@ -3773,8 +3936,8 @@ enum { #define ENABLE_NET_OFFLOAD_BIT 10 #define SORT_CRITERIA_MASK 0x0001 -#define AUTO_NET_SWITCH_MASK 0x0002 -#define ENABLE_BKGRD_SCAN_MASK 0x0004 +#define AUTO_NET_SWITCH_MASK 0x0002 +#define ENABLE_BKGRD_SCAN_MASK 0x0004 #define IMMEDIATE_SCAN_MASK 0x0008 #define AUTO_CONNECT_MASK 0x0010 @@ -3784,7 +3947,7 @@ enum { #define SUPPRESS_SSID_MASK 0x0200 #define ENABLE_NET_OFFLOAD_MASK 0x0400 -#define PFN_VERSION 2 +#define PFN_VERSION 2 #define PFN_SCANRESULT_VERSION 1 #define MAX_PFN_LIST_COUNT 16 @@ -3794,7 +3957,7 @@ enum { #define DEFAULT_BESTN 2 #define DEFAULT_MSCAN 0 #define DEFAULT_REPEAT 10 -#define DEFAULT_EXP 2 +#define DEFAULT_EXP 2 /* PFN network info structure */ typedef struct wl_pfn_subnet_info { @@ -3822,54 +3985,56 @@ typedef struct wl_pfn_param { int32 version; /* PNO parameters version */ int32 scan_freq; /* Scan frequency */ int32 lost_network_timeout; /* Timeout in sec. to declare - * discovered network as lost - */ + * discovered network as lost + */ int16 flags; /* Bit field to control features - * of PFN such as sort criteria auto - * enable switch and background scan - */ + * of PFN such as sort criteria auto + * enable switch and background scan + */ int16 rssi_margin; /* Margin to avoid jitter for choosing a - * PFN based on RSSI sort criteria - */ - uint8 bestn; /* number of best networks in each scan */ - uint8 mscan; /* number of scans recorded */ - uint8 repeat; /* Minimum number of scan intervals - *before scan frequency changes in adaptive scan - */ - uint8 exp; /* Exponent of 2 for maximum scan interval */ - int32 slow_freq; /* slow scan period */ + * PFN based on RSSI sort criteria + */ + uint8 bestn; /* number of best networks in each scan */ + uint8 mscan; /* number of scans recorded */ + uint8 repeat; /* Minimum number of scan intervals + *before scan frequency changes in adaptive scan + */ + uint8 exp; /* Exponent of 2 for maximum scan interval */ + int32 slow_freq; /* slow scan period */ } wl_pfn_param_t; typedef struct wl_pfn_bssid { - struct ether_addr macaddr; + struct ether_addr macaddr; /* Bit4: suppress_lost, Bit3: suppress_found */ - uint16 flags; + uint16 flags; } wl_pfn_bssid_t; #define WL_PFN_SUPPRESSFOUND_MASK 0x08 #define WL_PFN_SUPPRESSLOST_MASK 0x10 +#define WL_PFN_RSSI_MASK 0xff00 +#define WL_PFN_RSSI_SHIFT 8 typedef struct wl_pfn_cfg { - uint32 reporttype; - int32 channel_num; - uint16 channel_list[WL_NUMCHANNELS]; + uint32 reporttype; + int32 channel_num; + uint16 channel_list[WL_NUMCHANNELS]; } wl_pfn_cfg_t; -#define WL_PFN_REPORT_ALLNET 0 -#define WL_PFN_REPORT_SSIDNET 1 -#define WL_PFN_REPORT_BSSIDNET 2 +#define WL_PFN_REPORT_ALLNET 0 +#define WL_PFN_REPORT_SSIDNET 1 +#define WL_PFN_REPORT_BSSIDNET 2 typedef struct wl_pfn { - wlc_ssid_t ssid; /* ssid name and its length */ - int32 flags; /* bit2: hidden */ - int32 infra; /* BSS Vs IBSS */ - int32 auth; /* Open Vs Closed */ - int32 wpa_auth; /* WPA type */ - int32 wsec; /* wsec value */ + wlc_ssid_t ssid; /* ssid name and its length */ + int32 flags; /* bit2: hidden */ + int32 infra; /* BSS Vs IBSS */ + int32 auth; /* Open Vs Closed */ + int32 wpa_auth; /* WPA type */ + int32 wsec; /* wsec value */ } wl_pfn_t; -#define WL_PFN_HIDDEN_BIT 2 +#define WL_PFN_HIDDEN_BIT 2 #define PNO_SCAN_MAX_FW 508*1000 /* max time scan time in msec */ #define PNO_SCAN_MAX_FW_SEC PNO_SCAN_MAX_FW/1000 /* max time scan time in SEC */ -#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ -#define WL_PFN_HIDDEN_MASK 0x4 +#define PNO_SCAN_MIN_FW_SEC 10 /* min time scan time in SEC */ +#define WL_PFN_HIDDEN_MASK 0x4 #endif /* LINUX_POSTMOGRIFY_REMOVAL */ @@ -3925,7 +4090,7 @@ struct toe_ol_stats_t { #define ARP_ERRTEST_REPLY_HOST 0x2 #define ARP_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ -#define ND_MULTIHOMING_MAX 8 /* Maximum local host IP addresses */ +#define ND_MULTIHOMING_MAX 10 /* Maximum local host IP addresses */ /* Arp offload statistic counts */ struct arp_ol_stats_t { @@ -4065,6 +4230,8 @@ typedef struct wl_seq_cmd_ioctl { #define WL_PKTENG_SYNCHRONOUS 0x100 /* synchronous flag */ +#define WL_PKTENG_MAXPKTSZ 16384 /* max pktsz limit for pkteng */ + typedef struct wl_pkteng { uint32 flags; uint32 delay; /* Inter-packet delay */ @@ -4107,14 +4274,14 @@ typedef struct wl_pkteng_stats { #define MAGIC_PKT_MINLEN 102 /* Magic pkt min length is 6 * 0xFF + 16 * ETHER_ADDR_LEN */ #define WOWL_PATTEN_TYPE_ARP (1 << 0) /* ARP offload Pattern */ -#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ +#define WOWL_PATTEN_TYPE_NA (1 << 1) /* NA offload Pattern */ typedef struct { uint32 masksize; /* Size of the mask in #of bytes */ uint32 offset; /* Offset to start looking for the packet in # of bytes */ - uint32 patternoffset; /* Offset of start of pattern in the structure */ + uint32 patternoffset; /* Offset of start of pattern in the structure */ uint32 patternsize; /* Size of the pattern itself in #of bytes */ - uint32 id; /* id */ + uint32 id; /* id */ uint32 reasonsize; /* Size of the wakeup reason code */ uint32 flags; /* Flags to tell the pattern type and other properties */ /* Mask follows the structure above */ @@ -4248,6 +4415,37 @@ typedef struct { uint32 queue_capacity; /* the maximum capacity of the queue */ } pktq_log_counters_v01_t; +typedef struct { + uint32 requested; /* packets requested to be stored */ + uint32 stored; /* packets stored */ + uint32 saved; /* packets saved, + because a lowest priority queue has given away one packet + */ + uint32 selfsaved; /* packets saved, + because an older packet from the same queue has been dropped + */ + uint32 full_dropped; /* packets dropped, + because pktq is full with higher precedence packets + */ + uint32 dropped; /* packets dropped because pktq per that precedence is full */ + uint32 sacrificed; /* packets dropped, + in order to save one from a queue of a highest priority + */ + uint32 busy; /* packets droped because of hardware/transmission error */ + uint32 retry; /* packets re-sent because they were not received */ + uint32 ps_retry; /* packets retried again prior to moving power save mode */ + uint32 retry_drop; /* packets finally dropped after retry limit */ + uint32 max_avail; /* the high-water mark of the queue capacity for packets - + goes to zero as queue fills + */ + uint32 max_used; /* the high-water mark of the queue utilisation for packets - + increases with use ('inverse' of max_avail) + */ + uint32 queue_capacity; /* the maximum capacity of the queue */ + uint32 rtsfail; /* count of rts attempts that failed to receive cts */ + uint32 acked; /* count of packets sent (acked) successfully */ +} pktq_log_counters_v02_t; + #define sacrified sacrificed typedef struct { @@ -4256,12 +4454,21 @@ typedef struct { char headings[1]; } pktq_log_format_v01_t; +typedef struct { + uint8 num_prec[WL_IOV_MAC_PARAM_LEN]; + pktq_log_counters_v02_t counters[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; + uint32 throughput[WL_IOV_MAC_PARAM_LEN][WL_IOV_PKTQ_LOG_PRECS]; + uint32 time_delta; + char headings[1]; +} pktq_log_format_v02_t; + typedef struct { uint32 version; wl_iov_mac_params_t params; union { pktq_log_format_v01_t v01; + pktq_log_format_v02_t v02; } pktq_log; } wl_iov_pktq_log_t; @@ -4419,6 +4626,21 @@ typedef struct { #define VNDR_IE_IWAPID_FLAG 0x40 /* vendor IE in IW advertisement protocol ID field */ #define VNDR_IE_CUSTOM_FLAG 0x100 /* allow custom IE id */ +#if defined(WLP2P) +/* P2P Action Frames flags (spec ordered) */ +#define VNDR_IE_GONREQ_FLAG 0x001000 +#define VNDR_IE_GONRSP_FLAG 0x002000 +#define VNDR_IE_GONCFM_FLAG 0x004000 +#define VNDR_IE_INVREQ_FLAG 0x008000 +#define VNDR_IE_INVRSP_FLAG 0x010000 +#define VNDR_IE_DISREQ_FLAG 0x020000 +#define VNDR_IE_DISRSP_FLAG 0x040000 +#define VNDR_IE_PRDREQ_FLAG 0x080000 +#define VNDR_IE_PRDRSP_FLAG 0x100000 + +#define VNDR_IE_P2PAF_SHIFT 12 +#endif /* WLP2P */ + #define VNDR_IE_INFO_HDR_LEN (sizeof(uint32)) typedef BWL_PRE_PACKED_STRUCT struct { @@ -4493,6 +4715,35 @@ typedef BWL_PRE_PACKED_STRUCT struct { } BWL_POST_PACKED_STRUCT txfailinfo_t; #endif /* WLMEDIA_TXFAILEVENT */ +typedef BWL_PRE_PACKED_STRUCT struct { + uint32 flags; + chanspec_t chanspec; /* txpwr report for this channel */ + chanspec_t local_chanspec; /* channel on which we are associated */ + uint8 local_max; /* local max according to the AP */ + uint8 local_constraint; /* local constraint according to the AP */ + int8 antgain[2]; /* Ant gain for each band - from SROM */ + uint8 rf_cores; /* count of RF Cores being reported */ + uint8 est_Pout[4]; /* Latest tx power out estimate per RF chain */ + uint8 est_Pout_act[4]; /* Latest tx power out estimate per RF chain w/o adjustment */ + uint8 est_Pout_cck; /* Latest CCK tx power out estimate */ + uint8 tx_power_max[4]; /* Maximum target power among all rates */ + uint tx_power_max_rate_ind[4]; /* Index of the rate with the max target power */ + int8 clm_limits[WL_NUMRATES]; /* regulatory limits - 20, 40 or 80MHz */ + int8 clm_limits_subchan1[WL_NUMRATES]; /* regulatory limits - 20in40 or 40in80 */ + int8 clm_limits_subchan2[WL_NUMRATES]; /* regulatory limits - 20in80MHz */ + int8 sar; /* SAR limit for display by wl executable */ + int8 channel_bandwidth; /* 20, 40 or 80 MHz bandwidth? */ + uint8 version; /* Version of the data format wlu <--> driver */ + uint8 display_core; /* Displayed curpower core */ + int8 target_offsets[4]; /* Target power offsets for current rate per core */ + uint32 last_tx_ratespec; /* Ratespec for last transmition */ + uint user_target; /* user limit */ + uint32 board_limit_len; /* length of board limit buffer */ + uint32 target_len; /* length of target power buffer */ + int8 SARLIMIT[MAX_STREAMS_SUPPORTED]; + uint8 pprdata[1]; /* ppr serialization buffer */ +} BWL_POST_PACKED_STRUCT tx_pwr_rpt_t; + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ /* no strict structure packing */ @@ -4545,10 +4796,12 @@ struct wapi_sta_msg_t /* define for apcs reason code */ #define APCS_INIT 0 -#define APCS_IOCTL 1 -#define APCS_CHANIM 2 +#define APCS_IOCTL 1 +#define APCS_CHANIM 2 #define APCS_CSTIMER 3 #define APCS_BTA 4 +#define APCS_TXDLY 5 +#define APCS_NONACSD 6 /* number of ACS record entries */ #define CHANIM_ACS_RECORD 10 @@ -4820,7 +5073,9 @@ typedef struct wl_nic_cnx { uint8 SSID_len; uint8 SSID[32]; struct ether_addr abssid; - uint8 join_period; + uint16 beacon_interval; + uint16 sync_threshold; + uint16 beacon_wait_time; } wl_nic_cnx_t; /* opcode */ @@ -4834,16 +5089,23 @@ typedef struct wl_nic_cnx { typedef struct wl_nic_cfg { uint8 version; uint8 beacon_mode; - uint16 beacon_interval; uint8 diluted_beacon_period; - uint8 repeat_EQC; + uint8 beacon_probability; + uint8 num_awake_window_params; + struct { + uint8 channel_number; + uint8 awake_window_length; + uint8 repeat_EQC; + } awake_window_params[3]; uint8 scan_length; uint8 scan_interval; uint8 scan_probability; - uint8 awake_window_length; - int8 TSF_correction; uint8 ASID; uint8 channel_usage_mode; + uint8 CWmin_af; + uint8 NIC_priority; + uint8 NIC_data_ind; + uint8 allowed_wakeup_delay; } wl_nic_cfg_t; /* version */ @@ -4865,7 +5127,6 @@ typedef struct wl_nic_frm { } wl_nic_frm_t; /* type */ -#define WL_NIC_FRM_MYNET 1 #define WL_NIC_FRM_ACTION 2 /* i/f query */ @@ -4878,8 +5139,17 @@ typedef struct wl_nic_ifq { /* nic_dm iovar */ typedef struct wl_nic_dm { uint8 enab; + uint8 rsvd; + /* the following fields are valid when enabling... */ chanspec_t chspec; + uint8 DATA_priority; + uint8 NIC_priority; } wl_nic_dm_t; + +/* immediate scan request */ +typedef struct wl_nic_isq { + uint8 scan_length; +} wl_nic_isq_t; #endif /* WLNIC */ /* RFAWARE def */ @@ -5024,6 +5294,13 @@ enum { SPATIAL_MODE_MAX_IDX }; +#define WLC_TXCORE_MAX 4 /* max number of txcore supports */ +#define WLC_SUBBAND_MAX 4 /* max number of sub-band supports */ +typedef struct { + uint8 band2g[WLC_TXCORE_MAX]; + uint8 band5g[WLC_SUBBAND_MAX][WLC_TXCORE_MAX]; +} sar_limit_t; + /* IOVAR "mempool" parameter. Used to retrieve a list of memory pool statistics. */ typedef struct wl_mempool_stats { int num; /* Number of memory pools */ @@ -5059,15 +5336,23 @@ typedef struct { #define TRF_MGMT_MAX_PRIORITIES 3 #define TRF_MGMT_FLAG_ADD_DSCP 0x0001 /* Add DSCP to IP TOS field */ -#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Only support traffic clasification */ -#define TRF_MGMT_FLAG_DISABLE_PRIORITY_TAGGING 0x0004 /* Don't override packet's priority */ +#define TRF_MGMT_FLAG_DISABLE_SHAPING 0x0002 /* Don't shape traffic */ +#define TRF_MGMT_FLAG_MANAGE_LOCAL_TRAFFIC 0x0008 /* Manage traffic over our local subnet */ +#define TRF_MGMT_FLAG_FILTER_ON_MACADDR 0x0010 /* filter on MAC address */ +#define TRF_MGMT_FLAG_NO_RX 0x0020 /* do not apply fiters to rx packets */ + +#define TRF_FILTER_MAC_ADDR 0x0001 /* L2 filter use dst mac address for filtering */ +#define TRF_FILTER_IP_ADDR 0x0002 /* L3 filter use ip ddress for filtering */ +#define TRF_FILTER_L4 0x0004 /* L4 filter use tcp/udp for filtering */ +#define TRF_FILTER_FAVORED 0x0010 /* Tag the packet FAVORED */ /* Traffic management priority classes */ typedef enum trf_mgmt_priority_class { - trf_mgmt_priority_low = 0, /* Maps to 802.1p BO */ - trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ - trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ - trf_mgmt_priority_invalid = (trf_mgmt_priority_high + 1) + trf_mgmt_priority_low = 0, /* Maps to 802.1p BK */ + trf_mgmt_priority_medium = 1, /* Maps to 802.1p BE */ + trf_mgmt_priority_high = 2, /* Maps to 802.1p VI */ + trf_mgmt_priority_nochange = 3, /* do not update the priority */ + trf_mgmt_priority_invalid = (trf_mgmt_priority_nochange + 1) } trf_mgmt_priority_class_t; /* Traffic management configuration parameters */ @@ -5149,5 +5434,91 @@ typedef struct powersel_params { uint8 pwr_sel_exp_time; /* Time lapse for expiry of database */ } powersel_params_t; +/* tx pkt delay statistics */ +#define SCB_RETRY_SHORT_DEF 7 /* Default Short retry Limit */ +#define WLPKTDLY_HIST_NBINS 16 /* number of bins used in the Delay histogram */ + +/* structure to store per-AC delay statistics */ +typedef struct scb_delay_stats { + uint32 txmpdu_lost; /* number of MPDUs lost */ + uint32 txmpdu_cnt[SCB_RETRY_SHORT_DEF]; /* retry times histogram */ + uint32 delay_sum[SCB_RETRY_SHORT_DEF]; /* cumulative packet latency */ + uint32 delay_min; /* minimum packet latency observed */ + uint32 delay_max; /* maximum packet latency observed */ + uint32 delay_avg; /* packet latency average */ + uint32 delay_hist[WLPKTDLY_HIST_NBINS]; /* delay histogram */ +} scb_delay_stats_t; + +/* structure for txdelay event */ +typedef struct txdelay_event { + uint8 status; + int rssi; + chanim_stats_t chanim_stats; + scb_delay_stats_t delay_stats[AC_COUNT]; +} txdelay_event_t; + +/* structure for txdelay parameters */ +typedef struct txdelay_params { + uint16 ratio; /* Avg Txdelay Delta */ + uint8 cnt; /* Sample cnt */ + uint8 period; /* Sample period */ + uint8 tune; /* Debug */ +} txdelay_params_t; + #endif /* LINUX_POSTMOGRIFY_REMOVAL */ + +/* fbt_cap: FBT assoc / reassoc modes. */ +#define WLC_FBT_CAP_DRV_4WAY_AND_REASSOC 1 /* Driver 4-way handshake & reassoc (WLFBT). */ + +typedef struct bcnreq { + uint8 bcn_mode; + int dur; + int channel; + struct ether_addr da; + uint16 random_int; + wlc_ssid_t ssid; + uint16 reps; +} bcnreq_t; + +typedef struct rrmreq { + struct ether_addr da; + uint8 reg; + uint8 chan; + uint16 random_int; + uint16 dur; + uint16 reps; +} rrmreq_t; + +typedef struct framereq { + struct ether_addr da; + uint8 reg; + uint8 chan; + uint16 random_int; + uint16 dur; + struct ether_addr ta; + uint16 reps; +} framereq_t; + +typedef struct statreq { + struct ether_addr da; + struct ether_addr peer; + uint16 random_int; + uint16 dur; + uint8 group_id; + uint16 reps; +} statreq_t; + +#ifdef EVENT_LOG_COMPILE +typedef struct wlc_event_log_set_s { + uint8 set; /* Set number */ + uint32 size; /* Size to make/expand */ +} wlc_event_log_set_t; + +typedef struct wlc_event_log_tag_s { + uint16 tag; + uint8 set; + uint8 flags; +} wlc_event_log_tag_t; +#endif /* EVENT_LOG_COMPILE */ + #endif /* _wlioctl_h_ */ diff --git a/drivers/net/wireless/bcmdhd/linux_osl.c b/drivers/net/wireless/bcmdhd/linux_osl.c index d03a095..32f03d9 100644 --- a/drivers/net/wireless/bcmdhd/linux_osl.c +++ b/drivers/net/wireless/bcmdhd/linux_osl.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: linux_osl.c 355147 2012-09-05 15:03:49Z $ + * $Id: linux_osl.c 390461 2013-03-12 07:21:34Z $ */ #define LINUX_PORT @@ -35,10 +35,6 @@ #include <linux/delay.h> #include <pcicfg.h> -#ifdef BCMASSERT_LOG -#include <bcm_assert_log.h> -#endif - #include <linux/fs.h> @@ -48,7 +44,7 @@ #define BCM_MEM_FILENAME_LEN 24 #ifdef CONFIG_DHD_USE_STATIC_BUF -#define DHD_SKB_HDRSIZE 336 +#define DHD_SKB_HDRSIZE 336 #define DHD_SKB_1PAGE_BUFSIZE ((PAGE_SIZE*1)-DHD_SKB_HDRSIZE) #define DHD_SKB_2PAGE_BUFSIZE ((PAGE_SIZE*2)-DHD_SKB_HDRSIZE) #define DHD_SKB_4PAGE_BUFSIZE ((PAGE_SIZE*4)-DHD_SKB_HDRSIZE) @@ -72,7 +68,7 @@ static bcm_static_buf_t *bcm_static_buf = 0; #else #define STATIC_PKT_4PAGE_NUM 0 #define DHD_SKB_MAX_BUFSIZE DHD_SKB_2PAGE_BUFSIZE -#endif +#endif typedef struct bcm_static_pkt { struct sk_buff *skb_4k[STATIC_PKT_MAX_NUM]; @@ -104,6 +100,7 @@ struct osl_info { uint magic; void *pdev; atomic_t malloced; + atomic_t pktalloced; uint failed; uint bustype; bcm_mem_link_t *dbgmem_list; @@ -111,6 +108,16 @@ struct osl_info { spinlock_t pktalloc_lock; }; +#define OSL_PKTTAG_CLEAR(p) \ +do { \ + struct sk_buff *s = (struct sk_buff *)(p); \ + ASSERT(OSL_PKTTAG_SZ == 32); \ + *(uint32 *)(&s->cb[0]) = 0; *(uint32 *)(&s->cb[4]) = 0; \ + *(uint32 *)(&s->cb[8]) = 0; *(uint32 *)(&s->cb[12]) = 0; \ + *(uint32 *)(&s->cb[16]) = 0; *(uint32 *)(&s->cb[20]) = 0; \ + *(uint32 *)(&s->cb[24]) = 0; *(uint32 *)(&s->cb[28]) = 0; \ +} while (0) + @@ -188,14 +195,9 @@ osl_t * osl_attach(void *pdev, uint bustype, bool pkttag) { osl_t *osh; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - osh = kmalloc(sizeof(osl_t), flags); -#else - osh = kmalloc(sizeof(osl_t), GFP_ATOMIC); -#endif + if (!(osh = kmalloc(sizeof(osl_t), GFP_ATOMIC))) + return osh; ASSERT(osh); @@ -252,9 +254,9 @@ osl_attach(void *pdev, uint bustype, bool pkttag) bcm_static_skb = (bcm_static_pkt_t *)((char *)bcm_static_buf + 2048); skb_buff_ptr = dhd_os_prealloc(osh, 4, 0); - bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *)* + bcopy(skb_buff_ptr, bcm_static_skb, sizeof(struct sk_buff *) * (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM)); - for (i = 0; i < (STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM); i++) + for (i = 0; i < STATIC_PKT_MAX_NUM * 2 + STATIC_PKT_4PAGE_NUM; i++) bcm_static_skb->pkt_use[i] = 0; sema_init(&bcm_static_skb->osl_pkt_sem, 1); @@ -288,9 +290,10 @@ osl_detach(osl_t *osh) static struct sk_buff *osl_alloc_skb(unsigned int len) { #if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25) - gfp_t flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; + struct sk_buff *skb; - return __dev_alloc_skb(len, flags); + skb = __dev_alloc_skb(len, GFP_ATOMIC); + return skb; #else return dev_alloc_skb(len); #endif @@ -370,14 +373,7 @@ osl_ctfpool_replenish(osl_t *osh, uint thresh) int32 osl_ctfpool_init(osl_t *osh, uint numobj, uint size) { -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; - - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - osh->ctfpool = kmalloc(sizeof(ctfpool_t), flags); -#else osh->ctfpool = kmalloc(sizeof(ctfpool_t), GFP_ATOMIC); -#endif ASSERT(osh->ctfpool); bzero(osh->ctfpool, sizeof(ctfpool_t)); @@ -498,6 +494,9 @@ osl_pktfastget(osl_t *osh, uint len) #endif atomic_set(&skb->users, 1); + PKTSETCLINK(skb, NULL); + PKTCCLRATTR(skb); + return skb; } #endif @@ -505,22 +504,15 @@ osl_pktfastget(osl_t *osh, uint len) struct sk_buff * BCMFASTPATH osl_pkt_tonative(osl_t *osh, void *pkt) { -#ifndef WL_UMK struct sk_buff *nskb; - unsigned long flags; -#endif if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); + OSL_PKTTAG_CLEAR(pkt); -#ifndef WL_UMK for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced--; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_sub(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); } -#endif return (struct sk_buff *)pkt; } @@ -528,22 +520,15 @@ osl_pkt_tonative(osl_t *osh, void *pkt) void * BCMFASTPATH osl_pkt_frmnative(osl_t *osh, void *pkt) { -#ifndef WL_UMK struct sk_buff *nskb; - unsigned long flags; -#endif if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)pkt)->cb, OSL_PKTTAG_SZ); + OSL_PKTTAG_CLEAR(pkt); -#ifndef WL_UMK for (nskb = (struct sk_buff *)pkt; nskb; nskb = nskb->next) { - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced++; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_add(PKTISCHAINED(nskb) ? PKTCCNT(nskb) : 1, &osh->pktalloced); } -#endif return (void *)pkt; } @@ -552,7 +537,6 @@ void * BCMFASTPATH osl_pktget(osl_t *osh, uint len) { struct sk_buff *skb; - unsigned long flags; #ifdef CTFPOOL @@ -564,10 +548,7 @@ osl_pktget(osl_t *osh, uint len) skb_put(skb, len); skb->priority = 0; - - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced++; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_inc(&osh->pktalloced); } return ((void*) skb); @@ -590,10 +571,17 @@ osl_pktfastfree(osl_t *osh, struct sk_buff *skb) skb->dev = NULL; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 36) skb->dst = NULL; - memset(skb->cb, 0, sizeof(skb->cb)); +#endif + OSL_PKTTAG_CLEAR(skb); skb->ip_summed = 0; + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 36) + skb_orphan(skb); +#else skb->destructor = NULL; +#endif ctfpool = (ctfpool_t *)CTFPOOLPTR(osh, skb); ASSERT(ctfpool != NULL); @@ -616,7 +604,11 @@ void BCMFASTPATH osl_pktfree(osl_t *osh, void *p, bool send) { struct sk_buff *skb, *nskb; - unsigned long flags; + if (osh == NULL) + { + printk("%s: osh == NULL \n", __FUNCTION__); + return; + } skb = (struct sk_buff*) p; @@ -647,9 +639,7 @@ osl_pktfree(osl_t *osh, void *p, bool send) dev_kfree_skb(skb); } - spin_lock_irqsave(&osh->pktalloc_lock, flags); - osh->pub.pktalloced--; - spin_unlock_irqrestore(&osh->pktalloc_lock, flags); + atomic_dec(&osh->pktalloced); skb = nskb; } } @@ -661,10 +651,8 @@ osl_pktget_static(osl_t *osh, uint len) int i = 0; struct sk_buff *skb; - if (len > DHD_SKB_MAX_BUFSIZE) { - printk("osl_pktget_static: Do we really need this big skb??" - " len=%d\n", len); + printk("%s: attempt to allocate huge packet (0x%x)\n", __FUNCTION__, len); return osl_pktget(osh, len); } @@ -689,7 +677,6 @@ osl_pktget_static(osl_t *osh, uint len) } if (len <= DHD_SKB_2PAGE_BUFSIZE) { - for (i = 0; i < STATIC_PKT_MAX_NUM; i++) { if (bcm_static_skb->pkt_use[i + STATIC_PKT_MAX_NUM] == 0) @@ -721,7 +708,7 @@ osl_pktget_static(osl_t *osh, uint len) #endif up(&bcm_static_skb->osl_pkt_sem); - printk("osl_pktget_static: all static pkt in use!\n"); + printk("%s: all static pkt in use!\n", __FUNCTION__); return osl_pktget(osh, len); } @@ -752,15 +739,13 @@ osl_pktfree_static(osl_t *osh, void *p, bool send) } #ifdef ENHANCED_STATIC_BUF if (p == bcm_static_skb->skb_16k) { - bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM*2] = 0; + bcm_static_skb->pkt_use[STATIC_PKT_MAX_NUM * 2] = 0; up(&bcm_static_skb->osl_pkt_sem); return; } #endif up(&bcm_static_skb->osl_pkt_sem); - osl_pktfree(osh, p, send); - return; } #endif @@ -820,7 +805,11 @@ osl_pci_slot(osl_t *osh) { ASSERT(osh && (osh->magic == OS_HANDLE_MAGIC) && osh->pdev); +#if defined(__ARM_ARCH_7A__) && LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 35) + return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn) + 1; +#else return PCI_SLOT(((struct pci_dev *)osh->pdev)->devfn); +#endif } @@ -853,9 +842,6 @@ void * osl_malloc(osl_t *osh, uint size) { void *addr; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; -#endif if (osh) @@ -895,12 +881,7 @@ osl_malloc(osl_t *osh, uint size) original: #endif -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - if ((addr = kmalloc(size, flags)) == NULL) { -#else if ((addr = kmalloc(size, GFP_ATOMIC)) == NULL) { -#endif if (osh) osh->failed++; return (NULL); @@ -986,12 +967,45 @@ osl_dma_free_consistent(osl_t *osh, void *va, uint size, ulong pa) } uint BCMFASTPATH -osl_dma_map(osl_t *osh, void *va, uint size, int direction) +osl_dma_map(osl_t *osh, void *va, uint size, int direction, void *p, hnddma_seg_map_t *dmah) { int dir; ASSERT((osh && (osh->magic == OS_HANDLE_MAGIC))); dir = (direction == DMA_TX)? PCI_DMA_TODEVICE: PCI_DMA_FROMDEVICE; + +#if defined(__ARM_ARCH_7A__) && defined(BCMDMASGLISTOSL) + if (dmah != NULL) { + int32 nsegs, i, totsegs = 0, totlen = 0; + struct scatterlist *sg, _sg[16]; + struct sk_buff *skb; + for (skb = (struct sk_buff *)p; skb != NULL; skb = PKTNEXT(osh, skb)) { + sg = &_sg[totsegs]; + if (skb_is_nonlinear(skb)) { + nsegs = skb_to_sgvec(skb, sg, 0, PKTLEN(osh, skb)); + ASSERT((nsegs > 0) && (nsegs <= 16)); + pci_map_sg(osh->pdev, sg, nsegs, dir); + } else { + nsegs = 1; + sg->page_link = 0; + sg_set_buf(sg, PKTDATA(osh, skb), PKTLEN(osh, skb)); + + pci_map_single(osh->pdev, PKTDATA(osh, skb), + PKTISCTF(osh, skb) ? CTFMAPSZ : PKTLEN(osh, skb), dir); + } + totsegs += nsegs; + totlen += PKTLEN(osh, skb); + } + dmah->nsegs = totsegs; + dmah->origsize = totlen; + for (i = 0, sg = _sg; i < totsegs; i++, sg++) { + dmah->segs[i].addr = sg_phys(sg); + dmah->segs[i].length = sg->length; + } + return dmah->segs[0].addr; + } +#endif + return (pci_map_single(osh->pdev, va, size, dir)); } @@ -1020,12 +1034,10 @@ osl_assert(const char *exp, const char *file, int line) if (!basename) basename = file; -#ifdef BCMASSERT_LOG snprintf(tempbuf, 64, "\"%s\": file \"%s\", line %d\n", exp, basename, line); - bcm_assert_log(tempbuf); -#endif + printk("%s", tempbuf); } @@ -1049,20 +1061,13 @@ void * osl_pktdup(osl_t *osh, void *skb) { void * p; - unsigned long irqflags; -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - gfp_t flags; -#endif + + ASSERT(!PKTISCHAINED(skb)); PKTCTFMAP(osh, skb); -#if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 25)) - flags = (in_atomic() || in_interrupt()) ? GFP_ATOMIC : GFP_KERNEL; - if ((p = skb_clone((struct sk_buff *)skb, flags)) == NULL) -#else - if ((p = skb_clone((struct sk_buff*)skb, GFP_ATOMIC)) == NULL) -#endif + if ((p = skb_clone((struct sk_buff *)skb, GFP_ATOMIC)) == NULL) return NULL; #ifdef CTFPOOL @@ -1079,13 +1084,15 @@ osl_pktdup(osl_t *osh, void *skb) #endif + PKTSETCLINK(p, NULL); + PKTCCLRATTR(p); + + if (osh->pub.pkttag) - bzero((void*)((struct sk_buff *)p)->cb, OSL_PKTTAG_SZ); + OSL_PKTTAG_CLEAR(p); - spin_lock_irqsave(&osh->pktalloc_lock, irqflags); - osh->pub.pktalloced++; - spin_unlock_irqrestore(&osh->pktalloc_lock, irqflags); + atomic_inc(&osh->pktalloced); return (p); } @@ -1094,6 +1101,12 @@ osl_pktdup(osl_t *osh, void *skb) +uint +osl_pktalloced(osl_t *osh) +{ + return (atomic_read(&osh->pktalloced)); +} + void * osl_os_open_image(char *filename) @@ -1130,3 +1143,19 @@ osl_os_close_image(void *image) if (image) filp_close((struct file *)image, NULL); } + +int +osl_os_image_size(void *image) +{ + int len = 0, curroffset; + + if (image) { + + curroffset = generic_file_llseek(image, 0, 1); + + len = generic_file_llseek(image, 0, 2); + + generic_file_llseek(image, curroffset, 0); + } + return len; +} diff --git a/drivers/net/wireless/bcmdhd/siutils.c b/drivers/net/wireless/bcmdhd/siutils.c index db108b8..0c0ffd5 100644 --- a/drivers/net/wireless/bcmdhd/siutils.c +++ b/drivers/net/wireless/bcmdhd/siutils.c @@ -22,7 +22,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils.c 347632 2012-07-27 11:00:35Z $ + * $Id: siutils.c 369572 2012-11-19 12:57:59Z $ */ #include <bcm_cfg.h> @@ -108,6 +108,11 @@ si_kattach(osl_t *osh) { static bool ksii_attached = FALSE; + if (!osh) { + SI_ERROR(("%s: osh is NULL\n", __FUNCTION__)); + return NULL; + } + if (!ksii_attached) { void *regs = NULL; regs = REG_MAP(SI_ENUM_BASE, SI_CORE_SIZE); @@ -337,7 +342,8 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, chipcregs_t *cc; char *pvars = NULL; uint origidx; - +#if !defined(_CFEZ_) || defined(CFG_WL) +#endif ASSERT(GOODREGS(regs)); bzero((uchar*)sii, sizeof(si_info_t)); @@ -406,8 +412,12 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, if (CHIPTYPE(sii->pub.socitype) == SOCI_SB) { SI_MSG(("Found chip type SB (0x%08x)\n", w)); sb_scan(&sii->pub, regs, devid); - } else if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) { - SI_MSG(("Found chip type AI (0x%08x)\n", w)); + } else if ((CHIPTYPE(sii->pub.socitype) == SOCI_AI) || + (CHIPTYPE(sii->pub.socitype) == SOCI_NAI)) { + if (CHIPTYPE(sii->pub.socitype) == SOCI_AI) + SI_MSG(("Found chip type AI (0x%08x)\n", w)); + else + SI_MSG(("Found chip type NAI (0x%08x)\n", w)); /* pass chipc address instead of original core base */ ai_scan(&sii->pub, (void *)(uintptr)cc, devid); } else if (CHIPTYPE(sii->pub.socitype) == SOCI_UBUS) { @@ -430,6 +440,7 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, goto exit; } +#if !defined(_CFEZ_) || defined(CFG_WL) if (CHIPID(sih->chip) == BCM4322_CHIP_ID && (((sih->chipst & CST4322_SPROM_OTP_SEL_MASK) >> CST4322_SPROM_OTP_SEL_SHIFT) == (CST4322_OTP_PRESENT | CST4322_SPROM_PRESENT))) { @@ -458,6 +469,7 @@ si_doattach(si_info_t *sii, uint devid, osl_t *osh, void *regs, if (bustype == PCI_BUS) { } +#endif pvars = NULL; BCM_REFERENCE(pvars); @@ -576,7 +588,7 @@ si_intflag(si_t *sih) if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_intflag(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return R_REG(sii->osh, ((uint32 *)(uintptr) (sii->oob_router + OOB_STATUSA))); else { @@ -590,7 +602,7 @@ si_flag(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_flag(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_flag(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_flag(sih); @@ -605,7 +617,7 @@ si_setint(si_t *sih, int siflag) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_setint(sih, siflag); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_setint(sih, siflag); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_setint(sih, siflag); @@ -662,7 +674,7 @@ si_corevendor(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corevendor(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corevendor(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corevendor(sih); @@ -683,7 +695,7 @@ si_corerev(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corerev(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corerev(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corerev(sih); @@ -755,7 +767,7 @@ si_setcore(si_t *sih, uint coreid, uint coreunit) if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_setcoreidx(sih, idx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_setcoreidx(sih, idx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_setcoreidx(sih, idx); @@ -770,7 +782,7 @@ si_setcoreidx(si_t *sih, uint coreidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_setcoreidx(sih, coreidx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_setcoreidx(sih, coreidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_setcoreidx(sih, coreidx); @@ -827,7 +839,7 @@ si_numaddrspaces(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_numaddrspaces(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_numaddrspaces(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_numaddrspaces(sih); @@ -842,7 +854,7 @@ si_addrspace(si_t *sih, uint asidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_addrspace(sih, asidx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_addrspace(sih, asidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_addrspace(sih, asidx); @@ -857,7 +869,7 @@ si_addrspacesize(si_t *sih, uint asidx) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_addrspacesize(sih, asidx); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_addrspacesize(sih, asidx); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_addrspacesize(sih, asidx); @@ -871,7 +883,7 @@ void si_coreaddrspaceX(si_t *sih, uint asidx, uint32 *addr, uint32 *size) { /* Only supported for SOCI_AI */ - if (CHIPTYPE(sih->socitype) == SOCI_AI) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_coreaddrspaceX(sih, asidx, addr, size); else *size = 0; @@ -882,7 +894,7 @@ si_core_cflags(si_t *sih, uint32 mask, uint32 val) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_core_cflags(sih, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_core_cflags(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_core_cflags(sih, mask, val); @@ -897,7 +909,7 @@ si_core_cflags_wo(si_t *sih, uint32 mask, uint32 val) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_cflags_wo(sih, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_cflags_wo(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_cflags_wo(sih, mask, val); @@ -910,7 +922,7 @@ si_core_sflags(si_t *sih, uint32 mask, uint32 val) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_core_sflags(sih, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_core_sflags(sih, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_core_sflags(sih, mask, val); @@ -925,7 +937,7 @@ si_iscoreup(si_t *sih) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_iscoreup(sih); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_iscoreup(sih); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_iscoreup(sih); @@ -939,7 +951,7 @@ uint si_wrapperreg(si_t *sih, uint32 offset, uint32 mask, uint32 val) { /* only for AI back plane chips */ - if (CHIPTYPE(sih->socitype) == SOCI_AI) + if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return (ai_wrap_reg(sih, offset, mask, val)); return 0; } @@ -949,7 +961,7 @@ si_corereg(si_t *sih, uint coreidx, uint regoff, uint mask, uint val) { if (CHIPTYPE(sih->socitype) == SOCI_SB) return sb_corereg(sih, coreidx, regoff, mask, val); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) return ai_corereg(sih, coreidx, regoff, mask, val); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) return ub_corereg(sih, coreidx, regoff, mask, val); @@ -964,7 +976,7 @@ si_core_disable(si_t *sih, uint32 bits) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_disable(sih, bits); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_disable(sih, bits); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_disable(sih, bits); @@ -975,7 +987,7 @@ si_core_reset(si_t *sih, uint32 bits, uint32 resetbits) { if (CHIPTYPE(sih->socitype) == SOCI_SB) sb_core_reset(sih, bits, resetbits); - else if (CHIPTYPE(sih->socitype) == SOCI_AI) + else if ((CHIPTYPE(sih->socitype) == SOCI_AI) || (CHIPTYPE(sih->socitype) == SOCI_NAI)) ai_core_reset(sih, bits, resetbits); else if (CHIPTYPE(sih->socitype) == SOCI_UBUS) ub_core_reset(sih, bits, resetbits); @@ -1113,6 +1125,7 @@ si_watchdog(si_t *sih, uint ticks) if (PMUCTL_ENAB(sih)) { +#if !defined(_CFEZ_) || defined(CFG_WL) if ((CHIPID(sih->chip) == BCM4319_CHIP_ID) && (CHIPREV(sih->chiprev) == 0) && (ticks != 0)) { si_corereg(sih, SI_CC_IDX, OFFSETOF(chipcregs_t, clk_ctl_st), ~0, 0x2); @@ -1120,6 +1133,7 @@ si_watchdog(si_t *sih, uint ticks) si_core_disable(sih, 1); si_setcore(sih, CC_CORE_ID, 0); } +#endif nb = (sih->ccrev < 26) ? 16 : ((sih->ccrev >= 37) ? 32 : 24); /* The mips compiler uses the sllv instruction, @@ -1281,6 +1295,8 @@ si_clkctl_init(si_t *sih) si_clkctl_setdelay(sii, (void *)(uintptr)cc); + OSL_DELAY(20000); + if (!fast) si_setcoreidx(sih, origidx); } @@ -2068,6 +2084,7 @@ done: } +#if !defined(_CFEZ_) || defined(CFG_WL) void si_btcgpiowar(si_t *sih) { @@ -2264,6 +2281,7 @@ si_chipcontrl_epa4331_wowl(si_t *sih, bool enter_wowl) } si_setcoreidx(sih, origidx); } +#endif uint si_pll_reset(si_t *sih) @@ -2298,6 +2316,12 @@ si_clk_pmu_htavail_set(si_t *sih, bool set_clear) { } +/* Re-enable synth_pwrsw resource in min_res_mask for 4313 */ +void +si_pmu_synth_pwrsw_4313_war(si_t *sih) +{ +} + /* WL/BT control for 4313 btcombo boards >= P250 */ void si_btcombo_p250_4313_war(si_t *sih) @@ -2427,11 +2451,14 @@ si_is_sprom_available(si_t *sih) return ((sih->chipst & CST43239_SPROM_MASK) && !(sih->chipst & CST43239_SFLASH_MASK)); case BCM4324_CHIP_ID: + case BCM43242_CHIP_ID: return ((sih->chipst & CST4324_SPROM_MASK) && !(sih->chipst & CST4324_SFLASH_MASK)); case BCM4335_CHIP_ID: return ((sih->chipst & CST4335_SPROM_MASK) && !(sih->chipst & CST4335_SFLASH_MASK)); + case BCM4350_CHIP_ID: + return (sih->chipst & CST4350_SPROM_PRESENT) != 0; case BCM43131_CHIP_ID: case BCM43217_CHIP_ID: case BCM43227_CHIP_ID: @@ -2485,3 +2512,20 @@ int si_set_sromctl(si_t *sih, uint32 value) return BCME_OK; } + +uint +si_core_wrapperreg(si_t *sih, uint32 coreidx, uint32 offset, uint32 mask, uint32 val) +{ + uint origidx; + uint ret_val; + + origidx = si_coreidx(sih); + + si_setcoreidx(sih, coreidx); + + ret_val = si_wrapperreg(sih, offset, mask, val); + + /* return to the original core */ + si_setcoreidx(sih, origidx); + return ret_val; +} diff --git a/drivers/net/wireless/bcmdhd/siutils_priv.h b/drivers/net/wireless/bcmdhd/siutils_priv.h index 9a3270f..1ae06ba 100644 --- a/drivers/net/wireless/bcmdhd/siutils_priv.h +++ b/drivers/net/wireless/bcmdhd/siutils_priv.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: siutils_priv.h 309193 2012-01-19 00:03:57Z $ + * $Id: siutils_priv.h 348394 2012-08-01 18:38:50Z $ */ #ifndef _siutils_priv_h_ @@ -146,6 +146,7 @@ typedef struct si_info { #define ILP_DIV_5MHZ 0 /* ILP = 5 MHz */ #define ILP_DIV_1MHZ 4 /* ILP = 1 MHz */ +/* Force fast clock for 4360b0 */ #define PCI_FORCEHT(si) \ (((PCIE_GEN1(si)) && (si->pub.chip == BCM4311_CHIP_ID) && ((si->pub.chiprev <= 1))) || \ ((PCI(si) || PCIE_GEN1(si)) && (si->pub.chip == BCM4321_CHIP_ID)) || \ diff --git a/drivers/net/wireless/bcmdhd/wl_android.c b/drivers/net/wireless/bcmdhd/wl_android.c index 00b6969..3232e3b 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.c +++ b/drivers/net/wireless/bcmdhd/wl_android.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_android.c 358186 2012-09-21 14:36:14Z $ + * $Id: wl_android.c 390499 2013-03-12 11:38:47Z $ */ #include <linux/module.h> @@ -75,23 +75,33 @@ #define CMD_COUNTRY "COUNTRY" #define CMD_P2P_SET_NOA "P2P_SET_NOA" #if !defined WL_ENABLE_P2P_IF -#define CMD_P2P_GET_NOA "P2P_GET_NOA" +#define CMD_P2P_GET_NOA "P2P_GET_NOA" #endif +#define CMD_P2P_SD_OFFLOAD "P2P_SD_" #define CMD_P2P_SET_PS "P2P_SET_PS" #define CMD_SET_AP_WPS_P2P_IE "SET_AP_WPS_P2P_IE" +#define CMD_SETROAMMODE "SETROAMMODE" -#if defined(SUPPORT_HIDDEN_AP) +#ifdef CUSTOMER_HW4 +#ifdef SUPPORT_AUTO_CHANNEL +#define CMD_SET_HAPD_AUTO_CHANNEL "HAPD_AUTO_CHANNEL" +#endif /* SUPPORT_AUTO_CHANNEL */ +#ifdef SUPPORT_HIDDEN_AP /* Hostapd private command */ #define CMD_SET_HAPD_MAX_NUM_STA "HAPD_MAX_NUM_STA" -#define CMD_SET_HAPD_SSID "HAPD_SSID" +#define CMD_SET_HAPD_SSID "HAPD_SSID" #define CMD_SET_HAPD_HIDE_SSID "HAPD_HIDE_SSID" -#endif -#if defined(SUPPORT_AUTO_CHANNEL) -#define CMD_SET_HAPD_AUTO_CHANNEL "HAPD_AUTO_CHANNEL" -#endif -#if defined(SUPPORT_SOFTAP_SINGL_DISASSOC) +#endif /* SUPPORT_HIDDEN_AP */ +#ifdef SUPPORT_SOFTAP_SINGL_DISASSOC #define CMD_HAPD_STA_DISASSOC "HAPD_STA_DISASSOC" -#endif +#endif /* SUPPORT_SOFTAP_SINGL_DISASSOC */ +#ifdef SUPPORT_SET_LPC +#define CMD_HAPD_LPC_ENABLED "HAPD_LPC_ENABLED" +#endif /* SUPPORT_SET_LPC */ +#ifdef SUPPORT_TRIGGER_HANG_EVENT +#define CMD_TEST_FORCE_HANG "TEST_FORCE_HANG" +#endif /* SUPPORT_TRIGGER_HANG_EVENT */ +#endif /* CUSTOMER_HW4 */ /* CCX Private Commands */ #ifdef BCMCCX @@ -123,10 +133,11 @@ typedef struct cmd_tlv { } cmd_tlv_t; #endif /* PNO_SUPPORT */ -#ifdef OKC_SUPPORT #define CMD_OKC_SET_PMK "SET_PMK" #define CMD_OKC_ENABLE "OKC_ENABLE" -#endif + + +#ifdef CUSTOMER_HW4 #ifdef ROAM_API #define CMD_ROAMTRIGGER_SET "SETROAMTRIGGER" @@ -141,7 +152,7 @@ typedef struct cmd_tlv { #define CMD_COUNTRYREV_GET "GETCOUNTRYREV" #endif /* ROAM_API */ -#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) +#ifdef WES_SUPPORT #define CMD_GETROAMSCANCONTROL "GETROAMSCANCONTROL" #define CMD_SETROAMSCANCONTROL "SETROAMSCANCONTROL" #define CMD_GETROAMSCANCHANNELS "GETROAMSCANCHANNELS" @@ -189,8 +200,8 @@ typedef struct android_wifi_af_params { #ifdef SUPPORT_AMPDU_MPDU_CMD #define CMD_AMPDU_MPDU "AMPDU_MPDU" #endif /* SUPPORT_AMPDU_MPDU_CMD */ -#ifdef CUSTOMER_HW4 -#define CMD_CHANGE_RL "CHANGE_RL" + +#define CMD_CHANGE_RL "CHANGE_RL" #define CMD_RESTORE_RL "RESTORE_RL" #endif /* CUSTOMER_HW4 */ typedef struct android_wifi_priv_cmd { @@ -199,6 +210,46 @@ typedef struct android_wifi_priv_cmd { int total_len; } android_wifi_priv_cmd; +#ifdef WL_GENL +static s32 wl_genl_handle_msg(struct sk_buff *skb, struct genl_info *info); +static int wl_genl_init(void); +static int wl_genl_deinit(void); + +extern struct net init_net; +/* attribute policy: defines which attribute has which type (e.g int, char * etc) + * possible values defined in net/netlink.h + */ +static struct nla_policy wl_genl_policy[BCM_GENL_ATTR_MAX + 1] = { + [BCM_GENL_ATTR_STRING] = { .type = NLA_NUL_STRING }, + [BCM_GENL_ATTR_MSG] = { .type = NLA_BINARY }, +}; + +#define WL_GENL_VER 1 +/* family definition */ +static struct genl_family wl_genl_family = { + .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */ + .hdrsize = 0, + .name = "bcm-genl", /* Netlink I/F for Android */ + .version = WL_GENL_VER, /* Version Number */ + .maxattr = BCM_GENL_ATTR_MAX, +}; + +/* commands: mapping between the command enumeration and the actual function */ +struct genl_ops wl_genl_ops = { + .cmd = BCM_GENL_CMD_MSG, + .flags = 0, + .policy = wl_genl_policy, + .doit = wl_genl_handle_msg, + .dumpit = NULL, +}; + +static struct genl_multicast_group wl_genl_mcast = { + .id = GENL_ID_GENERATE, /* Genetlink would generate the ID */ + .name = "bcm-genl-mcast", +}; + +#endif /* WL_GENL */ + /** * Extern function declarations (TODO: move them to dhd_linux.h) */ @@ -222,7 +273,7 @@ int wl_cfg80211_get_p2p_noa(struct net_device *net, char* buf, int len) { return 0; } int wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) { return 0; } -#endif /* WL_CFG80211 */ +#endif /* WK_CFG80211 */ extern int dhd_os_check_if_up(void *dhdp); extern void *bcmsdh_get_drvdata(void); #if defined(PROP_TXSTATUS) && !defined(PROP_TXSTATUS_VSDB) @@ -239,12 +290,20 @@ extern int set_roamscan_channel_list(struct net_device *dev, unsigned char n, unsigned char channels[], int ioctl_ver); #endif +#ifdef ENABLE_4335BT_WAR +extern int bcm_bt_lock(int cookie); +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 */ + extern bool ap_fw_loaded; #if defined(CUSTOMER_HW2) || defined(CUSTOMER_HW4) extern char iface_name[IFNAMSIZ]; -#endif +#endif /* CUSTOMER_HW2 || CUSTOMER_HW4 */ +#ifndef WIFI_TURNOFF_DELAY #define WIFI_TURNOFF_DELAY 0 +#endif /** * Local (static) functions and variables */ @@ -336,7 +395,6 @@ static int wl_android_set_suspendmode(struct net_device *dev, char *command, int int suspend_flag; suspend_flag = *(command + strlen(CMD_SETSUSPENDMODE) + 1) - '0'; - if (suspend_flag != 0) suspend_flag = 1; @@ -345,6 +403,7 @@ static int wl_android_set_suspendmode(struct net_device *dev, char *command, int else DHD_ERROR(("%s: failed %d\n", __FUNCTION__, ret)); #endif + return ret; } @@ -361,6 +420,7 @@ static int wl_android_get_band(struct net_device *dev, char *command, int total_ return bytes_written; } +#ifdef CUSTOMER_HW4 #ifdef ROAM_API int wl_android_set_roam_trigger( struct net_device *dev, char* command, int total_len) @@ -462,7 +522,7 @@ int wl_android_set_full_roam_scan_period( char smbuf[WLC_IOCTL_SMLEN]; sscanf(command+sizeof("SETFULLROAMSCANPERIOD"), "%d", &full_roam_scan_period); - WL_TRACE(("%s: fullroamperiod = %d\n", __func__, full_roam_scan_period)); + WL_TRACE(("fullroamperiod = %d\n", full_roam_scan_period)); error = wldev_iovar_setbuf(dev, "fullroamperiod", &full_roam_scan_period, sizeof(full_roam_scan_period), smbuf, sizeof(smbuf), NULL); @@ -507,8 +567,7 @@ int wl_android_set_country_rev( memset(country_code, 0, sizeof(country_code)); sscanf(command+sizeof("SETCOUNTRYREV"), "%10s %10d", country_code, &rev); - WL_TRACE(("%s: country_code = %s, rev = %d\n", __FUNCTION__, - country_code, rev)); + WL_TRACE(("country_code = %s, rev = %d\n", country_code, rev)); memcpy(cspec.country_abbrev, country_code, sizeof(country_code)); memcpy(cspec.ccode, country_code, sizeof(country_code)); @@ -557,7 +616,7 @@ static int wl_android_get_country_rev( } #endif /* ROAM_API */ -#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) +#ifdef WES_SUPPORT int wl_android_get_roam_scan_control(struct net_device *dev, char *command, int total_len) { int error = 0; @@ -910,7 +969,7 @@ int wl_android_reassoc(struct net_device *dev, char *command, int total_len) } else { band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); - reassoc_params.chanspec_list[0] = channel | band | WL_LCHANSPEC_BW_20; + reassoc_params.chanspec_list[0] = channel | band | WL_CHANSPEC_BW_20; } #else band = ((channel <= CH_MAX_2G_CHANNEL) ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G); @@ -996,11 +1055,15 @@ int wl_android_set_okc_mode(struct net_device *dev, char *command, int total_len return -1; } + if (mode) + wldev_iovar_setint(dev, "ccx_enable", 0); + return error; } #endif /* WES_SUPPORT */ +#endif /* CUSTOMER_HW4 */ -#ifdef PNO_SUPPORT +#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) static int wl_android_set_pno_setup(struct net_device *dev, char *command, int total_len) { wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; @@ -1107,7 +1170,7 @@ static int wl_android_set_pno_setup(struct net_device *dev, char *command, int t exit_proc: return res; } -#endif /* PNO_SUPPORT */ +#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ static int wl_android_get_p2p_dev_addr(struct net_device *ndev, char *command, int total_len) { @@ -1294,51 +1357,81 @@ static int wl_android_set_fwpath(struct net_device *net, char *command, int tota return 0; } -#if defined(SUPPORT_HIDDEN_AP) + static int -wl_android_set_max_num_sta(struct net_device *dev, const char* string_num) +wl_android_set_pmk(struct net_device *dev, char *command, int total_len) { - int max_assoc; + uchar pmk[33]; + int error = 0; + char smbuf[WLC_IOCTL_SMLEN]; +#ifdef OKC_DEBUG + int i = 0; +#endif - max_assoc = bcm_atoi(string_num); - DHD_INFO(("%s : HAPD_MAX_NUM_STA = %d\n", __FUNCTION__, max_assoc)); - wldev_iovar_setint(dev, "maxassoc", max_assoc); - return 1; + bzero(pmk, sizeof(pmk)); + memcpy((char *)pmk, command + strlen("SET_PMK "), 32); + error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL); + if (error) { + DHD_ERROR(("Failed to set PMK for OKC, error = %d\n", error)); + } +#ifdef OKC_DEBUG + DHD_ERROR(("PMK is ")); + for (i = 0; i < 32; i++) + DHD_ERROR(("%02X ", pmk[i])); + + DHD_ERROR(("\n")); +#endif + return error; } static int -wl_android_set_ssid(struct net_device *dev, const char* hapd_ssid) +wl_android_okc_enable(struct net_device *dev, char *command, int total_len) { - wlc_ssid_t ssid; - s32 ret; + int error = 0; + char okc_enable = 0; - ssid.SSID_len = strlen(hapd_ssid); - bcm_strncpy_s(ssid.SSID, sizeof(ssid.SSID), hapd_ssid, ssid.SSID_len); - DHD_INFO(("%s: HAPD_SSID = %s\n", __FUNCTION__, ssid.SSID)); - ret = wldev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t), true); - if (ret < 0) { - DHD_ERROR(("%s : WLC_SET_SSID Error:%d\n", __FUNCTION__, ret)); + okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0'; + error = wldev_iovar_setint(dev, "okc_enable", okc_enable); + if (error) { + DHD_ERROR(("Failed to %s OKC, error = %d\n", + okc_enable ? "enable" : "disable", error)); } - return 1; + wldev_iovar_setint(dev, "ccx_enable", 0); + + return error; } + +#ifdef CUSTOMER_HW4 +#ifdef SUPPORT_AMPDU_MPDU_CMD +/* CMD_AMPDU_MPDU */ static int -wl_android_set_hide_ssid(struct net_device *dev, const char* string_num) +wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num) { - int hide_ssid; - int enable = 0; + int err = 0; + int ampdu_mpdu; - hide_ssid = bcm_atoi(string_num); - DHD_INFO(("%s: HAPD_HIDE_SSID = %d\n", __FUNCTION__, hide_ssid)); - if (hide_ssid) - enable = 1; - wldev_iovar_setint(dev, "closednet", enable); - return 1; + ampdu_mpdu = bcm_atoi(string_num); + + if (ampdu_mpdu > 32) { + DHD_ERROR(("%s : ampdu_mpdu MAX value is 32.\n", __FUNCTION__)); + return -1; + } + + DHD_ERROR(("%s : ampdu_mpdu = %d\n", __FUNCTION__, ampdu_mpdu)); + err = wldev_iovar_setint(dev, "ampdu_mpdu", ampdu_mpdu); + if (err < 0) { + DHD_ERROR(("%s : ampdu_mpdu set error. %d\n", __FUNCTION__, err)); + return -1; + } + + return 0; } -#endif /* SUPPORT_HIDDEN_AP */ +#endif /* SUPPORT_AMPDU_MPDU_CMD */ -#if defined(SUPPORT_AUTO_CHANNEL) +/* SoftAP feature */ +#ifdef SUPPORT_AUTO_CHANNEL static int wl_android_set_auto_channel(struct net_device *dev, const char* string_num, char* command, int total_len) @@ -1393,7 +1486,7 @@ wl_android_set_auto_channel(struct net_device *dev, const char* string_num, } } - if (retry == 0) { + if (retry == 0) { DHD_ERROR(("%s: auto channel timed out, failed\n", __FUNCTION__)); channel = 0; } @@ -1406,11 +1499,60 @@ done: } #endif /* SUPPORT_AUTO_CHANNEL */ -#if defined(SUPPORT_SOFTAP_SINGL_DISASSOC) +#ifdef SUPPORT_HIDDEN_AP +static int +wl_android_set_max_num_sta(struct net_device *dev, const char* string_num) +{ + int max_assoc; + + max_assoc = bcm_atoi(string_num); + DHD_INFO(("%s : HAPD_MAX_NUM_STA = %d\n", __FUNCTION__, max_assoc)); + wldev_iovar_setint(dev, "maxassoc", max_assoc); + return 1; +} + +static int +wl_android_set_ssid(struct net_device *dev, const char* hapd_ssid) +{ + wlc_ssid_t ssid; + s32 ret; + + ssid.SSID_len = strlen(hapd_ssid); + if (ssid.SSID_len > DOT11_MAX_SSID_LEN) { + ssid.SSID_len = DOT11_MAX_SSID_LEN; + DHD_ERROR(("%s : Too long SSID Length %d\n", __FUNCTION__, strlen(hapd_ssid))); + } + bcm_strncpy_s(ssid.SSID, sizeof(ssid.SSID), hapd_ssid, ssid.SSID_len); + DHD_INFO(("%s: HAPD_SSID = %s\n", __FUNCTION__, ssid.SSID)); + ret = wldev_ioctl(dev, WLC_SET_SSID, &ssid, sizeof(wlc_ssid_t), true); + if (ret < 0) { + DHD_ERROR(("%s : WLC_SET_SSID Error:%d\n", __FUNCTION__, ret)); + } + return 1; + +} + +static int +wl_android_set_hide_ssid(struct net_device *dev, const char* string_num) +{ + int hide_ssid; + int enable = 0; + + hide_ssid = bcm_atoi(string_num); + DHD_INFO(("%s: HAPD_HIDE_SSID = %d\n", __FUNCTION__, hide_ssid)); + if (hide_ssid) + enable = 1; + wldev_iovar_setint(dev, "closednet", enable); + return 1; +} +#endif /* SUPPORT_HIDDEN_AP */ + +#ifdef SUPPORT_SOFTAP_SINGL_DISASSOC static int wl_android_sta_diassoc(struct net_device *dev, const char* straddr) { scb_val_t scbval; + int error = 0; DHD_INFO(("%s: deauth STA %s\n", __FUNCTION__, straddr)); @@ -1418,62 +1560,43 @@ wl_android_sta_diassoc(struct net_device *dev, const char* straddr) scbval.val = htod32(1); bcm_ether_atoe(straddr, &scbval.ea); - DHD_INFO(("%s: deauth STA: "MACDBG "\n", __FUNCTION__, - MAC2STRDBG(scbval.ea.octet))); + DHD_ERROR(("%s: deauth STA: "MACDBG " scb_val.val %d\n", __FUNCTION__, + MAC2STRDBG(scbval.ea.octet), scbval.val)); - wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, + error = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scbval, sizeof(scb_val_t), true); + if (error) { + DHD_ERROR(("Fail to DEAUTH station, error = %d\n", error)); + } return 1; } #endif /* SUPPORT_SOFTAP_SINGL_DISASSOC */ -#ifdef OKC_SUPPORT - +#ifdef SUPPORT_SET_LPC static int -wl_android_set_pmk(struct net_device *dev, char *command, int total_len) +wl_android_set_lpc(struct net_device *dev, const char* string_num) { - uchar pmk[33]; - int error = 0; - char smbuf[WLC_IOCTL_SMLEN]; -#ifdef OKC_DEBUG - int i = 0; -#endif + int lpc_enabled, ret; + s32 val = 1; - bzero(pmk, sizeof(pmk)); - memcpy((char *)pmk, command + strlen("SET_PMK "), 32); - error = wldev_iovar_setbuf(dev, "okc_info_pmk", pmk, 32, smbuf, sizeof(smbuf), NULL); - if (error) { - DHD_ERROR(("Failed to set PMK for OKC, error = %d\n", error)); - } -#ifdef OKC_DEBUG - DHD_ERROR(("PMK is ")); - for (i = 0; i < 32; i++) - DHD_ERROR(("%02X ", pmk[i])); + lpc_enabled = bcm_atoi(string_num); + DHD_INFO(("%s : HAPD_LPC_ENABLED = %d\n", __FUNCTION__, lpc_enabled)); - DHD_ERROR(("\n")); -#endif - return error; -} + ret = wldev_ioctl(dev, WLC_DOWN, &val, sizeof(s32), true); + if (ret < 0) + DHD_ERROR(("WLC_DOWN error %d\n", ret)); -static int -wl_android_okc_enable(struct net_device *dev, char *command, int total_len) -{ - int error = 0; - char okc_enable = 0; + wldev_iovar_setint(dev, "lpc", lpc_enabled); - okc_enable = command[strlen(CMD_OKC_ENABLE) + 1] - '0'; - error = wldev_iovar_setint(dev, "okc_enable", okc_enable); - if (error) { - DHD_ERROR(("Failed to %s OKC, error = %d\n", - okc_enable ? "enable" : "disable", error)); - } + ret = wldev_ioctl(dev, WLC_UP, &val, sizeof(s32), true); + if (ret < 0) + DHD_ERROR(("WLC_UP error %d\n", ret)); - return error; + return 1; } +#endif /* SUPPORT_SET_LPC */ -#endif /* OKC_ SUPPORT */ -#ifdef CUSTOMER_HW4 static int wl_android_ch_res_rl(struct net_device *dev, bool change) { @@ -1497,35 +1620,36 @@ wl_android_ch_res_rl(struct net_device *dev, bool change) } #endif /* CUSTOMER_HW4 */ -#ifdef SUPPORT_AMPDU_MPDU_CMD -/* CMD_AMPDU_MPDU */ -static int -wl_android_set_ampdu_mpdu(struct net_device *dev, const char* string_num) +int wl_android_set_roam_mode(struct net_device *dev, char *command, int total_len) { - int err = 0; - int ampdu_mpdu; - - ampdu_mpdu = bcm_atoi(string_num); + int error = 0; + int mode = 0; - if (ampdu_mpdu > 32) { - DHD_ERROR(("%s : ampdu_mpdu MAX value is 32.\n", __FUNCTION__)); + if (sscanf(command, "%*s %d", &mode) != 1) { + DHD_ERROR(("%s: Failed to get Parameter\n", __FUNCTION__)); return -1; } - DHD_ERROR(("%s : ampdu_mpdu = %d\n", __FUNCTION__, ampdu_mpdu)); - err = wldev_iovar_setint(dev, "ampdu_mpdu", ampdu_mpdu); - if (err < 0) { - DHD_ERROR(("%s : ampdu_mpdu set error. %d\n", __FUNCTION__, err)); + error = wldev_iovar_setint(dev, "roam_off", mode); + if (error) { + DHD_ERROR(("%s: Failed to set roaming Mode %d, error = %d\n", + __FUNCTION__, mode, error)); return -1; } - + else + DHD_ERROR(("%s: succeeded to set roaming Mode %d, error = %d\n", + __FUNCTION__, mode, error)); return 0; } -#endif /* SUPPORT_AMPDU_MPDU_CMD */ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { +#ifdef CUSTOMER_HW4 +/* DO NOT CHANGE THIS: Samsung JBP branch requires 16KB buffer size */ +#define PRIVATE_COMMAND_MAX_LEN 16384 +#else #define PRIVATE_COMMAND_MAX_LEN 8192 +#endif int ret = 0; char *command = NULL; int bytes_written = 0; @@ -1545,8 +1669,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) { DHD_ERROR(("%s: too long priavte command\n", __FUNCTION__)); ret = -EINVAL; + goto exit; } - command = kmalloc(priv_cmd.total_len, GFP_KERNEL); + command = kmalloc((priv_cmd.total_len + 1), GFP_KERNEL); if (!command) { DHD_ERROR(("%s: failed to allocate memory\n", __FUNCTION__)); @@ -1557,12 +1682,14 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) ret = -EFAULT; goto exit; } + command[priv_cmd.total_len] = '\0'; + DHD_INFO(("%s: Android private cmd \"%s\" on %s\n", __FUNCTION__, command, ifr->ifr_name)); if (strnicmp(command, CMD_START, strlen(CMD_START)) == 0) { DHD_INFO(("%s, Received regular START command\n", __FUNCTION__)); #ifdef SUPPORT_DEEP_SLEEP - sleep_never = 1; + trigger_deep_sleep = 1; #else bytes_written = wl_android_wifi_on(net); #endif /* SUPPORT_DEEP_SLEEP */ @@ -1580,7 +1707,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) if (strnicmp(command, CMD_STOP, strlen(CMD_STOP)) == 0) { #ifdef SUPPORT_DEEP_SLEEP - sleep_never = 1; + trigger_deep_sleep = 1; #else bytes_written = wl_android_wifi_off(net); #endif /* SUPPORT_DEEP_SLEEP */ @@ -1642,11 +1769,18 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) else if (strnicmp(command, CMD_SETBAND, strlen(CMD_SETBAND)) == 0) { uint band = *(command + strlen(CMD_SETBAND) + 1) - '0'; #ifdef WL_HOST_BAND_MGMT - if (wl_cfg80211_set_band(net, band) < 0) { - bytes_written = -1; - goto exit; + s32 ret = 0; + if ((ret = wl_cfg80211_set_band(net, band)) < 0) { + if (ret == BCME_UNSUPPORTED) { + /* If roam_var is unsupported, fallback to the original method */ + WL_ERR(("WL_HOST_BAND_MGMT defined, " + "but roam_band iovar unsupported in the firmware\n")); + } else { + bytes_written = -1; + goto exit; + } } - if (band == WLC_BAND_AUTO) + if ((band == WLC_BAND_AUTO) || (ret == BCME_UNSUPPORTED)) bytes_written = wldev_set_band(net, band); #else bytes_written = wldev_set_band(net, band); @@ -1662,8 +1796,10 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) char *country_code = command + strlen(CMD_COUNTRY) + 1; bytes_written = wldev_set_country(net, country_code); } -#endif +#endif /* CUSTOMER_SET_COUNTRY */ #endif /* WL_CFG80211 */ + +#ifdef CUSTOMER_HW4 #ifdef ROAM_API else if (strnicmp(command, CMD_ROAMTRIGGER_SET, strlen(CMD_ROAMTRIGGER_SET)) == 0) { @@ -1701,14 +1837,13 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) strlen(CMD_COUNTRYREV_SET)) == 0) { bytes_written = wl_android_set_country_rev(net, command, priv_cmd.total_len); - wl_update_wiphybands(NULL); } else if (strnicmp(command, CMD_COUNTRYREV_GET, strlen(CMD_COUNTRYREV_GET)) == 0) { bytes_written = wl_android_get_country_rev(net, command, priv_cmd.total_len); } #endif /* ROAM_API */ -#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) +#ifdef WES_SUPPORT else if (strnicmp(command, CMD_GETROAMSCANCONTROL, strlen(CMD_GETROAMSCANCONTROL)) == 0) { bytes_written = wl_android_get_roam_scan_control(net, command, priv_cmd.total_len); } @@ -1766,7 +1901,9 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) bytes_written = wl_android_set_okc_mode(net, command, priv_cmd.total_len); } #endif /* WES_SUPPORT */ -#ifdef PNO_SUPPORT +#endif /* CUSTOMER_HW4 */ + +#if defined(PNO_SUPPORT) && !defined(WL_SCHED_SCAN) else if (strnicmp(command, CMD_PNOSSIDCLR_SET, strlen(CMD_PNOSSIDCLR_SET)) == 0) { bytes_written = dhd_dev_pno_reset(net); } @@ -1777,7 +1914,7 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) uint pfn_enabled = *(command + strlen(CMD_PNOENABLE_SET) + 1) - '0'; bytes_written = dhd_dev_pno_enable(net, pfn_enabled); } -#endif +#endif /* PNO_SUPPORT && !WL_SCHED_SCAN */ 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); } @@ -1804,15 +1941,38 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) priv_cmd.total_len - skip, *(command + skip - 2) - '0'); } #endif /* WL_CFG80211 */ -#if defined(SUPPORT_AUTO_CHANNEL) + else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) + bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len); + else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) + bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len); +#ifdef BCMCCX + else if (strnicmp(command, CMD_GETCCKM_RN, strlen(CMD_GETCCKM_RN)) == 0) { + bytes_written = wl_android_get_cckm_rn(net, command); + } + else if (strnicmp(command, CMD_SETCCKM_KRK, strlen(CMD_SETCCKM_KRK)) == 0) { + bytes_written = wl_android_set_cckm_krk(net, command); + } + else if (strnicmp(command, CMD_GET_ASSOC_RES_IES, strlen(CMD_GET_ASSOC_RES_IES)) == 0) { + bytes_written = wl_android_get_assoc_res_ies(net, command); + } +#endif /* BCMCCX */ +#ifdef CUSTOMER_HW4 +#ifdef SUPPORT_AMPDU_MPDU_CMD + /* CMD_AMPDU_MPDU */ + else if (strnicmp(command, CMD_AMPDU_MPDU, strlen(CMD_AMPDU_MPDU)) == 0) { + int skip = strlen(CMD_AMPDU_MPDU) + 1; + bytes_written = wl_android_set_ampdu_mpdu(net, (const char*)command+skip); + } +#endif /* SUPPORT_AMPDU_MPDU_CMD */ +#ifdef SUPPORT_AUTO_CHANNEL else if (strnicmp(command, CMD_SET_HAPD_AUTO_CHANNEL, strlen(CMD_SET_HAPD_AUTO_CHANNEL)) == 0) { int skip = strlen(CMD_SET_HAPD_AUTO_CHANNEL) + 3; bytes_written = wl_android_set_auto_channel(net, (const char*)command+skip, command, priv_cmd.total_len); } -#endif -#if defined(SUPPORT_HIDDEN_AP) +#endif /* SUPPORT_AUTO_CHANNEL */ +#ifdef SUPPORT_HIDDEN_AP else if (strnicmp(command, CMD_SET_HAPD_MAX_NUM_STA, strlen(CMD_SET_HAPD_MAX_NUM_STA)) == 0) { int skip = strlen(CMD_SET_HAPD_MAX_NUM_STA) + 3; @@ -1829,43 +1989,33 @@ int wl_android_priv_cmd(struct net_device *net, struct ifreq *ifr, int cmd) wl_android_set_hide_ssid(net, (const char*)command+skip); } #endif /* SUPPORT_HIDDEN_AP */ -#if defined(SUPPORT_SOFTAP_SINGL_DISASSOC) +#ifdef SUPPORT_SOFTAP_SINGL_DISASSOC else if (strnicmp(command, CMD_HAPD_STA_DISASSOC, strlen(CMD_HAPD_STA_DISASSOC)) == 0) { int skip = strlen(CMD_HAPD_STA_DISASSOC) + 1; wl_android_sta_diassoc(net, (const char*)command+skip); } #endif /* SUPPORT_SOFTAP_SINGL_DISASSOC */ -#ifdef OKC_SUPPORT - else if (strnicmp(command, CMD_OKC_SET_PMK, strlen(CMD_OKC_SET_PMK)) == 0) - bytes_written = wl_android_set_pmk(net, command, priv_cmd.total_len); - else if (strnicmp(command, CMD_OKC_ENABLE, strlen(CMD_OKC_ENABLE)) == 0) - bytes_written = wl_android_okc_enable(net, command, priv_cmd.total_len); -#endif /* OKC_SUPPORT */ -#ifdef BCMCCX - else if (strnicmp(command, CMD_GETCCKM_RN, strlen(CMD_GETCCKM_RN)) == 0) { - bytes_written = wl_android_get_cckm_rn(net, command); - } - else if (strnicmp(command, CMD_SETCCKM_KRK, strlen(CMD_SETCCKM_KRK)) == 0) { - bytes_written = wl_android_set_cckm_krk(net, command); - } - else if (strnicmp(command, CMD_GET_ASSOC_RES_IES, strlen(CMD_GET_ASSOC_RES_IES)) == 0) { - bytes_written = wl_android_get_assoc_res_ies(net, command); - } -#endif /* BCMCCX */ -#ifdef SUPPORT_AMPDU_MPDU_CMD - /* CMD_AMPDU_MPDU */ - else if (strnicmp(command, CMD_AMPDU_MPDU, strlen(CMD_AMPDU_MPDU)) == 0) { - int skip = strlen(CMD_AMPDU_MPDU) + 1; - bytes_written = wl_android_set_ampdu_mpdu(net, (const char*)command+skip); - } -#endif /* SUPPORT_AMPDU_MPDU_CMD */ -#ifdef CUSTOMER_HW4 +#ifdef SUPPORT_SET_LPC + else if (strnicmp(command, CMD_HAPD_LPC_ENABLED, + strlen(CMD_HAPD_LPC_ENABLED)) == 0) { + int skip = strlen(CMD_HAPD_LPC_ENABLED) + 3; + wl_android_set_lpc(net, (const char*)command+skip); + } +#endif /* SUPPORT_SET_LPC */ +#ifdef SUPPORT_TRIGGER_HANG_EVENT + else if (strnicmp(command, CMD_TEST_FORCE_HANG, + strlen(CMD_TEST_FORCE_HANG)) == 0) { + net_os_send_hang_message(net); + } +#endif /* SUPPORT_TRIGGER_HANG_EVENT */ else if (strnicmp(command, CMD_CHANGE_RL, strlen(CMD_CHANGE_RL)) == 0) bytes_written = wl_android_ch_res_rl(net, true); else if (strnicmp(command, CMD_RESTORE_RL, strlen(CMD_RESTORE_RL)) == 0) bytes_written = wl_android_ch_res_rl(net, false); #endif /* CUSTOMER_HW4 */ + else if (strnicmp(command, CMD_SETROAMMODE, strlen(CMD_SETROAMMODE)) == 0) + bytes_written = wl_android_set_roam_mode(net, command, priv_cmd.total_len); else { DHD_ERROR(("Unknown PRIVATE command %s - ignored\n", command)); snprintf(command, 3, "OK"); @@ -1904,7 +2054,6 @@ int wl_android_init(void) { int ret = 0; - dhd_msg_level |= DHD_ERROR_VAL; #ifdef ENABLE_INSMOD_NO_FW_LOAD dhd_download_fw_on_driverload = FALSE; #endif /* ENABLE_INSMOD_NO_FW_LOAD */ @@ -1914,6 +2063,11 @@ int wl_android_init(void) bcm_strncpy_s(iface_name, IFNAMSIZ, "wlan", IFNAMSIZ); } #endif /* CUSTOMER_HW2 || CUSTOMER_HW4 */ + +#ifdef WL_GENL + wl_genl_init(); +#endif + return ret; } @@ -1921,22 +2075,260 @@ int wl_android_exit(void) { int ret = 0; +#ifdef WL_GENL + wl_genl_deinit(); +#endif /* WL_GENL */ + return ret; } void wl_android_post_init(void) { +#ifdef ENABLE_4335BT_WAR + bcm_bt_unlock(lock_cookie_wifi); + printk("%s: btlock released\n", __FUNCTION__); +#endif /* ENABLE_4335BT_WAR */ + if (!dhd_download_fw_on_driverload) { /* Call customer gpio to turn off power with WL_REG_ON signal */ dhd_customer_gpio_wlan_ctrl(WLAN_RESET_OFF); g_wifi_on = 0; } } + +#ifdef WL_GENL +/* Generic Netlink Initializaiton */ +static int wl_genl_init(void) +{ + int ret; + + WL_DBG(("GEN Netlink Init\n\n")); + + /* register new family */ + ret = genl_register_family(&wl_genl_family); + if (ret != 0) + goto failure; + + /* register functions (commands) of the new family */ + ret = genl_register_ops(&wl_genl_family, &wl_genl_ops); + if (ret != 0) { + WL_ERR(("register ops failed: %i\n", ret)); + genl_unregister_family(&wl_genl_family); + goto failure; + } + + ret = genl_register_mc_group(&wl_genl_family, &wl_genl_mcast); + if (ret != 0) { + WL_ERR(("register mc_group failed: %i\n", ret)); + genl_unregister_ops(&wl_genl_family, &wl_genl_ops); + genl_unregister_family(&wl_genl_family); + goto failure; + } + + return 0; + +failure: + WL_ERR(("Registering Netlink failed!!\n")); + return -1; +} + +/* Generic netlink deinit */ +static int wl_genl_deinit(void) +{ + if (genl_unregister_ops(&wl_genl_family, &wl_genl_ops) < 0) + WL_ERR(("Unregister wl_genl_ops failed\n")); + + if (genl_unregister_family(&wl_genl_family) < 0) + WL_ERR(("Unregister wl_genl_ops failed\n")); + + return 0; +} + +s32 wl_event_to_bcm_event(u16 event_type) +{ + u16 event = -1; + + switch (event_type) { + case WLC_E_SERVICE_FOUND: + event = BCM_E_SVC_FOUND; + break; + case WLC_E_P2PO_ADD_DEVICE: + event = BCM_E_DEV_FOUND; + break; + case WLC_E_P2PO_DEL_DEVICE: + event = BCM_E_DEV_LOST; + break; + /* Above events are supported from BCM Supp ver 47 Onwards */ + + default: + WL_ERR(("Event not supported\n")); + } + + return event; +} + +s32 +wl_genl_send_msg( + struct net_device *ndev, + u32 event_type, + u8 *buf, + u16 len, + u8 *subhdr, + u16 subhdr_len) +{ + int ret = 0; + struct sk_buff *skb; + void *msg; + u32 attr_type = 0; + bcm_event_hdr_t *hdr = NULL; + int mcast = 1; /* By default sent as mutlicast type */ + int pid = 0; + u8 *ptr = NULL, *p = NULL; + u32 tot_len = sizeof(bcm_event_hdr_t) + subhdr_len + len; + u16 kflags = in_atomic() ? GFP_ATOMIC : GFP_KERNEL; + + + WL_DBG(("Enter \n")); + + /* Decide between STRING event and Data event */ + if (event_type == 0) + attr_type = BCM_GENL_ATTR_STRING; + else + attr_type = BCM_GENL_ATTR_MSG; + + skb = genlmsg_new(NLMSG_GOODSIZE, kflags); + if (skb == NULL) { + ret = -ENOMEM; + goto out; + } + + msg = genlmsg_put(skb, 0, 0, &wl_genl_family, 0, BCM_GENL_CMD_MSG); + if (msg == NULL) { + ret = -ENOMEM; + goto out; + } + + + if (attr_type == BCM_GENL_ATTR_STRING) { + /* Add a BCM_GENL_MSG attribute. Since it is specified as a string. + * make sure it is null terminated + */ + if (subhdr || subhdr_len) { + WL_ERR(("No sub hdr support for the ATTR STRING type \n")); + ret = -EINVAL; + goto out; + } + + ret = nla_put_string(skb, BCM_GENL_ATTR_STRING, buf); + if (ret != 0) { + WL_ERR(("nla_put_string failed\n")); + goto out; + } + } else { + /* ATTR_MSG */ + + /* Create a single buffer for all */ + p = ptr = kzalloc(tot_len, kflags); + if (!ptr) { + ret = -ENOMEM; + WL_ERR(("ENOMEM!!\n")); + goto out; + } + + /* Include the bcm event header */ + hdr = (bcm_event_hdr_t *)ptr; + hdr->event_type = wl_event_to_bcm_event(event_type); + hdr->len = len + subhdr_len; + ptr += sizeof(bcm_event_hdr_t); + + /* Copy subhdr (if any) */ + if (subhdr && subhdr_len) { + memcpy(ptr, subhdr, subhdr_len); + ptr += subhdr_len; + } + + /* Copy the data */ + if (buf && len) { + memcpy(ptr, buf, len); + } + + ret = nla_put(skb, BCM_GENL_ATTR_MSG, tot_len, p); + if (ret != 0) { + WL_ERR(("nla_put_string failed\n")); + goto out; + } + } + + if (mcast) { + int err = 0; + /* finalize the message */ + genlmsg_end(skb, msg); + /* NETLINK_CB(skb).dst_group = 1; */ + if ((err = genlmsg_multicast(skb, 0, wl_genl_mcast.id, GFP_ATOMIC)) < 0) + WL_ERR(("genlmsg_multicast for attr(%d) failed. Error:%d \n", + attr_type, err)); + else + WL_DBG(("Multicast msg sent successfully. attr_type:%d len:%d \n", + attr_type, tot_len)); + } else { + NETLINK_CB(skb).dst_group = 0; /* Not in multicast group */ + + /* finalize the message */ + genlmsg_end(skb, msg); + + /* send the message back */ + if (genlmsg_unicast(&init_net, skb, pid) < 0) + WL_ERR(("genlmsg_unicast failed\n")); + } + +out: + if (p) + kfree(p); + if (ret) + nlmsg_free(skb); + + return ret; +} + +static s32 +wl_genl_handle_msg( + struct sk_buff *skb, + struct genl_info *info) +{ + struct nlattr *na; + u8 *data = NULL; + + WL_DBG(("Enter \n")); + + if (info == NULL) { + return -EINVAL; + } + + na = info->attrs[BCM_GENL_ATTR_MSG]; + if (!na) { + WL_ERR(("nlattribute NULL\n")); + return -EINVAL; + } + + data = (char *)nla_data(na); + if (!data) { + WL_ERR(("Invalid data\n")); + return -EINVAL; + } else { + /* Handle the data */ + WL_DBG(("Data received from pid (%d) \n", info->snd_pid)); + } + + return 0; +} +#endif /* WL_GENL */ + /** * Functions for Android WiFi card detection */ #if defined(CONFIG_WIFI_CONTROL_FUNC) +bool g_wifi_poweron = FALSE; static int g_wifidev_registered = 0; static struct semaphore wifi_control_sem; static struct wifi_platform_data *wifi_control_data = NULL; @@ -2007,13 +2399,27 @@ int wifi_get_irq_number(unsigned long *irq_flags_ptr) int wifi_set_power(int on, unsigned long msec) { + int ret = 0; DHD_ERROR(("%s = %d\n", __FUNCTION__, on)); if (wifi_control_data && wifi_control_data->set_power) { - wifi_control_data->set_power(on); +#ifdef ENABLE_4335BT_WAR + if (on) { + printk("WiFi: trying to acquire BT lock\n"); + if (bcm_bt_lock(lock_cookie_wifi) != 0) + printk("** WiFi: timeout in acquiring bt lock**\n"); + printk("%s: btlock acquired\n", __FUNCTION__); + } + else { + /* For a exceptional case, release btlock */ + bcm_bt_unlock(lock_cookie_wifi); + } +#endif /* ENABLE_4335BT_WAR */ + ret = wifi_control_data->set_power(on); } - if (msec) + + if (msec && !ret) msleep(msec); - return 0; + return ret; } #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 35)) @@ -2053,6 +2459,7 @@ static int wifi_set_carddetect(int on) static int wifi_probe(struct platform_device *pdev) { + int err; struct wifi_platform_data *wifi_ctrl = (struct wifi_platform_data *)(pdev->dev.platform_data); @@ -2061,8 +2468,15 @@ static int wifi_probe(struct platform_device *pdev) wifi_irqres = platform_get_resource_byname(pdev, IORESOURCE_IRQ, "bcm4329_wlan_irq"); wifi_control_data = wifi_ctrl; - wifi_set_power(1, 0); /* Power On */ - wifi_set_carddetect(1); /* CardDetect (0->1) */ + err = wifi_set_power(1, 200); /* Power On */ + if (unlikely(err)) { + DHD_ERROR(("%s: set_power failed. err=%d\n", __FUNCTION__, err)); + wifi_set_power(0, WIFI_TURNOFF_DELAY); + /* WL_REG_ON state unknown, Power off forcely */ + } else { + wifi_set_carddetect(1); /* CardDetect (0->1) */ + g_wifi_poweron = TRUE; + } up(&wifi_control_sem); return 0; @@ -2076,8 +2490,11 @@ static int wifi_remove(struct platform_device *pdev) DHD_ERROR(("## %s\n", __FUNCTION__)); wifi_control_data = wifi_ctrl; - wifi_set_power(0, WIFI_TURNOFF_DELAY); /* Power Off */ - wifi_set_carddetect(0); /* CardDetect (1->0) */ + if (g_wifi_poweron) { + wifi_set_power(0, WIFI_TURNOFF_DELAY); /* Power Off */ + wifi_set_carddetect(0); /* CardDetect (1->0) */ + g_wifi_poweron = FALSE; + } up(&wifi_control_sem); return 0; @@ -2126,7 +2543,6 @@ static int wifi_add_dev(void) { int ret = 0; DHD_TRACE(("## Calling platform_driver_register\n")); - ret = platform_driver_register(&wifi_device); if (ret) return ret; diff --git a/drivers/net/wireless/bcmdhd/wl_android.h b/drivers/net/wireless/bcmdhd/wl_android.h index 583a167..c6f37f0 100644 --- a/drivers/net/wireless/bcmdhd/wl_android.h +++ b/drivers/net/wireless/bcmdhd/wl_android.h @@ -21,13 +21,22 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_android.h 307885 2012-01-12 23:30:48Z $ + * $Id: wl_android.h 367305 2012-11-07 13:49:55Z $ */ #include <linux/module.h> #include <linux/netdevice.h> #include <wldev_common.h> +/* If any feature uses the Generic Netlink Interface, put it here to enable WL_GENL + * automatically + */ + + +#ifdef WL_GENL +#include <net/genetlink.h> +#endif + /** * Android platform dependent functions, feel free to add Android specific functions here * (save the macros in dhd). Please do NOT declare functions that are NOT exposed to dhd @@ -55,3 +64,44 @@ int wifi_set_power(int on, unsigned long msec); int wifi_get_mac_addr(unsigned char *buf); void *wifi_get_country_code(char *ccode); #endif /* CONFIG_WIFI_CONTROL_FUNC */ + +#ifdef WL_GENL +typedef struct bcm_event_hdr { + u16 event_type; + u16 len; +} bcm_event_hdr_t; + +/* attributes (variables): the index in this enum is used as a reference for the type, + * userspace application has to indicate the corresponding type + * the policy is used for security considerations + */ +enum { + BCM_GENL_ATTR_UNSPEC, + BCM_GENL_ATTR_STRING, + BCM_GENL_ATTR_MSG, + __BCM_GENL_ATTR_MAX +}; +#define BCM_GENL_ATTR_MAX (__BCM_GENL_ATTR_MAX - 1) + +/* commands: enumeration of all commands (functions), + * used by userspace application to identify command to be ececuted + */ +enum { + BCM_GENL_CMD_UNSPEC, + BCM_GENL_CMD_MSG, + __BCM_GENL_CMD_MAX +}; +#define BCM_GENL_CMD_MAX (__BCM_GENL_CMD_MAX - 1) + +/* Enum values used by the BCM supplicant to identify the events */ +enum { + BCM_E_UNSPEC, + BCM_E_SVC_FOUND, + BCM_E_DEV_FOUND, + BCM_E_DEV_LOST, + BCM_E_MAX +}; + +s32 wl_genl_send_msg(struct net_device *ndev, u32 event_type, + u8 *string, u16 len, u8 *hdr, u16 hdrlen); +#endif /* WL_GENL */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.c b/drivers/net/wireless/bcmdhd/wl_cfg80211.c index 7324e53..c205695 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.c +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.c @@ -21,9 +21,9 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfg80211.c 359682 2012-09-28 20:23:14Z $ + * $Id: wl_cfg80211.c 394719 2013-04-03 13:22:12Z $ */ - +/* */ #include <typedefs.h> #include <linuxver.h> #include <osl.h> @@ -54,10 +54,16 @@ #include <linux/wait.h> #include <net/cfg80211.h> #include <net/rtnetlink.h> + #include <wlioctl.h> #include <wldev_common.h> #include <wl_cfg80211.h> #include <wl_cfgp2p.h> +#include <wl_android.h> + +#ifdef PROP_TXSTATUS +#include <dhd_wlfc.h> +#endif #ifdef WL11U #ifndef WL_ENABLE_P2P_IF @@ -110,7 +116,7 @@ u32 wl_dbg_level = WL_DBG_ERR; #ifdef VSDB /* sleep time to keep STA's connecting or connection for continuous af tx or finding a peer */ -#define DEFAULT_SLEEP_TIME_VSDB 200 +#define DEFAULT_SLEEP_TIME_VSDB 120 #define OFF_CHAN_TIME_THRESHOLD_MS 200 /* if sta is connected or connecting, sleep for a while before retry af tx or finding a peer */ @@ -140,6 +146,10 @@ u32 wl_dbg_level = WL_DBG_ERR; #define DNGL_FUNC(func, parameters) func parameters; #define COEX_DHCP +#define WLAN_EID_SSID 0 +#define CH_MIN_5G_CHANNEL 34 +#define CH_MIN_2G_CHANNEL 1 + /* This is to override regulatory domains defined in cfg80211 module (reg.c) * By default world regulatory domain defined in reg.c puts the flags NL80211_RRF_PASSIVE_SCAN * and NL80211_RRF_NO_IBSS for 5GHz channels (for 36..48 and 149..165). @@ -202,7 +212,7 @@ static const struct ieee80211_regdomain brcm_regdom = { #ifdef BCMCCX #ifndef WLAN_AKM_SUITE_CCKM -#define WLAN_AKM_SUITE_CCKM 0x000FAC04 +#define WLAN_AKM_SUITE_CCKM 0x00409600 #endif #define DOT11_LEAP_AUTH 0x80 /* LEAP auth frame paylod constants */ #endif /* BCMCCX */ @@ -255,10 +265,13 @@ static s32 wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, static s32 wl_cfg80211_config_default_mgmt_key(struct wiphy *wiphy, struct net_device *dev, u8 key_idx); static s32 wl_cfg80211_resume(struct wiphy *wiphy); +#if 1 //defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ + 2, 0)) static s32 wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, struct net_device *dev, u64 cookie); static s32 wl_cfg80211_del_station(struct wiphy *wiphy, struct net_device *ndev, u8* mac_addr); +#endif /* (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0)) */ #if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) static s32 wl_cfg80211_suspend(struct wiphy *wiphy, struct cfg80211_wowlan *wow); #else @@ -270,8 +283,14 @@ static s32 wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa); static s32 wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev); +static void wl_cfg80211_scan_abort(struct wl_priv *wl); static s32 wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, bool aborted, bool fw_abort); +#if 1 //LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) +static s32 wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + u8 *peer, enum nl80211_tdls_operation oper); +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) */ + /* * event & event Q handlers for cfg80211 interfaces */ @@ -305,8 +324,19 @@ static s32 wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); static s32 wl_notify_mic_status(struct wl_priv *wl, struct net_device *ndev, const wl_event_msg_t *e, void *data); +#ifdef WL_SCHED_SCAN +static s32 +wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); +#endif /* WL_SCHED_SCAN */ +#ifdef PNO_SUPPORT +static s32 wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); +#endif /* PNO_SUPPORT */ static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, enum wl_status state, bool set); +static s32 wl_tdls_event_handler(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data); /* * register/deregister parent device */ @@ -373,10 +403,10 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *dev); static void wl_free_wdev(struct wl_priv *wl); static s32 wl_inform_bss(struct wl_priv *wl); -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi); -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev); +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done); +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done); static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy); -static s32 wl_cfg80211_40MHz_to_20MHz_Channel(chanspec_t chspec); +s32 wl_cfg80211_channel_to_freq(u32 channel); static s32 wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, u8 key_idx, const u8 *mac_addr, @@ -445,6 +475,10 @@ static __used u32 wl_find_msb(u16 bit16); */ static int wl_setup_rfkill(struct wl_priv *wl, bool setup); static int wl_rfkill_set(void *data, bool blocked); +#ifdef DEBUGFS_CFG80211 +static s32 wl_setup_debugfs(struct wl_priv *wl); +static s32 wl_free_debugfs(struct wl_priv *wl); +#endif static wl_scan_params_t *wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size); @@ -459,20 +493,21 @@ int dhd_monitor_init(void *dhd_pub); int dhd_monitor_uninit(void); int dhd_start_xmit(struct sk_buff *skb, struct net_device *net); -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) void reset_roam_cache(void); void add_roam_cache(wl_bss_info_t *bi); int get_roam_channel_list(int target_chan, chanspec_t *channels, const wlc_ssid_t *ssid, int ioctl_ver); void print_roam_cache(void); void set_roam_band(int band); -#endif +void update_roam_cache(struct wl_priv *wl, int ioctl_ver); +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ -#define CHECK_SYS_UP(wlpriv) \ +#define RETURN_EIO_IF_NOT_UP(wlpriv) \ do { \ - struct net_device *ndev = wl_to_prmry_ndev(wlpriv); \ - if (unlikely(!wl_get_drv_status(wlpriv, READY, ndev))) { \ + struct net_device *checkSysUpNDev = wl_to_prmry_ndev(wlpriv); \ + if (unlikely(!wl_get_drv_status(wlpriv, READY, checkSysUpNDev))) { \ WL_INFO(("device is not ready\n")); \ return -EIO; \ } \ @@ -491,6 +526,11 @@ extern int dhd_wlfc_init(dhd_pub_t *dhd); extern void dhd_wlfc_deinit(dhd_pub_t *dhd); #endif /* PROP_TXSTATUS_VSDB */ +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) +extern int +dhdsdio_func_blocksize(dhd_pub_t *dhd, int function_num, int block_size); +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ + #if (WL_DBG_LEVEL > 0) #define WL_DBG_ESTR_MAX 50 static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = { @@ -547,18 +587,18 @@ static s8 wl_dbg_estr[][WL_DBG_ESTR_MAX] = { } static struct ieee80211_rate __wl_rates[] = { - RATETAB_ENT(WLC_RATE_1M, 0), - RATETAB_ENT(WLC_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(WLC_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(WLC_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), - RATETAB_ENT(WLC_RATE_6M, 0), - RATETAB_ENT(WLC_RATE_9M, 0), - RATETAB_ENT(WLC_RATE_12M, 0), - RATETAB_ENT(WLC_RATE_18M, 0), - RATETAB_ENT(WLC_RATE_24M, 0), - RATETAB_ENT(WLC_RATE_36M, 0), - RATETAB_ENT(WLC_RATE_48M, 0), - RATETAB_ENT(WLC_RATE_54M, 0) + RATETAB_ENT(DOT11_RATE_1M, 0), + RATETAB_ENT(DOT11_RATE_2M, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(DOT11_RATE_5M5, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(DOT11_RATE_11M, IEEE80211_RATE_SHORT_PREAMBLE), + RATETAB_ENT(DOT11_RATE_6M, 0), + RATETAB_ENT(DOT11_RATE_9M, 0), + RATETAB_ENT(DOT11_RATE_12M, 0), + RATETAB_ENT(DOT11_RATE_18M, 0), + RATETAB_ENT(DOT11_RATE_24M, 0), + RATETAB_ENT(DOT11_RATE_36M, 0), + RATETAB_ENT(DOT11_RATE_48M, 0), + RATETAB_ENT(DOT11_RATE_54M, 0) }; #define wl_a_rates (__wl_rates + 4) @@ -623,7 +663,10 @@ static const u32 __wl_cipher_suites[] = { WLAN_CIPHER_SUITE_CCMP, WLAN_CIPHER_SUITE_AES_CMAC, #ifdef BCMWAPI_WPI - WLAN_CIPHER_SUITE_SMS4 + WLAN_CIPHER_SUITE_SMS4, +#endif +#if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK) + WLAN_CIPHER_SUITE_PMK, #endif }; @@ -633,6 +676,20 @@ static const u32 __wl_cipher_suites[] = { /* IOCtl version read from targeted driver */ static int ioctl_version; +#ifdef DEBUGFS_CFG80211 +#define S_SUBLOGLEVEL 20 +static const struct { + u32 log_level; + char *sublogname; +} sublogname_map[] = { + {WL_DBG_ERR, "ERR"}, + {WL_DBG_INFO, "INFO"}, + {WL_DBG_DBG, "DBG"}, + {WL_DBG_SCAN, "SCAN"}, + {WL_DBG_TRACE, "TRACE"}, + {WL_DBG_P2P_ACTION, "P2PACTION"} +}; +#endif /* Return a new chanspec given a legacy chanspec * Returns INVCHANSPEC on error @@ -849,8 +906,7 @@ static void swap_key_to_BE(struct wl_wsec_key *key) key->iv_initialized = dtoh32(key->iv_initialized); } -//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) -#if 0 +#if 0 //LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) /* For debug: Dump the contents of the encoded wps ie buffe */ static void wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc) @@ -936,37 +992,6 @@ wl_validate_wps_ie(char *wps_ie, s32 wps_ie_len, bool *pbc) } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ -static s32 -wl_cfg80211_40MHz_to_20MHz_Channel(chanspec_t chspec) -{ - u32 channel = chspec & WL_CHANSPEC_CHAN_MASK; - - /* If chspec is not for 40MHz. Do nothing */ - if (!(chspec & WL_CHANSPEC_BW_40)) - return channel; - - if ((channel < 0) || (channel > MAXCHANNEL)) - return -1; - - switch (channel) { - /* 5G Channels */ - case 38: - case 46: - case 151: - case 159: - if (chspec & WL_CHANSPEC_CTL_SB_LOWER) - channel = channel - CH_10MHZ_APART; - else if (chspec & WL_CHANSPEC_CTL_SB_UPPER) - channel = channel + CH_10MHZ_APART; - break; - default: - /* Mhz adjustment not required. Use as is */ - WL_ERR(("Unsupported channel: %d \n", channel)); - } - - return channel; -} - static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) { chanspec_t chspec; @@ -995,12 +1020,7 @@ static chanspec_t wl_cfg80211_get_shared_freq(struct wiphy *wiphy) else { bss = (struct wl_bss_info *) (wl->extra_buf + 4); chspec = bss->chanspec; - if (chspec & WL_CHANSPEC_BW_40) { - uint32 channel = wl_cfg80211_40MHz_to_20MHz_Channel(chspec); - chspec = wl_ch_host_to_driver(channel); - } - - WL_DBG(("Valid BSS Found. chanspec:%d \n", chspec)); + WL_DBG(("Valid BSS Found. chanspec:%d \n", bss->chanspec)); } return chspec; } @@ -1084,6 +1104,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, return NULL; } if (wl->p2p_supported && (wlif_type != -1)) { + ASSERT(wl->p2p); /* ensure expectation of p2p initialization */ if (wl_get_p2p_status(wl, IF_DELETING)) { /* wait till IF_DEL is complete * release the lock for the unregister to proceed @@ -1092,8 +1113,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, rtnl_unlock(); rollback_lock = true; } - WL_INFO(("%s: Released the lock and wait till IF_DEL is complete\n", - __func__)); + WL_INFO(("Released the lock and wait till IF_DEL is complete\n")); timeout = wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_DELETING) == false), msecs_to_jiffies(MAX_WAIT_TIME)); @@ -1121,7 +1141,7 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, if (!dhd) return ERR_PTR(-ENODEV); #endif /* PROP_TXSTATUS_VSDB */ - if (!wl->p2p || !wl->p2p->vir_ifname) + if (!wl->p2p) return ERR_PTR(-ENODEV); if (wl->p2p && !wl->p2p->on && strstr(name, WL_P2P_INTERFACE_PREFIX)) { @@ -1136,7 +1156,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, memset(wl->p2p->vir_ifname, 0, IFNAMSIZ); strncpy(wl->p2p->vir_ifname, name, IFNAMSIZ - 1); - wl_notify_escan_complete(wl, _ndev, true, true); + + wl_cfg80211_scan_abort(wl); #ifdef PROP_TXSTATUS_VSDB if (!wl->wlfc_on && !disable_proptx) { dhd->wlfc_enabled = true; @@ -1203,6 +1224,10 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, val = 1; /* Disable firmware roaming for P2P interface */ wldev_iovar_setint(_ndev, "roam_off", val); + + if (mode != WL_MODE_AP) + wldev_iovar_setint(_ndev, "buf_key_b4_m4", 1); + WL_ERR((" virtual interface(%s) is " "created net attach done\n", wl->p2p->vir_ifname)); if (mode == WL_MODE_AP) @@ -1212,6 +1237,8 @@ wl_cfg80211_add_virtual_iface(struct wiphy *wiphy, char *name, else if (type == NL80211_IFTYPE_P2P_GO) dhd_mode = DHD_FLAG_P2P_GO_MODE; DNGL_FUNC(dhd_cfg80211_set_p2p_info, (wl, dhd_mode)); + /* reinitialize completion to clear previous count */ + INIT_COMPLETION(wl->iface_disable); } else { /* put back the rtnl_lock again */ if (rollback_lock) @@ -1250,6 +1277,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) struct wl_priv *wl = wiphy_priv(wiphy); s32 timeout = -1; s32 ret = 0; + s32 index = -1; WL_DBG(("Enter\n")); if (wl->p2p_net == dev) { @@ -1258,7 +1286,10 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) */ dev = wl_to_prmry_ndev(wl); } - + if (wl_cfgp2p_find_idx(wl, dev, &index) != BCME_OK) { + WL_ERR(("Find p2p index from ndev(%p) failed\n", dev)); + return BCME_ERROR; + } if (wl->p2p_supported) { memcpy(p2p_mac.octet, wl->p2p->int_addr.octet, ETHER_ADDR_LEN); @@ -1294,10 +1325,17 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) WL_ERR(("Wait for Link Down event for GO !!!\n")); wait_for_completion_timeout(&wl->iface_disable, msecs_to_jiffies(500)); - } else { +#ifndef CUSTOMER_HW4 + } else if (ret != BCME_UNSUPPORTED) { msleep(300); +#endif /* !CUSTOMER_HW4 */ } } + wl_cfgp2p_clear_management_ie(wl, index); + + if (wl_get_mode_by_netdev(wl, dev) != WL_MODE_AP) + wldev_iovar_setint(dev, "buf_key_b4_m4", 0); + /* delete interface after link down */ ret = wl_cfgp2p_ifdel(wl, &p2p_mac); /* Firmware could not delete the interface so we will not get WLC_E_IF @@ -1311,7 +1349,7 @@ wl_cfg80211_del_virtual_iface(struct wiphy *wiphy, struct net_device *dev) struct net_device *ndev = wl_to_prmry_ndev(wl); WL_ERR(("Firmware returned an error (%d) from p2p_ifdel" "HANG Notification sent to %s\n", ret, ndev->name)); - wl_cfg80211_hang(ndev, WLAN_REASON_UNSPECIFIED); + net_os_send_hang_message(ndev); } /* Wait for IF_DEL operation to be finished in firmware */ timeout = wait_event_interruptible_timeout(wl->netif_change_event, @@ -1335,6 +1373,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, { s32 ap = 0; s32 infra = 0; + s32 err = BCME_OK; s32 wlif_type; s32 mode = 0; chanspec_t chspec; @@ -1387,7 +1426,7 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, ndev->name, ap, infra, type)); wl_set_p2p_status(wl, IF_CHANGING); wl_clr_p2p_status(wl, IF_CHANGED); - wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); + err = wl_cfgp2p_ifchange(wl, &wl->p2p->int_addr, htod32(wlif_type), chspec); wait_event_interruptible_timeout(wl->netif_change_event, (wl_get_p2p_status(wl, IF_CHANGED) == true), msecs_to_jiffies(MAX_WAIT_TIME)); @@ -1406,6 +1445,9 @@ wl_cfg80211_change_virtual_iface(struct wiphy *wiphy, struct net_device *ndev, WL_ERR(("struct ap_saved_ie allocation failed\n")); return -ENOMEM; } +#if defined(CUSTOMER_HW4) && defined(USE_DYNAMIC_F2_BLKSIZE) + dhdsdio_func_blocksize(dhd, 2, DYNAMIC_F2_BLKSIZE_FOR_NONLEGACY); +#endif /* CUSTOMER_HW4 && USE_DYNAMIC_F2_BLKSIZE */ } else { WL_ERR(("Cannot change the interface for GO or SOFTAP\n")); return -EINVAL; @@ -1463,7 +1505,9 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) { struct wl_priv *wl = wlcfg_drv_priv; bool rollback_lock = false; - s32 index = 0; + s32 type = -1; + s32 bssidx = -1; + #ifdef PROP_TXSTATUS_VSDB dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); #endif /* PROP_TXSTATUS_VSDB */ @@ -1487,17 +1531,23 @@ wl_cfg80211_ifdel_ops(struct net_device *ndev) if (rollback_lock) rtnl_unlock(); } - WL_ERR(("IF_DEL event called from dongle, net %x, vif name: %s\n", - (unsigned int)ndev, wl->p2p->vir_ifname)); + WL_ERR(("IF_DEL event called from dongle, net %p, vif name: %s\n", + ndev, wl->p2p->vir_ifname)); memset(wl->p2p->vir_ifname, '\0', IFNAMSIZ); - index = wl_cfgp2p_find_idx(wl, ndev); - wl_to_p2p_bss_ndev(wl, index) = NULL; - wl_to_p2p_bss_bssidx(wl, index) = 0; + if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p bssidx from ndev(%p) failed\n", ndev)); + return BCME_ERROR; + } + if (wl_cfgp2p_find_type(wl, bssidx, &type) != BCME_OK) { + WL_ERR(("Find p2p type from bssidx(%d) failed\n", bssidx)); + return BCME_ERROR; + } + wl_to_p2p_bss_ndev(wl, type) = NULL; + wl_to_p2p_bss_bssidx(wl, type) = WL_INVALID; wl->p2p->vif_created = false; - wl_cfgp2p_clear_management_ie(wl, - index); - WL_DBG(("index : %d\n", index)); + + WL_DBG(("type : %d\n", type)); #ifdef PROP_TXSTATUS_VSDB if (dhd->wlfc_enabled && wl->wlfc_on) { dhd->wlfc_enabled = false; @@ -1547,13 +1597,14 @@ wl_cfg80211_notify_ifchange(void) /* Find listen channel */ static s32 wl_find_listen_channel(struct wl_priv *wl, - u8 *ie, u32 ie_len) + const u8 *ie, u32 ie_len) { wifi_p2p_ie_t *p2p_ie; u8 *end, *pos; s32 listen_channel; - p2p_ie = wl_cfgp2p_find_p2pie(ie, ie_len); + pos = (u8 *)ie; + p2p_ie = wl_cfgp2p_find_p2pie(pos, ie_len); if (p2p_ie == NULL) return 0; @@ -1711,8 +1762,9 @@ static void wl_scan_prep(struct wl_scan_params *params, struct cfg80211_scan_req htod32((n_ssids << WL_SCAN_PARAMS_NSSID_SHIFT) | (n_channels & WL_SCAN_PARAMS_COUNT_MASK)); - if (n_channels == 1 && wl_get_drv_status_all(wl, CONNECTED)) { - params->active_time = WL_SCAN_CONNECT_DWELL_TIME_MS; + if (n_channels == 1) { + params->active_time = htod32(WL_SCAN_CONNECT_DWELL_TIME_MS); + params->nprobes = htod32(params->active_time / WL_SCAN_JOIN_PROBE_INTERVAL_MS); } } @@ -1853,48 +1905,45 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, WL_SCAN((" LEGACY E-SCAN START\n")); #ifdef USE_INITIAL_2G_SCAN - if (ndev == wl_to_prmry_ndev(wl) && g_first_broadcast_scan == true) { - j = 0; - if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { - list = (wl_uint32_list_t *) chan_buf; - n_valid_chan = dtoh32(list->count); - for (i = 0; i < n_valid_chan && request->n_channels > j; - i++) { + if (ndev == wl_to_prmry_ndev(wl) && g_first_broadcast_scan == true) { + j = 0; + if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { + list = (wl_uint32_list_t *) chan_buf; + n_valid_chan = dtoh32(list->count); + for (i = 0; i < n_valid_chan && request->n_channels > j; + i++) { #if defined(BCM4334_CHIP) - request->channels[i]->flags |= - IEEE80211_CHAN_NO_HT40; + request->channels[i]->flags |= + IEEE80211_CHAN_NO_HT40; #endif - WL_SCAN(("list->element[%d]=%d\n", - i, list->element[i])); - if (list->element[i] > CH_MAX_2G_CHANNEL) - break; - j++; - } - request->n_channels = j; - - WL_SCAN(("request->n_channels=%d\n", request->n_channels)); - g_first_broadcast_scan = false; - is_first_init_2g_scan = true; + WL_SCAN(("list->element[%d]=%d\n", + i, list->element[i])); + if (list->element[i] > CH_MAX_2G_CHANNEL) + break; + j++; } + request->n_channels = j; + + WL_SCAN(("request->n_channels=%d\n", request->n_channels)); + g_first_broadcast_scan = false; + is_first_init_2g_scan = true; } + } #endif /* USE_INITIAL_2G_SCAN */ - /* if scan request is not empty parse scan request paramters */ - if (request != NULL) { - n_channels = request->n_channels; - n_ssids = request->n_ssids; - /* Allocate space for populating ssids in wl_iscan_params struct */ - if (n_channels % 2) - /* If n_channels is odd, add a padd of u16 */ - params_size += sizeof(u16) * (n_channels + 1); - else - params_size += sizeof(u16) * n_channels; + n_channels = request->n_channels; + n_ssids = request->n_ssids; + /* Allocate space for populating ssids in wl_iscan_params struct */ + if (n_channels % 2) + /* If n_channels is odd, add a padd of u16 */ + params_size += sizeof(u16) * (n_channels + 1); + else + params_size += sizeof(u16) * n_channels; - /* Allocate space for populating ssids in wl_iscan_params struct */ - params_size += sizeof(struct wlc_ssid) * n_ssids; - } + /* Allocate space for populating ssids in wl_iscan_params struct */ + params_size += sizeof(struct wlc_ssid) * n_ssids; params = (wl_escan_params_t *) kzalloc(params_size, GFP_KERNEL); if (params == NULL) { err = -ENOMEM; @@ -1910,7 +1959,7 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, params->version = htod32(ESCAN_REQ_VERSION); params->action = htod16(action); -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) params->sync_id = wl->escan_info.cur_sync_id; #else params->sync_id = htod16(0x1234); @@ -1942,6 +1991,9 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, goto exit; } if (!wl_get_valid_channels(ndev, chan_buf, sizeof(chan_buf))) { +#ifdef CUSTOMER_HW4 + int SS_WAR_Printed = false; +#endif list = (wl_uint32_list_t *) chan_buf; n_valid_chan = dtoh32(list->count); for (i = 0; i < num_chans; i++) @@ -1965,6 +2017,16 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, (IEEE80211_CHAN_RADAR | IEEE80211_CHAN_PASSIVE_SCAN)) continue; +#ifdef CUSTOMER_HW4 + /* CUSTOMER want to skip these channels explicitly */ + if (channel >= 52 && channel <= 140) { + if (SS_WAR_Printed == false) { + WL_ERR(("SKIP DFS CHANs(52~140)\n")); + SS_WAR_Printed = true; + } + continue; + } +#endif for (j = 0; j < n_valid_chan; j++) { /* allows only supported channel on @@ -1999,7 +2061,11 @@ wl_run_escan(struct wl_priv *wl, struct net_device *ndev, } err = wl_cfgp2p_escan(wl, ndev, wl->active_scan, num_chans, default_chan_list, search_state, action, - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE)); + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE), NULL); + + if (!err) + wl->p2p->search_state = search_state; + kfree(default_chan_list); } exit: @@ -2019,8 +2085,8 @@ wl_do_escan(struct wl_priv *wl, struct wiphy *wiphy, struct net_device *ndev, wl_scan_results_t *results; WL_SCAN(("Enter \n")); mutex_lock(&wl->usr_sync); -#if defined(DUAL_ESCAN_RESULT_BUFFER) - results = (wl_scan_results_t *) wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2]; +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) + results = (wl_scan_results_t *) wl->escan_info.escan_buf[wl->escan_info.cur_sync_id % 2]; #else results = (wl_scan_results_t *) wl->escan_info.escan_buf; #endif @@ -2060,7 +2126,6 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, bool p2p_ssid; #ifdef WL11U bcm_tlv_t *interworking_ie; - u32 ie_len; #endif s32 err = 0; s32 bssidx = -1; @@ -2069,6 +2134,14 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, unsigned long flags; static s32 busy_count = 0; + dhd_pub_t *dhd; + + dhd = (dhd_pub_t *)(wl->pub); + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + WL_ERR(("Invalid Scan Command at SoftAP mode\n")); + return -EINVAL; + } + /* If scan req comes for p2p0, send it over primary I/F * Scan results will be delivered corresponding to cfg80211_scan_request */ @@ -2106,6 +2179,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } #endif /* WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ + /* Arm scan timeout timer */ mod_timer(&wl->scan_timeout, jiffies + msecs_to_jiffies(WL_SCAN_TIMER_INTERVAL_MS)); iscan_req = false; @@ -2160,13 +2234,16 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } } if (!wl->p2p_supported || !p2p_scan(wl)) { - bssidx = wl_cfgp2p_find_idx(wl, ndev); + if (wl_cfgp2p_find_idx(wl, ndev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from ndev(%p) failed\n", + ndev)); + err = BCME_ERROR; + goto scan_out; + } #ifdef WL11U if ((interworking_ie = wl_cfg80211_find_interworking_ie( (u8 *)request->ie, request->ie_len)) != NULL) { - ie_len = interworking_ie->len; - err = wl_cfg80211_add_iw_ie(wl, ndev, bssidx, VNDR_IE_CUSTOM_FLAG, interworking_ie->id, interworking_ie->data, interworking_ie->len); @@ -2183,6 +2260,7 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, wldev_iovar_setint_bsscfg(ndev, "grat_arp", 0, bssidx); + wl->wl11u = FALSE; /* we don't care about error */ } #endif /* WL11U */ @@ -2201,6 +2279,8 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, /* we don't do iscan in ibss */ ssids = this_ssid; } + if (request && !p2p_scan(wl)) + WL_TRACE_HW4(("START SCAN\n")); wl->scan_request = request; wl_set_drv_status(wl, SCANNING, ndev); if (iscan_req) { @@ -2215,10 +2295,10 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, /* find my listen channel */ wl->afx_hdl->my_listen_chan = - wl_find_listen_channel(wl, (u8 *)request->ie, + wl_find_listen_channel(wl, request->ie, request->ie_len); err = wl_cfgp2p_enable_discovery(wl, ndev, - request->ie, request->ie_len); + request->ie, request->ie_len); if (unlikely(err)) { goto scan_out; @@ -2266,13 +2346,11 @@ __wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, } scan_success: - busy_count = 0; return 0; scan_out: - if (err == BCME_BUSY || err == BCME_NOTREADY) { WL_ERR(("Scan err = (%d), busy?%d", err, -EBUSY)); err = -EBUSY; @@ -2299,21 +2377,22 @@ scan_out: if ((ret = wldev_ioctl(ndev, WLC_GET_BSSID, &bssid, ETHER_ADDR_LEN, false)) == 0) WL_ERR(("FW is connected with " MACDBG "/n", - MAC2STRDBG(bssid.octet))); + MAC2STRDBG(bssid.octet))); else WL_ERR(("GET BSSID failed with %d\n", ret)); - - wl_cfg80211_disconnect(wiphy, ndev, DOT11_RC_DISASSOC_LEAVING); + wl_notify_escan_complete(wl, ndev, true, true); } } else { busy_count = 0; } + wl_clr_drv_status(wl, SCANNING, ndev); if (timer_pending(&wl->scan_timeout)) del_timer_sync(&wl->scan_timeout); spin_lock_irqsave(&wl->cfgdrv_lock, flags); wl->scan_request = NULL; spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); + return err; } @@ -2325,7 +2404,7 @@ wl_cfg80211_scan(struct wiphy *wiphy, struct net_device *ndev, struct wl_priv *wl = wiphy_priv(wiphy); WL_DBG(("Enter \n")); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); err = __wl_cfg80211_scan(wiphy, ndev, request, NULL); if (unlikely(err)) { @@ -2380,7 +2459,7 @@ static s32 wl_cfg80211_set_wiphy_params(struct wiphy *wiphy, u32 changed) struct net_device *ndev = wl_to_prmry_ndev(wl); s32 err = 0; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); WL_DBG(("Enter\n")); if (changed & WIPHY_PARAM_RTS_THRESHOLD && (wl->conf->rts_threshold != wiphy->rts_threshold)) { @@ -2429,7 +2508,7 @@ wl_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev, bool rollback_lock = false; WL_TRACE(("In\n")); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); if (params->bssid) { WL_ERR(("Invalid bssid\n")); return -EOPNOTSUPP; @@ -2497,7 +2576,7 @@ static s32 wl_cfg80211_leave_ibss(struct wiphy *wiphy, struct net_device *dev) struct wl_priv *wl = wiphy_priv(wiphy); s32 err = 0; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); wl_link_down(wl); return err; @@ -2510,7 +2589,11 @@ wl_set_wpa_version(struct net_device *dev, struct cfg80211_connect_params *sme) struct wl_security *sec; s32 val = 0; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (sme->crypto.wpa_versions & NL80211_WPA_VERSION_1) val = WPA_AUTH_PSK | @@ -2554,9 +2637,13 @@ wl_set_set_wapi_ie(struct net_device *dev, struct cfg80211_connect_params *sme) { struct wl_priv *wl = wlcfg_drv_priv; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } - WL_DBG((" %s \n", __FUNCTION__)); + WL_DBG(("Enter\n")); if (sme->crypto.wpa_versions & NL80211_WAPI_VERSION_1) { err = wldev_iovar_setbuf_bsscfg(dev, "wapiie", sme->ie, @@ -2579,7 +2666,12 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) struct wl_security *sec; s32 val = 0; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } + switch (sme->auth_type) { case NL80211_AUTHTYPE_OPEN_SYSTEM: val = WL_AUTH_OPEN_SYSTEM; @@ -2590,21 +2682,17 @@ wl_set_auth_type(struct net_device *dev, struct cfg80211_connect_params *sme) WL_DBG(("shared key\n")); break; case NL80211_AUTHTYPE_AUTOMATIC: -#ifdef USE_WEP_AUTH_SHARED_OPEN - val = WL_AUTH_SHARED_OPEN; -#else val = WL_AUTH_OPEN_SHARED; -#endif /* USE_WEP_AUTH_SHARED_OPEN */ WL_DBG(("automatic\n")); break; #ifdef BCMCCX case NL80211_AUTHTYPE_NETWORK_EAP: WL_DBG(("network eap\n")); - val = DOT11_LEAP_AUTH; + val = WL_AUTH_OPEN_SYSTEM; break; #endif default: - val = WL_AUTH_OPEN_SHARED; + val = 2; WL_ERR(("invalid auth type (%d)\n", sme->auth_type)); break; } @@ -2630,7 +2718,11 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) #ifdef BCMWAPI_WPI s32 val = 0; #endif - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (sme->crypto.n_ciphers_pairwise) { switch (sme->crypto.ciphers_pairwise[0]) { @@ -2642,8 +2734,6 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) pval = TKIP_ENABLED; break; case WLAN_CIPHER_SUITE_CCMP: - pval = AES_ENABLED; - break; case WLAN_CIPHER_SUITE_AES_CMAC: pval = AES_ENABLED; break; @@ -2659,6 +2749,24 @@ wl_set_set_cipher(struct net_device *dev, struct cfg80211_connect_params *sme) return -EINVAL; } } +#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) + /* Ensure in-dongle supplicant is turned on when FBT wants to do the 4-way + * handshake. + * Note that the FW feature flag only exists on kernels that support the + * FT-EAP AKM suite. + */ + if (wl->wdev->wiphy->features & NL80211_FEATURE_FW_4WAY_HANDSHAKE) { + if (pval == AES_ENABLED) + err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 1, bssidx); + else + err = wldev_iovar_setint_bsscfg(dev, "sup_wpa", 0, bssidx); + + if (err) { + WL_ERR(("FBT: Error setting sup_wpa (%d)\n", err)); + return err; + } + } +#endif /* BCMSUP_4WAY_HANDSHAKE && WLAN_AKM_SUITE_FT_8021X */ if (sme->crypto.cipher_group) { switch (sme->crypto.cipher_group) { case WLAN_CIPHER_SUITE_WEP40: @@ -2728,7 +2836,11 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) struct wl_security *sec; s32 val = 0; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (sme->crypto.n_akm_suites) { err = wldev_iovar_getint(dev, "wpa_auth", &val); @@ -2770,6 +2882,16 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) case WLAN_AKM_SUITE_PSK: val = WPA2_AUTH_PSK; break; +#if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_8021X) + case WLAN_AKM_SUITE_FT_8021X: + val = WPA2_AUTH_UNSPECIFIED | WPA2_AUTH_FT; + break; +#endif +#if defined(WLFBT) && defined(WLAN_AKM_SUITE_FT_PSK) + case WLAN_AKM_SUITE_FT_PSK: + val = WPA2_AUTH_PSK | WPA2_AUTH_FT; + break; +#endif #ifdef BCMCCX case WLAN_AKM_SUITE_CCKM: val = WPA2_AUTH_CCKM; @@ -2799,6 +2921,25 @@ wl_set_key_mgmt(struct net_device *dev, struct cfg80211_connect_params *sme) #endif WL_DBG(("setting wpa_auth to %d\n", val)); +#ifdef BCMCCX + if (val & (WPA_AUTH_CCKM|WPA2_AUTH_CCKM)) { + WL_DBG(("SET CCX enable\n")); + wldev_iovar_setint_bsscfg(dev, "okc_enable", 0, bssidx); + err = wldev_iovar_setint_bsscfg(dev, "ccx_enable", 1, bssidx); + + if (unlikely(err)) { + WL_ERR(("could not set ccx_enable (%d)\n", err)); + return err; + } + } else { + err = wldev_iovar_setint_bsscfg(dev, "ccx_enable", 0, bssidx); + + if (unlikely(err)) { + WL_ERR(("could not set ccx_disable (%d)\n", err)); + } + } +#endif /* BCMCCX */ + err = wldev_iovar_setint_bsscfg(dev, "wpa_auth", val, bssidx); if (unlikely(err)) { WL_ERR(("could not set wpa_auth (%d)\n", err)); @@ -2820,7 +2961,11 @@ wl_set_set_sharedkey(struct net_device *dev, struct wl_wsec_key key; s32 val; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } WL_DBG(("key len (%d)\n", sme->key_len)); if (sme->key_len) { @@ -2891,14 +3036,15 @@ wl_set_set_sharedkey(struct net_device *dev, return err; } -#ifdef ESCAN_RESULT_PATCH +#if defined(ESCAN_RESULT_PATCH) static u8 connect_req_bssid[6]; static u8 broad_bssid[6]; -#endif +#endif /* ESCAN_RESULT_PATCH */ + -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) #define MAX_ROAM_CACHE_NUM 100 -#endif +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ static s32 wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, @@ -2909,7 +3055,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, wl_extjoin_params_t *ext_join_params; struct wl_join_params join_params; size_t join_params_size; -#ifdef ROAM_AP_ENV_DETECTION +#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); #endif /* ROAM_AP_ENV_DETECTION */ s32 err = 0; @@ -2919,10 +3065,12 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, u32 wpaie_len = 0; u32 chan_cnt = 0; struct ether_addr bssid; -#ifdef ROAM_CHANNEL_CACHE + s32 bssidx; +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) chanspec_t chanspec_list[MAX_ROAM_CACHE_NUM]; -#endif +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ int ret; + int wait_cnt; WL_DBG(("In\n")); @@ -2931,7 +3079,13 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, return -EOPNOTSUPP; } - CHECK_SYS_UP(wl); + if (unlikely(sme->ssid_len > DOT11_MAX_SSID_LEN)) { + WL_ERR(("Invalid SSID info: SSID=%s, length=%d\n", + sme->ssid, sme->ssid_len)); + return -EINVAL; + } + + RETURN_EIO_IF_NOT_UP(wl); /* * Cancel ongoing scan to sync up with sme state machine of cfg80211. @@ -2946,13 +3100,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, wl->block_gon_req_tx_count = 0; wl->block_gon_req_rx_count = 0; #endif /* WL_CFG80211_GON_COLLISION */ -#ifdef ESCAN_RESULT_PATCH - if (sme->bssid) { +#if defined(ESCAN_RESULT_PATCH) + if (sme->bssid) memcpy(connect_req_bssid, sme->bssid, ETHER_ADDR_LEN); - } - else { + else bzero(connect_req_bssid, ETHER_ADDR_LEN); - } bzero(broad_bssid, ETHER_ADDR_LEN); #endif @@ -2975,12 +3127,23 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, WL_ERR(("error (%d)\n", err)); return err; } - while (wl_get_drv_status(wl, DISCONNECTING, dev)) { - WL_ERR(("Waiting for disconnection terminated.\n")); - msleep(20); + wait_cnt = 500/10; + while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) { + WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", + wait_cnt)); + wait_cnt--; + msleep(10); } } else WL_DBG(("Currently not associated!\n")); + } else { + /* if status is DISCONNECTING, wait for disconnection terminated max 500 ms */ + wait_cnt = 500/10; + while (wl_get_drv_status(wl, DISCONNECTING, dev) && wait_cnt) { + WL_DBG(("Waiting for disconnection terminated, wait_cnt: %d\n", wait_cnt)); + wait_cnt--; + msleep(10); + } } /* Clean BSSID */ @@ -2990,7 +3153,11 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, if (p2p_is_on(wl) && (dev != wl_to_prmry_ndev(wl))) { /* we only allow to connect using virtual interface in case of P2P */ - wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_ASSOCREQ_FLAG, sme->ie, sme->ie_len); } else if (dev == wl_to_prmry_ndev(wl)) { /* find the RSN_IE */ @@ -3014,13 +3181,17 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); } - err = wl_cfgp2p_set_management_ie(wl, dev, wl_cfgp2p_find_idx(wl, dev), + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } + err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_ASSOCREQ_FLAG, (u8 *)sme->ie, sme->ie_len); if (unlikely(err)) { return err; } } -#ifdef ROAM_AP_ENV_DETECTION +#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) if (dhd->roam_env_detection && (wldev_iovar_setint(dev, "roam_env_detection", AP_ENV_DETECT_NOT_USED) == BCME_OK)) { s32 roam_trigger[2] = {WL_AUTO_ROAM_TRIGGER, WLC_BAND_ALL}; @@ -3032,7 +3203,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } #endif /* ROAM_AP_ENV_DETECTION */ if (chan) { -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) wlc_ssid_t ssid; int band; @@ -3048,7 +3219,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, #else wl->channel = ieee80211_frequency_to_channel(chan->center_freq); chan_cnt = 1; -#endif /* ROAM_CHANNEL_CACHE */ +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ WL_DBG(("channel (%d), center_req (%d), %d channels\n", wl->channel, chan->center_freq, chan_cnt)); } else @@ -3117,6 +3288,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, } ext_join_params->ssid.SSID_len = min(sizeof(ext_join_params->ssid.SSID), sme->ssid_len); memcpy(&ext_join_params->ssid.SSID, sme->ssid, ext_join_params->ssid.SSID_len); + wl_update_prof(wl, dev, NULL, &ext_join_params->ssid, WL_PROF_SSID); ext_join_params->ssid.SSID_len = htod32(ext_join_params->ssid.SSID_len); /* increate dwell time to receive probe response or detect Beacon * from target AP at a noisy air only during connect command @@ -3135,7 +3307,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, memcpy(&ext_join_params->assoc.bssid, ðer_bcast, ETH_ALEN); ext_join_params->assoc.chanspec_num = chan_cnt; if (chan_cnt) { -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) memcpy(ext_join_params->assoc.chanspec_list, chanspec_list, sizeof(chanspec_t) * chan_cnt); #else @@ -3151,7 +3323,7 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ext_join_params->assoc.chanspec_list[0] |= chspec; ext_join_params->assoc.chanspec_list[0] = wl_chspec_host_to_driver(ext_join_params->assoc.chanspec_list[0]); -#endif /* ROAM_CHANNEL_CACHE */ +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ } ext_join_params->assoc.chanspec_num = htod32(ext_join_params->assoc.chanspec_num); if (ext_join_params->ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { @@ -3159,8 +3331,13 @@ wl_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev, ext_join_params->ssid.SSID_len)); } wl_set_drv_status(wl, CONNECTING, dev); + + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } err = wldev_iovar_setbuf_bsscfg(dev, "join", ext_join_params, join_params_size, - wl->ioctl_buf, WLC_IOCTL_MAXLEN, wl_cfgp2p_find_idx(wl, dev), &wl->ioctl_buf_sync); + wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); kfree(ext_join_params); if (err) { wl_clr_drv_status(wl, CONNECTING, dev); @@ -3186,7 +3363,7 @@ set_ssid: memcpy(&join_params.params.bssid, ðer_bcast, ETH_ALEN); wl_ch_to_chanspec(wl->channel, &join_params, &join_params_size); - WL_DBG(("join_param_size %d\n", join_params_size)); + WL_DBG(("join_param_size %zu\n", join_params_size)); if (join_params.ssid.SSID_len < IEEE80211_MAX_SSID_LEN) { WL_INFO(("ssid \"%s\", len (%d)\n", join_params.ssid.SSID, @@ -3212,7 +3389,7 @@ wl_cfg80211_disconnect(struct wiphy *wiphy, struct net_device *dev, s32 err = 0; u8 *curbssid; WL_ERR(("Reason %d\n", reason_code)); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); act = *(bool *) wl_read_prof(wl, dev, WL_PROF_ACT); curbssid = wl_read_prof(wl, dev, WL_PROF_BSSID); if (act) { @@ -3252,7 +3429,7 @@ wl_cfg80211_set_tx_power(struct wiphy *wiphy, s32 err = 0; s32 disable = 0; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); switch (type) { case NL80211_TX_POWER_AUTOMATIC: break; @@ -3301,7 +3478,7 @@ static s32 wl_cfg80211_get_tx_power(struct wiphy *wiphy, s32 *dbm) u8 result; s32 err = 0; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); err = wldev_iovar_getint(ndev, "qtxpower", &txpwrdbm); if (unlikely(err)) { WL_ERR(("error (%d)\n", err)); @@ -3321,16 +3498,21 @@ wl_cfg80211_config_default_key(struct wiphy *wiphy, struct net_device *dev, u32 index; s32 wsec; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } WL_DBG(("key index (%d)\n", key_idx)); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); if (unlikely(err)) { WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); return err; } - if (wsec & WEP_ENABLED) { + /* fix IOT issue with Apple Airport */ + if (wsec == WEP_ENABLED) { /* Just select a new current key */ index = (u32) key_idx; index = htod32(index); @@ -3350,8 +3532,12 @@ wl_add_keyext(struct wiphy *wiphy, struct net_device *dev, struct wl_priv *wl = wiphy_priv(wiphy); struct wl_wsec_key key; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; s32 mode = wl_get_mode_by_netdev(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } memset(&key, 0, sizeof(key)); key.index = (u32) key_idx; @@ -3454,13 +3640,18 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, struct wl_priv *wl = wiphy_priv(wiphy); s32 mode = wl_get_mode_by_netdev(wl, dev); WL_DBG(("key index (%d)\n", key_idx)); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); - bssidx = wl_cfgp2p_find_idx(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } - if (mac_addr) { - wl_add_keyext(wiphy, dev, key_idx, mac_addr, params); - goto exit; + if (mac_addr && + ((params->cipher != WLAN_CIPHER_SUITE_WEP40) && + (params->cipher != WLAN_CIPHER_SUITE_WEP104))) { + wl_add_keyext(wiphy, dev, key_idx, mac_addr, params); + goto exit; } memset(&key, 0, sizeof(key)); @@ -3513,6 +3704,29 @@ wl_cfg80211_add_key(struct wiphy *wiphy, struct net_device *dev, val = SMS4_ENABLED; break; #endif /* BCMWAPI_WPI */ +#if defined(WLFBT) && defined(WLAN_CIPHER_SUITE_PMK) + case WLAN_CIPHER_SUITE_PMK: { + int j; + wsec_pmk_t pmk; + char keystring[WSEC_MAX_PSK_LEN + 1]; + char* charptr = keystring; + uint len; + + /* copy the raw hex key to the appropriate format */ + for (j = 0; j < (WSEC_MAX_PSK_LEN / 2); j++) { + sprintf(charptr, "%02x", params->key[j]); + charptr += 2; + } + len = strlen(keystring); + pmk.key_len = htod16(len); + bcopy(keystring, pmk.key, len); + pmk.flags = htod16(WSEC_PASSPHRASE); + + err = wldev_ioctl(dev, WLC_SET_WSEC_PMK, &pmk, sizeof(pmk), true); + if (err) + return err; + } break; +#endif /* WLFBT && WLAN_CIPHER_SUITE_PMK */ default: WL_ERR(("Invalid cipher (0x%x)\n", params->cipher)); return -EINVAL; @@ -3551,14 +3765,19 @@ wl_cfg80211_del_key(struct wiphy *wiphy, struct net_device *dev, struct wl_wsec_key key; struct wl_priv *wl = wiphy_priv(wiphy); s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); - + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } WL_DBG(("Enter\n")); + #ifndef IEEE80211W if ((key_idx >= DOT11_MAX_DEFAULT_KEYS) && (key_idx < DOT11_MAX_DEFAULT_KEYS+2)) return -EINVAL; #endif - CHECK_SYS_UP(wl); + + RETURN_EIO_IF_NOT_UP(wl); memset(&key, 0, sizeof(key)); key.flags = WL_PRIMARY_KEY; @@ -3595,10 +3814,13 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, struct wl_security *sec; s32 wsec; s32 err = 0; - s32 bssidx = wl_cfgp2p_find_idx(wl, dev); - + s32 bssidx; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } WL_DBG(("key index (%d)\n", key_idx)); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); memset(&key, 0, sizeof(key)); key.index = key_idx; swap_key_to_BE(&key); @@ -3606,7 +3828,7 @@ wl_cfg80211_get_key(struct wiphy *wiphy, struct net_device *dev, params.key_len = (u8) min_t(u8, DOT11_MAX_KEY_SIZE, key.len); memcpy(params.key, key.data, params.key_len); - wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); + err = wldev_iovar_getint_bsscfg(dev, "wsec", &wsec, bssidx); if (unlikely(err)) { WL_ERR(("WLC_GET_WSEC error (%d)\n", err)); return err; @@ -3663,11 +3885,11 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, s32 rate; s32 err = 0; sta_info_t *sta; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) s8 eabuf[ETHER_ADDR_STR_LEN]; #endif dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); if (wl_get_mode_by_netdev(wl, dev) == WL_MODE_AP) { err = wldev_iovar_getbuf(dev, "sta_info", (struct ether_addr *)mac, ETHER_ADDR_LEN, wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync); @@ -3683,7 +3905,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, sta->idle = dtoh32(sta->idle); sta->in = dtoh32(sta->in); sinfo->inactive_time = sta->idle * 1000; -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 0, 0) if (sta->flags & WL_STA_ASSOC) { sinfo->filled |= STATION_INFO_CONNECTED_TIME; sinfo->connected_time = sta->in; @@ -3746,7 +3968,7 @@ wl_cfg80211_get_station(struct wiphy *wiphy, struct net_device *dev, get_station_err: if (err && (err != -ERESTARTSYS)) { /* Disconnect due to zero BSSID or error to get RSSI */ - WL_ERR(("force cfg80211_disconnected\n")); + WL_ERR(("force cfg80211_disconnected: %d\n", err)); wl_clr_drv_status(wl, CONNECTED, dev); cfg80211_disconnected(dev, 0, NULL, 0, GFP_KERNEL); wl_link_down(wl); @@ -3756,24 +3978,6 @@ get_station_err: return err; } -/* Function to update sta power save mode for Kernel wifi stack */ -int wl_cfg80211_update_power_mode(struct net_device *dev) -{ - int pm = -1; - int err; - - err = wldev_ioctl(dev, WLC_GET_PM, &pm, sizeof(pm), false); - if (err || (pm == -1)) { - WL_ERR(("error (%d)\n", err)); - } else { - pm = (pm == PM_OFF) ? false : true; - WL_DBG(("%s: %d\n", __func__, pm)); - if (dev->ieee80211_ptr) - dev->ieee80211_ptr->ps = pm; - } - return err; -} - static s32 wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, bool enabled, s32 timeout) @@ -3782,30 +3986,24 @@ wl_cfg80211_set_power_mgmt(struct wiphy *wiphy, struct net_device *dev, s32 err = 0; struct wl_priv *wl = wiphy_priv(wiphy); struct net_info *_net_info = wl_get_netinfo_by_netdev(wl, dev); -#ifndef SUPPORT_PM2_ONLY - dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); -#endif - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); - if (wl->p2p_net == dev || _net_info == NULL) { + if (wl->p2p_net == dev || _net_info == NULL || wl->vsdb_mode) { return err; } - /* android has special hooks to change pm when kernel suspended */ -#ifndef SUPPORT_PM2_ONLY - pm = enabled ? ((dhd->in_suspend) ? PM_MAX : PM_FAST) : PM_OFF; -#else - pm = enabled ? PM_FAST : PM_OFF; -#endif + pm = enabled ? PM_FAST : PM_OFF; /* Do not enable the power save after assoc if it is p2p interface */ - if (_net_info->pm_block || wl->vsdb_mode) { - WL_DBG(("Do not enable the power save\n")); + if (_net_info->pm_block) { + /* Do not enable the power save if it is p2p interface or vsdb mode is set */ + WL_DBG(("%s:Do not enable the power save for pm_block %d or vsdb_mode %d\n", + dev->name, _net_info->pm_block, wl->vsdb_mode)); pm = PM_OFF; } pm = htod32(pm); - WL_DBG(("power save %s\n", (pm ? "enabled" : "disabled"))); + WL_DBG(("%s:power save %s\n", dev->name, (pm ? "enabled" : "disabled"))); err = wldev_ioctl(dev, WLC_SET_PM, &pm, sizeof(pm), true); if (unlikely(err)) { if (err == -ENODEV) @@ -3943,7 +4141,7 @@ wl_cfg80211_set_pmksa(struct wiphy *wiphy, struct net_device *dev, s32 err = 0; int i; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); for (i = 0; i < wl->pmk_list->pmkids.npmkid; i++) if (!memcmp(pmksa->bssid, &wl->pmk_list->pmkids.pmkid[i].BSSID, ETHER_ADDR_LEN)) @@ -3976,11 +4174,11 @@ wl_cfg80211_del_pmksa(struct wiphy *wiphy, struct net_device *dev, struct cfg80211_pmksa *pmksa) { struct wl_priv *wl = wiphy_priv(wiphy); - struct _pmkid_list pmkid; + struct _pmkid_list pmkid = {0}; s32 err = 0; int i; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); memcpy(&pmkid.pmkid[0].BSSID, pmksa->bssid, ETHER_ADDR_LEN); memcpy(pmkid.pmkid[0].PMKID, pmksa->pmkid, WPA2_PMKID_LEN); @@ -4023,7 +4221,7 @@ wl_cfg80211_flush_pmksa(struct wiphy *wiphy, struct net_device *dev) { struct wl_priv *wl = wiphy_priv(wiphy); s32 err = 0; - CHECK_SYS_UP(wl); + RETURN_EIO_IF_NOT_UP(wl); memset(wl->pmk_list, 0, sizeof(*wl->pmk_list)); err = wl_update_pmklist(dev, wl->pmk_list, err); return err; @@ -4043,7 +4241,7 @@ wl_cfg80211_scan_alloc_params(int channel, int nprobes, int *out_params_size) params_size = WL_SCAN_PARAMS_FIXED_SIZE + 1 * sizeof(uint16); params = (wl_scan_params_t*) kzalloc(params_size, GFP_KERNEL); if (params == NULL) { - WL_ERR(("%s: mem alloc failed (%d bytes)\n", __func__, params_size)); + WL_ERR(("mem alloc failed (%d bytes)\n", params_size)); return params; } memset(params, 0, params_size); @@ -4094,9 +4292,16 @@ wl_cfg80211_remain_on_channel(struct wiphy *wiphy, struct net_device *dev, } else { ndev = dev; } + + if (!wl->p2p) { + WL_ERR(("wl->p2p is not initialized\n")); + err = BCME_ERROR; + goto exit; + } + #ifndef WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST - if (wl_get_drv_status(wl, SCANNING, ndev)) { - wl_notify_escan_complete(wl, ndev, true, true); + if (wl_get_drv_status_all(wl, SCANNING)) { + wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); } #endif /* not WL_CFG80211_VSDB_PRIORITIZE_SCAN_REQUEST */ @@ -4212,7 +4417,8 @@ wl_cfg80211_afx_handler(struct work_struct *work) (100 * (1 + (random32() % 3)))); /* 100ms ~ 300ms */ } else { ret = wl_cfgp2p_act_frm_search(wl, wl->afx_hdl->dev, - wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan); + wl->afx_hdl->bssidx, wl->afx_hdl->peer_listen_chan, + NULL); } if (unlikely(ret != BCME_OK)) { WL_ERR(("ERROR occurred! returned value is (%d)\n", ret)); @@ -4247,7 +4453,7 @@ wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev) /* search peer on peer's listen channel */ schedule_work(&wl->afx_hdl->work); wait_for_completion_timeout(&wl->act_frm_scan, - msecs_to_jiffies(MAX_WAIT_TIME)); + msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX)); if ((wl->afx_hdl->peer_chan != WL_INVALID) || !(wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev))) @@ -4258,12 +4464,14 @@ wl_cfg80211_af_searching_channel(struct wl_priv *wl, struct net_device *dev) wl->afx_hdl->my_listen_chan)); /* listen on my listen channel */ wl->afx_hdl->is_listen = TRUE; - schedule_work(&wl->afx_hdl->work); + schedule_work(&wl->afx_hdl->work); wait_for_completion_timeout(&wl->act_frm_scan, - msecs_to_jiffies(MAX_WAIT_TIME)); + msecs_to_jiffies(WL_AF_SEARCH_TIME_MAX)); } - if (!wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)) + if ((wl->afx_hdl->peer_chan != WL_INVALID) || + !wl_get_drv_status(wl, FINDING_COMMON_CHANNEL, dev)) break; + wl->afx_hdl->retry++; WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl); @@ -4334,7 +4542,8 @@ wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy, case P2P_PAF_GON_RSP: { wl->next_af_subtype = act_frm->subtype + 1; /* increase dwell time to wait for CONF frame */ - af_params->dwell_time = WL_MED_DWELL_TIME; + af_params->dwell_time = WL_MED_DWELL_TIME + 100; + break; } case P2P_PAF_GON_CONF: { @@ -4403,7 +4612,7 @@ wl_cfg80211_config_p2p_pub_af_tx(struct wiphy *wiphy, case P2P_PAF_PROVDIS_RSP: { wl->next_af_subtype = P2P_PAF_GON_REQ; /* increase dwell time to MED level */ - af_params->dwell_time = WL_MED_DWELL_TIME; + af_params->dwell_time = WL_MIN_DWELL_TIME; #ifdef WL_CFG80211_SYNC_GON config_af_params->extra_listen = false; #endif /* WL_CFG80211_SYNC_GON */ @@ -4431,15 +4640,8 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, #ifdef VSDB ulong off_chan_started_jiffies = 0; #endif + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); -#ifdef WL11U - if (!af_params || !action_frame || (!p2p_is_on(wl) && !wl->wl11u)) -#else - if (!af_params || !action_frame || !p2p_is_on(wl)) - return false; -#endif - - wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len); category = action_frame->data[DOT11_ACTION_CAT_OFF]; action = action_frame->data[DOT11_ACTION_ACT_OFF]; @@ -4481,7 +4683,7 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, } else if (action_frame_len >= sizeof(wifi_p2psd_gas_pub_act_frame_t)) { /* service discovery process */ if (action == P2PSD_ACTION_ID_GAS_IREQ || - action == P2PSD_ACTION_ID_GAS_IREQ) { + action == P2PSD_ACTION_ID_GAS_CREQ) { /* configure service discovery query frame */ config_af_params.search_channel = true; @@ -4491,7 +4693,7 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, af_params->dwell_time = WL_MED_DWELL_TIME; } else if (action == P2PSD_ACTION_ID_GAS_IRESP || - action == P2PSD_ACTION_ID_GAS_IRESP) { + action == P2PSD_ACTION_ID_GAS_CRESP) { /* configure service discovery response frame */ af_params->dwell_time = WL_MIN_DWELL_TIME; } else { @@ -4500,12 +4702,16 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, } else { WL_DBG(("Unknown Frame: category 0x%x, action 0x%x, length %d\n", category, action, action_frame_len)); - } + } } else if (category == P2P_AF_CATEGORY) { /* do not configure anything. it will be sent with a default configuration */ } else { WL_DBG(("Unknown Frame: category 0x%x, action 0x%x\n", category, action)); + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + wl_clr_drv_status(wl, SENDING_ACT_FRM, dev); + return false; + } } /* To make sure to send successfully action frame, we have to turn off mpc */ @@ -4520,7 +4726,6 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, } else { config_af_params.search_channel = false; } - #ifdef WL11U if (ndev == wl_to_prmry_ndev(wl)) config_af_params.search_channel = false; @@ -4535,7 +4740,7 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, /* if scan is ongoing, abort current scan. */ if (wl_get_drv_status_all(wl, SCANNING)) { - wl_notify_escan_complete(wl, ndev, true, true); + wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); } /* set status and destination address before sending af */ @@ -4554,13 +4759,18 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, /* search peer's channel */ if (config_af_params.search_channel) { /* initialize afx_hdl */ - wl->afx_hdl->bssidx = wl_cfgp2p_find_idx(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &wl->afx_hdl->bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + goto exit; + } wl->afx_hdl->dev = dev; wl->afx_hdl->retry = 0; wl->afx_hdl->peer_chan = WL_INVALID; if (wl_cfg80211_af_searching_channel(wl, dev) == WL_INVALID) { WL_ERR(("couldn't find peer's channel.\n")); + wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, + af_params->channel); goto exit; } @@ -4582,6 +4792,8 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, off_chan_started_jiffies = jiffies; #endif /* VSDB */ + wl_cfgp2p_print_actframe(true, action_frame->data, action_frame->len, af_params->channel); + /* Now send a tx action frame */ ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? false : true; @@ -4594,6 +4806,8 @@ wl_cfg80211_send_action_frame(struct wiphy *wiphy, struct net_device *dev, WL_AF_TX_KEEP_PRI_CONNECTION_VSDB(wl); off_chan_started_jiffies = jiffies; } + else + msleep(40); } #endif /* VSDB */ ack = wl_cfgp2p_tx_action_frame(wl, dev, af_params, bssidx) ? @@ -4662,18 +4876,17 @@ exit: return ack; } +#define MAX_NUM_OF_ASSOCIATED_DEV 64 static s32 wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, struct ieee80211_channel *channel, bool offchan, enum nl80211_channel_type channel_type, bool channel_type_valid, unsigned int wait, const u8* buf, size_t len, -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) bool no_cck, #endif -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) bool dont_wait_for_ack, #endif u64 *cookie) @@ -4700,11 +4913,9 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, } /* find bssidx based on ndev */ - bssidx = wl_cfgp2p_find_idx(wl, dev); - if (bssidx == -1) { - - WL_ERR(("Can not find the bssidx for dev( %p )\n", dev)); - return -ENODEV; + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from ndev(%p) failed\n", dev)); + return BCME_ERROR; } if (p2p_is_on(wl)) { /* Suspend P2P discovery search-listen to prevent it from changing the @@ -4727,22 +4938,42 @@ wl_cfg80211_mgmt_tx(struct wiphy *wiphy, struct net_device *ndev, s32 ie_len = len - ie_offset; if (dev == wl_to_prmry_ndev(wl)) bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); - wl_cfgp2p_set_management_ie(wl, dev, bssidx, + wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_PRBRSP_FLAG, (u8 *)(buf + ie_offset), ie_len); cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; } else if (ieee80211_is_disassoc(mgmt->frame_control) || ieee80211_is_deauth(mgmt->frame_control)) { +#ifndef CUSTOMER_HW4 + char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV * + sizeof(struct ether_addr) + sizeof(uint)] = {0}; + int num_associated = 0; + struct maclist *assoc_maclist = (struct maclist *)mac_buf; + if (!bcmp((const uint8 *)BSSID_BROADCAST, + (const struct ether_addr *)mgmt->da, ETHER_ADDR_LEN)) { + assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV; + err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST, + assoc_maclist, sizeof(mac_buf), false); + if (err < 0) + WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err)); + else + num_associated = assoc_maclist->count; + } +#endif /* CUSTOMER_HW4 */ memcpy(scb_val.ea.octet, mgmt->da, ETH_ALEN); scb_val.val = mgmt->u.disassoc.reason_code; err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, sizeof(scb_val_t), true); if (err < 0) WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON error %d\n", err)); - WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + WL_ERR(("Disconnect STA : %s scb_val.val %d\n", bcm_ether_ntoa((const struct ether_addr *)mgmt->da, eabuf), scb_val.val)); - wl_delay(400); +#ifndef CUSTOMER_HW4 + if (num_associated) { + wl_delay(400); + } +#endif /* CUSTOMER_HW4 */ cfg80211_mgmt_tx_status(ndev, *cookie, buf, len, true, GFP_KERNEL); goto exit; @@ -4820,7 +5051,7 @@ wl_cfg80211_mgmt_frame_register(struct wiphy *wiphy, struct net_device *dev, u16 frame_type, bool reg) { - WL_DBG(("%s: frame_type: %x, reg: %d\n", __func__, frame_type, reg)); + WL_DBG(("frame_type: %x, reg: %d\n", frame_type, reg)); if (frame_type != (IEEE80211_FTYPE_MGMT | IEEE80211_STYPE_PROBE_REQ)) return; @@ -4861,11 +5092,16 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, enum nl80211_channel_type channel_type) { s32 _chan; -#ifdef HT40_GO - s32 center_chan; chanspec_t chspec = 0; -#endif + chanspec_t fw_chspec = 0; + u32 bw = WL_CHANSPEC_BW_20; + s32 err = BCME_OK; + s32 bw_cap = 0; + struct { + u32 band; + u32 bw_cap; + } param = {0, 0}; struct wl_priv *wl = wiphy_priv(wiphy); if (wl->p2p_net == dev) { @@ -4890,45 +5126,70 @@ wl_cfg80211_set_channel(struct wiphy *wiphy, struct net_device *dev, } #endif /* NOT_YET */ -#ifdef HT40_GO - switch (_chan) { - /* adjust channel to center of 40MHz band */ - case 40: - case 48: - case 153: - case 161: - if (_chan <= (MAXCHANNEL - CH_20MHZ_APART)) - center_chan = _chan - CH_10MHZ_APART; - chspec = CH40MHZ_CHSPEC(center_chan, WL_CHANSPEC_CTL_SB_UPPER); - break; - case 36: - case 44: - case 149: - case 157: - if (_chan <= (MAXCHANNEL - CH_20MHZ_APART)) - center_chan = _chan + CH_10MHZ_APART; - chspec = CH40MHZ_CHSPEC(center_chan, WL_CHANSPEC_CTL_SB_LOWER); - break; - default: - chspec = CH20MHZ_CHSPEC(_chan); - break; - } - chspec = wl_chspec_host_to_driver(chspec); - if ((err = wldev_iovar_setint(dev, "chanspec", chspec)) == BCME_BADCHAN) { - err = wldev_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), true); - if (err < 0) { - WL_ERR(("WLC_SET_CHANNEL error %d" - "chip may not be supporting this channel\n", err)); + if (chan->band == IEEE80211_BAND_5GHZ) { + param.band = WLC_BAND_5G; + err = wldev_iovar_getbuf(dev, "bw_cap", ¶m, sizeof(param), + wl->ioctl_buf, WLC_IOCTL_SMLEN, &wl->ioctl_buf_sync); + if (err) { + if (err != BCME_UNSUPPORTED) { + WL_ERR(("bw_cap failed, %d\n", err)); + return err; + } else { + err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); + if (err) { + WL_ERR(("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(wl->ioctl_buf[0])) + bw = WL_CHANSPEC_BW_80; + else if (WL_BW_CAP_40MHZ(wl->ioctl_buf[0])) + bw = WL_CHANSPEC_BW_40; + else + bw = WL_CHANSPEC_BW_20; + } + + } else if (chan->band == IEEE80211_BAND_2GHZ) + bw = WL_CHANSPEC_BW_20; +set_channel: + chspec = wf_channel2chspec(_chan, bw); + if (wf_chspec_valid(chspec)) { + fw_chspec = wl_chspec_host_to_driver(chspec); + if (fw_chspec != INVCHANSPEC) { + if ((err = wldev_iovar_setint(dev, "chanspec", + fw_chspec)) == BCME_BADCHAN) { + if (bw == WL_CHANSPEC_BW_80) + goto change_bw; + err = wldev_ioctl(dev, WLC_SET_CHANNEL, + &_chan, sizeof(_chan), true); + if (err < 0) { + WL_ERR(("WLC_SET_CHANNEL error %d" + "chip may not be supporting this channel\n", err)); + } + } else if (err) { + WL_ERR(("failed to set chanspec error %d\n", err)); + } + } else { + WL_ERR(("failed to convert host chanspec to fw chanspec\n")); + err = BCME_ERROR; + } + } else { +change_bw: + 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; + WL_ERR(("Invalid chanspec 0x%x\n", chspec)); + err = BCME_ERROR; } -#else - err = wldev_ioctl(dev, WLC_SET_CHANNEL, &_chan, sizeof(_chan), true); - if (err < 0) { - WL_ERR(("WLC_SET_CHANNEL error %d" - "chip may not be supporting this channel\n", err)); - } -#endif /* HT40_GO */ return err; } @@ -5312,8 +5573,7 @@ wl_cfg80211_bcn_validate_sec( } -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) static s32 wl_cfg80211_bcn_set_params( struct cfg80211_ap_settings *info, struct net_device *dev, @@ -5436,6 +5696,9 @@ wl_cfg80211_bcn_bringup_ap( goto exit; } + /* Do abort scan before creating GO */ + wl_cfg80211_scan_abort(wl); + if ((err = wl_cfgp2p_bss(wl, dev, bssidx, 1)) < 0) { WL_ERR(("GO Bring up error %d\n", err)); goto exit; @@ -5487,23 +5750,20 @@ exit: return err; } -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) s32 -wl_cfg80211_parse_set_ies( +wl_cfg80211_parse_ap_ies( struct net_device *dev, struct cfg80211_beacon_data *info, - struct parsed_ies *ies, - u32 dev_role, - s32 bssidx) + struct parsed_ies *ies) { - struct wl_priv *wl = wlcfg_drv_priv; struct parsed_ies prb_ies; + struct wl_priv *wl = wlcfg_drv_priv; + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + u8 *vndr; + u32 vndr_ie_len; s32 err = BCME_OK; - memset(ies, 0, sizeof(struct parsed_ies)); - memset(&prb_ies, 0, sizeof(struct parsed_ies)); - /* Parse Beacon IEs */ if (wl_cfg80211_parse_ies((u8 *)info->tail, info->tail_len, ies) < 0) { @@ -5512,6 +5772,42 @@ wl_cfg80211_parse_set_ies( goto fail; } + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + /* SoftAP mode */ + struct ieee80211_mgmt *mgmt; + mgmt = (struct ieee80211_mgmt *)info->probe_resp; + vndr = (u8 *)&mgmt->u.probe_resp.variable; + vndr_ie_len = info->probe_resp_len - + offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + } else { + /* Other mode */ + vndr = (u8 *)info->proberesp_ies; + vndr_ie_len = info->proberesp_ies_len; + } + + /* Parse Probe Response IEs */ + if (wl_cfg80211_parse_ies(vndr, vndr_ie_len, &prb_ies) < 0) { + WL_ERR(("PROBE RESP get IEs failed \n")); + err = -EINVAL; + } + +fail: + + return err; +} + +s32 +wl_cfg80211_set_ies( + struct net_device *dev, + struct cfg80211_beacon_data *info, + s32 bssidx) +{ + struct wl_priv *wl = wlcfg_drv_priv; + dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); + u8 *vndr; + u32 vndr_ie_len; + s32 err = BCME_OK; + /* Set Beacon IEs to FW */ if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, VNDR_IE_BEACON_FLAG, (u8 *)info->tail, @@ -5521,25 +5817,27 @@ wl_cfg80211_parse_set_ies( WL_DBG(("Applied Vndr IEs for Beacon \n")); } - /* Parse Probe Response IEs */ - if (wl_cfg80211_parse_ies((u8 *)info->proberesp_ies, - info->proberesp_ies_len, &prb_ies) < 0) { - WL_ERR(("PRB RESP get IEs failed \n")); - err = -EINVAL; - goto fail; + if (dhd->op_mode & DHD_FLAG_HOSTAP_MODE) { + /* SoftAP mode */ + struct ieee80211_mgmt *mgmt; + mgmt = (struct ieee80211_mgmt *)info->probe_resp; + vndr = (u8 *)&mgmt->u.probe_resp.variable; + vndr_ie_len = info->probe_resp_len - + offsetof(struct ieee80211_mgmt, u.probe_resp.variable); + } else { + /* Other mode */ + vndr = (u8 *)info->proberesp_ies; + vndr_ie_len = info->proberesp_ies_len; } /* Set Probe Response IEs to FW */ if ((err = wl_cfgp2p_set_management_ie(wl, dev, bssidx, - VNDR_IE_PRBRSP_FLAG, (u8 *)info->proberesp_ies, - info->proberesp_ies_len)) < 0) { + VNDR_IE_PRBRSP_FLAG, vndr, vndr_ie_len)) < 0) { WL_ERR(("Set Probe Resp IE Failed \n")); } else { WL_DBG(("Applied Vndr IEs for Probe Resp \n")); } -fail: - return err; } #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ @@ -5612,6 +5910,8 @@ static s32 wl_cfg80211_hostapd_sec( return 0; } +#if 1 //defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ + 2, 0)) static s32 wl_cfg80211_del_station( struct wiphy *wiphy, @@ -5622,6 +5922,13 @@ wl_cfg80211_del_station( struct wl_priv *wl = wiphy_priv(wiphy); scb_val_t scb_val; s8 eabuf[ETHER_ADDR_STR_LEN]; + int err; +#ifndef CUSTOMER_HW4 + char mac_buf[MAX_NUM_OF_ASSOCIATED_DEV * + sizeof(struct ether_addr) + sizeof(uint)] = {0}; + struct maclist *assoc_maclist = (struct maclist *)mac_buf; + int num_associated = 0; +#endif /* CUSTOMER_HW4 */ WL_DBG(("Entry\n")); if (mac_addr == NULL) { @@ -5645,20 +5952,34 @@ wl_cfg80211_del_station( } } +#ifndef CUSTOMER_HW4 + assoc_maclist->count = MAX_NUM_OF_ASSOCIATED_DEV; + err = wldev_ioctl(ndev, WLC_GET_ASSOCLIST, + assoc_maclist, sizeof(mac_buf), false); + if (err < 0) + WL_ERR(("WLC_GET_ASSOCLIST error %d\n", err)); + else + num_associated = assoc_maclist->count; +#endif /* CUSTOMER_HW4 */ + memcpy(scb_val.ea.octet, mac_addr, ETHER_ADDR_LEN); scb_val.val = DOT11_RC_DEAUTH_LEAVING; - if (wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, - sizeof(scb_val_t), true)) - WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON failed\n")); - WL_DBG(("Disconnect STA : %s scb_val.val %d\n", + err = wldev_ioctl(dev, WLC_SCB_DEAUTHENTICATE_FOR_REASON, &scb_val, + sizeof(scb_val_t), true); + if (err < 0) + WL_ERR(("WLC_SCB_DEAUTHENTICATE_FOR_REASON err %d\n", err)); + WL_ERR(("Disconnect STA : %s scb_val.val %d\n", bcm_ether_ntoa((const struct ether_addr *)mac_addr, eabuf), scb_val.val)); - wl_delay(400); +#ifndef CUSTOMER_HW4 + if (num_associated) + wl_delay(400); +#endif /* CUSTOMER_HW4 */ return 0; } +#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VER >= KERNEL_VERSION(3, 2, 0)) */ -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) static s32 wl_cfg80211_start_ap( struct wiphy *wiphy, @@ -5681,8 +6002,10 @@ wl_cfg80211_start_ap( dev = wl_to_prmry_ndev(wl); dev_role = NL80211_IFTYPE_P2P_GO; } - - bssidx = wl_cfgp2p_find_idx(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (p2p_is_on(wl) && (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION))) { @@ -5696,10 +6019,9 @@ wl_cfg80211_start_ap( goto fail; } - /* Set IEs to FW */ - if ((err = wl_cfg80211_parse_set_ies(dev, &info->beacon, - &ies, dev_role, bssidx) < 0)) { - WL_ERR(("Set IEs failed \n")); + /* Parse IEs */ + if ((err = wl_cfg80211_parse_ap_ies(dev, &info->beacon, &ies) < 0)) { + WL_ERR(("Parse IEs failed \n")); goto fail; } @@ -5718,6 +6040,10 @@ wl_cfg80211_start_ap( WL_DBG(("** AP/GO Created **\n")); + /* Set IEs to FW */ + if ((err = wl_cfg80211_set_ies(dev, &info->beacon, bssidx) < 0)) + WL_ERR(("Set IEs failed \n")); + fail: if (err) { WL_ERR(("ADD/SET beacon failed\n")); @@ -5747,7 +6073,10 @@ wl_cfg80211_stop_ap( dev = wl_to_prmry_ndev(wl); dev_role = NL80211_IFTYPE_P2P_GO; } - bssidx = wl_cfgp2p_find_idx(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (p2p_is_on(wl) && (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION))) { @@ -5787,6 +6116,7 @@ wl_cfg80211_stop_ap( exit: return err; } + static s32 wl_cfg80211_change_beacon( struct wiphy *wiphy, @@ -5808,17 +6138,24 @@ wl_cfg80211_change_beacon( dev = wl_to_prmry_ndev(wl); dev_role = NL80211_IFTYPE_P2P_GO; } - - bssidx = wl_cfgp2p_find_idx(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (p2p_is_on(wl) && (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION))) { dev_role = NL80211_IFTYPE_P2P_GO; } + /* Parse IEs */ + if ((err = wl_cfg80211_parse_ap_ies(dev, info, &ies) < 0)) { + WL_ERR(("Parse IEs failed \n")); + goto fail; + } + /* Set IEs to FW */ - if ((err = wl_cfg80211_parse_set_ies(dev, info, - &ies, dev_role, bssidx) < 0)) { + if ((err = wl_cfg80211_set_ies(dev, info, bssidx) < 0)) { WL_ERR(("Set IEs failed \n")); goto fail; } @@ -5857,8 +6194,10 @@ wl_cfg80211_add_set_beacon(struct wiphy *wiphy, struct net_device *dev, dev = wl_to_prmry_ndev(wl); dev_role = NL80211_IFTYPE_P2P_GO; } - - bssidx = wl_cfgp2p_find_idx(wl, dev); + if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (p2p_is_on(wl) && (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_CONNECTION))) { @@ -5955,6 +6294,105 @@ fail: } #endif /* LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) */ +#ifdef WL_SCHED_SCAN +#define PNO_TIME 30 +#define PNO_REPEAT 4 +#define PNO_FREQ_EXPO_MAX 2 +int wl_cfg80211_sched_scan_start(struct wiphy *wiphy, + struct net_device *dev, + struct cfg80211_sched_scan_request *request) +{ + ushort pno_time = PNO_TIME; + int pno_repeat = PNO_REPEAT; + int pno_freq_expo_max = PNO_FREQ_EXPO_MAX; + wlc_ssid_t ssids_local[MAX_PFN_LIST_COUNT]; + struct wl_priv *wl = wiphy_priv(wiphy); + struct cfg80211_ssid *ssid = NULL; + int ssid_count = 0; + int i; + int ret = 0; + + WL_DBG(("Enter \n")); + WL_PNO((">>> SCHED SCAN START\n")); + WL_PNO(("Enter n_match_sets:%d n_ssids:%d \n", + request->n_match_sets, request->n_ssids)); + WL_PNO(("ssids:%d pno_time:%d pno_repeat:%d pno_freq:%d \n", + request->n_ssids, pno_time, pno_repeat, pno_freq_expo_max)); + + + if (!request || !request->n_ssids || !request->n_match_sets) { + WL_ERR(("Invalid sched scan req!! n_ssids:%d \n", request->n_ssids)); + return -EINVAL; + } + + memset(&ssids_local, 0, sizeof(ssids_local)); + + if (request->n_match_sets > 0) { + for (i = 0; i < request->n_match_sets; i++) { + ssid = &request->match_sets[i].ssid; + memcpy(ssids_local[i].SSID, ssid->ssid, ssid->ssid_len); + ssids_local[i].SSID_len = ssid->ssid_len; + WL_PNO((">>> PNO filter set for ssid (%s) \n", ssid->ssid)); + ssid_count++; + } + } + + if (request->n_ssids > 0) { + for (i = 0; i < request->n_ssids; i++) { + /* Active scan req for ssids */ + WL_PNO((">>> Active scan req for ssid (%s) \n", request->ssids[i].ssid)); + + /* match_set ssids is a supert set of n_ssid list, so we need + * not add these set seperately + */ + } + } + + if (ssid_count) { + if ((ret = dhd_dev_pno_set(dev, ssids_local, request->n_match_sets, + pno_time, pno_repeat, pno_freq_expo_max)) < 0) { + WL_ERR(("PNO setup failed!! ret=%d \n", ret)); + return -EINVAL; + } + + /* Enable the PNO */ + if (dhd_dev_pno_enable(dev, 1) < 0) { + WL_ERR(("PNO enable failed!! ret=%d \n", ret)); + return -EINVAL; + } + wl->sched_scan_req = request; + } else { + return -EINVAL; + } + + return 0; +} + +int wl_cfg80211_sched_scan_stop(struct wiphy *wiphy, struct net_device *dev) +{ + struct wl_priv *wl = wiphy_priv(wiphy); + + WL_DBG(("Enter \n")); + WL_PNO((">>> SCHED SCAN STOP\n")); + + if (dhd_dev_pno_enable(dev, 0) < 0) + WL_ERR(("PNO disable failed")); + + if (dhd_dev_pno_reset(dev) < 0) + WL_ERR(("PNO reset failed")); + + if (wl->scan_request && wl->sched_scan_running) { + WL_PNO((">>> Sched scan running. Aborting it..\n")); + wl_notify_escan_complete(wl, dev, true, true); + } + + wl->sched_scan_req = NULL; + wl->sched_scan_running = FALSE; + + return 0; +} +#endif /* WL_SCHED_SCAN */ + static struct cfg80211_ops wl_cfg80211_ops = { .add_virtual_intf = wl_cfg80211_add_virtual_iface, .del_virtual_intf = wl_cfg80211_del_virtual_iface, @@ -5985,8 +6423,7 @@ static struct cfg80211_ops wl_cfg80211_ops = { .mgmt_frame_register = wl_cfg80211_mgmt_frame_register, .change_bss = wl_cfg80211_change_bss, .set_channel = wl_cfg80211_set_channel, -//#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) -#if 0 +#if 0 //LINUX_VERSION_CODE < KERNEL_VERSION(3, 4, 0) .set_beacon = wl_cfg80211_add_set_beacon, .add_beacon = wl_cfg80211_add_set_beacon, #else @@ -5998,8 +6435,14 @@ static struct cfg80211_ops wl_cfg80211_ops = { .sched_scan_start = wl_cfg80211_sched_scan_start, .sched_scan_stop = wl_cfg80211_sched_scan_stop, #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) */ +#if 1 //defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ + 2, 0)) .del_station = wl_cfg80211_del_station, .mgmt_tx_cancel_wait = wl_cfg80211_mgmt_tx_cancel_wait, +#endif /* WL_SUPPORT_BACKPORTED_KPATCHES || KERNEL_VERSION >= (3,2,0) */ +#if 1 //LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) + .tdls_oper = wl_cfg80211_tdls_oper +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) */ }; s32 wl_mode_to_nl80211_iftype(s32 mode) @@ -6035,6 +6478,12 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev /* Report how many SSIDs Driver can support per Scan request */ wdev->wiphy->max_scan_ssids = WL_SCAN_PARAMS_SSID_MAX; wdev->wiphy->max_num_pmkids = WL_NUM_PMKIDS_MAX; +#ifdef WL_SCHED_SCAN + wdev->wiphy->max_sched_scan_ssids = MAX_PFN_LIST_COUNT; + wdev->wiphy->max_match_sets = MAX_PFN_LIST_COUNT; + wdev->wiphy->max_sched_scan_ie_len = WL_SCAN_IE_LEN_MAX; + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; +#endif /* WL_SCHED_SCAN */ wdev->wiphy->interface_modes = BIT(NL80211_IFTYPE_STATION) #if !(defined(WLP2P) && defined(WL_ENABLE_P2P_IF)) @@ -6069,23 +6518,36 @@ static s32 wl_setup_wiphy(struct wireless_dev *wdev, struct device *sdiofunc_dev * to let Supplicant to provide channel info and FW letter may roam * if needed so DON'T advertise that featur eto Supplicant. */ -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 2, 0) /* wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_FW_ROAM; */ #endif -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) wdev->wiphy->flags |= WIPHY_FLAG_HAS_REMAIN_ON_CHANNEL | WIPHY_FLAG_OFFCHAN_TX; #endif -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -#if 1 +#if 1 //defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ + 4, 0)) /* From 3.4 kernel ownards AP_SME flag can be advertised * to remove the patch from supplicant */ wdev->wiphy->flags |= WIPHY_FLAG_HAVE_AP_SME; +#if 1 //(LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) + /* Supplicant distinguish between the SoftAP mode and other + * modes (e.g. P2P, WPS, HS2.0) when it builds the probe + * response frame from Supplicant MR1 and Kernel 3.4.0 or + * later version. To add Vendor specific IE into the + * probe response frame in case of SoftAP mode, + * AP_PROBE_RESP_OFFLOAD flag is set to wiphy->flags variable. + */ + if (strstr(fw_path, "_apsta") != NULL) { + wdev->wiphy->flags |= WIPHY_FLAG_AP_PROBE_RESP_OFFLOAD; + wdev->wiphy->probe_resp_offload = 0; + } +#endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ +#endif /* WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0)) */ +#if 1 //LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) + wdev->wiphy->flags |= WIPHY_FLAG_SUPPORTS_TDLS; #endif - WL_DBG(("Registering custom regulatory)\n")); wdev->wiphy->flags |= WIPHY_FLAG_CUSTOM_REGULATORY; wiphy_apply_custom_regulatory(wdev->wiphy, &brcm_regdom); @@ -6126,25 +6588,26 @@ static s32 wl_inform_bss(struct wl_priv *wl) bss_list = wl->bss_list; WL_DBG(("scanned AP count (%d)\n", bss_list->count)); -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) reset_roam_cache(); -#endif +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ bi = next_bss(bss_list, bi); for_each_bss(bss_list, bi, i) { -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) add_roam_cache(bi); -#endif - err = wl_inform_single_bss(wl, bi); +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ + err = wl_inform_single_bss(wl, bi, 0); if (unlikely(err)) break; } -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) /* print_roam_cache(); */ -#endif + update_roam_cache(wl, ioctl_version); +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ return err; } -static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) +static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi, u8 is_roam_done) { struct wiphy *wiphy = wl_to_wiphy(wl); struct ieee80211_mgmt *mgmt; @@ -6159,6 +6622,7 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) u32 freq; s32 err = 0; gfp_t aflags; + u8 *ie_offset = NULL; if (unlikely(dtoh32(bi->length) > WL_BSS_INFO_MAX)) { WL_DBG(("Beacon is larger than buffer. Discarding\n")); @@ -6199,7 +6663,36 @@ static s32 wl_inform_single_bss(struct wl_priv *wl, struct wl_bss_info *bi) beacon_proberesp->capab_info = cpu_to_le16(bi->capability); wl_rst_ie(wl); - wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); + ie_offset = ((u8 *) bi) + bi->ie_offset; + + if (is_roam_done && ((int)(*(ie_offset)) == WLAN_EID_SSID && + ((int)(*(ie_offset+1)) == 0 || (int)(*(ie_offset+2)) == 0))) { + u8 *ie_new_offset = NULL; + uint8 ie_new_length; + + WL_ERR(("WAR trace: Changing the SSID Info, from beacon %d\n", + bi->flags & WL_BSS_FLAGS_FROM_BEACON)); + + ie_new_offset = (u8 *)kzalloc(WL_BSS_INFO_MAX, GFP_KERNEL); + if (ie_new_offset) { + *(ie_new_offset) = WLAN_EID_SSID; + *(ie_new_offset+1) = bi->SSID_len; + memcpy(ie_new_offset+2, bi->SSID, bi->SSID_len); + ie_new_length = bi->ie_length - *(ie_offset+1) + bi->SSID_len; + + /* Copy the remaining IE apart from SSID IE from bi */ + memcpy(ie_new_offset+2 + bi->SSID_len, + ie_offset+2 + *(ie_offset+1), + bi->ie_length - 2 - *(ie_offset+1)); + wl_mrg_ie(wl, ie_new_offset, ie_new_length); + kfree(ie_new_offset); + } else { + wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); + } + } else { + wl_mrg_ie(wl, ((u8 *) bi) + bi->ie_offset, bi->ie_length); + } + wl_cp_ie(wl, beacon_proberesp->variable, WL_BSS_INFO_MAX - offsetof(struct wl_cfg80211_bss_info, frame_buf)); notif_bss_info->frame_len = offsetof(struct ieee80211_mgmt, @@ -6329,8 +6822,7 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, u32 reason = ntoh32(e->reason); u32 len = ntoh32(e->datalen); -//#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) -#if 0 +#if 0 //(LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) bool isfree = false; u8 *mgmt_frame; u8 bsscfgidx = e->bsscfgidx; @@ -6352,14 +6844,13 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, /* if link down, bsscfg is disabled. */ if (event == WLC_E_LINK && reason == WLC_E_LINK_BSSCFG_DIS && wl_get_p2p_status(wl, IF_DELETING) && (ndev != wl_to_prmry_ndev(wl))) { + wl_add_remove_eventmsg(ndev, WLC_E_PROBREQ_MSG, false); WL_INFO(("AP mode link down !! \n")); complete(&wl->iface_disable); return 0; } -//#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) -#if 0 - body = kzalloc(len, GFP_KERNEL); +#if 0 //(LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0)) && !defined(WL_CFG80211_STA_EVENT) WL_DBG(("Enter \n")); if (!len && (event == WLC_E_DEAUTH)) { len = 2; /* reason code field */ @@ -6436,19 +6927,19 @@ wl_notify_connect_status_ap(struct wl_priv *wl, struct net_device *ndev, isfree = true; if (event == WLC_E_ASSOC_IND && reason == DOT11_SC_SUCCESS) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); #else cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ } else if (event == WLC_E_DISASSOC_IND) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); #else cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ } else if ((event == WLC_E_DEAUTH_IND) || (event == WLC_E_DEAUTH)) { -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, len, GFP_ATOMIC); #else cfg80211_rx_mgmt(ndev, freq, mgmt_frame, len, GFP_ATOMIC); @@ -6518,7 +7009,7 @@ wl_notify_connect_status(struct wl_priv *wl, struct net_device *ndev, ntoh32(e->event_type), ntoh32(e->status), ndev)); if (event == WLC_E_ASSOC || event == WLC_E_AUTH) { wl_get_auth_assoc_status(wl, ndev, e); - return err; + return 0; } if (wl_is_linkup(wl, e, ndev)) { wl_link_up(wl); @@ -6686,8 +7177,8 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) if (conn_info->req_ie_len <= MAX_REQ_LINE) memcpy(conn_info->req_ie, wl->extra_buf, conn_info->req_ie_len); else { - WL_ERR(("%s IE size %d above max %d size \n", - __FUNCTION__, conn_info->req_ie_len, MAX_REQ_LINE)); + WL_ERR(("IE size %d above max %d size \n", + conn_info->req_ie_len, MAX_REQ_LINE)); return err; } } else { @@ -6704,8 +7195,8 @@ static s32 wl_get_assoc_ies(struct wl_priv *wl, struct net_device *ndev) if (conn_info->resp_ie_len <= MAX_REQ_LINE) memcpy(conn_info->resp_ie, wl->extra_buf, conn_info->resp_ie_len); else { - WL_ERR(("%s IE size %d above max %d size \n", - __FUNCTION__, conn_info->resp_ie_len, MAX_REQ_LINE)); + WL_ERR(("IE size %d above max %d size \n", + conn_info->resp_ie_len, MAX_REQ_LINE)); return err; } } else { @@ -6724,7 +7215,7 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, chanspec_t chanspec = 0; #endif if (ch != 0) { -#ifdef ROAM_CHANNEL_CACHE +#if defined(CUSTOMER_HW4) && defined(ROAM_CHANNEL_CACHE) int n_channels; n_channels = get_roam_channel_list(ch, join_params->params.chanspec_list, @@ -6755,14 +7246,14 @@ static void wl_ch_to_chanspec(int ch, struct wl_join_params *join_params, join_params->params.chanspec_num = htod32(join_params->params.chanspec_num); -#endif /* ROAM_CHANNEL_CACHE */ +#endif /* CUSTOMER_HW4 && ROAM_CHANNEL_CACHE */ WL_DBG(("join_params->params.chanspec_list[0]= %X, %d channels\n", join_params->params.chanspec_list[0], join_params->params.chanspec_num)); } } -static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) +static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev, u8 is_roam_done) { struct cfg80211_bss *bss; struct wl_bss_info *bi; @@ -6810,7 +7301,7 @@ static s32 wl_update_bss_info(struct wl_priv *wl, struct net_device *ndev) if (ssidie && ssidie[1] == bi->SSID_len && !ssidie[2] && bi->SSID[0]) memcpy(ssidie + 2, bi->SSID, bi->SSID_len); - err = wl_inform_single_bss(wl, bi); + err = wl_inform_single_bss(wl, bi, is_roam_done); if (unlikely(err)) goto update_bss_info_out; @@ -6857,21 +7348,52 @@ wl_bss_roaming_done(struct wl_priv *wl, struct net_device *ndev, struct wl_connect_info *conn_info = wl_to_conn(wl); s32 err = 0; u8 *curbssid; +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) + struct wl_bss_info *bss_info; + struct wiphy *wiphy = wl_to_wiphy(wl); + struct ieee80211_supported_band *band; + struct ieee80211_channel *notify_channel = NULL; + u8 *buf; + u16 channel; + u32 freq; +#endif /* LINUX_VERSION > 2.6.39 */ wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev); + wl_update_bss_info(wl, ndev, 1); wl_update_pmklist(ndev, wl->pmk_list, err); + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) + /* channel info for cfg80211_roamed introduced in 2.6.39-rc1 */ + buf = kzalloc(WL_EXTRA_BUF_MAX, GFP_KERNEL); + if (!buf) + goto done; + + *(__le32 *)buf = htod32(WL_EXTRA_BUF_MAX); + err = wldev_ioctl(ndev, WLC_GET_BSS_INFO, buf, WL_EXTRA_BUF_MAX, false); + if (err) + goto done; + + bss_info = (struct wl_bss_info *)(buf + 4); + channel = bss_info->ctl_ch ? bss_info->ctl_ch : + CHSPEC_CHANNEL(wl_chspec_driver_to_host(bss_info->chanspec)); + if (channel <= CH_MAX_2G_CHANNEL) + band = wiphy->bands[IEEE80211_BAND_2GHZ]; + else + band = wiphy->bands[IEEE80211_BAND_5GHZ]; + freq = ieee80211_channel_to_frequency(channel, band->band); + notify_channel = ieee80211_get_channel(wiphy, freq); +done: + kfree(buf); +#endif /* LINUX_VERSION > 2.6.39 */ + printk("wl_bss_roaming_done succeeded to " MACDBG "\n", MAC2STRDBG((u8*)(&e->addr))); cfg80211_roamed(ndev, - -#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 3, 0) - NULL, /* struct cfg80211_bss *bss */ -#elif LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) - NULL, +#if LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 39) + notify_channel, #endif curbssid, conn_info->req_ie, conn_info->req_ie_len, @@ -6889,7 +7411,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, { struct wl_connect_info *conn_info = wl_to_conn(wl); struct wl_security *sec = wl_read_prof(wl, ndev, WL_PROF_SEC); -#ifdef ROAM_AP_ENV_DETECTION +#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) dhd_pub_t *dhd = (dhd_pub_t *)(wl->pub); #endif /* ROAM_AP_ENV_DETECTION */ s32 err = 0; @@ -6902,7 +7424,7 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, #ifdef ESCAN_RESULT_PATCH if (wl_get_drv_status(wl, CONNECTED, ndev)) { if (memcmp(curbssid, connect_req_bssid, ETHER_ADDR_LEN) == 0) { - WL_ERR((" Connected event of connected device e=%d s=%d, ignore it\n", + WL_DBG((" Connected event of connected device e=%d s=%d, ignore it\n", ntoh32(e->event_type), ntoh32(e->status))); return err; } @@ -6929,14 +7451,18 @@ wl_bss_connect_done(struct wl_priv *wl, struct net_device *ndev, wl_get_assoc_ies(wl, ndev); wl_update_prof(wl, ndev, NULL, (void *)(e->addr.octet), WL_PROF_BSSID); curbssid = wl_read_prof(wl, ndev, WL_PROF_BSSID); - wl_update_bss_info(wl, ndev); + wl_update_bss_info(wl, ndev, 0); wl_update_pmklist(ndev, wl->pmk_list, err); wl_set_drv_status(wl, CONNECTED, ndev); -#ifdef ROAM_AP_ENV_DETECTION +#if defined(ROAM_ENABLE) && defined(ROAM_AP_ENV_DETECTION) if (dhd->roam_env_detection) wldev_iovar_setint(ndev, "roam_env_detection", AP_ENV_INDETERMINATE); #endif /* ROAM_AP_ENV_DETECTION */ + if (ndev != wl_to_prmry_ndev(wl)) { + /* reinitialize completion to clear previous count */ + INIT_COMPLETION(wl->iface_disable); + } } cfg80211_connect_result(ndev, curbssid, @@ -6985,10 +7511,12 @@ wl_notify_pfn_status(struct wl_priv *wl, struct net_device *ndev, WL_ERR((">>> PNO Event\n")); #ifndef WL_SCHED_SCAN +#ifndef CUSTOMER_HW4 mutex_lock(&wl->usr_sync); /* TODO: Use cfg80211_sched_scan_results(wiphy); */ cfg80211_disconnected(ndev, 0, NULL, 0, GFP_KERNEL); mutex_unlock(&wl->usr_sync); +#endif /* !CUSTOMER_HW4 */ #else /* If cfg80211 scheduled scan is supported, report the pno results via sched * scan results @@ -7156,24 +7684,23 @@ wl_gon_req_collision(struct wl_priv *wl, wl_action_frame_t *tx_act_frm, void wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev) { - if (wl_get_drv_status_all(wl, SENDING_ACT_FRM) && - (wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || - wl_get_p2p_status(wl, ACTION_TX_NOACK))) { + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + if (!(wl_get_p2p_status(wl, ACTION_TX_COMPLETED) || + wl_get_p2p_status(wl, ACTION_TX_NOACK))) + wl_set_p2p_status(wl, ACTION_TX_COMPLETED); + WL_DBG(("*** Wake UP ** abort actframe iovar\n")); /* if channel is not zero, "actfame" uses off channel scan. * So abort scan for off channel completion. */ if (wl->af_sent_channel) - /* wl_cfg80211_scan_abort(wl, ndev); */ - wl_notify_escan_complete(wl, - (ndev == wl->p2p_net) ? wl_to_prmry_ndev(wl) : ndev, true, true); + wl_cfg80211_scan_abort(wl); } #ifdef WL_CFG80211_SYNC_GON else if (wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM_LISTEN)) { WL_DBG(("*** Wake UP ** abort listen for next af frame\n")); /* So abort scan to cancel listen */ - wl_notify_escan_complete(wl, - (ndev == wl->p2p_net) ? wl_to_prmry_ndev(wl) : ndev, true, true); + wl_cfg80211_scan_abort(wl); } #endif /* WL_CFG80211_SYNC_GON */ } @@ -7196,19 +7723,19 @@ bool wl_cfg80211_is_wes(void *frame, u32 frame_len) unsigned char *data; if (frame == NULL) { - WL_ERR(("%s: Invalid frame \n", __FUNCTION__)); + WL_ERR(("Invalid frame \n")); return false; } if (frame_len < 4) { - WL_ERR(("%s: Invalid frame length [%d] \n", __FUNCTION__, frame_len)); + WL_ERR(("Invalid frame length [%d] \n", frame_len)); return false; } data = frame; if (memcmp(data, "\x7f\x00\x00\xf0", 4) == 0) { - WL_DBG(("%s: Receive WES VS Action Frame \n", __FUNCTION__)); + WL_DBG(("Receive WES VS Action Frame \n")); return true; } @@ -7278,8 +7805,8 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, &mgmt_frame, &mgmt_frame_len, (u8 *)((wl_event_rx_frame_data_t *)rxframe + 1)); if (err < 0) { - WL_ERR(("%s: Error in receiving action frame len %d channel %d freq %d\n", - __func__, mgmt_frame_len, channel, freq)); + WL_ERR(("Error in receiving action frame len %d channel %d freq %d\n", + mgmt_frame_len, channel, freq)); goto exit; } isfree = true; @@ -7294,6 +7821,7 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, (void) p2p_act_frm; } else if (wl_cfgp2p_is_gas_action(&mgmt_frame[DOT11_MGMT_HDR_LEN], mgmt_frame_len - DOT11_MGMT_HDR_LEN)) { + sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *) (&mgmt_frame[DOT11_MGMT_HDR_LEN]); if (sd_act_frm && wl_get_drv_status_all(wl, WAITING_NEXT_ACT_FRM)) { @@ -7311,8 +7839,8 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, (void) sd_act_frm; } else { /* - * if we got normal action frame and ndev is p2p0, - * we have to change ndev from p2p0 to wlan0 + * if we got normal action frame and ndev is p2p0, + * we have to change ndev from p2p0 to wlan0 */ #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) if (wl_cfg80211_is_wes(&mgmt_frame[DOT11_MGMT_HDR_LEN], @@ -7354,13 +7882,14 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, wl_to_prmry_ndev(wl) : ndev); /* Stop waiting for next AF. */ - wl_stop_wait_next_action_frame(wl, ndev); + if (act_frm->subtype != P2P_PAF_GON_CONF) + wl_stop_wait_next_action_frame(wl, ndev); } } } wl_cfgp2p_print_actframe(false, &mgmt_frame[DOT11_MGMT_HDR_LEN], - mgmt_frame_len - DOT11_MGMT_HDR_LEN); + mgmt_frame_len - DOT11_MGMT_HDR_LEN, channel); /* * After complete GO Negotiation, roll back to mpc mode */ @@ -7411,14 +7940,13 @@ wl_notify_rx_mgmt_frame(struct wl_priv *wl, struct net_device *ndev, } } -//#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) -#if 1 +#if 1 //LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) cfg80211_rx_mgmt(ndev, freq, 0, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); #else cfg80211_rx_mgmt(ndev, freq, mgmt_frame, mgmt_frame_len, GFP_ATOMIC); #endif /* LINUX_VERSION_CODE >= KERNEL_VERSION(3, 4, 0) */ - WL_DBG(("%s: mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", __func__, + WL_DBG(("mgmt_frame_len (%d) , e->datalen (%d), channel (%d), freq (%d)\n", mgmt_frame_len, ntoh32(e->datalen), channel, freq)); exit: if (isfree) @@ -7426,6 +7954,122 @@ exit: return 0; } +#ifdef WL_SCHED_SCAN +/* If target scan is not reliable, set the below define to "1" to do a + * full escan + */ +#define FULL_ESCAN_ON_PFN_NET_FOUND 0 +static s32 +wl_notify_sched_scan_results(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) +{ + wl_pfn_net_info_t *netinfo, *pnetinfo; + struct cfg80211_scan_request request; + struct wiphy *wiphy = wl_to_wiphy(wl); + int err = 0; + struct cfg80211_ssid ssid[MAX_PFN_LIST_COUNT]; + struct ieee80211_channel *channel = NULL; + int channel_req = 0; + int band = 0; + struct wl_pfn_scanresults *pfn_result = (struct wl_pfn_scanresults *)data; + + WL_DBG(("Enter\n")); + + if (e->event_type == WLC_E_PFN_NET_LOST) { + WL_PNO(("PFN NET LOST event. Do Nothing \n")); + return 0; + } + WL_PNO((">>> PFN NET FOUND event. count:%d \n", pfn_result->count)); + if (pfn_result->count > 0) { + int i; + + memset(&request, 0x00, sizeof(struct cfg80211_scan_request)); + memset(&ssid, 0x00, sizeof(ssid)); + request.wiphy = wiphy; + + pnetinfo = (wl_pfn_net_info_t *)(data + sizeof(wl_pfn_scanresults_t) + - sizeof(wl_pfn_net_info_t)); + channel = (struct ieee80211_channel *)kzalloc( + (sizeof(struct ieee80211_channel) * MAX_PFN_LIST_COUNT), + GFP_KERNEL); + if (!channel) { + WL_ERR(("No memory")); + err = -ENOMEM; + goto out_err; + } + + for (i = 0; i < pfn_result->count; i++) { + netinfo = &pnetinfo[i]; + if (!netinfo) { + WL_ERR(("Invalid netinfo ptr. index:%d", i)); + err = -EINVAL; + goto out_err; + } + WL_PNO((">>> SSID:%s Channel:%d \n", + netinfo->pfnsubnet.SSID, netinfo->pfnsubnet.channel)); + /* PFN result doesn't have all the info which are required by the supplicant + * (For e.g IEs) Do a target Escan so that sched scan results are reported + * via wl_inform_single_bss in the required format. Escan does require the + * scan request in the form of cfg80211_scan_request. For timebeing, create + * cfg80211_scan_request one out of the received PNO event. + */ + memcpy(ssid[i].ssid, netinfo->pfnsubnet.SSID, + netinfo->pfnsubnet.SSID_len); + ssid[i].ssid_len = netinfo->pfnsubnet.SSID_len; + request.n_ssids++; + + channel_req = netinfo->pfnsubnet.channel; + band = (channel_req <= CH_MAX_2G_CHANNEL) ? NL80211_BAND_2GHZ + : NL80211_BAND_5GHZ; + channel[i].center_freq = ieee80211_channel_to_frequency(channel_req, band); + channel[i].band = band; + channel[i].flags |= IEEE80211_CHAN_NO_HT40; + request.channels[i] = &channel[i]; + request.n_channels++; + } + + /* assign parsed ssid array */ + if (request.n_ssids) + request.ssids = &ssid[0]; + + if (wl_get_drv_status_all(wl, SCANNING)) { + /* Abort any on-going scan */ + wl_notify_escan_complete(wl, ndev, true, true); + } + + if (wl_get_p2p_status(wl, DISCOVERY_ON)) { + WL_PNO((">>> P2P discovery was ON. Disabling it\n")); + err = wl_cfgp2p_discover_enable_search(wl, false); + if (unlikely(err)) { + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } + } + + wl_set_drv_status(wl, SCANNING, ndev); +#if FULL_ESCAN_ON_PFN_NET_FOUND + WL_PNO((">>> Doing Full ESCAN on PNO event\n")); + err = wl_do_escan(wl, wiphy, ndev, NULL); +#else + WL_PNO((">>> Doing targeted ESCAN on PNO event\n")); + err = wl_do_escan(wl, wiphy, ndev, &request); +#endif + if (err) { + wl_clr_drv_status(wl, SCANNING, ndev); + goto out_err; + } + wl->sched_scan_running = TRUE; + } + else { + WL_ERR(("FALSE PNO Event. (pfn_count == 0) \n")); + } +out_err: + if (channel) + kfree(channel); + return err; +} +#endif /* WL_SCHED_SCAN */ + static void wl_init_conf(struct wl_conf *conf) { WL_DBG(("Enter \n")); @@ -7468,7 +8112,10 @@ static void wl_init_event_handler(struct wl_priv *wl) wl->evt_handler[WLC_E_P2P_DISC_LISTEN_COMPLETE] = wl_cfgp2p_listen_complete; wl->evt_handler[WLC_E_ACTION_FRAME_COMPLETE] = wl_cfgp2p_action_tx_complete; wl->evt_handler[WLC_E_ACTION_FRAME_OFF_CHAN_COMPLETE] = wl_cfgp2p_action_tx_complete; - +#ifdef PNO_SUPPORT + wl->evt_handler[WLC_E_PFN_NET_FOUND] = wl_notify_pfn_status; +#endif /* PNO_SUPPORT */ + wl->evt_handler[WLC_E_TDLS_PEER_EVENT] = wl_tdls_event_handler; } static s32 wl_init_priv_mem(struct wl_priv *wl) @@ -7532,7 +8179,7 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) WL_ERR(("wl->ie alloc failed\n")); goto init_priv_mem_out; } -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->escan_info.escan_buf[0] = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0); bzero(wl->escan_info.escan_buf[0], ESCAN_BUF_SIZE); wl->escan_info.escan_buf[1] = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN1, 0); @@ -7540,7 +8187,7 @@ static s32 wl_init_priv_mem(struct wl_priv *wl) #else wl->escan_info.escan_buf = dhd_os_prealloc(NULL, DHD_PREALLOC_WIPHY_ESCAN0, 0); bzero(wl->escan_info.escan_buf, ESCAN_BUF_SIZE); -#endif /* DUAL_ESCAN_RESULT_BUFFER */ +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ #endif /* STATIC_WL_PRIV_STRUCT */ wl->afx_hdl = (void *)kzalloc(sizeof(*wl->afx_hdl), GFP_KERNEL); if (unlikely(!wl->afx_hdl)) { @@ -7585,12 +8232,12 @@ static void wl_deinit_priv_mem(struct wl_priv *wl) wl->conn_info = NULL; kfree(wl->ie); wl->ie = NULL; -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->escan_info.escan_buf[0] = NULL; wl->escan_info.escan_buf[1] = NULL; #else wl->escan_info.escan_buf = NULL; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ #endif /* STATIC_WL_PRIV_STRUCT */ if (wl->afx_hdl) { cancel_work_sync(&wl->afx_hdl->work); @@ -7615,11 +8262,7 @@ static s32 wl_create_event_handler(struct wl_priv *wl) /* Do not use DHD in cfg driver */ wl->event_tsk.thr_pid = -1; -#ifdef USE_KTHREAD_API - PROC_START2(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler"); -#else - PROC_START(wl_event_handler, wl, &wl->event_tsk, 0); -#endif + PROC_START(wl_event_handler, wl, &wl->event_tsk, 0, "wl_event_handler"); if (wl->event_tsk.thr_pid < 0) ret = -ENOMEM; return ret; @@ -7799,23 +8442,34 @@ static s32 wl_iscan_thread(void *data) del_timer_sync(&iscan->timer); iscan->timer_on = 0; } - WL_DBG(("%s was terminated\n", __func__)); + WL_DBG(("was terminated\n")); return 0; } static void wl_scan_timeout(unsigned long data) { + wl_event_msg_t msg; struct wl_priv *wl = (struct wl_priv *)data; - if (wl->scan_request) { - WL_ERR(("timer expired\n")); - if (wl->escan_on) - wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); - else - wl_notify_iscan_complete(wl_to_iscan(wl), true); + if (!(wl->scan_request)) { + WL_ERR(("timer expired but no scan request\n")); + return; + } + bzero(&msg, sizeof(wl_event_msg_t)); + WL_ERR(("timer expired\n")); + if (wl->escan_on) { + msg.event_type = hton32(WLC_E_ESCAN_RESULT); + msg.status = hton32(WLC_E_STATUS_TIMEOUT); + msg.reason = 0xFFFFFFFF; + wl_cfg80211_event(wl_to_prmry_ndev(wl), &msg, NULL); + } else { + /* Need to check it try to access SDIO */ + WL_ERR(("SCAN Timeout(ISCAN)\n")); + wl_notify_iscan_complete(wl_to_iscan(wl), true); } } + static void wl_iscan_timer(unsigned long data) { struct wl_iscan_ctrl *iscan = (struct wl_iscan_ctrl *)data; @@ -7873,8 +8527,7 @@ wl_cfg80211_netdev_notifier_call(struct notifier_block * nb, case NETDEV_DOWN: while (work_pending(&wdev->cleanup_work) && refcnt < 100) { if (refcnt%5 == 0) - WL_ERR(("%s : [NETDEV_DOWN] work_pending (%d th)\n", - __FUNCTION__, refcnt)); + WL_ERR(("[NETDEV_DOWN] work_pending (%d th)\n", refcnt)); set_current_state(TASK_INTERRUPTIBLE); schedule_timeout(100); set_current_state(TASK_RUNNING); @@ -7906,20 +8559,45 @@ static struct notifier_block wl_cfg80211_netdev_notifier = { .notifier_call = wl_cfg80211_netdev_notifier_call, }; +static void wl_cfg80211_scan_abort(struct wl_priv *wl) +{ + wl_scan_params_t *params = NULL; + s32 params_size = 0; + s32 err = BCME_OK; + struct net_device *dev = wl_to_prmry_ndev(wl); + if (!in_atomic()) { + /* Our scan params only need space for 1 channel and 0 ssids */ + params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); + if (params == NULL) { + WL_ERR(("scan params allocation failed \n")); + err = -ENOMEM; + } else { + /* Do a scan abort to stop the driver's scan engine */ + err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); + if (err < 0) { + WL_ERR(("scan abort failed \n")); + } + kfree(params); + } + } +} + static s32 wl_notify_escan_complete(struct wl_priv *wl, struct net_device *ndev, bool aborted, bool fw_abort) { - wl_scan_params_t *params = NULL; - s32 params_size = 0; s32 err = BCME_OK; unsigned long flags; struct net_device *dev; WL_DBG(("Enter \n")); - if (wl->escan_info.ndev != ndev) - { + if (!ndev) { + WL_ERR(("ndev is null\n")); + return err; + } + + if (wl->escan_info.ndev != ndev) { WL_ERR(("ndev is different %p %p\n", wl->escan_info.ndev, ndev)); return err; } @@ -7936,25 +8614,16 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, ndev, wl_to_prmry_ndev(wl), wl->p2p_net)); dev = ndev; } + if (fw_abort && !in_atomic()) { - /* Our scan params only need space for 1 channel and 0 ssids */ - params = wl_cfg80211_scan_alloc_params(-1, 0, ¶ms_size); - if (params == NULL) { - WL_ERR(("scan params allocation failed \n")); - err = -ENOMEM; - } else { - /* Do a scan abort to stop the driver's scan engine */ - err = wldev_ioctl(dev, WLC_SCAN, params, params_size, true); - if (err < 0) { - WL_ERR(("scan abort failed \n")); - } - } + wl_cfg80211_scan_abort(wl); } + if (timer_pending(&wl->scan_timeout)) del_timer_sync(&wl->scan_timeout); #if defined(ESCAN_RESULT_PATCH) if (likely(wl->scan_request)) { -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) u8 temp_id = wl->escan_info.cur_sync_id; if (aborted) wl->bss_list = @@ -7964,11 +8633,22 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, (wl_scan_results_t *)wl->escan_info.escan_buf[(temp_id)%2]; #else wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ wl_inform_bss(wl); } #endif /* ESCAN_RESULT_PATCH */ spin_lock_irqsave(&wl->cfgdrv_lock, flags); +#ifdef WL_SCHED_SCAN + if (wl->sched_scan_req && !wl->scan_request) { + WL_PNO((">>> REPORTING SCHED SCAN RESULTS \n")); + if (aborted) + cfg80211_sched_scan_stopped(wl->sched_scan_req->wiphy); + else + cfg80211_sched_scan_results(wl->sched_scan_req->wiphy); + wl->sched_scan_running = FALSE; + wl->sched_scan_req = NULL; + } +#endif /* WL_SCHED_SCAN */ if (likely(wl->scan_request)) { cfg80211_scan_done(wl->scan_request, aborted); wl->scan_request = NULL; @@ -7977,8 +8657,6 @@ static s32 wl_notify_escan_complete(struct wl_priv *wl, wl_clr_p2p_status(wl, SCANNING); wl_clr_drv_status(wl, SCANNING, dev); spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); - if (params) - kfree(params); return err; } @@ -8011,8 +8689,9 @@ static s32 wl_escan_handler(struct wl_priv *wl, } if (!ndev || !wl->escan_on || - !wl_get_drv_status(wl, SCANNING, ndev)) { -#if defined(DUAL_ESCAN_RESULT_BUFFER) + (!wl_get_drv_status(wl, SCANNING, ndev) && + !wl->sched_scan_running)) { +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) WL_ERR(("escan is not ready ndev %p wl->escan_on %d" " drv_status 0x%x e_type %d e_states %d\n", ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev), @@ -8020,12 +8699,13 @@ static s32 wl_escan_handler(struct wl_priv *wl, #else WL_ERR(("escan is not ready ndev %p wl->escan_on %d drv_status 0x%x\n", ndev, wl->escan_on, wl_get_drv_status(wl, SCANNING, ndev))); -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ goto exit; } -#if defined(DUAL_ESCAN_RESULT_BUFFER) - escan_result = (wl_escan_result_t *) data; +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) + escan_result = (wl_escan_result_t *)data; #endif + if (status == WLC_E_STATUS_PARTIAL) { WL_INFO(("WLC_E_STATUS_PARTIAL \n")); escan_result = (wl_escan_result_t *) data; @@ -8047,14 +8727,14 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_ERR(("Invalid bss_info length %d: ignoring\n", bi_length)); goto exit; } -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) if (escan_result->sync_id != wl->escan_info.cur_sync_id) { WL_ERR(("Escan sync id mismatch: status %d " - "cur_sync_id %d coming_sync_id %d\n", - status, wl->escan_info.cur_sync_id, escan_result->sync_id)); + "cur_sync_id %d coming_sync_id %d\n", + status, wl->escan_info.cur_sync_id, escan_result->sync_id)); goto exit; } -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ if (!(wl_to_wiphy(wl)->interface_modes & BIT(NL80211_IFTYPE_ADHOC))) { if (dtoh16(bi->capability) & DOT11_CAP_IBSS) { @@ -8067,10 +8747,17 @@ static s32 wl_escan_handler(struct wl_priv *wl, p2p_dev_addr = wl_cfgp2p_retreive_p2p_dev_addr(bi, bi_length); if (p2p_dev_addr && !memcmp(p2p_dev_addr, wl->afx_hdl->tx_dst_addr.octet, ETHER_ADDR_LEN)) { - s32 channel = CHSPEC_CHANNEL( - wl_chspec_driver_to_host(bi->chanspec)); - WL_DBG(("ACTION FRAME SCAN : Peer " MACDBG " found, channel : %d\n", - MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), channel)); + s32 channel = wf_chspec_ctlchan( + wl_chspec_driver_to_host(bi->chanspec)); + + if ((channel > MAXCHANNEL) || (channel <= 0)) + channel = WL_INVALID; + else + WL_ERR(("ACTION FRAME SCAN : Peer " MACDBG " found," + " channel : %d\n", + MAC2STRDBG(wl->afx_hdl->tx_dst_addr.octet), + channel)); + wl_clr_p2p_status(wl, SCANNING); wl->afx_hdl->peer_chan = channel; complete(&wl->act_frm_scan); @@ -8078,13 +8765,13 @@ static s32 wl_escan_handler(struct wl_priv *wl, } } else { - int cur_len = 0; -#if defined(DUAL_ESCAN_RESULT_BUFFER) + int cur_len = WL_SCAN_RESULTS_FIXED_SIZE; +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) list = (wl_scan_results_t *) - wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2]; + wl->escan_info.escan_buf[wl->escan_info.cur_sync_id % 2]; #else list = (wl_scan_results_t *)wl->escan_info.escan_buf; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) if (wl->p2p_net && wl->scan_request && wl->scan_request->dev == wl->p2p_net) { @@ -8096,7 +8783,8 @@ static s32 wl_escan_handler(struct wl_priv *wl, s32 channel_band = 0; #endif /* WL_HOST_BAND_MGMT */ /* p2p scan && allow only probe response */ - if (bi->flags & WL_BSS_FLAGS_FROM_BEACON) + if ((wl->p2p->search_state != WL_P2P_DISC_ST_SCAN) && + (bi->flags & WL_BSS_FLAGS_FROM_BEACON)) goto exit; if ((p2p_ie = wl_cfgp2p_find_p2pie(((u8 *) bi) + bi->ie_offset, bi->ie_length)) == NULL) { @@ -8203,108 +8891,126 @@ static s32 wl_escan_handler(struct wl_priv *wl, WL_ERR(("Buffer is too small: ignoring\n")); goto exit; } -#if defined(DUAL_ESCAN_RESULT_BUFFER) - memcpy(&(wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2] +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) + memcpy(&(wl->escan_info.escan_buf[wl->escan_info.cur_sync_id % 2] [list->buflen]), bi, bi_length); #else memcpy(&(wl->escan_info.escan_buf[list->buflen]), bi, bi_length); -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ list->version = dtoh32(bi->version); list->buflen += bi_length; list->count++; + } } else if (status == WLC_E_STATUS_SUCCESS) { wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) if (escan_result->sync_id != wl->escan_info.cur_sync_id) WL_ERR(("Escan sync id mismatch: status %d " - "cur_sync_id %d coming_sync_id %d\n", - status, wl->escan_info.cur_sync_id, escan_result->sync_id)); -#endif + "cur_sync_id %d coming_sync_id %d\n", + status, wl->escan_info.cur_sync_id, escan_result->sync_id)); +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { WL_INFO(("ACTION FRAME SCAN DONE\n")); wl_clr_p2p_status(wl, SCANNING); wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { WL_INFO(("ESCAN COMPLETED\n")); #if defined(DUAL_ESCAN_RESULT_BUFFER) wl->bss_list = (wl_scan_results_t *) - wl->escan_info.escan_buf[wl->escan_info.cur_sync_id%2]; + wl->escan_info.escan_buf[wl->escan_info.cur_sync_id % 2]; #else wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ + if (wl->scan_request && wl->scan_request->dev != wl->p2p_net) { + WL_TRACE_HW4(("SCAN COMPLETED: scanned AP count=%d\n", + wl->bss_list->count)); + } wl_inform_bss(wl); wl_notify_escan_complete(wl, ndev, false, false); } -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->escan_info.cur_sync_id++; #endif } else if (status == WLC_E_STATUS_ABORT) { wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) if (escan_result->sync_id != wl->escan_info.cur_sync_id) WL_ERR(("Escan sync id mismatch: status %d " - "cur_sync_id %d coming_sync_id %d\n", - status, wl->escan_info.cur_sync_id, escan_result->sync_id)); -#endif + "cur_sync_id %d coming_sync_id %d\n", + status, wl->escan_info.cur_sync_id, escan_result->sync_id)); +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { WL_INFO(("ACTION FRAME SCAN DONE\n")); wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); wl_clr_p2p_status(wl, SCANNING); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { WL_INFO(("ESCAN ABORTED\n")); -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->bss_list = (wl_scan_results_t *) - wl->escan_info.escan_buf[(wl->escan_info.cur_sync_id+1)%2]; + wl->escan_info.escan_buf[(wl->escan_info.cur_sync_id + 1) % 2]; #else wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ + if (wl->scan_request && wl->scan_request->dev != wl->p2p_net) { + WL_TRACE_HW4(("SCAN ABORTED: scanned AP count=%d\n", + wl->bss_list->count)); + } wl_inform_bss(wl); wl_notify_escan_complete(wl, ndev, true, false); } -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->escan_info.cur_sync_id += 2; #endif - } - else if (status == WLC_E_STATUS_NEWSCAN) - { + } else if (status == WLC_E_STATUS_NEWSCAN) { escan_result = (wl_escan_result_t *) data; WL_ERR(("WLC_E_STATUS_NEWSCAN : scan_request[%p]\n", wl->scan_request)); WL_ERR(("sync_id[%d], bss_count[%d]\n", escan_result->sync_id, escan_result->bss_count)); + } else if (status == WLC_E_STATUS_TIMEOUT) { + WL_ERR(("WLC_E_STATUS_TIMEOUT : scan_request[%p]\n", wl->scan_request)); + WL_ERR(("escan_on[%d], reason[0x%x]\n", wl->escan_on, e->reason)); + if (e->reason == 0xFFFFFFFF) { + wl_notify_escan_complete(wl, wl->escan_info.ndev, true, true); + } } else { WL_ERR(("unexpected Escan Event %d : abort\n", status)); wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) if (escan_result->sync_id != wl->escan_info.cur_sync_id) WL_ERR(("Escan sync id mismatch: status %d " - "cur_sync_id %d coming_sync_id %d\n", - status, wl->escan_info.cur_sync_id, escan_result->sync_id)); -#endif + "cur_sync_id %d coming_sync_id %d\n", + status, wl->escan_info.cur_sync_id, escan_result->sync_id)); +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ if (wl_get_drv_status_all(wl, FINDING_COMMON_CHANNEL)) { WL_INFO(("ACTION FRAME SCAN DONE\n")); wl_clr_p2p_status(wl, SCANNING); wl_clr_drv_status(wl, SCANNING, wl->afx_hdl->dev); if (wl->afx_hdl->peer_chan == WL_INVALID) complete(&wl->act_frm_scan); - } else if (likely(wl->scan_request)) { -#if defined(DUAL_ESCAN_RESULT_BUFFER) + } else if ((likely(wl->scan_request)) || (wl->sched_scan_running)) { +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->bss_list = (wl_scan_results_t *) - wl->escan_info.escan_buf[(wl->escan_info.cur_sync_id+1)%2]; + wl->escan_info.escan_buf[(wl->escan_info.cur_sync_id + 1) % 2]; #else wl->bss_list = (wl_scan_results_t *)wl->escan_info.escan_buf; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ + if (wl->scan_request && wl->scan_request->dev != wl->p2p_net) { + WL_TRACE_HW4(("SCAN ABORTED(UNEXPECTED): " + "scanned AP count=%d\n", + wl->bss_list->count)); + } wl_inform_bss(wl); wl_notify_escan_complete(wl, ndev, true, false); } -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->escan_info.cur_sync_id += 2; #endif } @@ -8312,151 +9018,175 @@ exit: mutex_unlock(&wl->usr_sync); return err; } + +static void wl_cfg80211_concurrent_roam(struct wl_priv *wl, int enable) +{ + u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); + struct net_info *iter, *next; + int err; + + if (!wl->roamoff_on_concurrent) + return; + if (enable && connected_cnt > 1) { + for_each_ndev(wl, iter, next) { + /* Save the current roam setting */ + if ((err = wldev_iovar_getint(iter->ndev, "roam_off", + (s32 *)&iter->roam_off)) != BCME_OK) { + WL_ERR(("%s:Failed to get current roam setting err %d\n", + iter->ndev->name, err)); + continue; + } + if ((err = wldev_iovar_setint(iter->ndev, "roam_off", 1)) != BCME_OK) { + WL_ERR(("%s:failed to set roam_off : %d\n", + iter->ndev->name, err)); + } + } + } + else if (!enable) { + for_each_ndev(wl, iter, next) { + if (iter->roam_off != WL_INVALID) { + if ((err = wldev_iovar_setint(iter->ndev, "roam_off", + iter->roam_off)) == BCME_OK) + iter->roam_off = WL_INVALID; + else { + WL_ERR(("%s:failed to set roam_off : %d\n", + iter->ndev->name, err)); + } + } + } + } + return; +} + +static void wl_cfg80211_determine_vsdb_mode(struct wl_priv *wl) +{ +#ifdef CUSTOMER_HW4 + u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); + if (connected_cnt > 1) { + wl->vsdb_mode = true; + } else { + wl->vsdb_mode = false; + } + return; +#else + struct net_info *iter, *next; + u32 chan = 0; + u32 chanspec = 0; + u32 prev_chan = 0; + u32 connected_cnt = wl_get_drv_status_all(wl, CONNECTED); + wl->vsdb_mode = false; + + if (connected_cnt <= 1) { + return; + } + for_each_ndev(wl, iter, next) { + chanspec = 0; + chan = 0; + if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) { + if (wldev_iovar_getint(iter->ndev, "chanspec", + (s32 *)&chanspec) == BCME_OK) { + chan = CHSPEC_CHANNEL(chanspec); + if (CHSPEC_IS40(chanspec)) { + if (CHSPEC_SB_UPPER(chanspec)) + chan += CH_10MHZ_APART; + else + chan -= CH_10MHZ_APART; + } + wl_update_prof(wl, iter->ndev, NULL, + &chan, WL_PROF_CHAN); + } + if (!prev_chan && chan) + prev_chan = chan; + else if (prev_chan && (prev_chan != chan)) + wl->vsdb_mode = true; + } + } + return; +#endif /* CUSTOMER_HW4 */ +} static s32 wl_notifier_change_state(struct wl_priv *wl, struct net_info *_net_info, enum wl_status state, bool set) { s32 pm = PM_FAST; s32 err = BCME_OK; u32 chan = 0; - u32 chanspec = 0; - u32 prev_chan = 0; - u32 connected_cnt = 0; struct net_info *iter, *next; struct net_device *primary_dev = wl_to_prmry_ndev(wl); - if (set) { /* set */ - switch (state) { - case WL_STATUS_CONNECTED: { - if ((connected_cnt = wl_get_drv_status_all(wl, CONNECTED)) > 1) { - pm = PM_OFF; - WL_INFO(("Do not enable the power save for VSDB mode\n")); - } else if (_net_info->pm_block) { - pm = PM_OFF; - } else { - pm = PM_FAST; - } + WL_DBG(("Enter state %d set %d _net_info->pm_restore %d iface %s\n", + state, set, _net_info->pm_restore, _net_info->ndev->name)); + + if (state != WL_STATUS_CONNECTED) + return 0; + + if (set) { + wl_cfg80211_concurrent_roam(wl, 1); + + if (wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) { + + if (wl_add_remove_eventmsg(primary_dev, WLC_E_P2P_PROBREQ_MSG, false)) + WL_ERR((" failed to unset WLC_E_P2P_PROPREQ_MSG\n")); + } + wl_cfg80211_determine_vsdb_mode(wl); + if (wl->vsdb_mode || _net_info->pm_block) { + pm = PM_OFF; for_each_ndev(wl, iter, next) { - if ((connected_cnt == 1) && (iter->ndev != _net_info->ndev)) + if (iter->pm_restore) continue; - chanspec = 0; - chan = 0; - if (wl_get_drv_status(wl, CONNECTED, iter->ndev)) { - if (wldev_iovar_getint(iter->ndev, "chanspec", - (s32 *)&chanspec) == BCME_OK) { - chan = CHSPEC_CHANNEL(chanspec); - if (CHSPEC_IS40(chanspec)) { - if (CHSPEC_SB_UPPER(chanspec)) - chan += CH_10MHZ_APART; - else - chan -= CH_10MHZ_APART; - } - wl_update_prof(wl, iter->ndev, NULL, - &chan, WL_PROF_CHAN); - } - if ((wl_get_mode_by_netdev(wl, iter->ndev) - == WL_MODE_BSS)) { - pm = htod32(pm); - WL_DBG(("power save %s\n", - (pm ? "enabled" : "disabled"))); - err = wldev_ioctl(iter->ndev, WLC_SET_PM, - &pm, sizeof(pm), true); - if (unlikely(err)) { - if (err == -ENODEV) - WL_DBG(("net_device" - " is not ready\n")); - else - WL_ERR(("error" - " (%d)\n", err)); - break; - } else { - wl_cfg80211_update_power_mode(iter->ndev); - } - } - if (connected_cnt > 1) { - if (!prev_chan && chan) - prev_chan = chan; - else if (prev_chan && (prev_chan != chan)) { - wl->vsdb_mode = true; - } - if (wl->roamoff_on_concurrent) { - if ((err = wldev_iovar_getint(iter->ndev, - "roam_off", (s32 *)&iter->roam_off)) - == BCME_OK) { - if ((err = - wldev_iovar_setint(iter->ndev, - "roam_off", 1)) != - BCME_OK) { - WL_ERR((" failed to set " - "roam_off : %d\n", err)); - } - } else - WL_ERR(("failed to get" - " roam_off : %d\n", err)); - } - } + /* Save the current power mode */ + err = wldev_ioctl(iter->ndev, WLC_GET_PM, &iter->pm, + sizeof(iter->pm), false); + WL_DBG(("%s:power save %s\n", iter->ndev->name, + iter->pm ? "enabled" : "disabled")); + if (!err && iter->pm) { + iter->pm_restore = true; } + } - if (wl_get_mode_by_netdev(wl, _net_info->ndev) == WL_MODE_AP) { - if (wl_add_remove_eventmsg(primary_dev, - WLC_E_P2P_PROBREQ_MSG, false)) - WL_ERR((" failed to unset" - " WLC_E_P2P_PROPREQ_MSG\n")); - } - break; - } - default: - break; - } - } else { /* clear */ - switch (state) { - case WL_STATUS_CONNECTED: { - chan = 0; - /* clear chan information when the net device is disconnected */ - wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN); - if (wl_get_drv_status_all(wl, CONNECTED) == 1) { - wl->vsdb_mode = false; - for_each_ndev(wl, iter, next) { - if (wl_get_drv_status(wl, CONNECTED, iter->ndev) && - (wl_get_mode_by_netdev(wl, iter->ndev) - == WL_MODE_BSS)) { - if (wl_get_netinfo_by_netdev(wl, - iter->ndev)->pm_block) - pm = PM_OFF; - else - pm = PM_FAST; - pm = htod32(pm); - WL_DBG(("power save %s\n", - (pm ? "enabled" : "disabled"))); - err = wldev_ioctl(iter->ndev, - WLC_SET_PM, &pm, sizeof(pm), true); - if (unlikely(err)) { - if (err == -ENODEV) - WL_DBG(("net_device" - " is not ready\n")); - else - WL_ERR(("error" - " (%d)\n", err)); - break; - } else { - wl_cfg80211_update_power_mode(iter->ndev); - } - } + for_each_ndev(wl, iter, next) { + if ((err = wldev_ioctl(iter->ndev, WLC_SET_PM, &pm, + sizeof(pm), true)) != 0) { + if (err == -ENODEV) + WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); + else + WL_ERR(("%s:error (%d)\n", iter->ndev->name, err)); + iter->ndev->ieee80211_ptr->ps = false; } } - if (wl->roamoff_on_concurrent) { - for_each_ndev(wl, iter, next) { - if ((iter->roam_off != WL_INVALID) && - ((err = wldev_iovar_setint(iter->ndev, "roam_off", - iter->roam_off)) == BCME_OK)) { - iter->roam_off = WL_INVALID; - } else if (err) - WL_ERR((" failed to set roam_off : %d\n", err)); + } +#if defined(CUSTOMER_HW4) && defined(WLTDLS) + if (wl->vsdb_mode) { + err = wldev_iovar_setint(primary_dev, "tdls_enable", 0); + } +#endif /* defined(CUSTOMER_HW4) && defined(WLTDLS) */ + } + else { /* clear */ + chan = 0; + /* clear chan information when the net device is disconnected */ + wl_update_prof(wl, _net_info->ndev, NULL, &chan, WL_PROF_CHAN); + wl_cfg80211_determine_vsdb_mode(wl); + for_each_ndev(wl, iter, next) { + if (iter->pm_restore && iter->pm) { + WL_DBG(("%s:restoring power save %s\n", + iter->ndev->name, (iter->pm ? "enabled" : "disabled"))); + err = wldev_ioctl(iter->ndev, + WLC_SET_PM, &iter->pm, sizeof(iter->pm), true); + if (unlikely(err)) { + if (err == -ENODEV) + WL_DBG(("%s:netdev not ready\n", iter->ndev->name)); + else + WL_ERR(("%s:error(%d)\n", iter->ndev->name, err)); + break; } + iter->pm_restore = 0; + iter->ndev->ieee80211_ptr->ps = true; } - break; } - default: - break; + wl_cfg80211_concurrent_roam(wl, 0); +#if defined(CUSTOMER_HW4) && defined(WLTDLS) + if (!wl->vsdb_mode) { + err = wldev_iovar_setint(primary_dev, "tdls_enable", 1); } +#endif /* defined(CUSTOMER_HW4) && defined(WLTDLS) */ } return err; } @@ -8484,7 +9214,7 @@ static s32 wl_init_scan(struct wl_priv *wl) } else if (wl->escan_on) { wl->evt_handler[WLC_E_ESCAN_RESULT] = wl_escan_handler; wl->escan_info.escan_state = WL_ESCAN_STATE_IDLE; -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) wl->escan_info.cur_sync_id = 0; #endif } @@ -8559,7 +9289,7 @@ static s32 wl_cfg80211_attach_p2p(void) WL_TRACE(("Enter \n")); if (wl_cfgp2p_register_ndev(wl) < 0) { - WL_ERR(("%s: P2P attach failed. \n", __func__)); + WL_ERR(("P2P attach failed. \n")); return -ENODEV; } @@ -8569,10 +9299,16 @@ static s32 wl_cfg80211_attach_p2p(void) static s32 wl_cfg80211_detach_p2p(void) { struct wl_priv *wl = wlcfg_drv_priv; - struct wireless_dev *wdev = wl->p2p_wdev; + struct wireless_dev *wdev; WL_DBG(("Enter \n")); - if (!wdev || !wl) { + if (!wl) { + WL_ERR(("Invalid Ptr\n")); + return -EINVAL; + } else + wdev = wl->p2p_wdev; + + if (!wdev) { WL_ERR(("Invalid Ptr\n")); return -EINVAL; } @@ -8686,13 +9422,21 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) WL_ERR(("Failed to setup rfkill %d\n", err)); goto cfg80211_attach_out; } +#ifdef DEBUGFS_CFG80211 + err = wl_setup_debugfs(wl); + if (err) { + WL_ERR(("Failed to setup debugfs %d\n", err)); + goto cfg80211_attach_out; + } +#endif err = register_netdevice_notifier(&wl_cfg80211_netdev_notifier); if (err) { WL_ERR(("Failed to register notifierl %d\n", err)); goto cfg80211_attach_out; } #if defined(COEX_DHCP) - if (wl_cfg80211_btcoex_init(wl)) + err = wl_cfg80211_btcoex_init(wl); + if (err) goto cfg80211_attach_out; #endif @@ -8707,7 +9451,7 @@ s32 wl_cfg80211_attach(struct net_device *ndev, void *data) return err; cfg80211_attach_out: - err = wl_setup_rfkill(wl, FALSE); + wl_setup_rfkill(wl, FALSE); wl_free_wdev(wl); return err; } @@ -8726,9 +9470,13 @@ void wl_cfg80211_detach(void *para) #endif wl_setup_rfkill(wl, FALSE); +#ifdef DEBUGFS_CFG80211 + wl_free_debugfs(wl); +#endif if (wl->p2p_supported) { - WL_ERR(("wl_cfgp2p_down() is not called yet\n")); - wl_cfgp2p_down(wl); + if (timer_pending(&wl->p2p->listen_timer)) + del_timer_sync(&wl->p2p->listen_timer); + wl_cfgp2p_deinit_priv(wl); } #if defined(WLP2P) && defined(WL_ENABLE_P2P_IF) @@ -8795,6 +9543,7 @@ static s32 wl_event_handler(void *data) tsk_ctl_t *tsk = (tsk_ctl_t *)data; wl = (struct wl_priv *)tsk->parent; + #ifndef USE_KTHREAD_API DAEMONIZE("dhd_cfg80211_event"); complete(&tsk->completed); @@ -8828,7 +9577,7 @@ static s32 wl_event_handler(void *data) } DHD_OS_WAKE_UNLOCK(wl->pub); } - WL_ERR(("%s was terminated\n", __func__)); + WL_ERR(("was terminated\n")); complete_and_exit(&tsk->completed, 0); return 0; } @@ -8839,10 +9588,6 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data) u32 event_type = ntoh32(e->event_type); struct wl_priv *wl = wlcfg_drv_priv; -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) - int pno_wakelock_timeout = 10; /* 10 second */ -#endif - #if (WL_DBG_LEVEL > 0) s8 *estr = (event_type <= sizeof(wl_dbg_estr) / WL_DBG_ESTR_MAX - 1) ? wl_dbg_estr[event_type] : (s8 *) "Unknown"; @@ -8850,9 +9595,6 @@ wl_cfg80211_event(struct net_device *ndev, const wl_event_msg_t * e, void *data) #endif /* (WL_DBG_LEVEL > 0) */ if (event_type == WLC_E_PFN_NET_FOUND) { -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) - net_os_wake_lock_timeout_for_pno(ndev, pno_wakelock_timeout); -#endif WL_DBG((" PNOEVENT: PNO_NET_FOUND\n")); } else if (event_type == WLC_E_PFN_NET_LOST) { @@ -9032,6 +9774,7 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) bool update; bool ht40_allowed; u8 *pbuf = NULL; + bool dfs_radar_disabled = FALSE; #define LOCAL_BUF_LEN 1024 pbuf = kzalloc(LOCAL_BUF_LEN, GFP_KERNEL); @@ -9040,7 +9783,7 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) WL_ERR(("failed to allocate local buf\n")); return -ENOMEM; } - list = (wl_uint32_list_t *)(void *) pbuf; + list = (wl_uint32_list_t *)(void *)pbuf; list->count = htod32(WL_NUMCHANSPECS); @@ -9067,14 +9810,18 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) channel += CH_10MHZ_APART; else channel -= CH_10MHZ_APART; + } else if (CHSPEC_IS80(c)) { + WL_DBG(("HT80 center channel : %d\n", channel)); + continue; } - if (CHSPEC_IS2G(c) && channel <= CH_MAX_2G_CHANNEL) { + if (CHSPEC_IS2G(c) && (channel >= CH_MIN_2G_CHANNEL) && + (channel <= CH_MAX_2G_CHANNEL)) { band_chan_arr = __wl_2ghz_channels; array_size = ARRAYSIZE(__wl_2ghz_channels); n_cnt = &n_2g; band = IEEE80211_BAND_2GHZ; ht40_allowed = (bw_cap == WLC_N_BW_40ALL)? true : false; - } else if (CHSPEC_IS5G(c) && channel > CH_MAX_2G_CHANNEL) { + } else if (CHSPEC_IS5G(c) && channel >= CH_MIN_5G_CHANNEL) { band_chan_arr = __wl_5ghz_a_channels; array_size = ARRAYSIZE(__wl_5ghz_a_channels); n_cnt = &n_5g; @@ -9084,6 +9831,8 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) WL_ERR(("Invalid channel Sepc. 0x%x.\n", c)); continue; } + if (!ht40_allowed && CHSPEC_IS40(c)) + continue; for (j = 0; (j < *n_cnt && (*n_cnt < array_size)); j++) { if (band_chan_arr[j].hw_value == channel) { update = true; @@ -9106,8 +9855,8 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) if (CHSPEC_IS40(c) && ht40_allowed) { /* assuming the order is HT20, HT40 Upper, - HT40 lower from chanspecs - */ + * HT40 lower from chanspecs + */ u32 ht40_flag = band_chan_arr[index].flags & IEEE80211_CHAN_NO_HT40; if (CHSPEC_SB_UPPER(c)) { if (ht40_flag == IEEE80211_CHAN_NO_HT40) @@ -9116,8 +9865,8 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) band_chan_arr[index].flags |= IEEE80211_CHAN_NO_HT40PLUS; } else { /* It should be one of - IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS - */ + * IEEE80211_CHAN_NO_HT40 or IEEE80211_CHAN_NO_HT40PLUS + */ band_chan_arr[index].flags &= ~IEEE80211_CHAN_NO_HT40; if (ht40_flag == IEEE80211_CHAN_NO_HT40) band_chan_arr[index].flags |= @@ -9125,21 +9874,24 @@ static int wl_construct_reginfo(struct wl_priv *wl, s32 bw_cap) } } else { band_chan_arr[index].flags = IEEE80211_CHAN_NO_HT40; - if (band == IEEE80211_BAND_2GHZ) - channel |= WL_CHANSPEC_BAND_2G; - else - channel |= WL_CHANSPEC_BAND_5G; - channel |= WL_CHANSPEC_BW_20; - channel = wl_chspec_host_to_driver(channel); - err = wldev_iovar_getint(dev, "per_chan_info", &channel); - if (!err) { - if (channel & WL_CHAN_RADAR) - band_chan_arr[index].flags |= - (IEEE80211_CHAN_RADAR | - IEEE80211_CHAN_NO_IBSS); - if (channel & WL_CHAN_PASSIVE) - band_chan_arr[index].flags |= - IEEE80211_CHAN_PASSIVE_SCAN; + if (!dfs_radar_disabled) { + if (band == IEEE80211_BAND_2GHZ) + channel |= WL_CHANSPEC_BAND_2G; + else + channel |= WL_CHANSPEC_BAND_5G; + channel |= WL_CHANSPEC_BW_20; + channel = wl_chspec_host_to_driver(channel); + err = wldev_iovar_getint(dev, "per_chan_info", &channel); + if (!err) { + if (channel & WL_CHAN_RADAR) + band_chan_arr[index].flags |= + (IEEE80211_CHAN_RADAR | + IEEE80211_CHAN_NO_IBSS); + if (channel & WL_CHAN_PASSIVE) + band_chan_arr[index].flags |= + IEEE80211_CHAN_PASSIVE_SCAN; + } else if (err == BCME_UNSUPPORTED) + dfs_radar_disabled = TRUE; } } if (!update) @@ -9166,6 +9918,8 @@ s32 wl_update_wiphybands(struct wl_priv *wl) bool rollback_lock = false; s32 bw_cap = 0; s32 cur_band = -1; + struct ieee80211_supported_band *bands[IEEE80211_NUM_BANDS] = {NULL, }; + if (wl == NULL) { wl = wlcfg_drv_priv; mutex_lock(&wl->usr_sync); @@ -9191,10 +9945,10 @@ s32 wl_update_wiphybands(struct wl_priv *wl) if (unlikely(err)) { WL_ERR(("error reading nmode (%d)\n", err)); } else { - /* For nmodeonly check bw cap */ + /* For nmodeonly check bw cap */ err = wldev_iovar_getint(dev, "mimo_bw_cap", &bw_cap); if (unlikely(err)) { - WL_ERR(("error get mimo_bw_cap (%d)\n", err)); + WL_ERR(("error get mimo_bw_cap (%d)\n", err)); } } @@ -9207,47 +9961,52 @@ s32 wl_update_wiphybands(struct wl_priv *wl) } wiphy = wl_to_wiphy(wl); nband = bandlist[0]; - wiphy->bands[IEEE80211_BAND_5GHZ] = NULL; - wiphy->bands[IEEE80211_BAND_2GHZ] = NULL; + for (i = 1; i <= nband && i < ARRAYSIZE(bandlist); i++) { index = -1; if (bandlist[i] == WLC_BAND_5G && __wl_band_5ghz_a.n_channels > 0) { - wiphy->bands[IEEE80211_BAND_5GHZ] = + bands[IEEE80211_BAND_5GHZ] = &__wl_band_5ghz_a; - index = IEEE80211_BAND_5GHZ; + index = IEEE80211_BAND_5GHZ; if (bw_cap == WLC_N_BW_40ALL || bw_cap == WLC_N_BW_20IN2G_40IN5G) - wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; } else if (bandlist[i] == WLC_BAND_2G && __wl_band_2ghz.n_channels > 0) { - wiphy->bands[IEEE80211_BAND_2GHZ] = + bands[IEEE80211_BAND_2GHZ] = &__wl_band_2ghz; - index = IEEE80211_BAND_2GHZ; + index = IEEE80211_BAND_2GHZ; if (bw_cap == WLC_N_BW_40ALL) - wiphy->bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; + bands[index]->ht_cap.cap |= IEEE80211_HT_CAP_SGI_40; } if ((index >= 0) && nmode) { - wiphy->bands[index]->ht_cap.cap |= + bands[index]->ht_cap.cap |= (IEEE80211_HT_CAP_SGI_20 | IEEE80211_HT_CAP_DSSSCCK40); - wiphy->bands[index]->ht_cap.ht_supported = TRUE; - wiphy->bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; - wiphy->bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; + bands[index]->ht_cap.ht_supported = TRUE; + bands[index]->ht_cap.ampdu_factor = IEEE80211_HT_MAX_AMPDU_64K; + bands[index]->ht_cap.ampdu_density = IEEE80211_HT_MPDU_DENSITY_16; /* An HT shall support all EQM rates for one spatial stream */ - wiphy->bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; + bands[index]->ht_cap.mcs.rx_mask[0] = 0xff; } } + wiphy->bands[IEEE80211_BAND_2GHZ] = bands[IEEE80211_BAND_2GHZ]; + wiphy->bands[IEEE80211_BAND_5GHZ] = bands[IEEE80211_BAND_5GHZ]; + wiphy_apply_custom_regulatory(wiphy, &brcm_regdom); end_bands: if (rollback_lock) mutex_unlock(&wl->usr_sync); - return err; + return err; } static s32 __wl_cfg80211_up(struct wl_priv *wl) { s32 err = 0; +#ifdef WL_HOST_BAND_MGMT + s32 ret = 0; +#endif /* WL_HOST_BAND_MGMT */ struct net_device *ndev = wl_to_prmry_ndev(wl); struct wireless_dev *wdev = ndev->ieee80211_ptr; @@ -9271,9 +10030,17 @@ static s32 __wl_cfg80211_up(struct wl_priv *wl) #ifdef WL_HOST_BAND_MGMT /* By default the curr_band is initialized to BAND_AUTO */ - if (wl_cfg80211_set_band(ndev, WLC_BAND_AUTO) < 0) { - WL_ERR(("roam_band set failed\n")); - err = -1; + if ((ret = wl_cfg80211_set_band(ndev, WLC_BAND_AUTO)) < 0) { + if (ret == BCME_UNSUPPORTED) { + /* Don't fail the initialization, lets just + * fall back to the original method + */ + WL_ERR(("WL_HOST_BAND_MGMT defined, " + "but roam_band iovar not supported \n")); + } else { + WL_ERR(("roam_band failed. ret=%d", ret)); + err = -1; + } } #endif /* WL_HOST_BAND_MGMT */ @@ -9287,19 +10054,27 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) unsigned long flags; struct net_info *iter, *next; struct net_device *ndev = wl_to_prmry_ndev(wl); -#ifdef WL_ENABLE_P2P_IF -#if !defined(CUSTOMER_HW4) +#if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP) struct net_device *p2p_net = wl->p2p_net; -#endif /* !defined(CUSTOMER_HW4) */ -#endif /* WL_ENABLE_P2P_IF */ +#endif + u32 bssidx = 0; WL_DBG(("In\n")); + + + /* If primary BSS is operational (for e.g SoftAP), bring it down */ + if (!(wl_cfgp2p_find_idx(wl, ndev, &bssidx)) && + wl_cfgp2p_bss_isup(ndev, bssidx)) { + if (wl_cfgp2p_bss(wl, ndev, bssidx, 0) < 0) + WL_ERR(("BSS down failed \n")); + } + /* Check if cfg80211 interface is already down */ if (!wl_get_drv_status(wl, READY, ndev)) return err; /* it is even not ready */ - for_each_ndev(wl, iter, next) wl_set_drv_status(wl, SCAN_ABORTING, iter->ndev); + wl_term_iscan(wl); spin_lock_irqsave(&wl->cfgdrv_lock, flags); if (wl->scan_request) { @@ -9320,9 +10095,11 @@ static s32 __wl_cfg80211_down(struct wl_priv *wl) } wl_to_prmry_ndev(wl)->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION; -#if !defined(CUSTOMER_HW4) - if (p2p_net) - dev_close(p2p_net); +#if defined(WL_CFG80211) && defined(SUPPORT_DEEP_SLEEP) + if (!trigger_deep_sleep) { + if (p2p_net) + dev_close(p2p_net); + } #endif DNGL_FUNC(dhd_cfg80211_down, (wl)); wl_flush_eq(wl); @@ -9366,6 +10143,10 @@ s32 wl_cfg80211_up(void *para) if (unlikely(err)) return err; } +#if defined(BCMSUP_4WAY_HANDSHAKE) && defined(WLAN_AKM_SUITE_FT_8021X) + if (dhd->fw_4way_handshake) + wl->wdev->wiphy->features |= NL80211_FEATURE_FW_4WAY_HANDSHAKE; +#endif err = __wl_cfg80211_up(wl); if (unlikely(err)) WL_ERR(("__wl_cfg80211_up failed\n")); @@ -9423,6 +10204,7 @@ static void *wl_read_prof(struct wl_priv *wl, struct net_device *ndev, s32 item) break; case WL_PROF_SSID: rptr = &profile->ssid; + break; case WL_PROF_CHAN: rptr = &profile->channel; break; @@ -9473,13 +10255,14 @@ wl_update_prof(struct wl_priv *wl, struct net_device *ndev, break; case WL_PROF_CHAN: profile->channel = *(u32*)data; + break; default: err = -EOPNOTSUPP; break; } spin_unlock_irqrestore(&wl->cfgdrv_lock, flags); - if (err == EOPNOTSUPP) + if (err == -EOPNOTSUPP) WL_ERR(("unsupported item (%d)\n", item)); return err; @@ -9651,6 +10434,87 @@ s32 wl_cfg80211_set_p2p_ps(struct net_device *net, char* buf, int len) return wl_cfgp2p_set_p2p_ps(wl, net, buf, len); } +s32 wl_cfg80211_channel_to_freq(u32 channel) +{ + int freq = 0; + +#if LINUX_VERSION_CODE == KERNEL_VERSION(2, 6, 38) && !defined(WL_COMPAT_WIRELESS) + freq = ieee80211_channel_to_frequency(channel); +#else + { + u16 band = 0; + if (channel <= CH_MAX_2G_CHANNEL) + band = IEEE80211_BAND_2GHZ; + else + band = IEEE80211_BAND_5GHZ; + freq = ieee80211_channel_to_frequency(channel, band); + } +#endif + return freq; +} + +static s32 +wl_tdls_event_handler(struct wl_priv *wl, struct net_device *ndev, + const wl_event_msg_t *e, void *data) { + + u32 reason = ntoh32(e->reason); + s8 *msg = NULL; + switch (reason) { + case WLC_E_TDLS_PEER_DISCOVERED : + msg = " TDLS PEER DISCOVERD "; + break; + case WLC_E_TDLS_PEER_CONNECTED : + msg = " TDLS PEER CONNECTED "; + break; + case WLC_E_TDLS_PEER_DISCONNECTED : + msg = "TDLS PEER DISCONNECTED "; + break; + } + if (msg) { + WL_ERR(("%s: " MACDBG " on %s ndev\n", msg, MAC2STRDBG((u8*)(&e->addr)), + (wl_to_prmry_ndev(wl) == ndev) ? "primary" : "secondary")); + } + return 0; + +} +#if 1 //LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) +static s32 +wl_cfg80211_tdls_oper(struct wiphy *wiphy, struct net_device *dev, + u8 *peer, enum nl80211_tdls_operation oper) +{ + s32 ret = 0; +#ifdef WLTDLS + struct wl_priv *wl; + tdls_iovar_t info; + wl = wlcfg_drv_priv; + memset(&info, 0, sizeof(tdls_iovar_t)); + if (peer) + memcpy(&info.ea, peer, ETHER_ADDR_LEN); + switch (oper) { + case NL80211_TDLS_DISCOVERY_REQ: + info.mode = TDLS_MANUAL_EP_DISCOVERY; + break; + case NL80211_TDLS_SETUP: + info.mode = TDLS_MANUAL_EP_CREATE; + break; + case NL80211_TDLS_TEARDOWN: + info.mode = TDLS_MANUAL_EP_DELETE; + break; + default: + WL_ERR(("Unsupported operation : %d\n", oper)); + goto out; + } + ret = wldev_iovar_setbuf(dev, "tdls_endpoint", &info, sizeof(info), + wl->ioctl_buf, WLC_IOCTL_MAXLEN, &wl->ioctl_buf_sync); + if (ret) { + WL_ERR(("tdls_endpoint error %d\n", ret)); + } +out: +#endif /* WLTDLS */ + return ret; +} +#endif /* LINUX_VERSION_CODE > KERNEL_VERSION(3, 2, 0) */ + s32 wl_cfg80211_set_wps_p2p_ie(struct net_device *net, char *buf, int len, enum wl_management_type type) { @@ -9767,7 +10631,127 @@ static int wl_setup_rfkill(struct wl_priv *wl, bool setup) err_out: return err; } +#ifdef DEBUGFS_CFG80211 +/** +* Format : echo "SCAN:1 DBG:1" > /sys/kernel/debug/dhd/debug_level +* to turn on SCAN and DBG log. +* To turn off SCAN partially, echo "SCAN:0" > /sys/kernel/debug/dhd/debug_level +* To see current setting of debug level, +* cat /sys/kernel/debug/dhd/debug_level +*/ +static ssize_t +wl_debuglevel_write(struct file *file, const char __user *userbuf, + size_t count, loff_t *ppos) +{ + char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)], sublog[S_SUBLOGLEVEL]; + char *params, *token, *colon; + uint i, tokens, log_on = 0; + memset(tbuf, 0, sizeof(tbuf)); + memset(sublog, 0, sizeof(sublog)); + if (copy_from_user(&tbuf, userbuf, min_t(size_t, sizeof(tbuf), count))) + return -EFAULT; + + params = &tbuf[0]; + colon = strchr(params, '\n'); + if (colon != NULL) + *colon = '\0'; + while ((token = strsep(¶ms, " ")) != NULL) { + memset(sublog, 0, sizeof(sublog)); + if (token == NULL || !*token) + break; + if (*token == '\0') + continue; + colon = strchr(token, ':'); + if (colon != NULL) { + *colon = ' '; + } + tokens = sscanf(token, "%s %u", sublog, &log_on); + if (colon != NULL) + *colon = ':'; + + if (tokens == 2) { + for (i = 0; i < ARRAYSIZE(sublogname_map); i++) { + if (!strncmp(sublog, sublogname_map[i].sublogname, + strlen(sublogname_map[i].sublogname))) { + if (log_on) + wl_dbg_level |= + (sublogname_map[i].log_level); + else + wl_dbg_level &= + ~(sublogname_map[i].log_level); + } + } + } else + WL_ERR(("%s: can't parse '%s' as a " + "SUBMODULE:LEVEL (%d tokens)\n", + tbuf, token, tokens)); + + + } + return count; +} + +static ssize_t +wl_debuglevel_read(struct file *file, char __user *user_buf, + size_t count, loff_t *ppos) +{ + char *param; + char tbuf[S_SUBLOGLEVEL * ARRAYSIZE(sublogname_map)]; + uint i; + memset(tbuf, 0, sizeof(tbuf)); + param = &tbuf[0]; + for (i = 0; i < ARRAYSIZE(sublogname_map); i++) { + param += snprintf(param, sizeof(tbuf) - 1, "%s:%d ", + sublogname_map[i].sublogname, + (wl_dbg_level & sublogname_map[i].log_level) ? 1 : 0); + } + *param = '\n'; + return simple_read_from_buffer(user_buf, count, ppos, tbuf, strlen(&tbuf[0])); + +} +static const struct file_operations fops_debuglevel = { + .open = NULL, + .write = wl_debuglevel_write, + .read = wl_debuglevel_read, + .owner = THIS_MODULE, + .llseek = NULL, +}; + +static s32 wl_setup_debugfs(struct wl_priv *wl) +{ + s32 err = 0; + struct dentry *_dentry; + if (!wl) + return -EINVAL; + wl->debugfs = debugfs_create_dir(KBUILD_MODNAME, NULL); + if (!wl->debugfs || IS_ERR(wl->debugfs)) { + if (wl->debugfs == ERR_PTR(-ENODEV)) + WL_ERR(("Debugfs is not enabled on this kernel\n")); + else + WL_ERR(("Can not create debugfs directory\n")); + wl->debugfs = NULL; + goto exit; + } + _dentry = debugfs_create_file("debug_level", S_IRUSR | S_IWUSR, + wl->debugfs, wl, &fops_debuglevel); + if (!_dentry || IS_ERR(_dentry)) { + WL_ERR(("failed to create debug_level debug file\n")); + wl_free_debugfs(wl); + } +exit: + return err; +} +static s32 wl_free_debugfs(struct wl_priv *wl) +{ + if (!wl) + return -EINVAL; + if (wl->debugfs) + debugfs_remove_recursive(wl->debugfs); + wl->debugfs = NULL; + return 0; +} +#endif /* DEBUGFS_CFG80211 */ struct device *wl_cfg80211_get_parent_dev(void) { return cfg80211_parent_dev; @@ -9810,6 +10794,21 @@ void wl_cfg80211_enable_trace(bool set, u32 level) else wl_dbg_level |= (WL_DBG_LEVEL & level); } +#if 1 //defined(WL_SUPPORT_BACKPORTED_KPATCHES) || (LINUX_VERSION_CODE >= KERNEL_VERSION(3, \ + 2, 0)) +static s32 +wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, + struct net_device *dev, u64 cookie) +{ + /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION + * is passed with CMD_FRAME. This callback is supposed to cancel + * the OFFCHANNEL Wait. Since we are already taking care of that + * with the tx_mgmt logic, do nothing here. + */ + + return 0; +} +#endif /* WL_SUPPORT_BACKPORTED_PATCHES || KERNEL >= 3.2.0 */ #ifdef WL11U bcm_tlv_t * @@ -9858,7 +10857,8 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s if (wl->iw_ie_len == data_len && !memcmp(wl->iw_ie, data, data_len)) { WL_ERR(("Previous IW IE is equals to current IE\n")); - return err; + err = BCME_OK; + goto exit; } strncpy(ie_setbuf->cmd, "add", VNDR_IE_CMD_LEN - 1); @@ -9882,7 +10882,7 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s wl->ioctl_buf, WLC_IOCTL_MAXLEN, bssidx, &wl->ioctl_buf_sync); if (err != BCME_OK) - return err; + goto exit; } ie_setbuf->ie_buffer.ie_list[0].ie_data.len = data_len; @@ -9899,20 +10899,35 @@ wl_cfg80211_add_iw_ie(struct wl_priv *wl, struct net_device *ndev, s32 bssidx, s err = wldev_iovar_setint_bsscfg(ndev, "grat_arp", 1, bssidx); } - kfree(ie_setbuf); +exit: + if (ie_setbuf) + kfree(ie_setbuf); return err; } #endif /* WL11U */ -static s32 -wl_cfg80211_mgmt_tx_cancel_wait(struct wiphy *wiphy, - struct net_device *dev, u64 cookie) +#ifdef WL_HOST_BAND_MGMT +s32 +wl_cfg80211_set_band(struct net_device *ndev, int band) { - /* CFG80211 checks for tx_cancel_wait callback when ATTR_DURATION - * is passed with CMD_FRAME. This callback is supposed to cancel - * the OFFCHANNEL Wait. Since we are already taking care of that - * with the tx_mgmt logic, do nothing here. - */ + struct wl_priv *wl = wlcfg_drv_priv; + int ret = 0; + char ioctl_buf[50]; + + if ((band < WLC_BAND_AUTO) || (band > WLC_BAND_2G)) { + WL_ERR(("Invalid band\n")); + return -EINVAL; + } + + if ((ret = wldev_iovar_setbuf(ndev, "roam_band", &band, + sizeof(int), ioctl_buf, sizeof(ioctl_buf), NULL)) < 0) { + WL_ERR(("seting roam_band failed code=%d\n", ret)); + return ret; + } + + WL_DBG(("Setting band to %d\n", band)); + wl->curr_band = band; return 0; } +#endif /* WL_HOST_BAND_MGMT */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfg80211.h b/drivers/net/wireless/bcmdhd/wl_cfg80211.h index 35a4f05..b512b12 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfg80211.h +++ b/drivers/net/wireless/bcmdhd/wl_cfg80211.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfg80211.h 358186 2012-09-21 14:36:14Z $ + * $Id: wl_cfg80211.h 393930 2013-03-29 12:06:51Z $ */ #ifndef _wl_cfg80211_h_ @@ -62,19 +62,25 @@ struct wl_ibss; /* 0 invalidates all debug messages. default is 1 */ #define WL_DBG_LEVEL 0xFF +#ifdef CUSTOMER_HW4 +#define CFG80211_ERROR_TEXT "CFG80211-INFO2) " +#else +#define CFG80211_ERROR_TEXT "CFG80211-ERROR) " +#endif + #if defined(DHD_DEBUG) #define WL_ERR(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO "CFG80211-INFO2) %s : ", __func__); \ + printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \ printk args; \ - } \ + } \ } while (0) #else /* defined(DHD_DEBUG) */ #define WL_ERR(args) \ do { \ if ((wl_dbg_level & WL_DBG_ERR) && net_ratelimit()) { \ - printk(KERN_INFO "CFG80211-INFO2) %s : ", __func__); \ + printk(KERN_INFO CFG80211_ERROR_TEXT "%s : ", __func__); \ printk args; \ } \ } while (0) @@ -135,12 +141,14 @@ do { \ #else /* !(WL_DBG_LEVEL > 0) */ #define WL_DBG(args) #endif /* (WL_DBG_LEVEL > 0) */ +#define WL_PNO(x) +#define WL_SD(x) #define WL_SCAN_RETRY_MAX 3 #define WL_NUM_PMKIDS_MAX MAXPMKID #define WL_SCAN_BUF_MAX (1024 * 8) -#define WL_TLV_INFO_MAX 1500 +#define WL_TLV_INFO_MAX 1500 #define WL_SCAN_IE_LEN_MAX 2048 #define WL_BSS_INFO_MAX 2048 #define WL_ASSOC_INFO_MAX 512 @@ -152,15 +160,18 @@ do { \ #define WL_AP_MAX 256 #define WL_FILE_NAME_MAX 256 #define WL_DWELL_TIME 200 -#define WL_MED_DWELL_TIME 400 +#define WL_MED_DWELL_TIME 400 #define WL_MIN_DWELL_TIME 100 #define WL_LONG_DWELL_TIME 1000 #define IFACE_MAX_CNT 2 -#define WL_SCAN_CONNECT_DWELL_TIME_MS 200 -#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 20 -#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 -#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 -#define WL_AF_TX_MAX_RETRY 5 +#define WL_SCAN_CONNECT_DWELL_TIME_MS 300 +#define WL_SCAN_JOIN_PROBE_INTERVAL_MS 60 +#define WL_SCAN_JOIN_ACTIVE_DWELL_TIME_MS 320 +#define WL_SCAN_JOIN_PASSIVE_DWELL_TIME_MS 400 +#define WL_AF_TX_MAX_RETRY 5 + +#define WL_AF_SEARCH_TIME_MAX 450 +#define WL_AF_TX_EXTRA_TIME_MAX 200 #define WL_SCAN_TIMER_INTERVAL_MS 8000 /* Scan timeout */ #define WL_CHANNEL_SYNC_RETRY 5 @@ -168,7 +179,7 @@ do { \ /* Bring down SCB Timeout to 20secs from 60secs default */ #ifndef WL_SCB_TIMEOUT -#define WL_SCB_TIMEOUT 20 +#define WL_SCB_TIMEOUT 20 #endif /* driver status */ @@ -342,7 +353,9 @@ struct net_info { s32 mode; s32 roam_off; unsigned long sme_state; + bool pm_restore; bool pm_block; + s32 pm; struct list_head list; /* list of all net_info structure */ }; typedef s32(*ISCAN_HANDLER) (struct wl_priv *wl); @@ -400,22 +413,22 @@ struct escan_info { #if defined(STATIC_WL_PRIV_STRUCT) #ifndef CONFIG_DHD_USE_STATIC_BUF #error STATIC_WL_PRIV_STRUCT should be used with CONFIG_DHD_USE_STATIC_BUF -#endif -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#endif /* CONFIG_DHD_USE_STATIC_BUF */ +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) u8 *escan_buf[2]; #else u8 *escan_buf; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ #else -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) u8 escan_buf[2][ESCAN_BUF_SIZE]; #else u8 escan_buf[ESCAN_BUF_SIZE]; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ #endif /* STATIC_WL_PRIV_STRUCT */ -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) u8 cur_sync_id; -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ struct wiphy *wiphy; struct net_device *ndev; }; @@ -477,9 +490,10 @@ struct parsed_ies { u32 wpa2_ie_len; }; + #ifdef WL11U /* Max length of Interworking element */ -#define IW_IES_MAX_BUF_LEN 9 +#define IW_IES_MAX_BUF_LEN 9 #endif /* private data of cfg80211 interface */ @@ -519,7 +533,7 @@ struct wl_priv { #else struct wl_connect_info conn_info; #endif - + struct dentry *debugfs; struct wl_pmk_list *pmk_list; /* wpa2 pmk list */ tsk_ctl_t event_tsk; /* task of main event handler thread */ void *pub; @@ -546,7 +560,7 @@ struct wl_priv { bool wlfc_on; bool vsdb_mode; bool roamoff_on_concurrent; - u8 *ioctl_buf; /* ioctl buffer */ + u8 *ioctl_buf; /* ioctl buffer */ struct mutex ioctl_buf_sync; u8 *escan_ioctl_buf; u8 *extra_buf; /* maily to grab assoc information */ @@ -609,6 +623,8 @@ wl_alloc_netinfo(struct wl_priv *wl, struct net_device *ndev, _net_info->mode = mode; _net_info->ndev = ndev; _net_info->wdev = wdev; + _net_info->pm_restore = 0; + _net_info->pm = 0; _net_info->pm_block = pm_block; _net_info->roam_off = WL_INVALID; wl->iface_cnt++; @@ -678,8 +694,8 @@ wl_set_status_all(struct wl_priv *wl, s32 status, u32 op) return; /* change all status is not allowed */ default: return; /* unknown operation */ - } } + } } static inline void wl_set_status_by_netdev(struct wl_priv *wl, s32 status, @@ -794,7 +810,7 @@ wl_get_netinfo_by_netdev(struct wl_priv *wl, struct net_device *ndev) (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 1)) #define wl_clr_drv_status(wl, stat, ndev) \ (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 2)) -#define wl_clr_drv_status_all(wl, stat) \ +#define wl_clr_drv_status_all(wl, stat) \ (wl_set_status_all(wl, WL_STATUS_ ## stat, 2)) #define wl_chg_drv_status(wl, stat, ndev) \ (wl_set_status_by_netdev(wl, WL_STATUS_ ## stat, ndev, 4)) @@ -848,6 +864,7 @@ extern s32 wl_cfg80211_if_is_group_owner(void); extern chanspec_t wl_ch_host_to_driver(u16 channel); extern s32 wl_add_remove_eventmsg(struct net_device *ndev, u16 event, bool add); extern void wl_stop_wait_next_action_frame(struct wl_priv *wl, struct net_device *ndev); +#ifdef WL_HOST_BAND_MGMT extern s32 wl_cfg80211_set_band(struct net_device *ndev, int band); -extern int wl_cfg80211_update_power_mode(struct net_device *dev); +#endif /* WL_HOST_BAND_MGMT */ #endif /* _wl_cfg80211_h_ */ diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c index 7a9cbea..00334f5 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.c +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.c 358702 2012-09-25 06:48:56Z $ + * $Id: wl_cfgp2p.c 391443 2013-03-18 07:53:46Z $ * */ #include <typedefs.h> @@ -53,7 +53,7 @@ static bool wl_cfgp2p_has_ie(u8 *ie, u8 **tlvs, u32 *tlvs_len, const u8 *oui, u32 oui_len, u8 type); static u32 -wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, +wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd); static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev); @@ -109,11 +109,6 @@ bool wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len) return false; } -/* -* Currently Action frame just pass to P2P interface regardless real dst. -* but GAS Action can be used for Hotspot2.0 as well -* Need to distingush that it's for P2P or HS20 -*/ #ifdef WL11U #define GAS_RESP_LEN 2 #define DOUBLE_TLV_BODY_OFF 4 @@ -185,9 +180,9 @@ bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len) return true; else return false; -#endif /* WLC11U */ +#endif /* WL11U */ } -void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) +void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel) { wifi_p2p_pub_act_frame_t *pact_frm; wifi_p2p_action_frame_t *act_frm; @@ -199,44 +194,44 @@ void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) pact_frm = (wifi_p2p_pub_act_frame_t *)frame; switch (pact_frm->subtype) { case P2P_PAF_GON_REQ: - CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Group Owner Negotiation Req Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_GON_RSP: - CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Group Owner Negotiation Rsp Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_GON_CONF: - CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Group Owner Negotiation Confirm Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_INVITE_REQ: - CFGP2P_ACTION(("%s P2P Invitation Request Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Invitation Request Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_INVITE_RSP: - CFGP2P_ACTION(("%s P2P Invitation Response Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Invitation Response Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_DEVDIS_REQ: - CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Device Discoverability Request Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_DEVDIS_RSP: - CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Device Discoverability Response Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_PROVDIS_REQ: - CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Provision Discovery Request Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_PAF_PROVDIS_RSP: - CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Provision Discovery Response Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; default: - CFGP2P_ACTION(("%s Unknown P2P Public Action Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s Unknown P2P Public Action Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); } @@ -244,48 +239,48 @@ void wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len) act_frm = (wifi_p2p_action_frame_t *)frame; switch (act_frm->subtype) { case P2P_AF_NOTICE_OF_ABSENCE: - CFGP2P_ACTION(("%s P2P Notice of Absence Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Notice of Absence Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_AF_PRESENCE_REQ: - CFGP2P_ACTION(("%s P2P Presence Request Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Presence Request Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_AF_PRESENCE_RSP: - CFGP2P_ACTION(("%s P2P Presence Response Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Presence Response Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; case P2P_AF_GO_DISC_REQ: - CFGP2P_ACTION(("%s P2P Discoverability Request Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s P2P Discoverability Request Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); break; default: - CFGP2P_ACTION(("%s Unknown P2P Action Frame\n", - (tx)? "TX": "RX")); + CFGP2P_ACTION(("%s Unknown P2P Action Frame," + " channel=%d\n", (tx)? "TX": "RX", channel)); } } else if (wl_cfgp2p_is_gas_action(frame, frame_len)) { sd_act_frm = (wifi_p2psd_gas_pub_act_frame_t *)frame; switch (sd_act_frm->action) { case P2PSD_ACTION_ID_GAS_IREQ: - CFGP2P_ACTION(("%s P2P GAS Initial Request\n", - (tx)? "TX" : "RX")); + CFGP2P_ACTION(("%s P2P GAS Initial Request," + " channel=%d\n", (tx)? "TX" : "RX", channel)); break; case P2PSD_ACTION_ID_GAS_IRESP: - CFGP2P_ACTION(("%s P2P GAS Initial Response\n", - (tx)? "TX" : "RX")); + CFGP2P_ACTION(("%s P2P GAS Initial Response," + " channel=%d\n", (tx)? "TX" : "RX", channel)); break; case P2PSD_ACTION_ID_GAS_CREQ: - CFGP2P_ACTION(("%s P2P GAS Comback Request\n", - (tx)? "TX" : "RX")); + CFGP2P_ACTION(("%s P2P GAS Comback Request," + " channel=%d\n", (tx)? "TX" : "RX", channel)); break; case P2PSD_ACTION_ID_GAS_CRESP: - CFGP2P_ACTION(("%s P2P GAS Comback Response\n", - (tx)? "TX" : "RX")); + CFGP2P_ACTION(("%s P2P GAS Comback Response," + " channel=%d\n", (tx)? "TX" : "RX", channel)); break; default: - CFGP2P_ACTION(("%s Unknown P2P GAS Frame\n", - (tx)? "TX" : "RX")); + CFGP2P_ACTION(("%s Unknown P2P GAS Frame," + " channel=%d\n", (tx)? "TX" : "RX", channel)); } @@ -360,7 +355,11 @@ wl_cfgp2p_set_firm_p2p(struct wl_priv *wl) s32 ret = BCME_OK; s32 val = 0; /* Do we have to check whether APSTA is enabled or not ? */ - wldev_iovar_getint(ndev, "apsta", &val); + ret = wldev_iovar_getint(ndev, "apsta", &val); + if (ret < 0) { + CFGP2P_ERR(("get apsta error %d\n", ret)); + return ret; + } if (val == 0) { val = 1; ret = wldev_ioctl(ndev, WLC_DOWN, &val, sizeof(s32), true); @@ -566,12 +565,12 @@ wl_cfgp2p_set_p2p_mode(struct wl_priv *wl, u8 mode, u32 channel, u16 listen_ms, struct net_device *dev; CFGP2P_DBG(("enter\n")); - if (unlikely(bssidx == WL_INVALID || bssidx >= P2PAPI_BSSCFG_MAX)) { + if (unlikely(bssidx == WL_INVALID)) { CFGP2P_ERR((" %d index out of range\n", bssidx)); return -1; } - dev = wl_to_p2p_bss_ndev(wl, bssidx); + dev = wl_cfgp2p_find_ndev(wl, bssidx); if (unlikely(dev == NULL)) { CFGP2P_ERR(("bssidx %d is not assigned\n", bssidx)); return BCME_NOTFOUND; @@ -677,7 +676,7 @@ wl_cfgp2p_deinit_discovery(struct wl_priv *wl) /* Clear the saved bsscfg index of the discovery BSSCFG to indicate we * have no discovery BSS. */ - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = 0; + wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) = WL_INVALID; wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_DEVICE) = NULL; return ret; @@ -695,8 +694,14 @@ wl_cfgp2p_enable_discovery(struct wl_priv *wl, struct net_device *dev, const u8 *ie, u32 ie_len) { s32 ret = BCME_OK; - s32 bssidx = (wl_to_prmry_ndev(wl) == dev) ? - wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE) : wl_cfgp2p_find_idx(wl, dev); + s32 bssidx; + + if (wl_to_prmry_ndev(wl) == dev) { + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + } else if (wl_cfgp2p_find_idx(wl, dev, &bssidx) != BCME_OK) { + WL_ERR(("Find p2p index from dev(%p) failed\n", dev)); + return BCME_ERROR; + } if (wl_get_p2p_status(wl, DISCOVERY_ON)) { CFGP2P_INFO((" DISCOVERY is already initialized, we have nothing to do\n")); goto set_ie; @@ -777,7 +782,7 @@ exit: s32 wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_chans, u16 *channels, - s32 search_state, u16 action, u32 bssidx) + s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr) { s32 ret = BCME_OK; s32 memsize; @@ -804,7 +809,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, memsize = sizeof(wl_p2p_scan_t) + eparams_size; memblk = scanparambuf; if (memsize > sizeof(scanparambuf)) { - CFGP2P_ERR((" scanpar buf too small (%u > %u)\n", + CFGP2P_ERR((" scanpar buf too small (%u > %zu)\n", memsize, sizeof(scanparambuf))); return -1; } @@ -816,8 +821,9 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, * because dongle use P2P WILDCARD internally by default */ wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SEARCH, 0, 0, bssidx); - ssid.SSID_len = htod32(0); - + /* use null ssid */ + ssid.SSID_len = 0; + memset(&ssid.SSID, 0, sizeof(ssid.SSID)); } else if (search_state == WL_P2P_DISC_ST_SCAN) { /* SCAN STATE 802.11 SCAN * WFD Supplicant has p2p_find command with (type=progressive, type= full) @@ -825,12 +831,12 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, * we have to set ssid to P2P WILDCARD because * we just do broadcast scan unless setting SSID */ - strncpy(ssid.SSID, WL_P2P_WILDCARD_SSID, sizeof(ssid.SSID) - 1); - ssid.SSID[sizeof(ssid.SSID) - 1] = 0; - ssid.SSID_len = htod32(WL_P2P_WILDCARD_SSID_LEN); wl_cfgp2p_set_p2p_mode(wl, WL_P2P_DISC_ST_SCAN, 0, 0, bssidx); - } - else { + /* use wild card ssid */ + ssid.SSID_len = WL_P2P_WILDCARD_SSID_LEN; + memset(&ssid.SSID, 0, sizeof(ssid.SSID)); + memcpy(&ssid.SSID, WL_P2P_WILDCARD_SSID, WL_P2P_WILDCARD_SSID_LEN); + } else { CFGP2P_ERR((" invalid search state %d\n", search_state)); return -1; } @@ -847,7 +853,11 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, else eparams->params.scan_type = DOT11_SCANTYPE_PASSIVE; - memcpy(&eparams->params.bssid, ðer_bcast, ETHER_ADDR_LEN); + if (tx_dst_addr == NULL) + memcpy(&eparams->params.bssid, ðer_bcast, ETHER_ADDR_LEN); + else + memcpy(&eparams->params.bssid, tx_dst_addr, ETHER_ADDR_LEN); + if (ssid.SSID_len) memcpy(&eparams->params.ssid, &ssid, sizeof(wlc_ssid_t)); @@ -887,11 +897,11 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, } eparams->version = htod32(ESCAN_REQ_VERSION); eparams->action = htod16(action); -#if defined(DUAL_ESCAN_RESULT_BUFFER) +#if defined(CUSTOMER_HW4) && defined(DUAL_ESCAN_RESULT_BUFFER) eparams->sync_id = wl->escan_info.cur_sync_id; #else eparams->sync_id = htod16(0x1234); -#endif +#endif /* CUSTOMER_HW4 && DUAL_ESCAN_RESULT_BUFFER */ CFGP2P_INFO(("SCAN CHANNELS : ")); for (i = 0; i < num_chans; i++) { @@ -917,7 +927,7 @@ wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, */ s32 wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, - s32 bssidx, s32 channel) + s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr) { s32 ret = 0; u32 chan_cnt = 0; @@ -925,8 +935,8 @@ wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, if (!p2p_is_on(wl) || ndev == NULL || bssidx == WL_INVALID) return -BCME_ERROR; CFGP2P_ERR((" Enter\n")); - if (bssidx == P2PAPI_BSSCFG_PRIMARY) - bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); + if (bssidx == wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_PRIMARY)) + bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); if (channel) chan_cnt = AF_PEER_SEARCH_CNT; else @@ -950,7 +960,7 @@ wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, } ret = wl_cfgp2p_escan(wl, ndev, true, chan_cnt, default_chan_list, WL_P2P_DISC_ST_SEARCH, - WL_SCAN_ACTION_START, bssidx); + WL_SCAN_ACTION_START, bssidx, tx_dst_addr); kfree(default_chan_list); exit: return ret; @@ -966,7 +976,9 @@ exit: #define wl_cfgp2p_is_p2p_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_P2P) /* Check whether the given IE looks like WFA WFDisplay IE. */ +#ifndef WFA_OUI_TYPE_WFD #define WFA_OUI_TYPE_WFD 0x0a /* WiFi Display OUI TYPE */ +#endif #define wl_cfgp2p_is_wfd_ie(ie, tlvs, len) wl_cfgp2p_has_ie(ie, tlvs, len, \ (const uint8 *)WFA_OUI, WFA_OUI_LEN, WFA_OUI_TYPE_WFD) @@ -1055,45 +1067,50 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss struct parsed_vndr_ies new_vndr_ies; s32 i; u8 *ptr; + s32 type = -1; s32 remained_buf_len; - #define IE_TYPE(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie) #define IE_TYPE_LEN(type, bsstype) (wl_to_p2p_bss_saved_ie(wl, bsstype).p2p_ ## type ## _ie_len) memset(g_mgmt_ie_buf, 0, sizeof(g_mgmt_ie_buf)); curr_ie_buf = g_mgmt_ie_buf; CFGP2P_DBG((" bssidx %d, pktflag : 0x%02X\n", bssidx, pktflag)); if (wl->p2p != NULL) { + if (wl_cfgp2p_find_type(wl, bssidx, &type)) { + CFGP2P_ERR(("cannot find type from bssidx : %d\n", bssidx)); + return BCME_ERROR; + } + switch (pktflag) { case VNDR_IE_PRBREQ_FLAG : - mgmt_ie_buf = IE_TYPE(probe_req, bssidx); - mgmt_ie_len = &IE_TYPE_LEN(probe_req, bssidx); - mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, bssidx)); + mgmt_ie_buf = IE_TYPE(probe_req, type); + mgmt_ie_len = &IE_TYPE_LEN(probe_req, type); + mgmt_ie_buf_len = sizeof(IE_TYPE(probe_req, type)); break; case VNDR_IE_PRBRSP_FLAG : - mgmt_ie_buf = IE_TYPE(probe_res, bssidx); - mgmt_ie_len = &IE_TYPE_LEN(probe_res, bssidx); - mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, bssidx)); + mgmt_ie_buf = IE_TYPE(probe_res, type); + mgmt_ie_len = &IE_TYPE_LEN(probe_res, type); + mgmt_ie_buf_len = sizeof(IE_TYPE(probe_res, type)); break; case VNDR_IE_ASSOCREQ_FLAG : - mgmt_ie_buf = IE_TYPE(assoc_req, bssidx); - mgmt_ie_len = &IE_TYPE_LEN(assoc_req, bssidx); - mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, bssidx)); + mgmt_ie_buf = IE_TYPE(assoc_req, type); + mgmt_ie_len = &IE_TYPE_LEN(assoc_req, type); + mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_req, type)); break; case VNDR_IE_ASSOCRSP_FLAG : - mgmt_ie_buf = IE_TYPE(assoc_res, bssidx); - mgmt_ie_len = &IE_TYPE_LEN(assoc_res, bssidx); - mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, bssidx)); + mgmt_ie_buf = IE_TYPE(assoc_res, type); + mgmt_ie_len = &IE_TYPE_LEN(assoc_res, type); + mgmt_ie_buf_len = sizeof(IE_TYPE(assoc_res, type)); break; case VNDR_IE_BEACON_FLAG : - mgmt_ie_buf = IE_TYPE(beacon, bssidx); - mgmt_ie_len = &IE_TYPE_LEN(beacon, bssidx); - mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, bssidx)); + mgmt_ie_buf = IE_TYPE(beacon, type); + mgmt_ie_len = &IE_TYPE_LEN(beacon, type); + mgmt_ie_buf_len = sizeof(IE_TYPE(beacon, type)); break; default: mgmt_ie_buf = NULL; mgmt_ie_len = NULL; CFGP2P_ERR(("not suitable type\n")); - return -1; + return BCME_ERROR; } } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_AP) { switch (pktflag) { @@ -1111,7 +1128,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss mgmt_ie_buf = NULL; mgmt_ie_len = NULL; CFGP2P_ERR(("not suitable type\n")); - return -1; + return BCME_ERROR; } bssidx = 0; } else if (wl_get_mode_by_netdev(wl, ndev) == WL_MODE_BSS) { @@ -1130,12 +1147,12 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss mgmt_ie_buf = NULL; mgmt_ie_len = NULL; CFGP2P_ERR(("not suitable type\n")); - return -1; + return BCME_ERROR; } bssidx = 0; } else { CFGP2P_ERR(("not suitable type\n")); - return -1; + return BCME_ERROR; } if (vndr_ie_len > mgmt_ie_buf_len) { @@ -1181,7 +1198,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss vndrie_info->vndrie.oui[2])); del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, - bssidx, pktflag, vndrie_info->vndrie.oui, + pktflag, vndrie_info->vndrie.oui, vndrie_info->vndrie.id, vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, vndrie_info->ie_len - VNDR_IE_FIXED_LEN, @@ -1211,7 +1228,7 @@ wl_cfgp2p_set_management_ie(struct wl_priv *wl, struct net_device *ndev, s32 bss vndrie_info->vndrie.oui[2])); del_add_ie_buf_len = wl_cfgp2p_vndr_ie(wl, curr_ie_buf, - bssidx, pktflag, vndrie_info->vndrie.oui, + pktflag, vndrie_info->vndrie.oui, vndrie_info->vndrie.id, vndrie_info->ie_ptr + VNDR_IE_FIXED_LEN, vndrie_info->ie_len - VNDR_IE_FIXED_LEN, @@ -1262,21 +1279,37 @@ exit: s32 wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx) { + + s32 vndrie_flag[] = {VNDR_IE_BEACON_FLAG, VNDR_IE_PRBRSP_FLAG, VNDR_IE_ASSOCRSP_FLAG, + VNDR_IE_PRBREQ_FLAG, VNDR_IE_ASSOCREQ_FLAG}; + s32 index = -1; + s32 type = -1; + struct net_device *ndev = wl_cfgp2p_find_ndev(wl, bssidx); #define INIT_IE(IE_TYPE, BSS_TYPE) \ do { \ memset(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie, 0, \ sizeof(wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie)); \ wl_to_p2p_bss_saved_ie(wl, BSS_TYPE).p2p_ ## IE_TYPE ## _ie_len = 0; \ } while (0); - if (bssidx < 0) { - CFGP2P_ERR(("invalid bssidx\n")); + + if (bssidx < 0 || ndev == NULL) { + CFGP2P_ERR(("invalid %s\n", (bssidx < 0) ? "bssidx" : "ndev")); return BCME_BADARG; } - INIT_IE(probe_req, bssidx); - INIT_IE(probe_res, bssidx); - INIT_IE(assoc_req, bssidx); - INIT_IE(assoc_res, bssidx); - INIT_IE(beacon, bssidx); + + if (wl_cfgp2p_find_type(wl, bssidx, &type)) { + CFGP2P_ERR(("invalid argument\n")); + return BCME_BADARG; + } + for (index = 0; index < ARRAYSIZE(vndrie_flag); index++) { + /* clean up vndr ies in dongle */ + wl_cfgp2p_set_management_ie(wl, ndev, bssidx, vndrie_flag[index], NULL, 0); + } + INIT_IE(probe_req, type); + INIT_IE(probe_res, type); + INIT_IE(assoc_req, type); + INIT_IE(assoc_res, type); + INIT_IE(beacon, type); return BCME_OK; } @@ -1358,7 +1391,7 @@ wl_cfgp2p_find_wfdie(u8 *parse, u32 len) return NULL; } static u32 -wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, +wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 pktflag, s8 *oui, s32 ie_id, s8 *data, s32 datalen, const s8* add_del_cmd) { vndr_ie_setbuf_t hdr; /* aligned temporary vndr_ie buffer header */ @@ -1415,33 +1448,82 @@ wl_cfgp2p_vndr_ie(struct wl_priv *wl, u8 *iebuf, s32 bssidx, s32 pktflag, * Parameters: * @wl : wl_private data * @ndev : net device to search bssidx - * Returns bssidx for ndev + * @bssidx : output arg to store bssidx of the bsscfg of firmware. + * Returns error */ s32 -wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev) +wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev, s32 *bssidx) { u32 i; - s32 index = -1; - - if (ndev == NULL) { - CFGP2P_ERR((" ndev is NULL\n")); - goto exit; + if (ndev == NULL || bssidx == NULL) { + CFGP2P_ERR((" argument is invalid\n")); + return BCME_BADARG; } if (!wl->p2p_supported) { - return P2PAPI_BSSCFG_PRIMARY; + *bssidx = P2PAPI_BSSCFG_PRIMARY; + return BCME_OK; } + /* we cannot find the bssidx of DISCOVERY BSS + * because the ndev is same with ndev of PRIMARY BSS. + */ for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { if (ndev == wl_to_p2p_bss_ndev(wl, i)) { - index = wl_to_p2p_bss_bssidx(wl, i); + *bssidx = wl_to_p2p_bss_bssidx(wl, i); + return BCME_OK; + } + } + return BCME_BADARG; +} +struct net_device * +wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx) +{ + u32 i; + struct net_device *ndev = NULL; + if (bssidx < 0) { + CFGP2P_ERR((" bsscfg idx is invalid\n")); + goto exit; + } + + for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { + if (bssidx == wl_to_p2p_bss_bssidx(wl, i)) { + ndev = wl_to_p2p_bss_ndev(wl, i); break; } } - if (index == -1) - return P2PAPI_BSSCFG_PRIMARY; + exit: - return index; + return ndev; } /* + * Search the driver array idx based on bssidx argument + * Parameters: + * @wl : wl_private data + * @bssidx : bssidx which indicate bsscfg->idx of firmware. + * @type : output arg to store array idx of p2p->bss. + * Returns error + */ + +s32 +wl_cfgp2p_find_type(struct wl_priv *wl, s32 bssidx, s32 *type) +{ + u32 i; + if (bssidx < 0 || type == NULL) { + CFGP2P_ERR((" argument is invalid\n")); + goto exit; + } + + for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { + if (bssidx == wl_to_p2p_bss_bssidx(wl, i)) { + *type = i; + return BCME_OK; + } + } + +exit: + return BCME_BADARG; +} + +/* * Callback function for WLC_E_P2P_DISC_LISTEN_COMPLETE */ s32 @@ -1657,24 +1739,29 @@ wl_cfgp2p_action_tx_complete(struct wl_priv *wl, struct net_device *ndev, u32 event_type = ntoh32(e->event_type); u32 status = ntoh32(e->status); CFGP2P_DBG((" Enter\n")); - if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) { + if (event_type == WLC_E_ACTION_FRAME_COMPLETE) { - CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status)); - if (status == WLC_E_STATUS_SUCCESS) { - wl_set_p2p_status(wl, ACTION_TX_COMPLETED); - CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n")); - } - else { - wl_set_p2p_status(wl, ACTION_TX_NOACK); - CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); - wl_stop_wait_next_action_frame(wl, ndev); - } - } else { - CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," - "status : %d\n", status)); + CFGP2P_INFO((" WLC_E_ACTION_FRAME_COMPLETE is received : %d\n", status)); + if (status == WLC_E_STATUS_SUCCESS) { + wl_set_p2p_status(wl, ACTION_TX_COMPLETED); + CFGP2P_DBG(("WLC_E_ACTION_FRAME_COMPLETE : ACK\n")); - if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) - complete(&wl->send_af_done); + } + else { + if (!wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { + wl_set_p2p_status(wl, ACTION_TX_NOACK); + CFGP2P_INFO(("WLC_E_ACTION_FRAME_COMPLETE : NO ACK\n")); + wl_stop_wait_next_action_frame(wl, ndev); + } + } + } else { + CFGP2P_INFO((" WLC_E_ACTION_FRAME_OFFCHAN_COMPLETE is received," + "status : %d\n", status)); + + if (wl_get_drv_status_all(wl, SENDING_ACT_FRM)) + complete(&wl->send_af_done); + } } return ret; } @@ -1700,7 +1787,6 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, wl_clr_p2p_status(wl, ACTION_TX_COMPLETED); wl_clr_p2p_status(wl, ACTION_TX_NOACK); -#define MAX_WAIT_TIME 2000 if (bssidx == P2PAPI_BSSCFG_PRIMARY) bssidx = wl_to_p2p_bss_bssidx(wl, P2PAPI_BSSCFG_DEVICE); @@ -1718,7 +1804,8 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, goto exit; } - timeout = wait_for_completion_timeout(&wl->send_af_done, msecs_to_jiffies(MAX_WAIT_TIME)); + timeout = wait_for_completion_timeout(&wl->send_af_done, + msecs_to_jiffies(af_params->dwell_time + WL_AF_TX_EXTRA_TIME_MAX)); if (timeout > 0 && wl_get_p2p_status(wl, ACTION_TX_COMPLETED)) { CFGP2P_INFO(("tx action frame operation is completed\n")); @@ -1733,7 +1820,6 @@ wl_cfgp2p_tx_action_frame(struct wl_priv *wl, struct net_device *dev, exit: CFGP2P_INFO((" via act frame iovar : status = %d\n", ret)); -#undef MAX_WAIT_TIME return ret; } @@ -1893,10 +1979,14 @@ wl_cfgp2p_supported(struct wl_priv *wl, struct net_device *ndev) s32 wl_cfgp2p_down(struct wl_priv *wl) { - + s32 i = 0, index = -1; wl_cfgp2p_cancel_listen(wl, wl->p2p_net ? wl->p2p_net : wl_to_prmry_ndev(wl), TRUE); - + for (i = 0; i < P2PAPI_BSSCFG_MAX; i++) { + index = wl_to_p2p_bss_bssidx(wl, i); + if (index != WL_INVALID) + wl_cfgp2p_clear_management_ie(wl, index); + } wl_cfgp2p_deinit_priv(wl); return 0; } @@ -2042,16 +2132,10 @@ wl_cfgp2p_set_p2p_ps(struct wl_priv *wl, struct net_device *ndev, char* buf, int } if ((legacy_ps != -1) && ((legacy_ps == PM_MAX) || (legacy_ps == PM_OFF))) { -#ifdef SUPPORT_PM2_ONLY - if (legacy_ps == PM_MAX) - legacy_ps = PM_FAST; -#endif ret = wldev_ioctl(wl_to_p2p_bss_ndev(wl, P2PAPI_BSSCFG_CONNECTION), WLC_SET_PM, &legacy_ps, sizeof(legacy_ps), true); if (unlikely(ret)) { CFGP2P_ERR(("error (%d)\n", ret)); - } else { - wl_cfg80211_update_power_mode(ndev); } } else @@ -2172,13 +2256,25 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) { int ret = 0; struct net_device* net = NULL; - struct wireless_dev *wdev; + struct wireless_dev *wdev = NULL; uint8 temp_addr[ETHER_ADDR_LEN] = { 0x00, 0x90, 0x4c, 0x33, 0x22, 0x11 }; + if (wl->p2p_net) { + CFGP2P_ERR(("p2p_net defined already.\n")); + return -EINVAL; + } + /* Allocate etherdev, including space for private structure */ if (!(net = alloc_etherdev(sizeof(struct wl_priv *)))) { CFGP2P_ERR(("%s: OOM - alloc_etherdev\n", __FUNCTION__)); - goto fail; + return -ENODEV; + } + + wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); + if (unlikely(!wdev)) { + WL_ERR(("Could not allocate wireless device\n")); + free_netdev(net); + return -ENOMEM; } strncpy(net->name, "p2p%d", sizeof(net->name) - 1); @@ -2201,12 +2297,6 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) /* Register with a dummy MAC addr */ memcpy(net->dev_addr, temp_addr, ETHER_ADDR_LEN); - wdev = kzalloc(sizeof(*wdev), GFP_KERNEL); - if (unlikely(!wdev)) { - WL_ERR(("Could not allocate wireless device\n")); - return -ENOMEM; - } - wdev->wiphy = wl->wdev->wiphy; wdev->iftype = wl_mode_to_nl80211_iftype(WL_MODE_BSS); @@ -2222,40 +2312,23 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl) /* Associate p2p0 network interface with new wdev */ wdev->netdev = net; - /* store p2p net ptr for further reference. Note that iflist won't have this - * entry as there corresponding firmware interface is a "Hidden" interface. - */ - if (wl->p2p_net) { - CFGP2P_ERR(("p2p_net defined already.\n")); - return -EINVAL; - } else { - wl->p2p_wdev = wdev; - wl->p2p_net = net; - } - ret = register_netdev(net); if (ret) { CFGP2P_ERR((" register_netdevice failed (%d)\n", ret)); - goto fail; + free_netdev(net); + kfree(wdev); + return -ENODEV; } + /* store p2p net ptr for further reference. Note that iflist won't have this + * entry as there corresponding firmware interface is a "Hidden" interface. + */ + wl->p2p_wdev = wdev; + wl->p2p_net = net; + printk("%s: P2P Interface Registered\n", net->name); return ret; -fail: - -#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 31) - net->open = NULL; -#else - net->netdev_ops = NULL; -#endif - - if (net) { - unregister_netdev(net); - free_netdev(net); - } - - return -ENODEV; } s32 @@ -2274,7 +2347,12 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl) } static int wl_cfgp2p_start_xmit(struct sk_buff *skb, struct net_device *ndev) { - CFGP2P_DBG(("(%s) is not used for data operations. Droping the packet. \n", ndev->name)); + if (skb) + { + CFGP2P_DBG(("(%s) is not used for data operations.Droping the packet.\n", + ndev->name)); + dev_kfree_skb_any(skb); + } return 0; } @@ -2350,3 +2428,8 @@ static int wl_cfgp2p_if_stop(struct net_device *net) BIT(NL80211_IFTYPE_P2P_GO))); return 0; } + +bool wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops) +{ + return (if_ops == &wl_cfgp2p_if_ops); +} diff --git a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h index 31b8dab..95e7c4ab3 100644 --- a/drivers/net/wireless/bcmdhd/wl_cfgp2p.h +++ b/drivers/net/wireless/bcmdhd/wl_cfgp2p.h @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_cfgp2p.h 358702 2012-09-25 06:48:56Z $ + * $Id: wl_cfgp2p.h 383351 2013-02-06 13:05:50Z $ */ #ifndef _wl_cfgp2p_h_ #define _wl_cfgp2p_h_ @@ -46,7 +46,7 @@ typedef enum { /* vendor ies max buffer length for probe response or beacon */ #define VNDR_IES_MAX_BUF_LEN 1400 /* normal vendor ies buffer length */ -#define VNDR_IES_BUF_LEN 512 +#define VNDR_IES_BUF_LEN 512 /* Structure to hold all saved P2P and WPS IEs for a BSSCFG */ struct p2p_saved_ie { @@ -72,12 +72,13 @@ struct p2p_bss { struct p2p_info { bool on; /* p2p on/off switch */ bool scan; + int16 search_state; bool vif_created; s8 vir_ifname[IFNAMSIZ]; unsigned long status; struct ether_addr dev_addr; struct ether_addr int_addr; - struct p2p_bss bss_idx[P2PAPI_BSSCFG_MAX]; + struct p2p_bss bss[P2PAPI_BSSCFG_MAX]; struct timer_list listen_timer; wl_p2p_sched_t noa; wl_p2p_ops_t ops; @@ -110,15 +111,16 @@ enum wl_cfgp2p_status { WLP2P_STATUS_ACTION_TX_COMPLETED, WLP2P_STATUS_ACTION_TX_NOACK, WLP2P_STATUS_SCANNING, - WLP2P_STATUS_GO_NEG_PHASE + WLP2P_STATUS_GO_NEG_PHASE, + WLP2P_STATUS_DISC_IN_PROGRESS }; -#define wl_to_p2p_bss_ndev(w, type) ((wl)->p2p->bss_idx[type].dev) -#define wl_to_p2p_bss_bssidx(w, type) ((wl)->p2p->bss_idx[type].bssidx) -#define wl_to_p2p_bss_saved_ie(w, type) ((wl)->p2p->bss_idx[type].saved_ie) -#define wl_to_p2p_bss_private(w, type) ((wl)->p2p->bss_idx[type].private_data) -#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss_idx[type]) +#define wl_to_p2p_bss_ndev(wl, type) ((wl)->p2p->bss[type].dev) +#define wl_to_p2p_bss_bssidx(wl, type) ((wl)->p2p->bss[type].bssidx) +#define wl_to_p2p_bss_saved_ie(wl, type) ((wl)->p2p->bss[type].saved_ie) +#define wl_to_p2p_bss_private(wl, type) ((wl)->p2p->bss[type].private_data) +#define wl_to_p2p_bss(wl, type) ((wl)->p2p->bss[type]) #define wl_get_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : test_bit(WLP2P_STATUS_ ## stat, \ &(wl)->p2p->status)) #define wl_set_p2p_status(wl, stat) ((!(wl)->p2p_supported) ? 0 : set_bit(WLP2P_STATUS_ ## stat, \ @@ -134,10 +136,17 @@ enum wl_cfgp2p_status { /* dword align allocation */ #define WLC_IOCTL_MAXLEN 8192 +#ifdef CUSTOMER_HW4 +#define CFGP2P_ERROR_TEXT "CFGP2P-INFO2) " +#else +#define CFGP2P_ERROR_TEXT "CFGP2P-ERROR) " +#endif + + #define CFGP2P_ERR(args) \ do { \ if (wl_dbg_level & WL_DBG_ERR) { \ - printk(KERN_INFO "CFGP2P-INFO2) %s : ", __func__); \ + printk(KERN_INFO CFGP2P_ERROR_TEXT "%s : ", __func__); \ printk args; \ } \ } while (0) @@ -180,7 +189,7 @@ wl_cfgp2p_is_p2p_action(void *frame, u32 frame_len); extern bool wl_cfgp2p_is_gas_action(void *frame, u32 frame_len); extern void -wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len); +wl_cfgp2p_print_actframe(bool tx, void *frame, u32 frame_len, u32 channel); extern s32 wl_cfgp2p_init_priv(struct wl_priv *wl); extern void @@ -212,11 +221,11 @@ wl_cfgp2p_disable_discovery(struct wl_priv *wl); extern s32 wl_cfgp2p_escan(struct wl_priv *wl, struct net_device *dev, u16 active, u32 num_chans, u16 *channels, - s32 search_state, u16 action, u32 bssidx); + s32 search_state, u16 action, u32 bssidx, struct ether_addr *tx_dst_addr); extern s32 wl_cfgp2p_act_frm_search(struct wl_priv *wl, struct net_device *ndev, - s32 bssidx, s32 channel); + s32 bssidx, s32 channel, struct ether_addr *tx_dst_addr); extern wpa_ie_fixed_t * wl_cfgp2p_find_wpaie(u8 *parse, u32 len); @@ -236,7 +245,11 @@ extern s32 wl_cfgp2p_clear_management_ie(struct wl_priv *wl, s32 bssidx); extern s32 -wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev); +wl_cfgp2p_find_idx(struct wl_priv *wl, struct net_device *ndev, s32 *index); +extern struct net_device * +wl_cfgp2p_find_ndev(struct wl_priv *wl, s32 bssidx); +extern s32 +wl_cfgp2p_find_type(struct wl_priv *wl, s32 bssidx, s32 *type); extern s32 @@ -295,6 +308,9 @@ wl_cfgp2p_register_ndev(struct wl_priv *wl); extern s32 wl_cfgp2p_unregister_ndev(struct wl_priv *wl); +extern bool +wl_cfgp2p_is_ifops(const struct net_device_ops *if_ops); + /* WiFi Direct */ #define SOCIAL_CHAN_1 1 #define SOCIAL_CHAN_2 6 @@ -311,7 +327,7 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); /* If the provision discovery is for JOIN operations, * then we need not do an internal scan to find GO. - */ +*/ #define IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len) \ (wl_cfgp2p_retreive_p2pattrib(p2p_ie, P2P_SEID_GROUP_ID) == NULL) @@ -320,9 +336,9 @@ wl_cfgp2p_unregister_ndev(struct wl_priv *wl); (frame->action == P2PSD_ACTION_ID_GAS_CREQ))) #define IS_P2P_PUB_ACT_REQ(frame, p2p_ie, len) \ (wl_cfgp2p_is_pub_action(frame, len) && \ - ((frame->subtype == P2P_PAF_GON_REQ) || \ - (frame->subtype == P2P_PAF_INVITE_REQ) || \ - ((frame->subtype == P2P_PAF_PROVDIS_REQ) && \ + ((frame->subtype == P2P_PAF_GON_REQ) || \ + (frame->subtype == P2P_PAF_INVITE_REQ) || \ + ((frame->subtype == P2P_PAF_PROVDIS_REQ) && \ IS_PROV_DISC_WITHOUT_GROUP_ID(p2p_ie, len)))) #define IS_P2P_PUB_ACT_RSP_SUBTYPE(subtype) ((subtype == P2P_PAF_GON_RSP) || \ ((subtype == P2P_PAF_GON_CONF) || \ diff --git a/drivers/net/wireless/bcmdhd/wl_iw.c b/drivers/net/wireless/bcmdhd/wl_iw.c index 6855314..b2acd6a 100644 --- a/drivers/net/wireless/bcmdhd/wl_iw.c +++ b/drivers/net/wireless/bcmdhd/wl_iw.c @@ -21,7 +21,7 @@ * software in any way with any other Broadcom software provided under a license * other than the GPL, without Broadcom's express prior written consent. * - * $Id: wl_iw.c 352251 2012-08-22 06:08:38Z $ + * $Id: wl_iw.c 367054 2012-11-06 15:06:04Z $ */ #if defined(USE_IW) @@ -73,6 +73,24 @@ typedef const struct si_pub si_t; #endif #endif + +#ifndef IW_AUTH_KEY_MGMT_FT_802_1X +#define IW_AUTH_KEY_MGMT_FT_802_1X 0x04 +#endif + +#ifndef IW_AUTH_KEY_MGMT_FT_PSK +#define IW_AUTH_KEY_MGMT_FT_PSK 0x08 +#endif + + +#ifndef IW_ENCODE_ALG_PMK +#define IW_ENCODE_ALG_PMK 4 +#endif +#ifndef IW_ENC_CAPA_4WAY_HANDSHAKE +#define IW_ENC_CAPA_4WAY_HANDSHAKE 0x00000010 +#endif + + #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 27)) #include <linux/rtnetlink.h> #endif @@ -669,6 +687,7 @@ wl_iw_get_range( {14, 29, 43, 58, 87, 116, 130, 144}, {27, 54, 81, 108, 162, 216, 243, 270}, {30, 60, 90, 120, 180, 240, 270, 300}}; + int fbt_cap = 0; WL_TRACE(("%s: SIOCGIWRANGE\n", dev->name)); @@ -724,15 +743,18 @@ wl_iw_get_range( range->num_bitrates = rateset.count; for (i = 0; i < rateset.count && i < IW_MAX_BITRATES; i++) range->bitrate[i] = (rateset.rates[i] & 0x7f) * 500000; - dev_wlc_intvar_get(dev, "nmode", &nmode); + if ((error = dev_wlc_intvar_get(dev, "nmode", &nmode))) + return error; if ((error = dev_wlc_ioctl(dev, WLC_GET_PHYTYPE, &phytype, sizeof(phytype)))) return error; - if (nmode == 1 && ((phytype == WLC_PHY_TYPE_SSN) || (phytype == WLC_PHY_TYPE_LCN) || (phytype == WLC_PHY_TYPE_LCN40))) { - dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap); - dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx); - dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)); + if ((error = dev_wlc_intvar_get(dev, "mimo_bw_cap", &bw_cap))) + return error; + if ((error = dev_wlc_intvar_get(dev, "sgi_tx", &sgi_tx))) + return error; + if ((error = dev_wlc_ioctl(dev, WLC_GET_CHANNEL, &ci, sizeof(channel_info_t)))) + return error; ci.hw_channel = dtoh32(ci.hw_channel); if (bw_cap == 0 || @@ -817,10 +839,14 @@ wl_iw_get_range( range->enc_capa |= IW_ENC_CAPA_CIPHER_TKIP; range->enc_capa |= IW_ENC_CAPA_CIPHER_CCMP; range->enc_capa |= IW_ENC_CAPA_WPA2; -#if (defined(BCMSUP_PSK) && defined(WLFBT)) + - range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE; -#endif + if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { + if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { + + range->enc_capa |= IW_ENC_CAPA_4WAY_HANDSHAKE; + } + } IW_EVENT_CAPA_SET_KERNEL(range->event_capa); @@ -1337,14 +1363,12 @@ wl_iw_handle_scanresults_ies(char **event_p, char *end, } ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); -#if defined(WLFBT) if ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_MDIE_ID))) { iwe.cmd = IWEVGENIE; iwe.u.data.length = ie->len + 2; event = IWE_STREAM_ADD_POINT(info, event, end, &iwe, (char *)ie); } ptr = ((uint8 *)bi) + sizeof(wl_bss_info_t); -#endif while ((ie = bcm_parse_tlvs(ptr, ptr_len, DOT11_MNG_WPA_ID))) { @@ -2389,7 +2413,6 @@ wl_iw_set_encodeext( return error; } } -#if (defined(BCMSUP_PSK) && defined(WLFBT)) else if (iwe->alg == IW_ENCODE_ALG_PMK) { int j; @@ -2412,7 +2435,6 @@ wl_iw_set_encodeext( if (error) return error; } -#endif else { if (iwe->key_len > sizeof(key.data)) @@ -2626,7 +2648,8 @@ wl_iw_set_wpaauth( break; case IW_AUTH_CIPHER_PAIRWISE: - case IW_AUTH_CIPHER_GROUP: + case IW_AUTH_CIPHER_GROUP: { + int fbt_cap = 0; if (paramid == IW_AUTH_CIPHER_PAIRWISE) { iw->pwsec = paramval; @@ -2668,33 +2691,42 @@ wl_iw_set_wpaauth( if ((error = dev_wlc_intvar_set(dev, "wsec", val))) return error; -#ifdef WLFBT - if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val | AES_ENABLED)) { - if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) - return error; - } - else if (val == 0) { - if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) - return error; + + + if (dev_wlc_intvar_get(dev, "fbt_cap", &fbt_cap) == 0) { + if (fbt_cap == WLC_FBT_CAP_DRV_4WAY_AND_REASSOC) { + if ((paramid == IW_AUTH_CIPHER_PAIRWISE) && (val & AES_ENABLED)) { + if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 1))) + return error; + } + else if (val == 0) { + if ((error = dev_wlc_intvar_set(dev, "sup_wpa", 0))) + return error; + } + } } -#endif break; + } case IW_AUTH_KEY_MGMT: if ((error = dev_wlc_intvar_get(dev, "wpa_auth", &val))) return error; if (val & (WPA_AUTH_PSK | WPA_AUTH_UNSPECIFIED)) { - if (paramval & IW_AUTH_KEY_MGMT_PSK) + if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) val = WPA_AUTH_PSK; else val = WPA_AUTH_UNSPECIFIED; + if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) + val |= WPA2_AUTH_FT; } else if (val & (WPA2_AUTH_PSK | WPA2_AUTH_UNSPECIFIED)) { - if (paramval & IW_AUTH_KEY_MGMT_PSK) + if (paramval & (IW_AUTH_KEY_MGMT_FT_PSK | IW_AUTH_KEY_MGMT_PSK)) val = WPA2_AUTH_PSK; else val = WPA2_AUTH_UNSPECIFIED; + if (paramval & (IW_AUTH_KEY_MGMT_FT_802_1X | IW_AUTH_KEY_MGMT_FT_PSK)) + val |= WPA2_AUTH_FT; } #ifdef BCMWAPI_WPI if (paramval & (IW_AUTH_KEY_MGMT_WAPI_PSK | IW_AUTH_KEY_MGMT_WAPI_CERT)) @@ -3615,7 +3647,7 @@ static void wl_iw_send_scan_complete(iscan_info_t *iscan) memset(&wrqu, 0, sizeof(wrqu)); - + wireless_send_event(iscan->dev, SIOCGIWSCAN, &wrqu, NULL); } diff --git a/drivers/net/wireless/bcmdhd/wl_roam.c b/drivers/net/wireless/bcmdhd/wl_roam.c index 708fb3b..25f93ab 100644..100755 --- a/drivers/net/wireless/bcmdhd/wl_roam.c +++ b/drivers/net/wireless/bcmdhd/wl_roam.c @@ -28,28 +28,33 @@ #include <osl.h> #include <bcmwifi_channels.h> #include <wlioctl.h> - -#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) +#include <bcmutils.h> +#include <wl_cfg80211.h> #include <wldev_common.h> -#define WL_ERROR(x) printk x -#endif +#define MAX_ROAM_CACHE 100 +#define MAX_CHANNEL_LIST 20 +#define MAX_SSID_BUFSIZE 36 -#define WL_DBG(x) - -#define MAX_ROAM_CACHE 100 +#define ROAMSCAN_MODE_NORMAL 0 +#define ROAMSCAN_MODE_WES 1 typedef struct { chanspec_t chanspec; int ssid_len; - char ssid[36]; + char ssid[MAX_SSID_BUFSIZE]; } roam_channel_cache; +typedef struct { + int n; + chanspec_t channels[MAX_CHANNEL_LIST]; +} channel_list_t; + static int n_roam_cache = 0; static int roam_band = WLC_BAND_AUTO; static roam_channel_cache roam_cache[MAX_ROAM_CACHE]; #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) -static int roamscan_mode = 0; +static int roamscan_mode = ROAMSCAN_MODE_NORMAL; #endif #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) @@ -68,7 +73,7 @@ int set_roamscan_mode(struct net_device *dev, int mode) error = wldev_iovar_setint(dev, "roamscan_mode", mode); if (error) { - WL_ERROR(("Failed to set roamscan mode to %d, error = %d\n", mode, error)); + WL_ERR(("Failed to set roamscan mode to %d, error = %d\n", mode, error)); } return error; @@ -78,11 +83,11 @@ int get_roamscan_channel_list(struct net_device *dev, unsigned char channels[]) { int n = 0; - if (roamscan_mode) { + if (roamscan_mode == ROAMSCAN_MODE_WES) { for (n = 0; n < n_roam_cache; n++) { channels[n] = roam_cache[n].chanspec & WL_CHANSPEC_CHAN_MASK; - WL_DBG(("%s: channel[%d] - [%02d] \n", __FUNCTION__, n, channels[n])); + WL_DBG(("channel[%d] - [%02d] \n", n, channels[n])); } } @@ -94,16 +99,13 @@ int set_roamscan_channel_list(struct net_device *dev, { int i; int error; - struct { - int n; - chanspec_t channels[20]; - } channel_list; - char iobuf[200]; - uint band, band2G, band5G, bw; - roamscan_mode = 1; + channel_list_t channel_list; + char iobuf[WLC_IOCTL_SMLEN]; + uint band2G, band5G, bw; + roamscan_mode = ROAMSCAN_MODE_WES; - if (n > 20) - n = 20; + if (n > MAX_CHANNEL_LIST) + n = MAX_CHANNEL_LIST; #ifdef D11AC_IOTYPES if (ioctl_ver == 1) { @@ -125,7 +127,7 @@ int set_roamscan_channel_list(struct net_device *dev, for (i = 0; i < n; i++) { chanspec_t chanspec; - if (channels[i] <= 14) { + if (channels[i] <= CH_MAX_2G_CHANNEL) { chanspec = band2G | bw | channels[i]; } else { chanspec = band5G | bw | channels[i]; @@ -133,17 +135,22 @@ int set_roamscan_channel_list(struct net_device *dev, roam_cache[i].chanspec = chanspec; channel_list.channels[i] = chanspec; - WL_DBG(("%s: channel[%d] - [%02d] \n", __FUNCTION__, i, channels[i])); + WL_DBG(("channel[%d] - [%02d] \n", i, channels[i])); } n_roam_cache = n; channel_list.n = n; + /* need to set ROAMSCAN_MODE_NORMAL to update roamscan_channels, + otherwise, it won't be updated + */ + wldev_iovar_setint(dev, "roamscan_mode", ROAMSCAN_MODE_NORMAL); error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list, sizeof(channel_list), iobuf, sizeof(iobuf), NULL); if (error) { - WL_ERROR(("Failed to set roamscan channels, error = %d\n", error)); + WL_DBG(("Failed to set roamscan channels, error = %d\n", error)); } + wldev_iovar_setint(dev, "roamscan_mode", ROAMSCAN_MODE_WES); return error; } @@ -157,7 +164,7 @@ void set_roam_band(int band) void reset_roam_cache(void) { #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) - if (roamscan_mode) + if (roamscan_mode == ROAMSCAN_MODE_WES) return; #endif @@ -170,11 +177,11 @@ void add_roam_cache(wl_bss_info_t *bi) uint8 channel; #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) - if (roamscan_mode) + if (roamscan_mode == ROAMSCAN_MODE_WES) return; #endif - if (n_roam_cache == MAX_ROAM_CACHE) + if (n_roam_cache >= MAX_ROAM_CACHE) return; for (i = 0; i < n_roam_cache; i++) { @@ -188,9 +195,11 @@ void add_roam_cache(wl_bss_info_t *bi) roam_cache[n_roam_cache].ssid_len = bi->SSID_len; channel = (bi->ctl_ch == 0) ? CHSPEC_CHANNEL(bi->chanspec) : bi->ctl_ch; + WL_DBG(("CHSPEC 0x%X %d, CTL %d\n", + bi->chanspec, CHSPEC_CHANNEL(bi->chanspec), bi->ctl_ch)); roam_cache[n_roam_cache].chanspec = WL_CHANSPEC_BW_20 | - (channel <= 14 ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) | + (channel <= CH_MAX_2G_CHANNEL ? WL_CHANSPEC_BAND_2G : WL_CHANSPEC_BAND_5G) | channel; memcpy(roam_cache[n_roam_cache].ssid, bi->SSID, bi->SSID_len); @@ -220,21 +229,21 @@ int get_roam_channel_list(int target_chan, bw = WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; #endif /* D11AC_IOTYPES */ - if (target_chan <= 14) + if (target_chan <= CH_MAX_2G_CHANNEL) band = band2G; else band = band5G; *channels = (target_chan & WL_CHANSPEC_CHAN_MASK) | band | bw; - WL_DBG((" %s: %02d 0x%04X\n", __FUNCTION__, target_chan, *channels)); + WL_DBG(("%02d 0x%04X\n", target_chan, *channels)); ++channels; #if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) - if (roamscan_mode) { + if (roamscan_mode == ROAMSCAN_MODE_WES) { for (i = 0; i < n_roam_cache; i++) { if ((roam_cache[i].chanspec & WL_CHANSPEC_CHAN_MASK) != target_chan) { *channels = roam_cache[i].chanspec & WL_CHANSPEC_CHAN_MASK; - WL_DBG((" %s: %02d\n", __FUNCTION__, *channels)); - if (*channels <= 14) + WL_DBG(("%02d\n", *channels)); + if (*channels <= CH_MAX_2G_CHANNEL) *channels |= band2G | bw; else *channels |= band5G | bw; @@ -258,13 +267,12 @@ int get_roam_channel_list(int target_chan, (memcmp(roam_cache[i].ssid, ssid->SSID, ssid->SSID_len) == 0)) { /* match found, add it */ *channels = ch & WL_CHANSPEC_CHAN_MASK; - if (*channels <= 14) + if (*channels <= CH_MAX_2G_CHANNEL) *channels |= band2G | bw; else *channels |= band5G | bw; - WL_DBG((" %s: %02d 0x%04X\n", __FUNCTION__, - ch & WL_CHANSPEC_CHAN_MASK, *channels)); + WL_DBG(("%02d 0x%04X\n", ch & WL_CHANSPEC_CHAN_MASK, *channels)); channels++; n++; } @@ -278,7 +286,7 @@ void print_roam_cache(void) { int i; - WL_DBG((" %d cache\n", n_roam_cache)); + WL_DBG(("%d cache\n", n_roam_cache)); for (i = 0; i < n_roam_cache; i++) { roam_cache[i].ssid[roam_cache[i].ssid_len] = 0; @@ -286,3 +294,102 @@ void print_roam_cache(void) roam_cache[i].ssid_len, roam_cache[i].ssid)); } } + +static void add_roamcache_channel(channel_list_t *channels, chanspec_t ch) +{ + int i; + + if (channels->n >= MAX_CHANNEL_LIST) /* buffer full */ + return; + + for (i = 0; i < channels->n; i++) { + if (channels->channels[i] == ch) /* already in the list */ + return; + } + + channels->channels[i] = ch; + channels->n++; + + WL_DBG((" RCC: %02d 0x%04X\n", + ch & WL_CHANSPEC_CHAN_MASK, ch)); +} + +void update_roam_cache(struct wl_priv *wl, int ioctl_ver) +{ + int error, i, prev_channels; + channel_list_t channel_list; + char iobuf[WLC_IOCTL_SMLEN]; + struct net_device *dev = wl_to_prmry_ndev(wl); + wlc_ssid_t ssid; + uint band2G, band5G, bw; + +#if defined(CUSTOMER_HW4) && defined(WES_SUPPORT) + if (roamscan_mode == ROAMSCAN_MODE_WES) { + /* no update when ROAMSCAN_MODE_WES */ + return; + } +#endif + + if (!wl_get_drv_status(wl, CONNECTED, dev)) { + WL_DBG(("Not associated\n")); + return; + } + + /* need to read out the current cache list + as the firmware may change dynamically + */ + error = wldev_iovar_getbuf(dev, "roamscan_channels", 0, 0, + (void *)&channel_list, sizeof(channel_list), NULL); + + WL_DBG(("%d AP, %d cache item(s), err=%d\n", n_roam_cache, channel_list.n, error)); + + error = wldev_get_ssid(dev, &ssid); + if (error) { + WL_ERR(("Failed to get SSID, err=%d\n", error)); + return; + } + +#ifdef D11AC_IOTYPES + if (ioctl_ver == 1) { + /* legacy chanspec */ + band2G = WL_LCHANSPEC_BAND_2G; + band5G = WL_LCHANSPEC_BAND_5G; + bw = WL_LCHANSPEC_BW_20 | WL_LCHANSPEC_CTL_SB_NONE; + } else { + band2G = WL_CHANSPEC_BAND_2G; + band5G = WL_CHANSPEC_BAND_5G; + bw = WL_CHANSPEC_BW_20; + } +#else + band2G = WL_CHANSPEC_BAND_2G; + band5G = WL_CHANSPEC_BAND_5G; + bw = WL_CHANSPEC_BW_20 | WL_CHANSPEC_CTL_SB_NONE; +#endif /* D11AC_IOTYPES */ + + prev_channels = channel_list.n; + for (i = 0; i < n_roam_cache; i++) { + chanspec_t ch = roam_cache[i].chanspec; + if ((roam_cache[i].ssid_len == ssid.SSID_len) && + ((roam_band == WLC_BAND_AUTO) || + ((roam_band == WLC_BAND_2G) && CHSPEC_IS2G(ch)) || + ((roam_band == WLC_BAND_5G) && CHSPEC_IS5G(ch))) && + (memcmp(roam_cache[i].ssid, ssid.SSID, ssid.SSID_len) == 0)) { + /* match found, add it */ + ch &= WL_CHANSPEC_CHAN_MASK; + if (ch <= CH_MAX_2G_CHANNEL) + ch |= band2G | bw; + else + ch |= band5G | bw; + + add_roamcache_channel(&channel_list, ch); + } + } + if (prev_channels != channel_list.n) { + /* channel list updated */ + error = wldev_iovar_setbuf(dev, "roamscan_channels", &channel_list, + sizeof(channel_list), iobuf, sizeof(iobuf), NULL); + if (error) { + WL_ERR(("Failed to update roamscan channels, error = %d\n", error)); + } + } +} diff --git a/drivers/net/wireless/bcmdhd/wldev_common.h b/drivers/net/wireless/bcmdhd/wldev_common.h index 099e83f..f9bf425 100644 --- a/drivers/net/wireless/bcmdhd/wldev_common.h +++ b/drivers/net/wireless/bcmdhd/wldev_common.h @@ -96,9 +96,7 @@ extern int net_os_set_suspend_disable(struct net_device *dev, int val); extern int net_os_set_suspend(struct net_device *dev, int val, int force); extern int wl_iw_parse_ssid_list_tlv(char** list_str, wlc_ssid_t* ssid, int max, int *bytes_left); -#if defined(CUSTOMER_HW4) && defined(PNO_SUPPORT) && defined(CONFIG_HAS_WAKELOCK) -int net_os_wake_lock_timeout_for_pno(struct net_device *dev, int sec); -#endif + /* Get the link speed from dongle, speed is in kpbs */ int wldev_get_link_speed(struct net_device *dev, int *plink_speed); |