aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsbrissen <sbrissen@hotmail.com>2013-04-24 13:09:33 -0400
committersbrissen <sbrissen@hotmail.com>2013-04-25 10:50:50 -0400
commitc421809918b7106b40a81134f9fb5103146fc715 (patch)
tree89b0147d51d2b2650c5ded666a08613ba0cab3c1
parent43aaedbcde478c8e032771d62a1956133b29b1d4 (diff)
downloadkernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.tar.gz
kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.tar.bz2
kernel_samsung_smdk4412-c421809918b7106b40a81134f9fb5103146fc715.zip
update bcmdhd driver from GT-9505 Source
drivers pulled from http://review.cyanogenmod.org/#/c/36122/ Change-Id: Ide4aef99ee1d594f4222ae69aca0bdb7d563e80a
-rw-r--r--drivers/net/wireless/bcmdhd/Kconfig56
-rw-r--r--drivers/net/wireless/bcmdhd/Makefile154
-rw-r--r--drivers/net/wireless/bcmdhd/aiutils.c43
-rw-r--r--drivers/net/wireless/bcmdhd/bcmevent.c12
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh.c8
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_linux.c70
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc.c225
-rw-r--r--drivers/net/wireless/bcmdhd/bcmsdh_sdmmc_linux.c58
-rwxr-xr-xdrivers/net/wireless/bcmdhd/bcmsdspi_linux.c11
-rwxr-xr-xdrivers/net/wireless/bcmdhd/bcmspibrcm.c12
-rw-r--r--drivers/net/wireless/bcmdhd/bcmutils.c96
-rw-r--r--drivers/net/wireless/bcmdhd/bcmwifi_channels.c56
-rw-r--r--drivers/net/wireless/bcmdhd/bcmwifi_channels.h41
-rw-r--r--drivers/net/wireless/bcmdhd/bcmwifi_rates.h138
-rw-r--r--drivers/net/wireless/bcmdhd/dhd.h194
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_bus.h2
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cdc.c587
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.c110
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_cfg80211.h9
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_common.c123
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_custom_gpio.c2
-rwxr-xr-x[-rw-r--r--]drivers/net/wireless/bcmdhd/dhd_custom_sec.c554
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_dbg.h4
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_linux.c1808
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_proto.h15
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_sdio.c1407
-rwxr-xr-xdrivers/net/wireless/bcmdhd/dhd_sec_feature.h107
-rw-r--r--drivers/net/wireless/bcmdhd/dhd_wlfc.h23
-rw-r--r--drivers/net/wireless/bcmdhd/hndpmu.c12
-rw-r--r--[-rwxr-xr-x]drivers/net/wireless/bcmdhd/include/Makefile8
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmdefs.h11
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmdevs.h99
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmnvram.h16
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdbus.h25
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdh.h6
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdh_sdmmc.h34
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdpcm.h29
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsdstd.h2
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmspibrcm.h336
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsrom_fmt.h26
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmsrom_tbl.h55
-rw-r--r--drivers/net/wireless/bcmdhd/include/bcmutils.h49
-rw-r--r--drivers/net/wireless/bcmdhd/include/dbus.h8
-rw-r--r--drivers/net/wireless/bcmdhd/include/dhdioctl.h5
-rw-r--r--drivers/net/wireless/bcmdhd/include/epivers.h18
-rw-r--r--drivers/net/wireless/bcmdhd/include/hndsoc.h52
-rw-r--r--drivers/net/wireless/bcmdhd/include/linux_osl.h107
-rw-r--r--drivers/net/wireless/bcmdhd/include/linuxver.h23
-rw-r--r--drivers/net/wireless/bcmdhd/include/osl.h20
-rw-r--r--drivers/net/wireless/bcmdhd/include/pcicfg.h3
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/802.11.h508
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmevent.h61
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/bcmip.h23
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/ethernet.h39
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/p2p.h5
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/vlan.h10
-rw-r--r--drivers/net/wireless/bcmdhd/include/proto/wpa.h14
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbchipc.h421
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbhnddma.h16
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbsdio.h10
-rw-r--r--drivers/net/wireless/bcmdhd/include/sbsdpcmdev.h2
-rw-r--r--drivers/net/wireless/bcmdhd/include/sdioh.h6
-rw-r--r--drivers/net/wireless/bcmdhd/include/siutils.h17
-rw-r--r--drivers/net/wireless/bcmdhd/include/spid.h6
-rw-r--r--drivers/net/wireless/bcmdhd/include/trxhdr.h45
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlfc_proto.h24
-rw-r--r--drivers/net/wireless/bcmdhd/include/wlioctl.h899
-rw-r--r--drivers/net/wireless/bcmdhd/linux_osl.c203
-rw-r--r--drivers/net/wireless/bcmdhd/siutils.c90
-rw-r--r--drivers/net/wireless/bcmdhd/siutils_priv.h3
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.c738
-rw-r--r--drivers/net/wireless/bcmdhd/wl_android.h52
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.c2439
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfg80211.h67
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.c433
-rw-r--r--drivers/net/wireless/bcmdhd/wl_cfgp2p.h52
-rw-r--r--drivers/net/wireless/bcmdhd/wl_iw.c84
-rwxr-xr-x[-rw-r--r--]drivers/net/wireless/bcmdhd/wl_roam.c181
-rw-r--r--drivers/net/wireless/bcmdhd/wldev_common.h4
79 files changed, 9568 insertions, 3753 deletions
diff --git a/drivers/net/wireless/bcmdhd/Kconfig b/drivers/net/wireless/bcmdhd/Kconfig
index 3d06eeb3c0d..da5c179697d 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 e115d07fd23..40bc790bc58 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 3ca17259e65..ea94da58d14 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 e41c7387a8a..e7ed4162acf 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 2f7c451c47b..b65dbdcc980 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 cd62e4b69ee..fe19e15278c 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 8137701bda7..8af2ca6ac30 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 ed37e8c2c9b..609f8d0f8c5 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 2dbb1684b46..9e3922bd3ae 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 d5f5754af49..2dd7c10ba60 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 06461956bdc..c50e66c293c 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 0a570f66af2..0cbc1cb8071 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 c7970474128..d9884132443 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 9896b2360a6..213fb93a2f1 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 94cbe912fe1..4afdb8cfc3a 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 fcb4bbd65c8..5f2c9ea234a 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 cd44b9246b4..9e405b038f2 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 e6a68371e89..781a78b3aba 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, &param27);
- 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 922d6edde00..985d9d25b0c 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 dab96860b54..c4ac414e271 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 9421e98dee2..ba833b3dcf2 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 1683501ee7f..be129b585be 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 314f0ee58c7..df3f5b0f29d 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 8702a442813..ff8e6345a69 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, &param);
+ }
+
+ 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 *)&ampdu_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 09d546809db..21dfe238008 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 422ad034f5e..138e8e5d0f0 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 fdad9589408..933a78a1916 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 40873514771..0eaaa0fa8c7 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 ad9a9ca4645..92a56db94ad 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 eca939fbaa9..bcc1267755f 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 a35ed72aa85..0462f81c1b9 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 c7e06ff4481..50e693a6406 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 ce0e0350874..ba22becea6a 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 29657d7ab0f..cbea8c5c13b 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 3348e844c89..e882d5e628e 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 25cd55b3706..bd85de3d0ef 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 80c0a3d13ee..1fc37f90605 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 896686cfcf2..2b5adf10bd1 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 d94e9e42920..a3e9b49a060 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 f5246a56129..0347674ce15 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 040ae6a44b0..cb49421e49c 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 cbbd7efdf53..1b21327b2e0 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 c5ea223ec8c..9784e1fe874 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 11fff555a8f..53bab2c84ba 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 60f9838c514..12470adc9e5 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 66640c3b0cb..f5c161b9463 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 5fd1dbd31b4..7d6481f515e 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 3c2a1683132..149b74002f2 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 ca171d8acd6..b7173fdf5f9 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 5f7df6a7a7e..0a984e8a59d 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 1632e7dcd67..aca93169f3f 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 312074dc4bf..243a97538fd 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 d5c3b76da5a..02ddd373685 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 e45518564c1..7b9b2e2b794 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 2b6fef6b7ac..8f7652f0bf9 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 9c94985cf95..2eb483294f3 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 47bc354c0ba..7ebeedacc19 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 5feb7430715..463c8afded1 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 da1f1a10a65..0b4460275ec 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 0e9ad7d74ee..30a891ed058 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 10c7401a81c..66ff3fe550f 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 5517a718507..7597901d9fb 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 a797b3d1e71..4a5be1ade4e 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 6d2d40319e2..bfe24ff10b2 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 bf92a5651af..da4763c89e3 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 1c8cc018dda..dfa8db0ff22 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 33811a17f5c..09ba05ccd50 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 d03a095f5fe..32f03d9f5a5 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 db108b8c4b2..0c0ffd51659 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 9a3270f7424..1ae06ba6dfb 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 00b696979b1..3232e3b0504 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 583a16735ec..c6f37f094e7 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 7324e53ea8c..c20569535cb 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, &ether_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, &ether_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", &param, 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, &params_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, &params_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(&params, " ")) != 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 35a4f0580f8..b512b126d01 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 7a9cbea04d3..00334f52297 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, &ether_bcast, ETHER_ADDR_LEN);
+ if (tx_dst_addr == NULL)
+ memcpy(&eparams->params.bssid, &ether_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 31b8dab7266..95e7c4ab3d1 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 6855314c4cc..b2acd6a6f5b 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 708fb3bb09c..25f93abf8fd 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 099e83fa89b..f9bf42584ea 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);